#!/bin/sh -e # sdn-install: integrate sdn with the shell, binding to M-o # vim: set sw=2 ts=2 sts=2 et tw=80: zsh() { cat <<'EOF' sdn-navigate () { # optionally: zle zle-line-finish while eval "`SDN=1 sdn "$BUFFER" "$CURSOR"`" do [ -z "$cd" ] || cd "$cd" [ -z "$insert" ] || LBUFFER="$LBUFFER$insert " [ -z "$helper" ] && break # Workaround for "zsh: suspended (tty output)" when invoking # helpers after the terminal has been resized while running sdn command true /bin/sh -c "$helper" /dev/tty 2>&1 } # XXX: the -dot is not a stable API, and may hence break soon # https://elv.sh/ref/builtin.html#do-not-use-functions-and-variables local:buffer = $edit:current-command local:cursor = (str:to-codepoints $buffer[0..$edit:-dot] | count) local:ns = (ns [&]) while ?(eval ($reesc (E:SDN=1 sdn $buffer $cursor | sed 's/^local //' | slurp)) &ns=$ns) { if (not-eq $ns[cd] "") { cd $ns[cd] } if (not-eq $ns[insert] "") { edit:insert-at-dot $ns[insert]" " } if (or (eq $ns[helper] "") (not ?($posix $ns[helper]))) { break } } edit:redraw &full=$true } EOF } shell= path= while getopts s:f:h opt do case $opt in s) shell=$OPTARG;; f) path=$OPTARG;; *) echo "Usage: $0 [-s SHELL] [-f RCPATH | -]"; exit 2 esac done # Figure out the shell to integrate with login=$(basename "$SHELL") actual=$(ps -p $$ -o ppid= | xargs ps -o comm= -p) if [ -z "$shell" ] then if [ "$login" != "$actual" ] then echo "Conflict between login ($login) and invoking ($actual) shell." echo "Specify the shell with the -s option." exit 1 fi shell=$actual fi # Figure out the default initialisation file case "$shell" in zsh|bash) rc=~/.${shell}rc;; fish) rc=${XDG_CONFIG_HOME:-$HOME/.config}/fish/conf.d/sdn.fish;; elvish) rc=~/.elvish/rc.elv;; *) echo "$shell is not supported." exit 1 esac # Just print out the snippet if requested if [ "$path" = "-" ] then $shell exit 0 fi # Finally append to or update the appropriate file b="# sdn-install begin" e="# sdn-install end" [ -z "$path" ] && path=$rc mkdir -p "$(dirname "$path")" touch "$path" if ! grep -q "^$b" "$path" 2>/dev/null || ! grep -q "^$e" "$path" 2>/dev/null then printf "\n$b\n%s\n$e\n" "$($shell)" >> "$path" echo "The snippet has been added to $path" exit 0 fi # POSIX-compliant in-place sed, trying to retain permissions here temp=$path.sdn.new cp -p -- "$path" "$temp" sed < "$path" > "$temp" "/^$b/,/^$e/c\\ $b\\ $($shell | sed 's/\\/&&/g; s/$/\\/') $e" mv -- "$temp" "$path" echo "The snippet in $path has been updated."