rc.xsh 6.7 KB

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