rc.xsh 6.2 KB

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