325 lines
No EOL
9.3 KiB
Bash
Executable file
325 lines
No EOL
9.3 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
if '[' '-n' "${ZSH_VERSION-}" ']'; then
|
|
'emulate' 'sh' '-o' 'err_exit' '-o' 'no_unset'
|
|
else
|
|
'set' '-ue'
|
|
fi
|
|
|
|
platform="$('command' 'uname' '-sm')"
|
|
platform="$('printf' '%s' "$platform" | 'command' 'tr' '[A-Z]' '[a-z]')"
|
|
|
|
case "$platform" in
|
|
'darwin arm64');;
|
|
'darwin x86_64');;
|
|
'linux aarch64');;
|
|
'linux armv6l');;
|
|
'linux armv7l');;
|
|
'linux armv8l');;
|
|
'linux x86_64');;
|
|
'linux i686');;
|
|
*)
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: sorry, unsupported platform: \033[31m%s\033[0m\n' "$platform"
|
|
'exit' '1'
|
|
;;
|
|
esac
|
|
|
|
if command -v 'curl' >'/dev/null' 2>&1; then
|
|
fetch='command curl -fsSLo'
|
|
elif command -v 'wget' >'/dev/null' 2>&1; then
|
|
fetch='command wget -O'
|
|
else
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: please install \033[32mcurl\033[0m or \033[32mwget\033[0m\n'
|
|
'exit' '1'
|
|
fi
|
|
|
|
if '[' '!' '-d' "${HOME-}" ']'; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: \033[1m$HOME\033[0m is not a directory\n'
|
|
'exit' '1'
|
|
fi
|
|
|
|
euid="$('command' 'id' '-u')"
|
|
if '[' "$euid" '=' '0' ']'; then
|
|
home_ls="$('command' 'ls' '-ld' '--' "$HOME")"
|
|
home_owner="$('printf' '%s\n' "$home_ls" | 'command' 'awk' 'NR==1 {print $3}')"
|
|
if '[' "$home_owner" '!=' 'root' ']'; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: please retry without \033[4;32msudo\033[0m\n'
|
|
'exit' '1'
|
|
fi
|
|
fi
|
|
|
|
if '[' '!' '-t' '0' ']'; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: standard input is not a \033[1mTTY\033[0m\n'
|
|
'exit' '1'
|
|
fi
|
|
|
|
if '[' '!' '-t' '1' ']'; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: standard output is not a \033[1mTTY\033[0m\n'
|
|
'exit' '1'
|
|
fi
|
|
|
|
if '[' '!' '-t' '2' ']'; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: standard error is not a \033[1mTTY\033[0m\n'
|
|
'exit' '1'
|
|
fi
|
|
|
|
saved_tty_settings="$('command' 'stty' '-g')"
|
|
|
|
zshenv=''
|
|
zshrc=''
|
|
foxshell=''
|
|
|
|
cleanup() {
|
|
'trap' '-' 'INT' 'TERM' 'EXIT'
|
|
'command' 'rm' '-f' '--' "$zshenv" "$zshrc" "${zshrc:+$zshrc.bak}" "$foxshell"
|
|
'command' 'stty' "$saved_tty_settings"
|
|
}
|
|
|
|
'trap' 'cleanup' 'INT' 'TERM' 'EXIT'
|
|
|
|
lf='
|
|
'
|
|
|
|
read_choice() {
|
|
choice=''
|
|
'command' 'stty' '-icanon' 'min' '1' 'time' '0'
|
|
while :; do
|
|
c="$('command' 'dd' 'bs=1' 'count=1' 2>'/dev/null' && 'echo' 'x')"
|
|
choice="$choice${c%x}"
|
|
n="$('printf' '%s' "$choice" | 'command' 'wc' '-m')"
|
|
'[' "$n" '-eq' '0' ']' || 'break'
|
|
done
|
|
'command' 'stty' "$saved_tty_settings"
|
|
'[' "$choice" '=' "$lf" ] || 'echo'
|
|
}
|
|
|
|
>&2 'printf' 'Welcome to FoxShell!\n'
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' 'What kind of \033[1mkeyboard\033[0m are you using?\n'
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' ' \033[1m(1)\033[0m Mac. It has \033[32mOption\033[0m key(s) and does not have \033[33mAlt\033[0m.\n'
|
|
>&2 'printf' ' \033[1m(2)\033[0m PC. It has \033[32mAlt\033[0m key(s) and does not have \033[33mOption\033[0m.\n'
|
|
>&2 'printf' ' \033[1m(q)\033[0m Quit and do nothing.\n'
|
|
>&2 'printf' '\n'
|
|
while 'true'; do
|
|
>&2 'printf' '\033[1mChoice [12q]:\033[0m '
|
|
'read_choice'
|
|
case "$choice" in
|
|
'1')
|
|
bs_key='Delete'
|
|
zshrc_suffix='.mac'
|
|
'break'
|
|
;;
|
|
'2')
|
|
bs_key='Backspace'
|
|
zshrc_suffix=''
|
|
'break'
|
|
;;
|
|
'q'|'Q')
|
|
'exit' '1'
|
|
;;
|
|
"$lf")
|
|
;;
|
|
*)
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: invalid choice: \033[31m%s\033[0m\n' "$choice"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' 'What \033[1mkeybindings\033[0m do you prefer?\n'
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' ' \033[1m(1)\033[0m Standard. I delete characters with \033[33m%s\033[0m key.\n' "$bs_key"
|
|
>&2 'printf' ' \033[1m(2)\033[0m Like in \033[32mvi\033[0m. I delete characters with \033[33mX\033[0m key in \033[33mcommand mode\033[0m.\n'
|
|
>&2 'printf' ' \033[1m(q)\033[0m Quit and do nothing.\n'
|
|
>&2 'printf' '\n'
|
|
while 'true'; do
|
|
>&2 'printf' '\033[1mChoice [12q]:\033[0m '
|
|
'read_choice'
|
|
case "$choice" in
|
|
'1')
|
|
'break'
|
|
;;
|
|
'2')
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' 'Sorry, \033[32mvi\033[0m keybindings are \033[31mnot supported\033[0m yet.\n'
|
|
'exit' '1'
|
|
'break'
|
|
;;
|
|
'q'|'Q')
|
|
'exit' '1'
|
|
;;
|
|
"$lf")
|
|
;;
|
|
*)
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: invalid choice: \033[31m%s\033[0m\n' "$choice"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' 'Do you want \033[32mzsh\033[0m to always run in \033[32mtmux\033[0m?\n'
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' ' \033[1m(y)\033[0m Yes.\n'
|
|
>&2 'printf' ' \033[1m(n)\033[0m No.\n'
|
|
>&2 'printf' ' \033[1m(q)\033[0m Quit and do nothing.\n'
|
|
>&2 'printf' '\n'
|
|
while 'true'; do
|
|
>&2 'printf' '\033[1mChoice [ynq]:\033[0m '
|
|
'read_choice'
|
|
case "$choice" in
|
|
'y'|'Y')
|
|
tmux='1'
|
|
'break'
|
|
;;
|
|
'n'|'N')
|
|
tmux='0'
|
|
'break'
|
|
;;
|
|
'q'|'Q')
|
|
'exit' '1'
|
|
;;
|
|
"$lf")
|
|
;;
|
|
*)
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: invalid choice: \033[31m%s\033[0m\n' "$choice"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' 'Do you use \033[32mdirenv\033[0m?\n'
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' ' \033[1m(y)\033[0m Yes.\n'
|
|
>&2 'printf' ' \033[1m(n)\033[0m No.\n'
|
|
>&2 'printf' ' \033[1m(q)\033[0m Quit and do nothing.\n'
|
|
>&2 'printf' '\n'
|
|
while 'true'; do
|
|
>&2 'printf' '\033[1mChoice [ynq]:\033[0m '
|
|
'read_choice'
|
|
case "$choice" in
|
|
'y'|'Y')
|
|
direnv='1'
|
|
'break'
|
|
;;
|
|
'n'|'N')
|
|
direnv='0'
|
|
'break'
|
|
;;
|
|
'q'|'Q')
|
|
'exit' '1'
|
|
;;
|
|
"$lf")
|
|
;;
|
|
*)
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: invalid choice: \033[31m%s\033[0m\n' "$choice"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' 'Do you want to enable \033[32mSSH\033[0m teleportation?\n'
|
|
>&2 'printf' '\n'
|
|
>&2 'printf' ' \033[1m(y)\033[0m Yes.\n'
|
|
>&2 'printf' ' \033[1m(n)\033[0m No.\n'
|
|
>&2 'printf' ' \033[1m(q)\033[0m Quit and do nothing.\n'
|
|
>&2 'printf' '\n'
|
|
while 'true'; do
|
|
>&2 'printf' '\033[1mChoice [ynq]:\033[0m '
|
|
'read_choice'
|
|
case "$choice" in
|
|
'y'|'Y')
|
|
ssh='1'
|
|
'break'
|
|
;;
|
|
'n'|'N')
|
|
ssh='0'
|
|
'break'
|
|
;;
|
|
'q'|'Q')
|
|
'exit' '1'
|
|
;;
|
|
"$lf")
|
|
;;
|
|
*)
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: invalid choice: \033[31m%s\033[0m\n' "$choice"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if 'command' 'mktemp' '-u' >'/dev/null' 2>&1; then
|
|
foxshell="$('command' 'mktemp' "$HOME"/.foxshell.XXXXXXXXXX)"
|
|
else
|
|
foxshell="$HOME"/.foxshell.tmp."$$"
|
|
fi
|
|
|
|
url='https://git.foxdale.tech/Arctic/foxshell/raw/branch/main'
|
|
|
|
>&2 printf '\033[33mfoxshell\033[0m: fetching \033[4mfoxshell.zsh\033[0m from \033[1mgit.foxdale.tech/Arctic/foxshell\033[0m\n'
|
|
if ! err="$($fetch "$foxshell" '--' "$url"/foxshell.zsh 2>&1)"; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: %s\n' "$err"
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: failed to download \033[31m%s\033[0m\n' "$url"/foxshell.zsh
|
|
'command' 'rm' '-rf' '--' "$foxshell" 2>'/dev/null'
|
|
'exit' '1'
|
|
fi
|
|
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: generating \033[4m~/.zshenv\033[0m\n'
|
|
if ! err="$($fetch "$HOME"/.zshenv.tmp -- "$url"/.zshenv 2>&1)"; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: %s\n' "$err"
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: failed to download \033[31m%s\033[0m\n' "$url"/.zshenv
|
|
'exit' '1'
|
|
fi
|
|
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: generating \033[4m~/.zshrc\033[0m\n'
|
|
if ! err="$($fetch "$HOME"/.zshrc.tmp -- "$url"/.zshrc"$zshrc_suffix" 2>&1)"; then
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: %s\n' "$err"
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: failed to download \033[31m%s\033[0m\n' "$url"/.zshrc"$zshrc_suffix"
|
|
'exit' '1'
|
|
fi
|
|
|
|
if '[' "$tmux" '=' '1' ']'; then
|
|
'command' 'awk' "/Mark up shell's output/ {print \"# Start tmux if not already in tmux.\"; print \"zstyle ':foxshell:' start-tmux command tmux -u new -A -D -t foxshell\"; print \"\"; print \"# Whether to move prompt to the bottom when zsh starts and on Ctrl+L.\"; print \"zstyle ':foxshell:' prompt-at-bottom 'no'\"; print \"\"} 1" "$HOME"/.zshrc.tmp >"$HOME"/.zshrc.bak
|
|
else
|
|
'command' 'awk' "/Mark up shell's output/ {print \"# Don't start tmux.\"; print \"zstyle ':foxshell:' start-tmux no\"; print \"\"} 1" "$HOME"/.zshrc.tmp >"$HOME"/.zshrc.bak
|
|
fi
|
|
|
|
'command' 'mv' '--' "$HOME"/.zshrc.bak "$HOME"/.zshrc.tmp
|
|
|
|
if '[' "$direnv" '=' '1' ']'; then
|
|
'command' 'awk' "/Enable direnv/ {print \"# Enable direnv to automatically source .envrc files.\"; print \"zstyle ':foxshell:direnv' enable 'yes'\"; print \"\"} 1" "$HOME"/.zshrc.tmp >"$HOME"/.zshrc.bak
|
|
'command' 'mv' '--' "$HOME"/.zshrc.bak "$HOME"/.zshrc.tmp
|
|
fi
|
|
|
|
if '[' "$ssh" '=' '1' ']'; then
|
|
'command' 'awk' "/Enable.*SSH/ {print \"# Enable automatic teleportation of foxshell over SSH.\"; print \"zstyle ':foxshell:ssh:*' enable 'yes'\"; print \"\"} 1" "$HOME"/.zshrc.tmp >"$HOME"/.zshrc.bak
|
|
'command' 'mv' '--' "$HOME"/.zshrc.bak "$HOME"/.zshrc.tmp
|
|
fi
|
|
|
|
FOXSHELL="${XDG_CACHE_HOME:-$HOME/.cache}/foxshell"
|
|
|
|
if '[' '-e' "$HOME"/.zshenv ']'; then
|
|
'command' 'cp' '--' "$HOME"/.zshenv "$HOME"/.zshenv.bak
|
|
fi
|
|
'command' 'rm' '-rf' '--' "$FOXSHELL"
|
|
'command' 'mkdir' '-p' -- "$FOXSHELL"
|
|
|
|
zshenv="$HOME"/.zshenv.tmp
|
|
zshrc="$HOME"/.zshrc.tmp
|
|
|
|
'command' 'sed' "s|\${XDG_CACHE_HOME:-\$HOME/.cache}/foxshell|$FOXSHELL|g" "$zshenv" >"$zshenv.bak"
|
|
'command' 'mv' '--' "$zshenv.bak" "$zshenv"
|
|
|
|
if '[' '-e' "$HOME"/.zshrc ']'; then
|
|
'command' 'cp' '--' "$HOME"/.zshrc "$HOME"/.zshrc.bak
|
|
fi
|
|
|
|
'command' 'mv' '--' "$zshenv" "$HOME"/.zshenv
|
|
'command' 'mv' '--' "$zshrc" "$HOME"/.zshrc
|
|
'command' 'mv' '--' "$foxshell" "$FOXSHELL"/foxshell.zsh
|
|
|
|
>&2 'printf' '\033[33mfoxshell\033[0m: restarting \033[32mzsh\033[0m\n'
|
|
if '[' '-n' "${TMUX-}" ']'; then
|
|
'exec' "$SHELL" '-l'
|
|
else
|
|
'exec' "$SHELL" '-l' '-c' 'exec zsh'
|
|
fi |