rc.xsh 6.4 KB

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