rc.xsh 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import contextlib
  2. import datetime as dt
  3. import grp
  4. import os
  5. import re
  6. import shutil
  7. import stat
  8. import subprocess
  9. import sys
  10. import tempfile
  11. TERMUX=shutil.which('termux-info') is not None
  12. $VI_MODE = True
  13. $AUTO_PUSHD = True
  14. $XONSH_AUTOPAIR = True
  15. # tab selection: do not execute cmd when pressing enter
  16. $COMPLETIONS_CONFIRM = True
  17. $_Z_EXCLUDE_DIRS = ['/tmp']
  18. # alias 'xontrib' wraps xontribs_load()
  19. # xontrib load vox z
  20. from xonsh.xontribs import xontribs_load
  21. xontribs_load(['vox', 'z'])
  22. def _last_exit_status():
  23. try:
  24. exit_status = __xonsh__.history.rtns[-1]
  25. return exit_status if exit_status != 0 else None
  26. except IndexError:
  27. return None
  28. $PROMPT_FIELDS['last_exit_status'] = _last_exit_status
  29. $SHLVL = int($SHLVL) + 1 if 'SHLVL' in ${...} else 1
  30. $XONSH_STDERR_PREFIX = '{RED}'
  31. $XONSH_STDERR_POSTFIX = '{NO_COLOR}'
  32. $DYNAMIC_CWD_WIDTH = '30%'
  33. $DYNAMIC_CWD_ELISION_CHAR = '…'
  34. $PROMPT = ''.join([
  35. '{RED}{last_exit_status:[{}] }',
  36. '{BOLD_GREEN}{user}@{hostname} ' if not TERMUX or 'SSH_CLIENT' in ${...} else '',
  37. '{YELLOW}{cwd} ',
  38. '{{BLUE}}{} '.format('{prompt_end}' * $SHLVL),
  39. '{NO_COLOR}',
  40. ])
  41. $RIGHT_PROMPT = '{gitstatus}{env_name: {}}'
  42. $XONSH_APPEND_NEWLINE = True
  43. os.umask(stat.S_IWGRP | stat.S_IRWXO) # 027
  44. # default locale
  45. # will be used for all non-explicitly set LC_* variables
  46. $LANG = 'en_US.UTF-8'
  47. # fallback locales
  48. # GNU gettext gives preference to LANGUAGE over LC_ALL and LANG
  49. # for the purpose of message handling
  50. # https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html
  51. # cave: if this list contains 'de(_.*)?' at any (sic!) position
  52. # vim 7.4.1689 will switch to german
  53. $LANGUAGE = ':'.join(['en_US', 'en'])
  54. $LC_COLLATE = 'C.UTF-8'
  55. # char classification, case conversion & other char attrs
  56. if not TERMUX: $LC_CTYPE = 'de_AT.UTF-8'
  57. # $ locale currency_symbol
  58. if not TERMUX: $LC_MONETARY = 'de_AT.UTF-8'
  59. # $ locale -k LC_NUMERIC | head -n 3
  60. # decimal_point="."
  61. # thousands_sep=""
  62. # grouping=-1
  63. $LC_NUMERIC = 'C.UTF-8'
  64. # A4
  65. $LC_PAPER = 'de_AT.UTF-8'
  66. USER_BIN_PATH = os.path.join($HOME, '.local', 'bin')
  67. if os.path.isdir(USER_BIN_PATH):
  68. $PATH.insert(0, USER_BIN_PATH)
  69. $PAGER = 'less'
  70. $EDITOR = 'vim'
  71. # i3-sensible-terminal
  72. $TERMINAL = 'termite'
  73. if shutil.which('gpgconf'):
  74. # required by pinentry-tty when using gpg command
  75. # takes approx 100ms in termux on galaxy S7
  76. $GPG_TTY = $(tty)
  77. # required by scute
  78. $GPG_AGENT_INFO = $(gpgconf --list-dir agent-socket).rstrip() + ':0:1'
  79. if not 'SSH_CLIENT' in ${...}:
  80. # in gnupg 2.1.13 the location of agents socket changed
  81. $SSH_AUTH_SOCK = $(gpgconf --list-dir agent-ssh-socket).rstrip()
  82. # wrapper for termite required when launching termite from ranger:
  83. $TERMCMD = os.path.join(os.path.dirname(__file__), 'ranger-termite-termcmd')
  84. # https://docs.docker.com/engine/security/trust/content_trust/
  85. # $DOCKER_CONTENT_TRUST = 1
  86. $PASSWORD_STORE_UMASK = '027'
  87. $PASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS = '1-9a-km-zA-HJKLMNPR-Z'
  88. $PASSWORD_STORE_CHARACTER_SET = $PASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS + r'*+!&#@%.\-_'
  89. @contextlib.contextmanager
  90. def chdir(path):
  91. import shlex
  92. previous = os.getcwd()
  93. try:
  94. sys.stderr.write('cd {}\n'.format(shlex.quote(path)))
  95. os.chdir(path)
  96. yield path
  97. finally:
  98. os.chdir(previous)
  99. sys.stderr.write('cd {}\n'.format(shlex.quote(previous)))
  100. def dpkg_welse(cmd):
  101. pkg_name, _ = dpkg_which(cmd)
  102. return $(dpkg --listfiles @(pkg_name)).split('\n')[:-1]
  103. def dpkg_which(cmd):
  104. cmd_path = shutil.which(cmd)
  105. assert cmd_path, 'cmd {!r} not found'.format(cmd)
  106. search_match = re.search(r'^(\S+): ', $(dpkg --search @(cmd_path)))
  107. assert search_match, f'{cmd_path!r} not installed via dpkg'
  108. return search_match.group(1), cmd_path
  109. @contextlib.contextmanager
  110. def encfs_mount(root_dir_path, mount_point_path, extpass=None):
  111. mount_arg_patterns = ['encfs', root_dir_path, mount_point_path]
  112. if extpass:
  113. mount_arg_patterns.extend(['--extpass', shlex_join(extpass)])
  114. with fuse_mount(mount_arg_patterns=mount_arg_patterns,
  115. mount_point_path=mount_point_path):
  116. yield mount_point_path
  117. @contextlib.contextmanager
  118. def fuse_mount(mount_arg_patterns, mount_point_path):
  119. import shlex
  120. mount_args = [a.format(mp=shlex.quote(mount_point_path))
  121. for a in mount_arg_patterns]
  122. sys.stderr.write('{}\n'.format(shlex_join(mount_args)))
  123. subprocess.check_call(mount_args)
  124. try:
  125. yield mount_point_path
  126. finally:
  127. umount_args = ['fusermount', '-u', '-z', mount_point_path]
  128. sys.stderr.write('{}\n'.format(shlex_join(umount_args)))
  129. subprocess.check_call(umount_args)
  130. def shlex_join(params):
  131. import shlex
  132. assert isinstance(params, list) or isinstance(params, tuple), params
  133. return ' '.join(shlex.quote(p) for p in params)
  134. def timestamp_now_utc():
  135. return dt.datetime.utcnow().replace(tzinfo=dt.timezone.utc)
  136. def timestamp_now_local():
  137. # if called without tz argument astimezone() assumes
  138. # the system local timezone for the target timezone
  139. return timestamp_now_utc().astimezone()
  140. def timestamp_iso_local():
  141. # if called without tz argument astimezone() assumes
  142. # the system local timezone for the target timezone
  143. return timestamp_now_local().strftime('%Y%m%dT%H%M%S%z')
  144. def yaml_load(path):
  145. import yaml
  146. with open(path, 'r') as f:
  147. return yaml.load(f.read())
  148. def yaml_write(path, data):
  149. import yaml
  150. with open(path, 'w') as f:
  151. f.write(yaml.dump(data, default_flow_style=False))
  152. aliases['cdtmp'] = lambda: os.chdir(tempfile.mkdtemp())
  153. try:
  154. docker_gid = grp.getgrnam('docker').gr_gid
  155. except KeyError:
  156. docker_gid = None
  157. if docker_gid:
  158. aliases['c'] = ['docker-compose'] if docker_gid in os.getgroups() else ['sudo', 'docker-compose']
  159. aliases['d'] = ['docker'] if docker_gid in os.getgroups() else ['sudo', 'docker']
  160. aliases['dpkg-welse'] = lambda args: '\n'.join(dpkg_welse(args[0]))
  161. aliases['dpkg-which'] = lambda args: '\t'.join(dpkg_which(args[0]))
  162. aliases['g'] = ['git']
  163. aliases['ip'] = ['ip', '-human-readable', '-color']
  164. aliases['j'] = ['journalctl', '--output=short-iso']
  165. aliases['less'] = ['less', '--jump-target=.2']
  166. aliases['ll'] = ['ls', '-l', '--all', '--indicator-style=slash',
  167. '--human-readable', '--time-style=long-iso', '--color=auto']
  168. aliases['mkdircd'] = lambda args: (os.makedirs(args[0]), os.chdir(args[0]))
  169. aliases['p'] = ['pass']
  170. if shutil.which('startx') and $(tty).rstrip() == '/dev/tty1':
  171. startx
  172. # vim: filetype=python