|
@@ -0,0 +1,98 @@
|
|
|
|
|
+"""
|
|
|
|
|
+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 subprocess
|
|
|
|
|
+import sys
|
|
|
|
|
+import traceback
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+BASH = 'bash'
|
|
|
|
|
+
|
|
|
|
|
+def comment(string):
|
|
|
|
|
+ return '\n'.join(['# ' + line for line in string.split('\n')])
|
|
|
|
|
+
|
|
|
|
|
+def gen_script():
|
|
|
|
|
+ divider = '-__-__-__bass___-env-output-__bass_-__-__-__-__'
|
|
|
|
|
+
|
|
|
|
|
+ # 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 = "python -c 'import os,json; print(json.dumps({k:v for k,v in os.environ.items()}))'"
|
|
|
|
|
+ args = [BASH, '-c', env_reader]
|
|
|
|
|
+ output = subprocess.check_output(args, universal_newlines=True)
|
|
|
|
|
+ old_env = output.strip()
|
|
|
|
|
+
|
|
|
|
|
+ command = '{} && (echo "{}"; {}; echo "{}"; alias)'.format(
|
|
|
|
|
+ ' '.join(sys.argv[1:]).rstrip().rstrip(';'),
|
|
|
|
|
+ divider,
|
|
|
|
|
+ env_reader,
|
|
|
|
|
+ divider,
|
|
|
|
|
+ )
|
|
|
|
|
+ args = [BASH, '-c', command]
|
|
|
|
|
+ output = subprocess.check_output(args, universal_newlines=True)
|
|
|
|
|
+ stdout, new_env, alias = output.split(divider, 2)
|
|
|
|
|
+ new_env = new_env.strip()
|
|
|
|
|
+
|
|
|
|
|
+ old_env = json.loads(old_env)
|
|
|
|
|
+ new_env = json.loads(new_env)
|
|
|
|
|
+
|
|
|
|
|
+ script_lines = []
|
|
|
|
|
+
|
|
|
|
|
+ for line in stdout.splitlines():
|
|
|
|
|
+ # some outputs might use documentation about the shell usage with dollar signs
|
|
|
|
|
+ line = line.replace(r'$', r'\$')
|
|
|
|
|
+ script_lines.append("printf %s;printf '\\n'" % json.dumps(line))
|
|
|
|
|
+ for k, v in new_env.items():
|
|
|
|
|
+ if k in ['PS1', 'SHLVL', 'XPC_SERVICE_NAME'] or k.startswith("BASH_FUNC"):
|
|
|
|
|
+ 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' % json.dumps(v))
|
|
|
|
|
+ continue
|
|
|
|
|
+ else:
|
|
|
|
|
+ continue
|
|
|
|
|
+ if k == 'PATH':
|
|
|
|
|
+ # use json.dumps to reliably escape quotes and backslashes
|
|
|
|
|
+ value = ' '.join([json.dumps(directory)
|
|
|
|
|
+ for directory in v.split(':')])
|
|
|
|
|
+ else:
|
|
|
|
|
+ # use json.dumps to reliably escape quotes and backslashes
|
|
|
|
|
+ value = json.dumps(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)
|
|
|
|
|
+
|
|
|
|
|
+ return script + '\n' + alias
|
|
|
|
|
+
|
|
|
|
|
+if not sys.argv[1:]:
|
|
|
|
|
+ print('__usage', end='')
|
|
|
|
|
+ sys.exit(0)
|
|
|
|
|
+
|
|
|
|
|
+try:
|
|
|
|
|
+ script = gen_script()
|
|
|
|
|
+except subprocess.CalledProcessError as e:
|
|
|
|
|
+ print('exit code:', e.returncode, file=sys.stderr)
|
|
|
|
|
+ print('__error', e.returncode, end='')
|
|
|
|
|
+except Exception as e:
|
|
|
|
|
+ print('unknown error:', str(e), file=sys.stderr)
|
|
|
|
|
+ traceback.print_exc(10, file=sys.stderr)
|
|
|
|
|
+ print('__error', end='')
|
|
|
|
|
+else:
|
|
|
|
|
+ print(script, end='')
|