From dc7e5a5f94cc89c57c4ff7f20f90a55a1a0e6ec4 Mon Sep 17 00:00:00 2001 From: Guangxiong Lin Date: Wed, 15 Nov 2023 21:51:23 +0800 Subject: Add bass into fish --- .bashrc | 1 + .config/fish/fish_plugins | 1 + .config/fish/fish_variables | 3 +- .config/fish/functions/__bass.py | 140 +++++++++++++++++++++++++++++++++++++++ .config/fish/functions/bass.fish | 29 ++++++++ 5 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 .config/fish/functions/__bass.py create mode 100644 .config/fish/functions/bass.fish diff --git a/.bashrc b/.bashrc index 5b2bf54..ecece72 100644 --- a/.bashrc +++ b/.bashrc @@ -11,6 +11,7 @@ source "$HOME/.path" PS1='[\u@\h \W]\$ ' source "$HOME/.aliases" +source "$HOME/.fzfrc" if command -v fish > /dev/null; then if [[ $(ps --no-header --pid=$PPID --format=comm) != "fish" && -z ${BASH_EXECUTION_STRING} ]] diff --git a/.config/fish/fish_plugins b/.config/fish/fish_plugins index 986ddc0..f37c206 100644 --- a/.config/fish/fish_plugins +++ b/.config/fish/fish_plugins @@ -1,3 +1,4 @@ jorgebucaran/fisher jorgebucaran/nvm.fish oh-my-fish/plugin-rvm +edc/bass diff --git a/.config/fish/fish_variables b/.config/fish/fish_variables index def1a29..b923556 100644 --- a/.config/fish/fish_variables +++ b/.config/fish/fish_variables @@ -1,10 +1,11 @@ # This file contains fish universal variable definitions. # VERSION: 3.0 SETUVAR __fish_initialized:3400 +SETUVAR _fisher_edc_2F_bass_files:\x7e/\x2econfig/fish/functions/__bass\x2epy\x1e\x7e/\x2econfig/fish/functions/bass\x2efish SETUVAR _fisher_jorgebucaran_2F_fisher_files:\x7e/\x2econfig/fish/functions/fisher\x2efish\x1e\x7e/\x2econfig/fish/completions/fisher\x2efish SETUVAR _fisher_jorgebucaran_2F_nvm_2E_fish_files:\x7e/\x2econfig/fish/functions/_nvm_index_update\x2efish\x1e\x7e/\x2econfig/fish/functions/_nvm_list\x2efish\x1e\x7e/\x2econfig/fish/functions/_nvm_version_activate\x2efish\x1e\x7e/\x2econfig/fish/functions/_nvm_version_deactivate\x2efish\x1e\x7e/\x2econfig/fish/functions/nvm\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/nvm\x2efish\x1e\x7e/\x2econfig/fish/completions/nvm\x2efish SETUVAR _fisher_oh_2D_my_2D_fish_2F_plugin_2D_rvm_files:\x7e/\x2econfig/fish/functions/rvm\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/rvm\x2efish -SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejorgebucaran/nvm\x2efish\x1eoh\x2dmy\x2dfish/plugin\x2drvm +SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejorgebucaran/nvm\x2efish\x1eoh\x2dmy\x2dfish/plugin\x2drvm\x1eedc/bass SETUVAR _fisher_upgraded_to_4_4:\x1d SETUVAR fish_color_autosuggestion:555\x1ebrblack SETUVAR fish_color_cancel:\x2dr diff --git a/.config/fish/functions/__bass.py b/.config/fish/functions/__bass.py new file mode 100644 index 0000000..3f02bd4 --- /dev/null +++ b/.config/fish/functions/__bass.py @@ -0,0 +1,140 @@ +""" +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 + if name.startswith('%'): + 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/.config/fish/functions/bass.fish b/.config/fish/functions/bass.fish new file mode 100644 index 0000000..2b3af16 --- /dev/null +++ b/.config/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 -- cgit v1.2.3