1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
from os import environ, path, pathsep
DEFAULT_SHELLS = ('bash', 'sh')
class Shell(object):
comment_starter = '#'
def __init__(self, home=None):
self.home = home or path.expanduser('~')
class Sh(Shell):
def config(self, location, front=True):
head, tail = (location, '$PATH') if front else ('$PATH', location)
new_path = '{}{}{}'.format(head, pathsep, tail)
return {path.join(self.home, '.profile'): 'PATH="{}"'.format(new_path)}
@classmethod
def show_path_commands(cls):
# TODO: Find out what file influences non-login shells. The issue may simply be our Docker setup.
return [['sh', '-i', '-l', '-c', 'echo $PATH']]
class Bash(Shell):
def config(self, location, front=True):
head, tail = (location, '$PATH') if front else ('$PATH', location)
new_path = '{}{}{}'.format(head, pathsep, tail)
contents = 'export PATH="{}"'.format(new_path)
configs = {path.join(self.home, '.bashrc'): contents}
# https://github.com/ofek/userpath/issues/3#issuecomment-492491977
profile_path = path.join(self.home, '.profile')
bash_profile_path = path.join(self.home, '.bash_profile')
if path.exists(profile_path) and not path.exists(bash_profile_path):
login_config = profile_path
else:
# NOTE: If it is decided in future that we want to make a distinction between
# login and non-login shells, be aware that macOS will still need this since
# Terminal.app runs a login shell by default for each new terminal window.
login_config = bash_profile_path
configs[login_config] = contents
return configs
@classmethod
def show_path_commands(cls):
return [['bash', '-i', '-c', 'echo $PATH'], ['bash', '-i', '-l', '-c', 'echo $PATH']]
class Fish(Shell):
def config(self, location, front=True):
location = ' '.join(location.split(pathsep))
head, tail = (location, '$PATH') if front else ('$PATH', location)
# https://github.com/fish-shell/fish-shell/issues/527#issuecomment-12436286
contents = 'set PATH {} {}'.format(head, tail)
return {path.join(self.home, '.config', 'fish', 'config.fish'): contents}
@classmethod
def show_path_commands(cls):
return [
['fish', '-i', '-c', 'for p in $PATH; echo "$p"; end'],
['fish', '-i', '-l', '-c', 'for p in $PATH; echo "$p"; end'],
]
class Xonsh(Shell):
def config(self, location, front=True):
locations = location.split(pathsep)
if front:
contents = '\n'.join('$PATH.insert(0, {!r})'.format(location) for location in reversed(locations))
else:
contents = '\n'.join('$PATH.append({!r})'.format(location) for location in locations)
return {path.join(self.home, '.xonshrc'): contents}
@classmethod
def show_path_commands(cls):
command = "print('{}'.join($PATH))".format(pathsep)
return [['xonsh', '-i', '-c', command], ['xonsh', '-i', '--login', '-c', command]]
class Zsh(Shell):
def config(self, location, front=True):
head, tail = (location, '$PATH') if front else ('$PATH', location)
new_path = '{}{}{}'.format(head, pathsep, tail)
contents = 'export PATH="{}"'.format(new_path)
zdotdir = environ.get('ZDOTDIR', self.home)
return {path.join(zdotdir, '.zshrc'): contents, path.join(zdotdir, '.zprofile'): contents}
@classmethod
def show_path_commands(cls):
return [['zsh', '-i', '-c', 'echo $PATH'], ['zsh', '-i', '-l', '-c', 'echo $PATH']]
SHELLS = {
'bash': Bash,
'fish': Fish,
'sh': Sh,
'xonsh': Xonsh,
'zsh': Zsh,
}
|