diff --git a/fish/completions/replay.fish b/fish/completions/replay.fish new file mode 100644 index 0000000..d4589a9 --- /dev/null +++ b/fish/completions/replay.fish @@ -0,0 +1,3 @@ +complete --command replay --no-files +complete --command replay --exclusive --long version --description "Print version" +complete --command replay --exclusive --long help --description "Print help" diff --git a/fish/conf.d/abbr_tips.fish b/fish/conf.d/abbr_tips.fish new file mode 100644 index 0000000..848ee6d --- /dev/null +++ b/fish/conf.d/abbr_tips.fish @@ -0,0 +1,155 @@ +for mode in default insert + bind --mode $mode " " '__abbr_tips_bind_space' + bind --mode $mode \n '__abbr_tips_bind_newline' + bind --mode $mode \r '__abbr_tips_bind_newline' +end + +set -g __abbr_tips_used 0 + +# Trim simple/double quotes from args +function trim_value + echo "$argv" | string trim --left --right --chars '"\'' | string join ' ' +end + +function __abbr_tips_install --on-event abbr_tips_install + # Regexes used to find abbreviation inside command + # Only the first matching group will be tested as an abbr + set -Ux ABBR_TIPS_REGEXES + set -a ABBR_TIPS_REGEXES '(^(\w+\s+)+(-{1,2})\w+)(\s\S+)' + set -a ABBR_TIPS_REGEXES '(^(\s?(\w-?)+){3}).*' + set -a ABBR_TIPS_REGEXES '(^(\s?(\w-?)+){2}).*' + set -a ABBR_TIPS_REGEXES '(^(\s?(\w-?)+){1}).*' + + set -Ux ABBR_TIPS_PROMPT "\n💡 \e[1m{{ .abbr }}\e[0m => {{ .cmd }}" + set -gx ABBR_TIPS_AUTO_UPDATE 'background' + + # Locking mechanism + # Prevent this file to spawn more than one subshell + if test "$USER" != 'root' + fish -c '__abbr_tips_init' & + end +end + +function __abbr_tips --on-event fish_postexec -d "Abbreviation reminder for the current command" + set -l command (string split ' ' -- "$argv") + set -l cmd (string replace -r -a '\\s+' ' ' -- "$argv" ) + + # Update abbreviations lists when adding/removing abbreviations + if test "$command[1]" = "abbr" + # Parse args as abbr options + argparse --name 'abbr' --ignore-unknown 'a/add' 'e/erase' 'g/global' 'U/universal' -- $command + + if set -q _flag_a + and not contains -- "$argv[2]" $__ABBR_TIPS_KEYS + set -a __ABBR_TIPS_KEYS "$argv[2]" + set -a __ABBR_TIPS_VALUES (trim_value "$argv[3..-1]") + else if set -q _flag_e + and set -l abb (contains -i -- "$argv[2]" $__ABBR_TIPS_KEYS) + set -e __ABBR_TIPS_KEYS[$abb] + set -e __ABBR_TIPS_VALUES[$abb] + end + else if test "$command[1]" = "alias" + # Update abbreviations list when adding aliases + set -l alias_key + set -l alias_value + + # Parse args as `alias` options + argparse --name 'alias' --ignore-unknown 's/save' -- $command + + if string match -q '*=*' -- "$argv[2]" + if test (count $argv) = 2 + set command_split (string split '=' -- $argv[2]) + set alias_key "a__$command_split[1]" + set alias_value $command_split[2] + set -a alias_value $command[3..-1] + end + else + set alias_key "a__$argv[2]" + set alias_value $argv[3..-1] + end + + set alias_value (trim_value "$alias_value") + + if set -l abb (contains -i -- "$argv[3..-1]" $__ABBR_TIPS_KEYS) + set __ABBR_TIPS_KEYS[$abb] $alias_key + set __ABBR_TIPS_VALUES[$abb] $alias_value + else + set -a __ABBR_TIPS_KEYS $alias_key + set -a __ABBR_TIPS_VALUES $alias_value + end + else if test "$command[1]" = "functions" + # Parse args as `functions` options + argparse --name 'functions' 'e/erase' -- $command + + # Update abbreviations list when removing aliases + if set -q _flag_e + and set -l abb (contains -i -- a__{$argv[2]} $__ABBR_TIPS_KEYS) + set -e __ABBR_TIPS_KEYS[$abb] + set -e __ABBR_TIPS_VALUES[$abb] + end + end + + # Exit in the following cases : + # - abbreviation has been used + # - command is already an abbreviation + # - command not found + # - or it's a function (alias) + if test $__abbr_tips_used = 1 + set -g __abbr_tips_used 0 + return + else if abbr -q "$cmd" + or not type -q "$command[1]" + return + else if string match -q -- "alias $cmd *" (alias) + return + else if test (type -t "$command[1]") = 'function' + and count $ABBR_TIPS_ALIAS_WHITELIST >/dev/null + and not contains "$command[1]" $ABBR_TIPS_ALIAS_WHITELIST + return + end + + set -l abb + if not set abb (contains -i -- "$cmd" $__ABBR_TIPS_VALUES) + for r in $ABBR_TIPS_REGEXES + if set abb (contains -i -- (string replace -r -a -- "$r" '$1' "$cmd") $__ABBR_TIPS_VALUES) + break + end + end + end + + if test -n "$abb" + if string match -q "a__*" -- "$__ABBR_TIPS_KEYS[$abb]" + set -l alias (string sub -s 4 -- "$__ABBR_TIPS_KEYS[$abb]") + if functions -q "$alias" + echo -e (string replace -a '{{ .cmd }}' -- "$__ABBR_TIPS_VALUES[$abb]" \ + (string replace -a '{{ .abbr }}' -- "$alias" "$ABBR_TIPS_PROMPT")) + else + set -e __ABBR_TIPS_KEYS[$abb] + set -e __ABBR_TIPS_VALUES[$abb] + end + else + echo -e (string replace -a '{{ .cmd }}' -- "$__ABBR_TIPS_VALUES[$abb]" \ + (string replace -a '{{ .abbr }}' -- "$__ABBR_TIPS_KEYS[$abb]" "$ABBR_TIPS_PROMPT")) + end + end + + return +end + +function __abbr_tips_uninstall --on-event abbr_tips_uninstall + bind --erase \n + bind --erase \r + bind --erase " " + set --erase __abbr_tips_used + set --erase __abbr_tips_run_once + set --erase __ABBR_TIPS_VALUES + set --erase __ABBR_TIPS_KEYS + set --erase ABBR_TIPS_PROMPT + set --erase ABBR_TIPS_AUTO_UPDATE + set --erase ABBR_TIPS_ALIAS_WHITELIST + set --erase ABBR_TIPS_REGEXES + functions --erase __abbr_tips_init + functions --erase __abbr_tips_bind_newline + functions --erase __abbr_tips_bind_space + functions --erase __abbr_tips +end diff --git a/fish/conf.d/autopair.fish b/fish/conf.d/autopair.fish new file mode 100644 index 0000000..abb4bf3 --- /dev/null +++ b/fish/conf.d/autopair.fish @@ -0,0 +1,39 @@ +status is-interactive || exit + +set --global autopair_left "(" "[" "{" '"' "'" +set --global autopair_right ")" "]" "}" '"' "'" +set --global autopair_pairs "()" "[]" "{}" '""' "''" + +function _autopair_fish_key_bindings --on-variable fish_key_bindings + set --query fish_key_bindings[1] || return + + test $fish_key_bindings = fish_default_key_bindings && + set --local mode default insert || + set --local mode insert default + + bind --mode $mode[-1] --erase \177 \b \t + + bind --mode $mode[1] \177 _autopair_backspace # macOS ⌫ + bind --mode $mode[1] \b _autopair_backspace + bind --mode $mode[1] \t _autopair_tab + + printf "%s\n" $autopair_pairs | while read --local left right --delimiter "" + bind --mode $mode[-1] --erase $left $right + if test $left = $right + bind --mode $mode[1] $left "_autopair_insert_same \\$left" + else + bind --mode $mode[1] $left "_autopair_insert_left \\$left \\$right" + bind --mode $mode[1] $right "_autopair_insert_right \\$right" + end + end +end + +_autopair_fish_key_bindings + +function _autopair_uninstall --on-event autopair_uninstall + string collect ( + bind --all | string replace --filter --regex -- "_autopair.*" --erase + set --names | string replace --filter --regex -- "^autopair" "set --erase autopair" + ) | source + functions --erase (functions --all | string match "_autopair_*") +end diff --git a/fish/fish_plugins b/fish/fish_plugins index dc469f2..4b727d9 100644 --- a/fish/fish_plugins +++ b/fish/fish_plugins @@ -1,2 +1,6 @@ jorgebucaran/fisher jethrokuan/z +jorgebucaran/replay.fish +jorgebucaran/autopair.fish +gazorby/fish-abbreviation-tips +edc/bass diff --git a/fish/fish_variables b/fish/fish_variables index 1af61b4..067a4b9 100644 --- a/fish/fish_variables +++ b/fish/fish_variables @@ -1,16 +1,24 @@ # This file contains fish universal variable definitions. # VERSION: 3.0 +SETUVAR --export ABBR_TIPS_PROMPT:\x5cn\U0001f4a1\x20\x5ce\x5b1m\x7b\x7b\x20\x2eabbr\x20\x7d\x7d\x5ce\x5b0m\x20\x3d\x3e\x20\x7b\x7b\x20\x2ecmd\x20\x7d\x7d +SETUVAR --export ABBR_TIPS_REGEXES:\x28\x5e\x28\x5cw\x2b\x5cs\x2b\x29\x2b\x28\x2d\x7b1\x2c2\x7d\x29\x5cw\x2b\x29\x28\x5cs\x5cS\x2b\x29\x1e\x28\x5e\x28\x5cs\x3f\x28\x5cw\x2d\x3f\x29\x2b\x29\x7b3\x7d\x29\x2e\x2a\x1e\x28\x5e\x28\x5cs\x3f\x28\x5cw\x2d\x3f\x29\x2b\x29\x7b2\x7d\x29\x2e\x2a\x1e\x28\x5e\x28\x5cs\x3f\x28\x5cw\x2d\x3f\x29\x2b\x29\x7b1\x7d\x29\x2e\x2a SETUVAR EDITOR:nvim SETUVAR ZO_CMD:zo SETUVAR Z_CMD:z SETUVAR Z_DATA:/Users/stefan\x2eimhoff/\x2elocal/share/z/data SETUVAR Z_DATA_DIR:/Users/stefan\x2eimhoff/\x2elocal/share/z SETUVAR Z_EXCLUDE:\x5e/Users/stefan\x2eimhoff\x24 +SETUVAR --export __ABBR_TIPS_KEYS:mux\x1ea__\x2e\x2e\x2e\x1ea__c\x1ea__cat\x1ea__cd\x2e\x2e\x1ea__dotfiles\x1ea__\x22\x3a\x28exclude\x29yarn\x2elock\x22\x27\x1ea__gl\x1ea__glr\x1ea__glu\x1ea__glx\x1ea__gp\x1ea__gpf\x1ea__gst\x1ea__gw\x1ea__gwp\x1ea__icloud\x1ea__lg\x1ea__ll\x1ea__lla\x1ea__ls\x1ea__mkdir\x1ea__ms\x1ea__mux\x1ea__reload\x1ea__t\x1ea__v\x1ea__vim +SETUVAR --export __ABBR_TIPS_VALUES:tmuxinator\x1ecd\x20\x2e\x2e/\x2e\x2e\x1eclear\x1ebat\x1ecd\x20\x2e\x2e\x1ecd\x20\x7e/\x2edotfiles\x1e\x1egit\x20pull\x1egit\x20pull\x20\x2d\x2drebase\x1egit\x20config\x20user\x2ename\x20\x22Stefan\x20Imhoff\x22\x20\x26\x26\x20git\x20config\x20user\x2eemail\x20\x22stefan\x40imhoff\x2ename\x22\x3b\x1egit\x20config\x20user\x2ename\x20\x22Stefan\x20Imhoff\x22\x20\x26\x26\x20git\x20config\x20user\x2eemail\x20\x22stefan\x2eimhoff\x40xing\x2ecom\x22\x3b\x1egit\x20push\x1egit\x20push\x20\x2d\x2dforce\x2dwith\x2dlease\x1egit\x20status\x20\x2dsb\x1egit\x20whatchanged\x1egit\x20whatchanged\x20\x2dp\x1eicloud\x5c\x5c\x5c\x20cd\x5c\x5c\x5c\x20\x5c\x5c\x5c\x7e/Library/Mobile\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x20Documents/com\x5c\x5c\x5c\x7eapple\x5c\x5c\x5c\x7eCloudDocs\x1elazygit\x1eexa\x20\x2dl\x20\x2d\x2dgit\x20\x2d\x2dgroup\x2ddirectories\x2dfirst\x20\x2d\x2dicons\x1ell\x20\x2da\x1eexa\x20\x2d\x2dgit\x20\x2d\x2dgroup\x2ddirectories\x2dfirst\x20\x2d\x2dicons\x1emkdir\x20\x2dp\x1emux\x20start\x1etmuxinator\x1eexec\x20fish\x1etmux\x1evim\x1envim SETUVAR __fish_initialized:3400 SETUVAR _fish_abbr_mux:tmuxinator +SETUVAR _fisher_edc_2F_bass_files:\x7e/\x2econfig/fish/functions/__bass\x2epy\x1e\x7e/\x2econfig/fish/functions/bass\x2efish +SETUVAR _fisher_gazorby_2F_fish_2D_abbreviation_2D_tips_files:\x7e/\x2econfig/fish/functions/__abbr_tips_bind_newline\x2efish\x1e\x7e/\x2econfig/fish/functions/__abbr_tips_bind_space\x2efish\x1e\x7e/\x2econfig/fish/functions/__abbr_tips_init\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/abbr_tips\x2efish SETUVAR _fisher_jethrokuan_2F_z_files:\x7e/\x2econfig/fish/functions/__z\x2efish\x1e\x7e/\x2econfig/fish/functions/__z_add\x2efish\x1e\x7e/\x2econfig/fish/functions/__z_clean\x2efish\x1e\x7e/\x2econfig/fish/functions/__z_complete\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/z\x2efish +SETUVAR _fisher_jorgebucaran_2F_autopair_2E_fish_files:\x7e/\x2econfig/fish/functions/_autopair_backspace\x2efish\x1e\x7e/\x2econfig/fish/functions/_autopair_insert_left\x2efish\x1e\x7e/\x2econfig/fish/functions/_autopair_insert_right\x2efish\x1e\x7e/\x2econfig/fish/functions/_autopair_insert_same\x2efish\x1e\x7e/\x2econfig/fish/functions/_autopair_tab\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/autopair\x2efish SETUVAR _fisher_jorgebucaran_2F_fisher_files:\x7e/\x2econfig/fish/functions/fisher\x2efish\x1e\x7e/\x2econfig/fish/completions/fisher\x2efish -SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejethrokuan/z +SETUVAR _fisher_jorgebucaran_2F_replay_2E_fish_files:\x7e/\x2econfig/fish/functions/replay\x2efish\x1e\x7e/\x2econfig/fish/completions/replay\x2efish +SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejethrokuan/z\x1ejorgebucaran/replay\x2efish\x1ejorgebucaran/autopair\x2efish\x1egazorby/fish\x2dabbreviation\x2dtips\x1eedc/bass SETUVAR _fisher_upgraded_to_4_4:\x1d SETUVAR fish_color_autosuggestion:555\x1ebrblack SETUVAR fish_color_cancel:\x2dr diff --git a/fish/functions/__abbr_tips_bind_newline.fish b/fish/functions/__abbr_tips_bind_newline.fish new file mode 100644 index 0000000..8cc8992 --- /dev/null +++ b/fish/functions/__abbr_tips_bind_newline.fish @@ -0,0 +1,10 @@ +function __abbr_tips_bind_newline + if test $__abbr_tips_used != 1 + if abbr -q -- (string trim -- (commandline)) + set -g __abbr_tips_used 1 + else + set -g __abbr_tips_used 0 + end + end + commandline -f 'execute' +end diff --git a/fish/functions/__abbr_tips_bind_space.fish b/fish/functions/__abbr_tips_bind_space.fish new file mode 100644 index 0000000..0f37103 --- /dev/null +++ b/fish/functions/__abbr_tips_bind_space.fish @@ -0,0 +1,11 @@ +function __abbr_tips_bind_space + commandline -i " " + if test $__abbr_tips_used != 1 + if abbr -q -- (string trim -- (commandline)) + set -g __abbr_tips_used 1 + else + set -g __abbr_tips_used 0 + end + end + commandline -f 'expand-abbr' +end diff --git a/fish/functions/__abbr_tips_init.fish b/fish/functions/__abbr_tips_init.fish new file mode 100644 index 0000000..9cda53a --- /dev/null +++ b/fish/functions/__abbr_tips_init.fish @@ -0,0 +1,24 @@ +function __abbr_tips_init -d "Initialize abbreviations variables for fish-abbr-tips" + set -e __ABBR_TIPS_KEYS + set -e __ABBR_TIPS_VALUES + set -Ux __ABBR_TIPS_KEYS + set -Ux __ABBR_TIPS_VALUES + + set -l i 1 + set -l abb (string replace -r '.*-- ' '' -- (abbr -s)) + while test $i -le (count $abb) + set -l current_abb (string split -m1 -- ' ' "$abb[$i]") + set -a __ABBR_TIPS_KEYS "$current_abb[1]" + set -a __ABBR_TIPS_VALUES (string trim -c '\'' -- "$current_abb[2]") + set i (math $i + 1) + end + + set -l i 1 + set -l abb (string replace -r '.*-- ' '' -- (alias -s)) + while test $i -le (count $abb) + set -l current_abb (string split -m2 -- ' ' "$abb[$i]") + set -a __ABBR_TIPS_KEYS "a__$current_abb[2]" + set -a __ABBR_TIPS_VALUES (string trim -c '\'' -- "$current_abb[3]") + set i (math $i + 1) + end +end diff --git a/fish/functions/__bass.py b/fish/functions/__bass.py new file mode 100644 index 0000000..3fe17fc --- /dev/null +++ b/fish/functions/__bass.py @@ -0,0 +1,138 @@ +""" +To be used with a companion fish function like this: + + function refish + set -l _x (python /tmp/bass.py source ~/.nvm/nvim.sh ';' nvm use iojs); source $_x; and rm -f $_x + end + +""" + +from __future__ import print_function + +import json +import os +import signal +import subprocess +import sys +import traceback + + +BASH = 'bash' + +FISH_READONLY = [ + 'PWD', 'SHLVL', 'history', 'pipestatus', 'status', 'version', + 'FISH_VERSION', 'fish_pid', 'hostname', '_', 'fish_private_mode' +] + +IGNORED = [ + 'PS1', 'XPC_SERVICE_NAME' +] + +def ignored(name): + if name == 'PWD': # this is read only, but has special handling + return False + # ignore other read only variables + if name in FISH_READONLY: + return True + if name in IGNORED or name.startswith("BASH_FUNC"): + return True + return False + +def escape(string): + # use json.dumps to reliably escape quotes and backslashes + return json.dumps(string).replace(r'$', r'\$') + +def escape_identifier(word): + return escape(word.replace('?', '\\?')) + +def comment(string): + return '\n'.join(['# ' + line for line in string.split('\n')]) + +def gen_script(): + # Use the following instead of /usr/bin/env to read environment so we can + # deal with multi-line environment variables (and other odd cases). + env_reader = "%s -c 'import os,json; print(json.dumps({k:v for k,v in os.environ.items()}))'" % (sys.executable) + args = [BASH, '-c', env_reader] + output = subprocess.check_output(args, universal_newlines=True) + old_env = output.strip() + + pipe_r, pipe_w = os.pipe() + if sys.version_info >= (3, 4): + os.set_inheritable(pipe_w, True) + command = 'eval $1 && ({}; alias) >&{}'.format( + env_reader, + pipe_w + ) + args = [BASH, '-c', command, 'bass', ' '.join(sys.argv[1:])] + p = subprocess.Popen(args, universal_newlines=True, close_fds=False) + os.close(pipe_w) + with os.fdopen(pipe_r) as f: + new_env = f.readline() + alias_str = f.read() + if p.wait() != 0: + raise subprocess.CalledProcessError( + returncode=p.returncode, + cmd=' '.join(sys.argv[1:]), + output=new_env + alias_str + ) + new_env = new_env.strip() + + old_env = json.loads(old_env) + new_env = json.loads(new_env) + + script_lines = [] + + for k, v in new_env.items(): + if ignored(k): + continue + v1 = old_env.get(k) + if not v1: + script_lines.append(comment('adding %s=%s' % (k, v))) + elif v1 != v: + script_lines.append(comment('updating %s=%s -> %s' % (k, v1, v))) + # process special variables + if k == 'PWD': + script_lines.append('cd %s' % escape(v)) + continue + else: + continue + if k == 'PATH': + value = ' '.join([escape(directory) + for directory in v.split(':')]) + else: + value = escape(v) + script_lines.append('set -g -x %s %s' % (k, value)) + + for var in set(old_env.keys()) - set(new_env.keys()): + script_lines.append(comment('removing %s' % var)) + script_lines.append('set -e %s' % var) + + script = '\n'.join(script_lines) + + alias_lines = [] + for line in alias_str.splitlines(): + _, rest = line.split(None, 1) + k, v = rest.split("=", 1) + alias_lines.append("alias " + escape_identifier(k) + "=" + v) + alias = '\n'.join(alias_lines) + + return script + '\n' + alias + +script_file = os.fdopen(3, 'w') + +if not sys.argv[1:]: + print('__bass_usage', file=script_file, end='') + sys.exit(0) + +try: + script = gen_script() +except subprocess.CalledProcessError as e: + sys.exit(e.returncode) +except Exception: + print('Bass internal error!', file=sys.stderr) + raise # traceback will output to stderr +except KeyboardInterrupt: + signal.signal(signal.SIGINT, signal.SIG_DFL) + os.kill(os.getpid(), signal.SIGINT) +else: + script_file.write(script) diff --git a/fish/functions/_autopair_backspace.fish b/fish/functions/_autopair_backspace.fish new file mode 100644 index 0000000..a43fa79 --- /dev/null +++ b/fish/functions/_autopair_backspace.fish @@ -0,0 +1,9 @@ +function _autopair_backspace + set --local index (commandline --cursor) + set --local buffer (commandline) + + test $index -ge 1 && + contains -- (string sub --start=$index --length=2 -- "$buffer") $autopair_pairs && + commandline --function delete-char + commandline --function backward-delete-char +end diff --git a/fish/functions/_autopair_insert_left.fish b/fish/functions/_autopair_insert_left.fish new file mode 100644 index 0000000..f078e86 --- /dev/null +++ b/fish/functions/_autopair_insert_left.fish @@ -0,0 +1,13 @@ +function _autopair_insert_left --argument-names left right + set --local buffer (commandline) + set --local before (commandline --cut-at-cursor) + + commandline --insert -- $left + + switch "$buffer" + case "$before"{," "\*,$autopair_right\*} + set --local index (commandline --cursor) + commandline --insert -- $right + commandline --cursor $index + end +end diff --git a/fish/functions/_autopair_insert_right.fish b/fish/functions/_autopair_insert_right.fish new file mode 100644 index 0000000..a0bd61c --- /dev/null +++ b/fish/functions/_autopair_insert_right.fish @@ -0,0 +1,11 @@ +function _autopair_insert_right --argument-names key + set --local buffer (commandline) + set --local before (commandline --cut-at-cursor) + + switch "$buffer" + case "$before$key"\* + commandline --cursor (math (commandline --cursor) + 1) + case \* + commandline --insert -- $key + end +end diff --git a/fish/functions/_autopair_insert_same.fish b/fish/functions/_autopair_insert_same.fish new file mode 100644 index 0000000..27f971d --- /dev/null +++ b/fish/functions/_autopair_insert_same.fish @@ -0,0 +1,20 @@ +function _autopair_insert_same --argument-names key + set --local buffer (commandline) + set --local index (commandline --cursor) + set --local next (string sub --start=(math $index + 1) --length=1 -- "$buffer") + + if test (math (count (string match --all --regex -- "$key" "$buffer")) % 2) = 0 + test $key = $next && commandline --cursor (math $index + 1) && return + + commandline --insert -- $key + + if test $index -lt 1 || + contains -- (string sub --start=$index --length=1 -- "$buffer") "" " " $autopair_left && + contains -- $next "" " " $autopair_right + commandline --insert -- $key + commandline --cursor (math $index + 1) + end + else + commandline --insert -- $key + end +end diff --git a/fish/functions/_autopair_tab.fish b/fish/functions/_autopair_tab.fish new file mode 100644 index 0000000..f2ab8eb --- /dev/null +++ b/fish/functions/_autopair_tab.fish @@ -0,0 +1,7 @@ +function _autopair_tab + commandline --paging-mode && down-or-search && return + + string match --quiet --regex -- '\$[^\s]*"$' (commandline --current-token) && + commandline --function end-of-line --function backward-delete-char + commandline --function complete +end diff --git a/fish/functions/bass.fish b/fish/functions/bass.fish new file mode 100644 index 0000000..2b3af16 --- /dev/null +++ b/fish/functions/bass.fish @@ -0,0 +1,29 @@ +function bass + set -l bash_args $argv + set -l bass_debug + if test "$bash_args[1]_" = '-d_' + set bass_debug true + set -e bash_args[1] + end + + set -l script_file (mktemp) + if command -v python3 >/dev/null 2>&1 + command python3 -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file + else + command python -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file + end + set -l bass_status $status + if test $bass_status -ne 0 + return $bass_status + end + + if test -n "$bass_debug" + cat $script_file + end + source $script_file + command rm $script_file +end + +function __bass_usage + echo "Usage: bass [-d] " +end diff --git a/fish/functions/replay.fish b/fish/functions/replay.fish new file mode 100644 index 0000000..809a3b1 --- /dev/null +++ b/fish/functions/replay.fish @@ -0,0 +1,48 @@ +function replay --description "Run Bash commands replaying changes in Fish" + switch "$argv" + case -v --version + echo "replay, version 1.2.1" + case "" -h --help + echo "Usage: replay Run Bash commands replaying changes in Fish" + echo "Options:" + echo " -v or --version Print version" + echo " -h or --help Print this help message" + case \* + set --local env + set --local sep @$fish_pid(random)(command date +%s) + set --local argv $argv[1] (string escape -- $argv[2..-1]) + set --local out (command bash -c " + $argv + status=\$? + [ \$status -gt 0 ] && exit \$status + + command compgen -e | command awk -v sep=$sep '{ + gsub(/\n/, \"\\\n\", ENVIRON[\$0]) + print \$0 sep ENVIRON[\$0] + }' && alias + ") || return + + string replace --all -- \\n \n ( + for line in $out + if string split -- $sep $line | read --local --line name value + set --append env $name + + contains -- $name SHLVL PS1 BASH_FUNC || test "$$name" = "$value" && continue + + if test "$name" = PATH + echo set PATH (string split -- : $value | string replace --regex --all -- '(^.*$)' '"$1"') + else if test "$name" = PWD + echo builtin cd "\"$value\"" + else + echo "set --global --export $name "(string escape -- $value) + end + else + set --query env[1] && string match --entire --regex -- "^alias" $line || echo "echo \"$line\"" + end + end | string replace --all -- \$ \\\$ + for name in (set --export --names) + contains -- $name $env || echo "set --erase $name" + end + ) | source + end +end