mirror of
https://github.com/jarun/nnn.git
synced 2026-09-28 13:01:45 +02:00
414 lines
12 KiB
Bash
Executable File
414 lines
12 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Interactively configure nnn's quitcd helper and common beginner options.
|
|
# Detect terminal background and color palette and suggest context colors.
|
|
# Optionally install plugins and configure nuke as the opener.
|
|
#
|
|
# Shell: POSIX compliant
|
|
# Author: Arun Prakash Jana
|
|
|
|
REPO_URL='https://raw.githubusercontent.com/jarun/nnn/master'
|
|
TMPFILE=''
|
|
|
|
cleanup()
|
|
{
|
|
status=$?
|
|
[ -z "$TMPFILE" ] || rm -f -- "$TMPFILE"
|
|
return "$status"
|
|
}
|
|
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
check_nnn()
|
|
{
|
|
if ! command -v nnn >/dev/null 2>&1; then
|
|
printf 'nnn is not installed or is not available on PATH.\n' >&2
|
|
printf 'Installation: https://github.com/jarun/nnn/wiki/Usage#installation\n' >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
ask_yes_no()
|
|
{
|
|
prompt=$1
|
|
|
|
while :; do
|
|
printf '%s [y/N] ' "$prompt"
|
|
IFS= read -r answer || exit 1
|
|
case $answer in
|
|
y|Y|yes|YES|Yes) return 0 ;;
|
|
''|n|N|no|NO|No) return 1 ;;
|
|
*) printf 'Please answer y or n.\n' ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
print_configuration_help()
|
|
{
|
|
cat <<'EOF'
|
|
|
|
Optional environment variables (add selected exports to your shell rc file):
|
|
NNN_BMS Key-to-directory bookmarks, e.g. 'd:$HOME/Documents'
|
|
NNN_PLUG Key-to-plugin pairs, e.g. 'o:fzopen;v:imgview'
|
|
NNN_OPENER Custom file opener; useful for CLI-only setups
|
|
NNN_COLORS Context colours, e.g. '1234'
|
|
NNN_FCOLORS File-type colours for xterm-256color terminals
|
|
NNN_TRASH Custom trash command instead of rm -rf
|
|
NNN_ARCHIVE Extra archive filename extensions
|
|
NNN_FIFO FIFO path for live previews or integrations
|
|
NNN_SEL Custom selection file path
|
|
|
|
See https://github.com/jarun/nnn/wiki/Usage#configuration for details.
|
|
|
|
EOF
|
|
}
|
|
|
|
detect_shell()
|
|
{
|
|
shell_name=$(ps -p "$PPID" -o comm= 2>/dev/null)
|
|
shell_name=${shell_name##*/}
|
|
|
|
if [ -z "$shell_name" ]; then
|
|
shell_name=${SHELL##*/}
|
|
fi
|
|
|
|
case $shell_name in
|
|
ash|dash|ksh|mksh|yash) shell_name='sh' ;;
|
|
nu) shell_name='nushell' ;;
|
|
esac
|
|
|
|
printf 'Detected shell: %s\n' "$shell_name"
|
|
|
|
case $shell_name in
|
|
bash)
|
|
helper='quitcd.bash_sh_zsh'
|
|
rc_file=${BASHRC:-"$HOME/.bashrc"}
|
|
format='bash'
|
|
;;
|
|
sh)
|
|
helper='quitcd.bash_sh_zsh'
|
|
rc_file="$HOME/.profile"
|
|
format='posix'
|
|
;;
|
|
zsh)
|
|
helper='quitcd.bash_sh_zsh'
|
|
rc_file="${ZDOTDIR:-$HOME}/.zshrc"
|
|
format='zsh'
|
|
;;
|
|
fish)
|
|
helper='quitcd.fish'
|
|
rc_file="${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish"
|
|
format='fish'
|
|
;;
|
|
csh)
|
|
helper='quitcd.csh'
|
|
rc_file="$HOME/.cshrc"
|
|
format='csh'
|
|
;;
|
|
tcsh)
|
|
helper='quitcd.csh'
|
|
rc_file="$HOME/.tcshrc"
|
|
format='csh'
|
|
;;
|
|
elvish)
|
|
helper='quitcd.elv'
|
|
rc_file="$HOME/.elvish/rc.elv"
|
|
format='elvish'
|
|
;;
|
|
nushell|nu)
|
|
helper='quitcd.nu'
|
|
rc_file="${XDG_CONFIG_HOME:-$HOME/.config}/nushell/config.nu"
|
|
format='nushell'
|
|
;;
|
|
*)
|
|
printf 'Unsupported shell: %s\n' "$shell_name" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
add_option()
|
|
{
|
|
option=$1
|
|
description=$2
|
|
|
|
if ask_yes_no "$option: $description"; then
|
|
options="$options $option"
|
|
fi
|
|
}
|
|
|
|
configure_context_colors()
|
|
{
|
|
terminal_colors=$(tput colors 2>/dev/null)
|
|
case $terminal_colors in
|
|
''|*[!0-9]*) terminal_colors=8 ;;
|
|
esac
|
|
|
|
terminal_background=${COLORFGBG##*;}
|
|
case $terminal_background in
|
|
7|8|9|1[0-5])
|
|
terminal_theme='light'
|
|
colors_8='41254125'
|
|
colors_256='#19a01c5a1e19a01c'
|
|
;;
|
|
*)
|
|
terminal_theme='dark'
|
|
colors_8='36735673'
|
|
colors_256='#51e2d0c652d59f7b'
|
|
;;
|
|
esac
|
|
|
|
if [ "$terminal_colors" -ge 256 ]; then
|
|
context_colors="$colors_256;$colors_8"
|
|
printf 'Detected a %s terminal with %s colors.\n' "$terminal_theme" "$terminal_colors"
|
|
else
|
|
context_colors=$colors_8
|
|
printf 'Detected a %s terminal with %s colors; using the 8-color palette.\n' \
|
|
"$terminal_theme" "$terminal_colors"
|
|
fi
|
|
|
|
if [ -z "${COLORFGBG:-}" ]; then
|
|
printf 'COLORFGBG is unavailable, so the terminal background is assumed dark.\n'
|
|
fi
|
|
}
|
|
|
|
function_exists()
|
|
{
|
|
[ -f "$rc_file" ] || return 1
|
|
|
|
case $format in
|
|
bash|posix|zsh)
|
|
grep -Eq "^[[:space:]]*${function_name}[[:space:]]*\\(\\)" "$rc_file"
|
|
;;
|
|
fish)
|
|
grep -Eq "^[[:space:]]*function[[:space:]]+$function_name([[:space:]]|$)" "$rc_file"
|
|
;;
|
|
csh)
|
|
grep -Eq "^[[:space:]]*alias[[:space:]]+$function_name([[:space:]]|$)" "$rc_file"
|
|
;;
|
|
elvish)
|
|
grep -Eq "^[[:space:]]*fn[[:space:]]+$function_name([[:space:]]|$)" "$rc_file"
|
|
;;
|
|
nushell)
|
|
grep -Eq "^[[:space:]]*export[[:space:]]+def([[:space:]]+--env)?[[:space:]]+$function_name([[:space:]]|$)" "$rc_file"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
select_function_name()
|
|
{
|
|
while :; do
|
|
printf 'Function name [n]: '
|
|
IFS= read -r function_name || exit 1
|
|
function_name=${function_name:-n}
|
|
|
|
case $function_name in
|
|
[!A-Za-z_]*|*[!A-Za-z0-9_]* )
|
|
printf 'Use a name containing only letters, numbers, and underscores.\n'
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
if function_exists; then
|
|
if ask_yes_no "Function $function_name already exists in $rc_file. Append another definition?"; then
|
|
return
|
|
fi
|
|
continue
|
|
fi
|
|
return
|
|
done
|
|
}
|
|
|
|
download_helper()
|
|
{
|
|
TMPFILE=$(mktemp "${TMPDIR:-/tmp}/nnn-quitcd.XXXXXX") || exit 1
|
|
|
|
if command -v curl >/dev/null 2>&1; then
|
|
curl --connect-timeout 10 --max-time 60 -fsSL "$REPO_URL/misc/quitcd/$helper" > "$TMPFILE"
|
|
elif command -v wget >/dev/null 2>&1; then
|
|
wget --timeout=60 -qO "$TMPFILE" "$REPO_URL/misc/quitcd/$helper"
|
|
else
|
|
printf 'curl or wget is required to download the %s helper.\n' "$shell_name" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -s "$TMPFILE" ]; then
|
|
printf 'Could not download %s from the nnn repository.\n' "$helper" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
configure_helper()
|
|
{
|
|
case $format in
|
|
bash|posix|zsh)
|
|
sed "s|command nnn \"\$@\"|command nnn$options \"\$@\"|" "$TMPFILE"
|
|
;;
|
|
fish)
|
|
sed "s|command nnn \$argv|command nnn$options \$argv|" "$TMPFILE"
|
|
;;
|
|
csh)
|
|
sed "s|\\\\nnn; source|\\\\nnn$options; source|" "$TMPFILE"
|
|
;;
|
|
elvish)
|
|
sed "s|e:nnn \$@a|e:nnn$options \$@a|" "$TMPFILE"
|
|
;;
|
|
nushell)
|
|
sed "s|\^nnn \.\.\.\$args|^nnn$options ...\$args|g" "$TMPFILE"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
rename_function()
|
|
{
|
|
case $format in
|
|
bash|posix|zsh)
|
|
sed "s|^n ()|$function_name ()|";
|
|
;;
|
|
fish)
|
|
sed "s|^function n\\([[:space:]]\\)|function $function_name\\1|";
|
|
;;
|
|
csh)
|
|
sed "s|^alias n\\([[:space:]]\\)|alias $function_name\\1|";
|
|
;;
|
|
elvish)
|
|
sed "s|^fn n |fn $function_name |";
|
|
;;
|
|
nushell)
|
|
sed "s|^export def --env n |export def --env $function_name |";
|
|
;;
|
|
esac
|
|
}
|
|
|
|
configure_nuke()
|
|
{
|
|
if [ "$use_nuke" -eq 0 ]; then
|
|
cat
|
|
return
|
|
fi
|
|
|
|
case $format in
|
|
bash|posix|zsh)
|
|
# shellcheck disable=SC2016
|
|
sed '/^[[:space:]]*export NNN_TMPFILE=/a\ export NNN_OPENER="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"'
|
|
;;
|
|
fish)
|
|
# shellcheck disable=SC2016
|
|
sed '/^function /a\ set -x NNN_OPENER (path join (or $XDG_CONFIG_HOME "$HOME/.config") nnn/plugins/nuke)'
|
|
;;
|
|
csh)
|
|
# shellcheck disable=SC2016
|
|
sed '/^set NNN_TMPFILE=/a\setenv NNN_OPENER "$HOME/.config/nnn/plugins/nuke"'
|
|
;;
|
|
elvish)
|
|
# shellcheck disable=SC2016
|
|
sed '/^fn /a\ set-env NNN_OPENER (path:join (or $E:XDG_CONFIG_HOME (path:join $E:HOME .config)) nnn/plugins/nuke)'
|
|
;;
|
|
nushell)
|
|
# shellcheck disable=SC2016
|
|
sed '/^export def --env /a\ let-env NNN_OPENER = ($env.XDG_CONFIG_HOME | default ($env.HOME | path join .config) | path join nnn/plugins/nuke)'
|
|
;;
|
|
esac
|
|
}
|
|
|
|
configure_colors()
|
|
{
|
|
if [ "$use_context_colors" -eq 0 ]; then
|
|
cat
|
|
return
|
|
fi
|
|
|
|
case $format in
|
|
bash|posix|zsh)
|
|
sed "/^[[:space:]]*export NNN_TMPFILE=/a\\ export NNN_COLORS='$context_colors'"
|
|
;;
|
|
fish)
|
|
sed "/^function /a\\ set -x NNN_COLORS '$context_colors'"
|
|
;;
|
|
csh)
|
|
sed "/^set NNN_TMPFILE=/a\\setenv NNN_COLORS '$context_colors'"
|
|
;;
|
|
elvish)
|
|
sed "/^fn /a\\ set-env NNN_COLORS '$context_colors'"
|
|
;;
|
|
nushell)
|
|
sed "/^export def --env /a\\ \$env.NNN_COLORS = '$context_colors'"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
install_plugins()
|
|
{
|
|
if ! ask_yes_no "$(printf '\n%s' 'Install (or update) all nnn plugins now?')"; then
|
|
return
|
|
fi
|
|
|
|
if command -v curl >/dev/null 2>&1; then
|
|
if sh -c "$(curl --connect-timeout 10 --max-time 60 -fsSL https://raw.githubusercontent.com/jarun/nnn/master/plugins/getplugs)"; then
|
|
if ask_yes_no 'Set NNN_OPENER to the installed nuke plugin?'; then
|
|
use_nuke=1
|
|
printf 'The generated function will use nuke to open files.\n'
|
|
fi
|
|
fi
|
|
else
|
|
printf 'Plugin installation requires curl.\n' >&2
|
|
fi
|
|
}
|
|
|
|
check_nnn
|
|
detect_shell
|
|
|
|
options=''
|
|
select_function_name
|
|
|
|
if ask_yes_no "$(printf '\n%s' 'Open text files in the terminal editor (-e)?')"; then
|
|
options=' -e'
|
|
editor=${VISUAL:-${EDITOR:-vi}}
|
|
printf 'Text files will be opened with: %s\n' "$editor"
|
|
fi
|
|
|
|
printf '\nChoose any additional beginner-friendly options.\n'
|
|
add_option '-d' 'Start in detail mode (permissions, size, and time)'
|
|
add_option '-D' 'Show directories in their context colour'
|
|
add_option '-H' 'Show hidden files by default'
|
|
add_option '-n' 'Type to navigate (filter mode always on)'
|
|
add_option '-Q' 'Quit without a confirmation prompt'
|
|
add_option '-R' 'Stop at the first and last entry instead of wrapping around'
|
|
|
|
use_context_colors=0
|
|
if ask_yes_no 'Detect terminal colours and set NNN_COLORS for all 8 contexts?'; then
|
|
use_context_colors=1
|
|
configure_context_colors
|
|
fi
|
|
|
|
use_nuke=0
|
|
install_plugins
|
|
|
|
download_helper
|
|
configured_helper=$(configure_helper | rename_function | configure_nuke | configure_colors) || exit 1
|
|
|
|
printf '\nGenerated nnn function with:%s\n' "${options:- no option selected}"
|
|
print_configuration_help
|
|
|
|
if ask_yes_no "Append this function to $rc_file? It changes directory on quit."; then
|
|
mkdir -p "$(dirname "$rc_file")" || exit 1
|
|
{
|
|
printf '\n# nnn quitcd helper generated by misc/quitcd/setup.sh\n'
|
|
printf '%s\n' "$configured_helper"
|
|
} >> "$rc_file" || exit 1
|
|
printf 'Appended the nnn function to %s\n' "$rc_file"
|
|
else
|
|
printf '\n# >>> nnn quitcd helper >>>\n%s\n# <<< nnn quitcd helper <<<\n' "$configured_helper"
|
|
fi
|
|
|
|
cat <<'EOF'
|
|
|
|
Useful links:
|
|
Usage, Config: https://github.com/jarun/nnn/wiki/Usage
|
|
Plugins: https://github.com/jarun/nnn/tree/master/plugins
|
|
Wiki: https://github.com/jarun/nnn/wiki
|
|
Use cases: https://github.com/jarun/nnn/wiki/Basic-use-cases#the-nnn-magic
|
|
Advanced: https://github.com/jarun/nnn/wiki/Advanced-use-cases
|
|
Live Previews: https://github.com/jarun/nnn/wiki/Live-previews
|
|
Troubleshooting: https://github.com/jarun/nnn/wiki/Troubleshooting
|
|
EOF |