├── .gitignore ├── README.markdown ├── _old ├── README.markdown ├── archlinux │ ├── makepkg.conf │ └── module.py ├── dunst │ ├── dunstrc │ └── module.py ├── mksh │ ├── mkshrc │ └── module.py ├── mutt │ ├── color │ ├── gpg │ ├── headers │ ├── macros │ ├── module.py │ └── muttrc ├── picard │ ├── Picard.conf │ └── module.py ├── tcsh │ ├── login │ ├── module.py │ └── tcsh │ │ ├── aliases.tcsh │ │ ├── completions.tcsh │ │ ├── cwdcmd.tcsh │ │ ├── env.tcsh │ │ ├── keybinds.tcsh │ │ ├── settings.tcsh │ │ └── tcshrc └── x11 │ └── Xdefaults ├── bash ├── bashrc ├── inputrc └── module.py ├── diffexpr.vim ├── doas ├── doas.conf └── module.py ├── git ├── config └── module.py ├── htop ├── htoprc └── module.py ├── less ├── less ├── lesskey └── module.py ├── local ├── module.py └── script │ ├── bl-connect │ ├── dmenu-list │ ├── dmenu-uni │ ├── flac2v0 │ ├── game │ ├── git │ ├── git-prunebranches │ ├── git-undolast │ ├── go │ ├── gorun │ ├── jsonfmt │ ├── pa-mv │ ├── set-meta │ ├── set-screen │ ├── sleep-until │ ├── timeadd │ ├── timecalc │ ├── tmux-gc │ ├── tmux-site │ ├── tz │ ├── wifi │ ├── wm-brightness │ ├── wm-media │ ├── wm-scratch │ ├── wm-screenshot │ ├── xdg-open │ └── yaml2json ├── manage-dotfiles.py ├── mpv ├── input.conf ├── module.py ├── mpv.conf ├── script-opts │ ├── console.conf │ ├── encode_slice.conf │ ├── encode_webm.conf │ └── osc.conf └── scripts │ ├── encode.lua │ └── martin.lua ├── psql ├── module.py └── psqlrc ├── pubkey ├── id_ed25519.pub └── module.py ├── redshift ├── module.py └── redshift.conf ├── rg ├── module.py └── ripgrep ├── service ├── xbanish │ └── run └── xcape │ └── run ├── sqlite ├── module.py └── sqliterc ├── tmux ├── module.py └── tmux.conf ├── vim ├── module.py ├── packman.conf ├── spell │ ├── en.utf-8.add │ └── en.utf-8.add.spl └── vimrc ├── x11 ├── XCompose ├── Xmodmap ├── fonts.conf ├── gtk3-settings.ini ├── icons ├── module.py ├── service │ ├── xbanish │ │ └── run │ └── xcape │ │ └── run └── xinitrc └── zsh ├── module.py └── zshrc /.gitignore: -------------------------------------------------------------------------------- 1 | config.local 2 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | My dotfiles. 2 | 3 | `manage-dotfiles.py` is a tool to manage your dotfiles. 4 | 5 | Why another tool? 6 | 7 | - It's so obvious how to use this that your grandmother could do it. 8 | - Not tied with git, or any other VCS (does have optional features which require 9 | either `hg` or `git`). 10 | - Just a few lines of code. Not a crapload some other tools. 11 | - Easy installation *and* upgrade; also makes it easy to *merge* your files. 12 | - Not based on symlinks. Be free to modify your files and *not* merge changes back. 13 | 14 | So, how do you use it: 15 | 16 | - In the directory `modules` you keep modules. 17 | - Every module has a `module.py` code, here you can assign `files`, `dirs`, and 18 | `symlinks` to manage as a dict where the key is the destination directory, and 19 | the value is the directory from which to source them (relative to the module 20 | dir). 21 | - Run `./manage-dotfiles.py` to install & merge everything, or 22 | `./manage-dotfiles.py module1 module2` to install only `module1` & `module2`. 23 | You can also use the `-i` to switch to ask confirmation for everything, and 24 | the `-f` switch to override all local files regardless of any changes. 25 | 26 | Alternatives: [dotfiles.github.io](http://dotfiles.github.io/) lists some. 27 | 28 | -------------------------------------------------------------------------------- /_old/README.markdown: -------------------------------------------------------------------------------- 1 | Stuff I don't currently use (but may start using in the future again). 2 | -------------------------------------------------------------------------------- /_old/archlinux/makepkg.conf: -------------------------------------------------------------------------------- 1 | # Don't compress files; it's just a waste of time/CPU cycles. 2 | PKGEXT='.pkg.tar' 3 | -------------------------------------------------------------------------------- /_old/archlinux/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/pacman/makepkg.conf': 'makepkg.conf', 3 | } 4 | -------------------------------------------------------------------------------- /_old/dunst/dunstrc: -------------------------------------------------------------------------------- 1 | [global] 2 | font = Monospace 10 3 | 4 | # Allow a small subset of html markup: 5 | # bold 6 | # italic 7 | # strikethrough 8 | # underline 9 | # 10 | # For a complete reference see 11 | # . 12 | # If markup is not allowed, those tags will be stripped out of the 13 | # message. 14 | markup = yes 15 | 16 | # The format of the message. Possible variables are: 17 | # %a appname 18 | # %s summary 19 | # %b body 20 | # %i iconname (including its path) 21 | # %I iconname (without its path) 22 | # %p progress value if set ([ 0%] to [100%]) or nothing 23 | # Markup is allowed 24 | format = "%s\n%b" 25 | 26 | # Sort messages by urgency. 27 | sort = yes 28 | 29 | # Show how many messages are currently hidden (because of geometry). 30 | indicate_hidden = yes 31 | 32 | # Alignment of message text. 33 | # Possible values are "left", "center" and "right". 34 | alignment = left 35 | 36 | # The frequency with wich text that is longer than the notification 37 | # window allows bounces back and forth. 38 | # This option conflicts with "word_wrap". 39 | # Set to 0 to disable. 40 | bounce_freq = 0 41 | 42 | # Show age of message if message is older than show_age_threshold 43 | # seconds. 44 | # Set to -1 to disable. 45 | show_age_threshold = 60 46 | 47 | # Split notifications into multiple lines if they don't fit into 48 | # geometry. 49 | word_wrap = yes 50 | 51 | # Ignore newlines '\n' in notifications. 52 | ignore_newline = no 53 | 54 | # The geometry of the window: 55 | # [{width}]x{height}[+/-{x}+/-{y}] 56 | # The geometry of the message window. 57 | # The height is measured in number of notifications everything else 58 | # in pixels. If the width is omitted but the height is given 59 | # ("-geometry x2"), the message window expands over the whole screen 60 | # (dmenu-like). If width is 0, the window expands to the longest 61 | # message displayed. A positive x is measured from the left, a 62 | # negative from the right side of the screen. Y is measured from 63 | # the top and down respectevly. 64 | # The width can be negative. In this case the actual width is the 65 | # screen width minus the width defined in within the geometry option. 66 | geometry = "300x5-30+20" 67 | 68 | # Shrink window if it's smaller than the width. Will be ignored if 69 | # width is 0. 70 | shrink = no 71 | 72 | # The transparency of the window. Range: [0; 100]. 73 | # This option will only work if a compositing windowmanager is 74 | # present (e.g. xcompmgr, compiz, etc.). 75 | transparency = 0 76 | 77 | # Don't remove messages, if the user is idle (no mouse or keyboard input) 78 | # for longer than idle_threshold seconds. 79 | # Set to 0 to disable. 80 | idle_threshold = 120 81 | 82 | # Which monitor should the notifications be displayed on. 83 | monitor = 0 84 | 85 | # Display notification on focused monitor. Possible modes are: 86 | # mouse: follow mouse pointer 87 | # keyboard: follow window with keyboard focus 88 | # none: don't follow anything 89 | # 90 | # "keyboard" needs a windowmanager that exports the 91 | # _NET_ACTIVE_WINDOW property. 92 | # This should be the case for almost all modern windowmanagers. 93 | # 94 | # If this option is set to mouse or keyboard, the monitor option 95 | # will be ignored. 96 | follow = mouse 97 | 98 | # Should a notification popped up from history be sticky or timeout 99 | # as if it would normally do. 100 | sticky_history = yes 101 | 102 | # Maximum amount of notifications kept in history 103 | history_length = 20 104 | 105 | # Display indicators for URLs (U) and actions (A). 106 | show_indicators = yes 107 | 108 | # The height of a single line. If the height is smaller than the 109 | # font height, it will get raised to the font height. 110 | # This adds empty space above and under the text. 111 | line_height = 0 112 | 113 | # Draw a line of "separatpr_height" pixel height between two 114 | # notifications. 115 | # Set to 0 to disable. 116 | separator_height = 8 117 | 118 | # Padding between text and separator. 119 | padding = 8 120 | 121 | # Horizontal padding. 122 | horizontal_padding = 8 123 | 124 | # Define a color for the separator. 125 | # possible values are: 126 | # * auto: dunst tries to find a color fitting to the background; 127 | # * foreground: use the same color as the foreground; 128 | # * frame: use the same color as the frame; 129 | # * anything else will be interpreted as a X color. 130 | separator_color = transparent 131 | 132 | # Print a notification on startup. 133 | # This is mainly for error detection, since dbus (re-)starts dunst 134 | # automatically after a crash. 135 | startup_notification = false 136 | 137 | # dmenu path. 138 | dmenu = /usr/bin/dmenu -p dunst: 139 | 140 | # Browser for opening urls in context menu. 141 | browser = /usr/bin/opera 142 | 143 | # Align icons left/right/off 144 | icon_position = left 145 | 146 | # Paths to default icons. 147 | icon_folders = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ 148 | 149 | frame_width = 0 150 | frame_color = "#ff0000" 151 | 152 | [shortcuts] 153 | # Shortcuts are specified as [modifier+][modifier+]...key 154 | # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2", 155 | # "mod3" and "mod4" (windows-key). 156 | # Xev might be helpful to find names for keys. 157 | 158 | # Close notification. 159 | close = ctrl+space 160 | 161 | # Close all notifications. 162 | close_all = ctrl+shift+space 163 | 164 | # Redisplay last message(s). 165 | # On the US keyboard layout "grave" is normally above TAB and left 166 | # of "1". 167 | history = ctrl+grave 168 | 169 | # Context menu. 170 | context = ctrl+shift+period 171 | 172 | 173 | [urgency_low] 174 | # IMPORTANT: colors have to be defined in quotation marks. 175 | # Otherwise the "#" and following would be interpreted as a comment. 176 | background = "#222222" 177 | foreground = "#888888" 178 | timeout = 0 179 | 180 | [urgency_normal] 181 | background = "#285577" 182 | foreground = "#ffffff" 183 | timeout = 0 184 | 185 | [urgency_critical] 186 | background = "#900000" 187 | foreground = "#ffffff" 188 | timeout = 0 189 | 190 | 191 | # Every section that isn't one of the above is interpreted as a rules to 192 | # override settings for certain messages. 193 | # Messages can be matched by "appname", "summary", "body", "icon", "category", 194 | # "msg_urgency" and you can override the "timeout", "urgency", "foreground", 195 | # "background", "new_icon" and "format". 196 | # Shell-like globbing will get expanded. 197 | # 198 | # SCRIPTING 199 | # You can specify a script that gets run when the rule matches by 200 | # setting the "script" option. 201 | # The script will be called as follows: 202 | # script appname summary body icon urgency 203 | # where urgency can be "LOW", "NORMAL" or "CRITICAL". 204 | # 205 | # NOTE: if you don't want a notification to be displayed, set the format 206 | # to "". 207 | # NOTE: It might be helpful to run dunst -print in a terminal in order 208 | # to find fitting options for rules. 209 | 210 | #[espeak] 211 | # summary = "*" 212 | # script = dunst_espeak.sh 213 | 214 | #[script-test] 215 | # summary = "*script*" 216 | # script = dunst_test.sh 217 | 218 | #[ignore] 219 | # # This notification will not be displayed 220 | # summary = "foobar" 221 | # format = "" 222 | 223 | #[signed_on] 224 | # appname = Pidgin 225 | # summary = "*signed on*" 226 | # urgency = low 227 | # 228 | #[signed_off] 229 | # appname = Pidgin 230 | # summary = *signed off* 231 | # urgency = low 232 | # 233 | #[says] 234 | # appname = Pidgin 235 | # summary = *says* 236 | # urgency = critical 237 | # 238 | #[twitter] 239 | # appname = Pidgin 240 | # summary = *twitter.com* 241 | # urgency = normal 242 | # 243 | # vim: ft=cfg 244 | -------------------------------------------------------------------------------- /_old/dunst/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/dunstrc': 'dunstrc' 3 | } 4 | -------------------------------------------------------------------------------- /_old/mksh/mkshrc: -------------------------------------------------------------------------------- 1 | # Basic environment ... (? I think?) 2 | \: "${TERM:=vt100}${HOSTNAME:=$(\ulimit -c \ 3 | 0; hostname 2>/dev/null)}${EDITOR:=/bin/ed}${USER:=$(\ulimit -c 0; id -un \ 4 | 2>/dev/null || \echo \?)}${MKSH:=$(\builtin whence -p mksh)}" 5 | 6 | HOSTNAME=${HOSTNAME%%*([ ]).*} 7 | HOSTNAME=${HOSTNAME##*([ ])} 8 | [[ $HOSTNAME = ?(ip6-)localhost?(6) ]] && HOSTNAME= 9 | \: "${HOSTNAME:=nil}${MKSH:=/bin/mksh}" 10 | export EDITOR HOSTNAME MKSH TERM USER 11 | 12 | PS1='#' # Root 13 | (( USER_ID )) && PS1='%' # Regular user 14 | PS1=$'\001\r''${| 15 | # Store exit code for later 16 | \typeset e=$? 17 | 18 | \typeset d=${PWD:-?}/ 19 | \typeset p=~ 20 | 21 | # Replace $HOME with ~ 22 | [[ $p = ?(*/) ]] || d=${d/#$p\//\~/} 23 | d=${d%/} 24 | 25 | # Hmmm...? 26 | \typeset m=${%d} n p=… 27 | (( m > 0 )) || m=${#d} 28 | (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p= 29 | 30 | REPLY+="[$p$d]" 31 | 32 | # Add exit code 33 | (( e )) && REPLY+=" $e " 34 | 35 | \return $e 36 | }'"$PS1 " 37 | 38 | PS4='[$EPOCHREALTIME] ' 39 | 40 | ### 41 | ### ENV 42 | ### 43 | export HISTFILE=~/.mksh_history 44 | export HISTSIZE=32767 45 | 46 | # Path 47 | export PATH=~/Local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games 48 | [ -d /usr/local/bin ] && export PATH=$PATH:/usr/local/bin:/usr/local/sbin 49 | [ -d /usr/X11R6/bin ] && export PATH=$PATH:/usr/X11R6/bin:/usr/X11R6/sbin 50 | 51 | if [ -d ~/.gem/ruby/2.3.0/bin ]; then 52 | export PATH=$PATH:~/.gem/ruby/2.3.0/bin 53 | elif [ -d ~/.gem/ruby/2.2.0/bin ]; then 54 | export PATH=$PATH:~/.gem/ruby/2.2.0/bin 55 | fi 56 | 57 | # Go stuff 58 | \export GOPATH=~/gocode 59 | \export PATH=$PATH:~/gocode/bin 60 | 61 | # Various applications settings 62 | \export BLOCKSIZE=K 63 | \export PAGER=less 64 | \export LESS='--ignore-case --LONG-PROMPT --SILENT --no-init --no-lessopen' 65 | 66 | # Make man pages 80 characters wide at the most; this is the default on BSD, but 67 | # not Linux 68 | \export MANWIDTH=80 69 | 70 | # Colors for ls(1) 71 | \export LS_COLORS="no=00:fi=00:di=34:ln=01;31:pi=34;43:so=31;43:bd=30;43:cd=30;43:or=01;35:ex=31:" 72 | 73 | # Older GNU grep; BSD grep 74 | \export GREP_COLOR=31 75 | 76 | # Newer GNU grep, I guess GREP_COLOR was too easy to use 77 | \export GREP_COLORS="ms=31:mc=31:sl=0:cx=0:fn=0:ln=0:bn=0:se=0" 78 | 79 | # Fix scrolling in GTK3; https://www.pekwm.org/projects/pekwm/tasks/350 80 | \export GDK_CORE_DEVICE_EVENTS=1 81 | 82 | # Make compose key work for GTK, Qt 83 | \export GTK_IM_MODULE=xim 84 | \export QT_IM_MODULE=xim 85 | 86 | # Disable retarded "overlay scrollbar" 87 | \export GTK_OVERLAY_SCROLLING=0 88 | 89 | # Don't output to a pager 90 | \export SYSTEMD_PAGER= 91 | 92 | \export TERM=screen-256color 93 | # Do the $TERM dance; these options seem to work best on various systems... 94 | #if (($?TMUX)) then 95 | # setenv TERM screen-256color 96 | #else if ($uname == OpenBSD) then 97 | # setenv TERM xterm-xfree86 98 | #else if ($uname == FreeBSD) then 99 | # if ($tty =~ ttyv*) then 100 | # setenv TERM cons25 101 | # else 102 | # setenv TERM xterm-256color 103 | # endif 104 | #else if ($uname == Linux) then 105 | # setenv TERM xterm-256color 106 | # #setenv TERM xterm-color 107 | #else 108 | # setenv TERM vt220 109 | #endif 110 | 111 | # UTF-8 112 | if [ -x "$(command -v locale)" ]; then 113 | \export LANG=en_US.UTF-8 114 | \export LC_CTYPE=en_US.UTF-8 115 | \export LC_COLLATE=en_US.UTF-8 116 | 117 | #setenv I18NPATH ~/.locale 118 | #setenv LOCPATH ~/.locale 119 | fi 120 | 121 | # Set editor 122 | \export EDITOR=vim 123 | \alias vim='vim -p' 124 | \alias vi='vim' 125 | 126 | \export BROWSER=chromium 127 | 128 | # Run commands from this file; only run for interactive prompt 129 | [ -f ~/Local/python-startup ] && \ 130 | \export PYTHONSTARTUP=~/Local/python-startup 131 | 132 | #foreach f ( /etc/profile.d/*.csh ) 133 | # if ( -r $f ) source $f 134 | #end 135 | #unset f 136 | 137 | 138 | ### 139 | ### Aliases 140 | ### 141 | \alias ls='ls -F --quoting-style=literal --color' 142 | \alias l='ls' 143 | \alias lc='ls -lhN' 144 | \alias la='l -A' 145 | \alias lac='ls -lhA' 146 | 147 | \alias pdiff='diff -urN -x .git -x .hg' 148 | 149 | # Run last command as root 150 | \alias dosu='sudo mksh -c "$(\builtin fc -ln -1)"' 151 | 152 | [ -x "$(\command -v systemctl)" ] && \ 153 | \alias zzz='systemctl suspend' 154 | 155 | # bsdtar/libarchive works with many file formats, not just tar 156 | [ -x "$(\command -v bsdtar)" ] && \ 157 | \alias tar=bsdtar 158 | 159 | # Linux top is an unusable piece of shit after recent changes 160 | [ -x "$(\command -v htop)" ] && \ 161 | \alias top=htop 162 | 163 | \alias cp='cp -i' 164 | \alias mv='mv -i' 165 | \alias make='nice -n 20 make' 166 | \alias lman='groff -man -Tascii' # `local man' .1 167 | \alias dejson='python -mjson.tool' 168 | \alias ag='ag -S --color-match 31 --color-line-number 35 --color-path 1\;4' 169 | \alias decolor="sed 's|\x1b\[[;0-9]*m||g'" 170 | 171 | # I type mplayer out of habbit... 172 | \alias mplayer=mpv 173 | 174 | \alias muttp='mutt -F ~/.mutt/muttrc-prive' 175 | \alias muttw='mutt -F ~/.mutt/muttrc-work' 176 | \alias mutt-sunbeam='mutt -F ~/.mutt/muttrc-sunbeam' 177 | 178 | # Use title in filename 179 | \alias youtube-dl='youtube-dl --no-part -t' 180 | 181 | # Some typos 182 | \alias sl="ls" 183 | \alias l="ls" 184 | \alias c="cd" 185 | \alias vo="vi" 186 | \alias ci="vi" 187 | \alias iv="vi" # Some image viewer I never use, annoying 188 | \alias grpe="grep" 189 | \alias Grep="grep" 190 | \alias les=less 191 | 192 | # TODO 193 | #alias helpcommand man 194 | #bind -m '^[OP'=man 195 | #alias cwdcmd source ~/.tcsh/cwdcmd.tcsh 196 | 197 | ### 198 | ### Key bindings 199 | ### 200 | \bind '^L'=clear-screen 201 | 202 | # Up/down arrows 203 | \bind '^[[A'=search-history-up 204 | \bind '^[[B'=search-history-down 205 | 206 | #\bind -m '^[[A'='^[[5~^E' 207 | #\bind -m '^[[B'='^[[6~^E' 208 | 209 | # vim:filetype=sh 210 | -------------------------------------------------------------------------------- /_old/mksh/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.mkshrc': 'mkshrc', 3 | } 4 | -------------------------------------------------------------------------------- /_old/mutt/color: -------------------------------------------------------------------------------- 1 | # vim:ts=8 2 | 3 | uncolor index * 4 | uncolor header * 5 | uncolor body * 6 | 7 | color attachment black green 8 | color hdrdefault red default 9 | color quoted red default 10 | color error red default 11 | color search default yellow 12 | color status brightwhite black 13 | color tree red default 14 | color normal default default 15 | color tilde blue default 16 | color bold blue default 17 | color markers red default 18 | color header blue default "^(From|Subject|Date):" 19 | 20 | color indicator brightwhite blue 21 | color index brightblue default ~N 22 | color index blue default ~O 23 | color index brightwhite black ~D 24 | 25 | color body blue default "(http|https|ftp|news|telnet|finger)://[^ \">\t\r\n]*" 26 | color body blue default "mailto:[-a-z_0-9.]+@[-a-z_0-9.]+" 27 | color body blue default "news:[^ \">\t\r\n]*" 28 | color body blue default "[-a-z_0-9.%$]+@[-a-z_0-9.]+\\.[-a-z][-a-z]+" 29 | color body blue default "(^|[[:space:]])\\*[^[:space:]]+\\*([[:space:]]|$)" # *Bold* text. 30 | color body blue default "(^|[[:space:]])_[^[:space:]]+_([[:space:]]|$)" # _Underlined_ text. 31 | color body blue default "(^|[[:space:]])/[^[:space:]]+/([[:space:]]|$)" # /Italic/ text. 32 | -------------------------------------------------------------------------------- /_old/mutt/gpg: -------------------------------------------------------------------------------- 1 | # Command formats for gpg. 2 | # 3 | # This version uses gpg-2comp from 4 | # http://70t.de/download/gpg-2comp.tar.gz 5 | # 6 | # %p The empty string when no passphrase is needed, 7 | # the string "PGPPASSFD=0" if one is needed. 8 | # 9 | # This is mostly used in conditional % sequences. 10 | # 11 | # %f Most PGP commands operate on a single file or a file 12 | # containing a message. %f expands to this file's name. 13 | # 14 | # %s When verifying signatures, there is another temporary file 15 | # containing the detached signature. %s expands to this 16 | # file's name. 17 | # 18 | # %a In "signing" contexts, this expands to the value of the 19 | # configuration variable $pgp_sign_as. You probably need to 20 | # use this within a conditional % sequence. 21 | # 22 | # %r In many contexts, mutt passes key IDs to pgp. %r expands to 23 | # a list of key IDs. 24 | 25 | # Note that we explicitly set the comment armor header since GnuPG, when used 26 | # in some localiaztion environments, generates 8bit data in that header, thereby 27 | # breaking PGP/MIME. 28 | 29 | # decode application/pgp 30 | set pgp_decode_command="gpg --status-fd=2 %?p?--passphrase-fd 0? --no-verbose --quiet --batch --output - %f" 31 | 32 | # verify a pgp/mime signature 33 | set pgp_verify_command="gpg --status-fd=2 --no-verbose --quiet --batch --output - --verify %s %f" 34 | 35 | # decrypt a pgp/mime attachment 36 | set pgp_decrypt_command="gpg --status-fd=2 %?p?--passphrase-fd 0? --no-verbose --quiet --batch --output - %f" 37 | 38 | # create a pgp/mime signed attachment 39 | # set pgp_sign_command="gpg-2comp --comment '' --no-verbose --batch --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f" 40 | set pgp_sign_command="gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f" 41 | 42 | # create a application/pgp signed (old-style) message 43 | # set pgp_clearsign_command="gpg-2comp --comment '' --no-verbose --batch --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f" 44 | set pgp_clearsign_command="gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f" 45 | 46 | # create a pgp/mime encrypted attachment 47 | # set pgp_encrypt_only_command="pgpewrap gpg-2comp -v --batch --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f" 48 | set pgp_encrypt_only_command="pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f" 49 | 50 | # create a pgp/mime encrypted and signed attachment 51 | # set pgp_encrypt_sign_command="pgpewrap gpg-2comp %?p?--passphrase-fd 0? -v --batch --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f" 52 | set pgp_encrypt_sign_command="pgpewrap gpg %?p?--passphrase-fd 0? --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f" 53 | 54 | # import a key into the public key ring 55 | set pgp_import_command="gpg --no-verbose --import %f" 56 | 57 | # export a key from the public key ring 58 | set pgp_export_command="gpg --no-verbose --export --armor %r" 59 | 60 | # verify a key 61 | set pgp_verify_key_command="gpg --verbose --batch --fingerprint --check-sigs %r" 62 | 63 | # read in the public key ring 64 | set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons --list-keys %r" 65 | 66 | # read in the secret key ring 67 | set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons --list-secret-keys %r" 68 | 69 | # fetch keys 70 | # set pgp_getkeys_command="pkspxycwrap %r" 71 | 72 | # pattern for good signature - may need to be adapted to locale! 73 | 74 | # set pgp_good_sign="^gpgv?: Good signature from " 75 | 76 | # OK, here's a version which uses gnupg's message catalog: 77 | # set pgp_good_sign="`gettext -d gnupg -s 'Good signature from "' | tr -d '"'`" 78 | 79 | # This version uses --status-fd messages 80 | set pgp_good_sign="^\\[GNUPG:\\] GOODSIG" 81 | -------------------------------------------------------------------------------- /_old/mutt/headers: -------------------------------------------------------------------------------- 1 | ignore * 2 | 3 | unignore To: 4 | unignore Reply-To: 5 | unignore Mail-Followup-To: 6 | unignore CC: 7 | unignore BCC: 8 | unignore Date: 9 | unignore From: 10 | unignore Subject: 11 | 12 | hdr_order To: CC: BCC: Reply-To: Mail-Followup-To: Date: From: Subject: 13 | -------------------------------------------------------------------------------- /_old/mutt/macros: -------------------------------------------------------------------------------- 1 | # http://dev.mutt.org/trac/wiki/MacroSamples 2 | 3 | # urlview 4 | macro index B "urlview-ng" 5 | macro pager B "urlview-ng" 6 | 7 | # general 8 | #macro pager \e1 "set pager_index_lines=0" 9 | #macro pager \e2 "set pager_index_lines=10" 10 | 11 | # http://unix.stackexchange.com/questions/137043/mutt-ask-for-confirmation-before-moving-message-to-archive 12 | macro pager a "t;s=Archive$y" 13 | macro index a "t;s=Archive$y" 14 | #macro pager d "t;s=Archive$y" 15 | #macro index d "t;s=Archive$y" 16 | 17 | # http://askubuntu.com/questions/122480/how-to-manage-multiple-imap-accounts-with-mutt 18 | macro index \e1 "source ~/.mutt/accountc!" 19 | macro index \e2 "source ~/.mutt/account2c!" 20 | -------------------------------------------------------------------------------- /_old/mutt/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.mutt': '.' 3 | } 4 | -------------------------------------------------------------------------------- /_old/mutt/muttrc: -------------------------------------------------------------------------------- 1 | #source ~/.mutt/account-work 2 | #source ~/.mutt/account-prive 3 | 4 | # Allow Mutt to open new imap connection automatically. 5 | unset imap_passive 6 | 7 | # Keep IMAP connection alive by polling intermittently (time in seconds). 8 | set imap_keepalive = 300 9 | 10 | # How often to check for new mail (time in seconds). 11 | set mail_check = 120 12 | 13 | # .... 14 | 15 | # Store drafts here 16 | set postponed = "+Drafts" 17 | 18 | # Messages marked as deleted will be saved with the trashed flag instead of 19 | # unlinked. 20 | set maildir_trash = yes 21 | 22 | set mbox_type = "Maildir" 23 | set editor = "vim" 24 | set charset = "utf-8" 25 | set send_charset="us-ascii:UTF-8" 26 | 27 | 28 | # Hold messages in $MAIL 29 | set move = no 30 | 31 | # Don't mark unread new msgs as old 32 | set mark_old = no 33 | 34 | # Ask before printing 35 | set print = ask-yes 36 | 37 | # Don't ask before doing a delete 38 | set delete = yes 39 | 40 | # Include the message in replies 41 | set include 42 | 43 | # Don't show + when wrapping to the next line 44 | set nomarkers 45 | 46 | # Sort in threads 47 | set sort = threads 48 | 49 | # Sort threads by date received 50 | set sort_aux = date-received 51 | 52 | # 8bit isn't safe via Demon 53 | set allow_8bit = no 54 | 55 | # Keep copies of outgoing mail ... 56 | set copy 57 | 58 | # We don't need no beeping software. 59 | set beep = no 60 | 61 | # Fill out messages with '~' (like Vi) 62 | set tilde 63 | 64 | # Show 5 lines of context when pressing space 65 | set pager_context = 5 66 | 67 | set menu_context = 5 68 | set menu_scroll 69 | 70 | # Show 10 index lines in pages 71 | #set pager_index_lines = 10 72 | 73 | # Don't go to next message automaticly 74 | set pager_stop = yes 75 | 76 | # Ask before exiting 77 | set quit = ask-yes 78 | 79 | # Add a Mail-Followup-To header to subcribed maillists 80 | set followup_to = yes 81 | 82 | # Don't press key after we're done with external program 83 | set wait_key = no 84 | 85 | # Don't show help bar 86 | set help = no 87 | 88 | # edit the header of your outgoing messages 89 | set edit_headers = yes 90 | 91 | # Go directly to editor after pressing m 92 | set autoedit = yes 93 | 94 | # Include forwarded mails as attachment instead of inline 95 | set mime_forward = yes 96 | 97 | # Just append, don't hassle me. 98 | set confirmappend = no 99 | 100 | # Set terminal title 101 | # TODO: Doesn't get cleared after we leave mutt 102 | #set ts_enabled = yes 103 | 104 | # flags│ date│ from│ subject 105 | set index_format="%Z│ %{%b %d}│ %-20.20F│ %s" 106 | 107 | #set mask = "." 108 | #set signature = "~/.mutt/signature.sh |" 109 | auto_view text/html 110 | alternative_order text/plain text/enriched text/html 111 | 112 | set mailcap_path = ~/.mutt/mailcap 113 | 114 | # Cache 115 | set message_cachedir =~/.mutt/cache 116 | 117 | #source ~/.mutt/gpg 118 | source ~/.mutt/headers 119 | source ~/.mutt/color 120 | source ~/.mutt/macros 121 | -------------------------------------------------------------------------------- /_old/picard/Picard.conf: -------------------------------------------------------------------------------- 1 | [application] 2 | version=1.3.2final0 3 | 4 | [setting] 5 | acoustid_fpcalc=/usr/bin/fpcalc 6 | starting_directory_path=/data/tmp/music 7 | ignore_regex= 8 | ignore_hidden_files=false 9 | cd_lookup_device=/dev/cdrom 10 | save_images_to_tags=false 11 | save_only_front_images_to_tags=true 12 | save_images_to_files=true 13 | cover_image_filename=cover 14 | ca_provider_use_amazon=true 15 | ca_provider_use_caa=true 16 | ca_provider_use_caa_release_group_fallback=false 17 | ca_provider_use_whitelist=true 18 | caa_image_size=1 19 | caa_approved_only=true 20 | caa_image_type_as_filename=false 21 | save_images_overwrite=false 22 | caa_restrict_image_types=true 23 | server_host=musicbrainz.org 24 | server_port=80 25 | username= 26 | password= 27 | analyze_new_files=false 28 | ignore_file_mbids=false 29 | toolbar_show_labels=true 30 | toolbar_multiselect=false 31 | use_adv_search_syntax=false 32 | quit_confirmation=true 33 | starting_directory=false 34 | max_tags=5 35 | min_tag_usage=90 36 | join_tags= 37 | ignore_tags="seen live,favorites,fixme,owned" 38 | only_my_tags=false 39 | enable_ratings=false 40 | rating_user_email=users@musicbrainz.org 41 | submit_ratings=true 42 | file_lookup_threshold=0.7 43 | cluster_lookup_threshold=0.8 44 | track_matching_threshold=0.4 45 | translate_artist_names=false 46 | artist_locale=en 47 | convert_punctuation=false 48 | release_ars=true 49 | track_ars=false 50 | folksonomy_tags=false 51 | va_name=Various Artists 52 | standardize_artists=false 53 | release_type_scores=@Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x15(VAlbum\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x1a(VSpokenword\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x15(VRemix\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x14(VDemo\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x1b(VCompilation\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x19(VAudiobook\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x1e(VMixtape/Street\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x19(VBroadcast\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x16(VSingle\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x15(VOther\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x16(VDJ-mix\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x14(VLive\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x1a(VSoundtrack\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x19(VInterview\np0\nF0.5\ntp1\n.), @Variant(\0\0\0\x7f\0\0\0\xePyQt_PyObject\0\0\0\0\x12(VEP\np0\nF0.5\ntp1\n.) 54 | preferred_release_countries=@Invalid() 55 | preferred_release_formats=@Invalid() 56 | enable_tagger_script=false 57 | tagger_script= 58 | windows_compatibility=false 59 | ascii_filenames=false 60 | rename_files=true 61 | file_naming_format="$if2(%albumartist%,%artist%)/$left($if2(%originaldate%, %date%), 4) %album%/%discnumber%.$num(%tracknumber%,2)$if(%compilation%, %artist% -,) %title%" 62 | move_files=true 63 | move_files_to=/data/music 64 | move_additional_files=true 65 | move_additional_files_pattern=*.jpg *.png *.log *.cue *.jpeg\n 66 | delete_empty_dirs=true 67 | enabled_plugins=@Invalid() 68 | use_proxy=false 69 | proxy_server_host= 70 | proxy_server_port=80 71 | proxy_username= 72 | proxy_password= 73 | browser_integration=true 74 | browser_integration_port=8000 75 | browser_integration_localhost_only=true 76 | dont_write_tags=false 77 | preserve_timestamps=false 78 | clear_existing_tags=true 79 | write_id3v1=false 80 | write_id3v23=false 81 | id3v23_join_with=/ 82 | id3v2_encoding=utf-8 83 | remove_ape_from_mp3=true 84 | remove_id3_from_flac=true 85 | preserved_tags= 86 | fingerprinting_system=acoustid 87 | acoustid_apikey= 88 | 89 | [persist] 90 | window_state=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\0\0\0\x6k\0\0\x3\x9d\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x2\0\0\0\x18\0m\0\x61\0i\0n\0_\0t\0o\0o\0l\0\x62\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x1c\0s\0\x65\0\x61\0r\0\x63\0h\0_\0t\0o\0o\0l\0\x62\0\x61\0r\x1\0\0\x3\x31\xff\xff\xff\xff\0\0\0\0\0\0\0\0) 91 | window_position=@Point(0 37) 92 | window_size=@Size(1643 1019) 93 | window_maximized=false 94 | view_cover_art=true 95 | view_file_browser=true 96 | bottom_splitter_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x2\0\0\x2\xc4\0\0\0\xd8\x1\0\0\0\x1\x1\0\0\0\x2) 97 | splitter_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x3\0\0\x1\x98\0\0\x1\x84\0\0\x3\"\x1\0\0\0\x1\x1\0\0\0\x1) 98 | file_view_sizes=250 40 99 | album_view_sizes=688 96 100 | metadatabox_header_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x5\xc9\0\0\0\x3\0\0\x1\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x84\0\0\0\0\0\0\0\x3\0\0\0\xd6\0\0\0\x1\0\0\0\0\0\0\0\xd5\0\0\0\x1\0\0\0\0\0\0\x4\x1e\0\0\0\x1\0\0\0\0) 101 | options_position=@Point(436 364) 102 | options_size=@Size(1292 553) 103 | options_splitter=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x2\0\0\0J\0\0\x2`\x1\0\0\0\x1\x1\0\0\0\x1) 104 | current_browser_path=/data/tmp/music 105 | -------------------------------------------------------------------------------- /_old/picard/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/MusicBrainz/Picard.conf': 'Picard.conf', 3 | } 4 | -------------------------------------------------------------------------------- /_old/tcsh/login: -------------------------------------------------------------------------------- 1 | if ( -X fortune ) then 2 | fortune -a 3 | endif 4 | 5 | if ( -f ~/.tcsh/cwdcmd ) then 6 | source ~/.tcsh/cwdcmd 7 | endif 8 | -------------------------------------------------------------------------------- /_old/tcsh/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.tcsh': 'tcsh', 3 | } 4 | 5 | files = { 6 | '~/.login': 'login', 7 | } 8 | 9 | symlinks = { 10 | '~/.tcsh/tcshrc': '~/.tcshrc', 11 | } 12 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/aliases.tcsh: -------------------------------------------------------------------------------- 1 | # TODO: alias precmd for branch stuff? 2 | 3 | if ( $uname != win32 && -f ~/.tcsh/cwdcmd.tcsh ) then 4 | alias cwdcmd source ~/.tcsh/cwdcmd.tcsh 5 | cwdcmd 6 | else 7 | unalias cwdcmd 8 | endif 9 | 10 | # What to run on F1 11 | alias helpcommand man 12 | 13 | if ($uname == FreeBSD) then 14 | alias ls "ls-F -I" 15 | alias la "ls-F -A" 16 | alias lc "ls-F -lThoI" 17 | alias lac "ls-F -lThoA" 18 | 19 | # bsdgrep is FreeBSD >=9 20 | # bsdgrep doesn't seem stable/reliable (yet) 21 | #if (-X bsdgrep) then 22 | # alias grep "bsdgrep --color" 23 | #else 24 | alias grep "grep --color" 25 | #endif 26 | else if ($uname == OpenBSD) then 27 | if (-X colorls) then 28 | alias ls "colorls -FG" 29 | alias la "colorls -FGA" 30 | alias lc "colorls -FGlTho" 31 | alias lac "colorls -FGlThoA" 32 | else 33 | alias ls "ls -F" 34 | alias la "ls -FA" 35 | alias lc "ls -FlTho" 36 | alias lac "ls -FAlTho" 37 | endif 38 | else if ($uname == SunOS) then 39 | alias ls "ls-F" 40 | alias la "/bin/ls -FA" 41 | alias lc "/bin/ls -Flho" 42 | alias lac "/bin/ls -FlAho" 43 | else if ($uname == Linux) then 44 | unalias ls 45 | 46 | alias ls 'ls-F' 47 | # -N disabled retarded GNU shit of quoting the filenames (which is suddenly 48 | # the default?!) 49 | # No idea how compatible it is... 50 | alias lc ls -lhN 51 | alias la ls -A 52 | alias lac ls -lhA 53 | alias grep "grep --color" 54 | 55 | alias sockstat "netstat -lnptu --protocol=inet,unix" 56 | if (-X systemctl) then 57 | alias zzz 'systemctl suspend' 58 | else if (-X pm-suspend) then 59 | alias zzz sudo pm-suspend 60 | endif 61 | 62 | # bsdtar/libarchive works with many file formats, not just tar 63 | if (-X bsdtar) alias tar bsdtar 64 | 65 | # Linux top is an unusable piece of shit after recent changes 66 | if (-X htop) alias top htop 67 | 68 | # TODO: I'm not sure if all Linux systems use the same cal flavour? 69 | #alias cal 'cal -m3' 70 | else if ($uname == win32) then 71 | alias ls ls-F 72 | alias la "ls -a" 73 | alias lc "ls -l" 74 | alias lac "ls -la" 75 | 76 | alias clear cls 77 | else 78 | # These should work on almost any platform ... 79 | alias la "ls -a" 80 | alias lc "ls -l" 81 | alias lac "ls -la" 82 | endif 83 | 84 | # Override the tcsh builtins 85 | if (-x /usr/bin/nice) then 86 | alias nice "/usr/bin/nice" 87 | else if (-x /bin/nice) then 88 | alias nice "/bin/nice" 89 | endif 90 | if (-x /usr/bin/time) alias time "/usr/bin/time -h" 91 | 92 | # A few more aliases... 93 | alias cp "cp -i" 94 | alias mv "mv -i" 95 | alias make "nice -n 20 make" 96 | alias j "jobs -l" 97 | alias lman "groff -man -Tascii" # `local man' .1 98 | 99 | # Third-party stuff 100 | if (-X mpv) alias music "mpv $* *.{mp3,flac}" 101 | # HipHop and no PHP 102 | if (-X hhvm && ! -X php) alias php hhvm 103 | 104 | if (-X curl) then 105 | alias curl-post 'curl -X POST' 106 | alias curl-put 'curl -X PUT' 107 | alias curl-delete 'curl -X DELETE' 108 | endif 109 | 110 | if (-X drill) then 111 | alias dig drill 112 | else if (-X dig) then 113 | alias drill dig 114 | endif 115 | 116 | alias dejson 'python -mjson.tool' 117 | alias ag 'ag -S --color-match 31 --color-line-number 35 --color-path 1\;4' 118 | 119 | # Use title in filename 120 | alias youtube-dl 'youtube-dl --no-part -t' 121 | 122 | 123 | # Typos 124 | alias sl "ls" 125 | alias l "ls" 126 | alias c "cd" 127 | alias vo "vi" 128 | alias ci "vi" # ci already exists, but few people use it and it mangles files! 129 | alias iv "vi" # Some image viewer I never use, annoying 130 | alias grpe "grep" 131 | alias Grep "grep" 132 | alias les less 133 | 134 | 135 | # Visual separator 136 | alias sep "echo '\033[1;34m=========================================\033[0m'" 137 | 138 | # http://superuser.com/questions/380772/removing-ansi-color-codes-from-text-stream#380778 139 | # man Term::ANSIColor 140 | # http://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences 141 | # http://www.andrewnoske.com/wiki/Unix_-_ANSI_colors 142 | alias decolor "sed 's|\x1b\[[;0-9]*m||g'" 143 | alias trcolor "sed -e 's|\x1b\[36m|\x1b\[31m|g'; 's|\x1b\[33m|\x1b\[31m|g'" 144 | 145 | # Until I can find/make a colour scheme that works 146 | alias ipython 'ipython --colors=NoColor --no-confirm-exit' 147 | 148 | alias xvi xvim 149 | alias write mlterm -e vim -c :WriteMode\ '&' 150 | alias vh 'vim -c ':help $1' -c :only' 151 | alias vims 'vim -c ScratchBuffer' 152 | alias vim-basic 'vim -u ~/.vim/basic' 153 | alias tclsh 'rlwrap tclsh' 154 | 155 | alias mplayer mpv 156 | 157 | alias muttp mutt -F ~/.mutt/muttrc-prive 158 | alias muttw mutt -F ~/.mutt/muttrc-work 159 | alias mutt-sunbeam mutt -F ~/.mutt/muttrc-sunbeam 160 | #alias mutt /usr/bin/mutt -F ~/.mutt/muttrc-prive 161 | 162 | alias rdiff "diff -urN -x CVS -x .svn -x .git -x .hg " 163 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/completions.tcsh: -------------------------------------------------------------------------------- 1 | set noglob 2 | 3 | set hosts 4 | if ( -r "$HOME/.hosts" ) then 5 | set hosts=($hosts `grep -Ev '(^#|^$)' $HOME/.hosts`) 6 | endif 7 | 8 | if ( -r "$HOME/.ssh/config" ) then 9 | set hosts=($hosts `grep ^Host $HOME/.ssh/config | cut -d' ' -f2`) 10 | endif 11 | 12 | if ( -r "$HOME/.ssh/known_hosts" ) then 13 | set hosts=($hosts `cut -d' ' -f 1 $HOME/.ssh/known_hosts | cut -d, -f1`) 14 | endif 15 | 16 | set hosts = `echo "$hosts" | tr -d '[]' | tr ' ' '\012' | sort -u` 17 | 18 | # From src/tcsh/complete.tcsh 19 | # set hosts=(`echo $hosts | tr ' ' '\012' | sort -u`) 20 | 21 | # Show directories only 22 | complete cd 'C/*/d/' 23 | complete rmdir 'C/*/d/' 24 | 25 | # Various built-in 26 | complete alias 'p/1/a/' 27 | complete unalias 'p/1/a/' 28 | complete unset 'p/1/s/' 29 | complete set 'p/1/s/' 30 | complete unsetenv 'p/1/e/' 31 | complete setenv 'p/1/e/' 32 | complete limit 'p/1/l/' 33 | complete bindkey 'C/*/b/' 34 | complete uncomplete 'p/*/X/' 35 | complete fg 'c/%/j/' 36 | 37 | # Users 38 | complete chgrp 'p/1/g/' 39 | complete chown 'c/*[.:]/g/' 'p/1/u/:' 'n/*/f/' 40 | 41 | # Procs 42 | complete kill 'c/-/S/' 'n/*/`ps axco pid= | sort`/' 43 | complete pkill 'c/-/S/' 'n/*/`ps axco command= | sort -u`/' 44 | complete killall 'c/-/S/' 'n/*/`ps axco command= | sort -u`/' 45 | 46 | # Use available commands as arguments 47 | complete which 'p/1/c/' 48 | complete where 'p/1/c/' 49 | complete man 'p/1/c/' 50 | complete apropos 'p/1/c/' 51 | 52 | # set up programs to complete only with files ending in certain extensions 53 | complete cc 'p/*/f:*.[cao]/' 54 | #complete python 'p/*/f:*.py/' 55 | #complete perl 'p/*/f:*.[pP][lL]/' 56 | 57 | # Complete hosts 58 | complete ssh 'p/1/$hosts/' 59 | complete pssh 'p/1/$hosts/' 60 | complete sftp 'p/1/$hosts/' 61 | complete ftp 'p/1/$hosts/' 62 | complete scp 'p/1/$hosts/' 63 | complete ping 'p/1/$hosts/' 64 | 65 | # Misc. 66 | complete hg 'p/1/(add addremove annotate archive backout bisect bookmarks \ 67 | branch branches bundle cat clone commit copy diff export forget graft \ 68 | grep heads help identify import incoming init locate log manifest \ 69 | merge outgoing parents paths phase pull push recover remove rename \ 70 | resolve revert rollback root serve showconfig status summary tag tags \ 71 | tip unbundle update verify version)/' 72 | 73 | complete svn 'p/1/(add blame cat changelist checkout cleanup commit copy \ 74 | delete diff export help import info list lock log merge mergeinfo \ 75 | mkdir move propdel propedit propget proplist propset resolve \ 76 | resolved revert status switch unlock update)/' \ 77 | 'n/help/(add blame cat changelist checkout cleanup commit copy \ 78 | delete diff export help import info list lock log merge mergeinfo \ 79 | mkdir move propdel propedit propget proplist propset resolve \ 80 | resolved revert status switch unlock update)/' 81 | 82 | complete git 'p/1/(add merge-recursive add--interactive merge-resolve am \ 83 | merge-subtree annotate merge-tree apply mergetool archimport mktag \ 84 | archive mktree bisect mv bisect--helper name-rev blame notes branch \ 85 | pack-objects bundle pack-redundant cat-file pack-refs check-attr \ 86 | patch-id check-ref-format peek-remote checkout prune checkout-index \ 87 | prune-packed cherry pull cherry-pick push clean quiltimport clone \ 88 | read-tree column rebase commit receive-pack commit-tree reflog config \ 89 | relink count-objects remote credential-cache remote-ext \ 90 | credential-cache--daemon remote-fd credential-store remote-ftp daemon \ 91 | remote-ftps describe remote-http diff remote-https diff-files \ 92 | remote-testgit diff-index repack diff-tree replace difftool \ 93 | repo-config difftool--helper request-pull fast-export rerere \ 94 | fast-import reset fetch rev-list fetch-pack rev-parse filter-branch \ 95 | revert fmt-merge-msg rm for-each-ref send-email format-patch send-pack \ 96 | fsck sh-i18n--envsubst fsck-objects shell gc shortlog \ 97 | get-tar-commit-id show grep show-branch hash-object show-index help \ 98 | show-ref http-backend stage http-fetch stash http-push status \ 99 | imap-send stripspace index-pack submodule init symbolic-ref init-db \ 100 | tag instaweb tar-tree log unpack-file lost-found unpack-objects \ 101 | ls-files update-index ls-remote update-ref ls-tree update-server-info \ 102 | mailinfo upload-archive mailsplit upload-pack merge var merge-base \ 103 | verify-pack merge-file verify-tag merge-index web--browse \ 104 | merge-octopus whatchanged merge-one-file write-tree merge-ours)/' \ 105 | 'n@checkout@`git branch -a | sed -r "s|^[\* ]+(remotes/origin/)?||; /^HEAD/d" | sort -u`@' \ 106 | 'n@co@`git branch -a | sed -r "s|^[\* ]+(remotes/origin/)?||; /^HEAD/d" | sort -u`@' \ 107 | 'n@branch@`git branch -a | sed -r "s|^[\* ]+(remotes/origin/)?||; /^HEAD/d" | sort -u`@' 108 | 109 | complete find 'n/-fstype/"(nfs 4.2)"/' 'n/-name/f/' \ 110 | 'n/-type/(c b d f p l s)/' \ 111 | 'n/-user/u/ n/-group/g/' \ 112 | 'n/-exec/c/' 'n/-ok/c/' \ 113 | 'n/-cpio/f/' \ 114 | 'n/-ncpio/f/' \ 115 | 'n/-newer/f/' \ 116 | 'c/-/(fstype name perm prune type user nouser group nogroup size inum \ 117 | atime mtime ctime exec ok print ls cpio ncpio newer xdev depth \ 118 | daystart follow maxdepth mindepth noleaf version anewer cnewer \ 119 | amin cmin mmin true false uid gid ilname iname ipath iregex \ 120 | links lname empty path regex used xtype fprint fprint0 fprintf \ 121 | print0 printf not a and o or)/' \ 122 | 'n/*/d/' 123 | 124 | # pmake & GNU make 125 | if ( $uname == FreeBSD ) then 126 | set backslash_quote 127 | complete gmake 'n@*@`make -qp | awk -F: \'/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ { split($1,A,/ /); for(i in A)print A[i] }\' | sort -u`@' 128 | unset backslash_quote 129 | 130 | if ( `uname -r | cut -d. -f1` < 10 ) then 131 | complete make 'n@*@`make -pn | sed -n -E "/^[#_.\/[:blank:]]+/d; /=/d; s/[[:blank:]]*:.*//gp;"`@' 132 | else 133 | complete make 'n/*/`make -V .ALLTARGETS`/' 134 | endif 135 | else if ( $uname == Linux ) then 136 | set backslash_quote 137 | complete make 'n@*@`make -qp | awk -F: \'/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ { split($1,A,/ /); for(i in A)print A[i] }\' | sort -u`@' 138 | unset backslash_quote 139 | endif 140 | 141 | complete dd 'c/if=/f/' 'c/of=/f/' \ 142 | 'c/conv=*,/(ascii block ebcdic lcase pareven noerror notrunc osync sparse swab sync unblock)/,' \ 143 | 'c/conv=/(ascii block ebcdic lcase pareven noerror notrunc osync sparse swab sync unblock)/,' \ 144 | 'p/*/(bs cbs count files fillcahr ibs if iseek obs of oseek seek skip conv)/=' 145 | 146 | # FreeBSD-specific stuff 147 | if ($uname == FreeBSD) then 148 | complete service 'p/1/`service -l`/' 'n/*/(start stop reload restart status rcvar onestart onestop)/' 149 | complete ifconfig 'p/1/`ifconfig -l`/' 150 | complete sysctl 'n/*/`sysctl -Na`/' 151 | 152 | complete pkg_delete 'n@*@`/bin/ls /var/db/pkg`@' 153 | complete pkg_info 'n@*@`/bin/ls /var/db/pkg`@' 154 | complete kldload 'n@*@`/bin/ls -1 /boot/modules/ /boot/kernel/ | grep -v symbols | sed "s|\.ko||g"`@' 155 | complete kldunload 'n@*@`kldstat | awk \{sub\(\/\.ko\/,\"\",\$NF\)\;print\ \$NF\} | grep -v Name`@' 156 | complete netstat 'n/-I/`ifconfig -l`/' 'n/*/(start stop restart reload status)/' 157 | # Linux 158 | else if ($uname == Linux) then 159 | complete service 'p@1@`/bin/ls /etc/init.d`@' 160 | complete ifconfig 'p/1/`ifconfig -a -s | sed 1d | cut -d" " -f1`/' 161 | complete sysctl 'n/*/`sysctl -N -a`/' 162 | 163 | complete chkconfig 'c/--/(list add del)/' 'n@*@`/bin/ls /etc/init.d`@' 164 | 165 | complete systemctl 'p@*@`systemctl list-units --all -t service,timer,socket,mount,automount,path,snapshot,swap --no-legend | cut -d\ -f1`@' 166 | endif 167 | 168 | unset noglob 169 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/cwdcmd.tcsh: -------------------------------------------------------------------------------- 1 | # vim:set syntax=tcsh 2 | 3 | # Show the directory in the xterm title 4 | echo -n "\033]2;tcsh: $cwd\007" 5 | 6 | # Setup GOPATH 7 | #setenv GOPATH 8 | 9 | # Show git branch in prompt 10 | unset printexitvalue 11 | git rev-parse --abbrev-ref HEAD >& /dev/null 12 | if ( $? == 0 ) then 13 | set branch = "`git rev-parse --abbrev-ref HEAD`" 14 | # We're not in a repo 15 | else 16 | unset branch 17 | endif 18 | set printexitvalue 19 | 20 | # Set prompt 21 | set promptchars = "%#" 22 | set prompt = "[%~]" 23 | if ( $?branch ) then 24 | set prompt = "$prompt($branch)" 25 | endif 26 | set prompt = "$prompt%# " 27 | 28 | # Blue prompt if we're in a sandbox 29 | #if ( ${?SANDBOX} == 1 ) then 30 | # set blue = "%{\033[34m%}" 31 | # set end = "%{\033[0m%}" 32 | # set prompt = "[%~]${blue}%#${end} " 33 | #endif 34 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/env.tcsh: -------------------------------------------------------------------------------- 1 | # Setup PATH 2 | if ($uname != win32) then 3 | setenv PATH ~/Local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games 4 | 5 | if (-d /usr/local/bin && $prefix != "/usr/local") then 6 | setenv PATH ${PATH}:/usr/local/bin:/usr/local/sbin 7 | endif 8 | if ($prefix != 0) setenv PATH ${PATH}:${prefix}/bin:${prefix}/sbin 9 | if (-d /usr/X11R6/bin) setenv PATH ${PATH}:/usr/X11R6/bin:/usr/X11R6/sbin 10 | endif 11 | 12 | # Some commonly installed packages on OpenSolaris 13 | if ($uname == SunOS) setenv PATH ${PATH}:/opt/VirtualBox:/opt/csw/gcc4/bin 14 | 15 | # Only use the newest Ruby 16 | if ( -d "$HOME/.gem/ruby/2.3.0/bin" ) then 17 | setenv PATH "${PATH}:$HOME/.gem/ruby/2.3.0/bin/" 18 | else if ( -d "$HOME/.gem/ruby/2.2.0/bin" ) then 19 | setenv PATH "${PATH}:$HOME/.gem/ruby/2.2.0/bin/" 20 | else if ( -d "$HOME/.gem/ruby/2.1.0/bin" ) then 21 | setenv PATH "${PATH}:$HOME/.gem/ruby/2.1.0/bin/" 22 | endif 23 | 24 | # Setup Go 25 | setenv GOPATH ~/gocode 26 | #setenv GOPATH ~/code/TeamworkDesk 27 | #setenv GOPATH ~/gocode:/home/martin/code/TeamworkDesk 28 | if ( -d "$HOME/gocode/bin" ) setenv PATH "${PATH}:$HOME/gocode/bin" 29 | 30 | # Various applications settings 31 | setenv BLOCKSIZE K 32 | setenv PAGER less 33 | setenv LESS "--ignore-case --LONG-PROMPT --SILENT --no-init --no-lessopen" 34 | 35 | # Make man pages 80 characters wide at the most; this is the default on BSD, but 36 | # not Linux 37 | setenv MANWIDTH 80 38 | 39 | # Colors for ls(1) 40 | setenv LS_COLORS "no=00:fi=00:di=34:ln=01;31:pi=34;43:so=31;43:bd=30;43:cd=30;43:or=01;35:ex=31:" 41 | 42 | # Older GNU grep; BSD grep 43 | setenv GREP_COLOR 31 44 | 45 | # Newer GNU grep, I guess GREP_COLOR was too easy to use 46 | setenv GREP_COLORS "ms=31:mc=31:sl=0:cx=0:fn=0:ln=0:bn=0:se=0" 47 | 48 | # Fix scrolling in GTK3; https://www.pekwm.org/projects/pekwm/tasks/350 49 | setenv GDK_CORE_DEVICE_EVENTS 1 50 | 51 | # Make compose key work for GTK, Qt 52 | setenv GTK_IM_MODULE xim 53 | setenv QT_IM_MODULE xim 54 | 55 | # Disable retarded "overlay scrollbar" 56 | setenv GTK_OVERLAY_SCROLLING 0 57 | 58 | # Don't output to a pager 59 | setenv SYSTEMD_PAGER 60 | 61 | # /var/ is a memory device on my laptop 62 | if ($uname == FreeBSD && -d /pkgdb) setenv PKG_DBDIR /pkgdb/ 63 | 64 | if ($uname == OpenBSD) then 65 | setenv PKG_PATH "ftp://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/" 66 | setenv CVSROOT "anoncvs@anoncvs.fr.openbsd.org:/cvs" 67 | endif 68 | 69 | # Do the $TERM dance; these options seem to work best on various systems... 70 | if (($?TMUX)) then 71 | setenv TERM screen-256color 72 | else if ($uname == OpenBSD) then 73 | setenv TERM xterm-xfree86 74 | else if ($uname == FreeBSD) then 75 | if ($tty =~ ttyv*) then 76 | setenv TERM cons25 77 | else 78 | setenv TERM xterm-256color 79 | endif 80 | else if ($uname == Linux) then 81 | setenv TERM xterm-256color 82 | #setenv TERM xterm-color 83 | else 84 | setenv TERM vt220 85 | endif 86 | 87 | # UTF-8 88 | if (-X locale) then 89 | setenv LANG en_US.UTF-8 90 | setenv LC_CTYPE en_US.UTF-8 91 | setenv LC_COLLATE en_US.UTF-8 92 | 93 | #setenv I18NPATH ~/.locale 94 | #setenv LOCPATH ~/.locale 95 | endif 96 | 97 | # Set editor 98 | if (-X vim) then 99 | setenv EDITOR vim 100 | # TODO: What if vim has no +clientserver? 101 | #alias vim "vim -p --servername vim" 102 | alias vim "vim -p" 103 | alias vi "vim" 104 | else if (-X vi) then 105 | setenv EDITOR vi 106 | endif 107 | 108 | if (-X chromium) setenv BROWSER chromium 109 | 110 | # Set DISPLAY on remote login 111 | if ($?REMOTEHOST && ! $?DISPLAY) then 112 | setenv DISPLAY ${REMOTEHOST}:0 113 | endif 114 | 115 | # Run commands from this file; only run for interactive prompt 116 | if (-f "$HOME/Local/python-startup") setenv PYTHONSTARTUP ~/Local/python-startup 117 | 118 | # This makes font looks non-ugly in Java applications 119 | setenv _JAVA_OPTIONS "-Dswing.aatext=true -Dawt.useSystemAAFontSettings=on -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel" 120 | 121 | # Stupid Android Sdk tricks 122 | #setenv ANDROID_HOME /home/martin/milo/android-sdk-linux 123 | #setenv PATH "${PATH}:/home/martin/milo/android-sdk-linux/tools:/home/martin/milo/android-sdk-linux/platform-tools" 124 | 125 | foreach f ( /etc/profile.d/*.csh ) 126 | if ( -r $f ) source $f 127 | end 128 | unset f 129 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/keybinds.tcsh: -------------------------------------------------------------------------------- 1 | # F1 2 | bindkey ^[[M run-help 3 | bindkey ^[OP run-help 4 | bindkey ^[[11~ run-help # Putty 5 | 6 | # Delete 7 | bindkey ^[[3~ delete-char 8 | 9 | # Home 10 | bindkey ^[[H beginning-of-line 11 | bindkey ^[[1~ beginning-of-line 12 | 13 | # End 14 | bindkey ^[[F end-of-line 15 | bindkey ^[[4~ end-of-line 16 | 17 | # Arrow keys 18 | bindkey -k up history-search-backward 19 | bindkey -k down history-search-forward 20 | 21 | # Page Up, Page Down 22 | bindkey "^[[5~" undefined-key 23 | bindkey "^[[6~" undefined-key 24 | 25 | # Insert 26 | bindkey ^[[L yank 27 | bindkey ^[[2 yank 28 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/settings.tcsh: -------------------------------------------------------------------------------- 1 | # Basic corrections when completing 2 | set autocorrect 3 | 4 | # Show options when autocompleting 5 | set autolist 6 | 7 | # Use history to aid expansion 8 | set autoexpand 9 | 10 | # Never autologout 11 | set autologout 12 | 13 | # Makes tab-completion: 14 | # - ignore case, unless a capital is types 15 | # - difference between hyphen and underscore 16 | set complete=Enhance 17 | 18 | # Colorize ls-F 19 | set color 20 | 21 | # set -n and set '\003' will both work 22 | set echo_style=both 23 | 24 | # file completion 25 | set filec 26 | 27 | # Keep n items in history 28 | set history = 8192 29 | 30 | # Logout on ^D 31 | unset ignoreeof 32 | 33 | # Show '>' for symlink to dir, and '&' for symlink to nowhere 34 | set listlinks 35 | 36 | # List all jobs after ^Z 37 | set listjobs 38 | 39 | # Show current dir 40 | set prompt = "[%~]%# " 41 | 42 | # Use % for normal user and # for super 43 | set promptchars = "%#" 44 | 45 | # Show date & hostname on right side 46 | set rprompt = "%B%U%m%b%u:%T" 47 | 48 | # Never print "DING!" as the time 49 | set noding 50 | 51 | # Don't beep 52 | set nobeep 53 | 54 | # Ask before doing > redirection on non-empty existing files 55 | set noclobber = (notempty ask) 56 | 57 | # Print exit value if >0 58 | set printexitvalue 59 | 60 | # Ask for confirmation if we do rm * 61 | set rmstar 62 | 63 | # Save history 64 | set savehist = 8192 merge 65 | 66 | # Save history here 67 | set histfile=~/.tcsh/history 68 | 69 | # Lists file name suffixes to be ignored by completion 70 | set fignore = (.pyc) 71 | 72 | # Allow ** for recursive glob 73 | set globstar 74 | 75 | # No need for rehash 76 | set autorehash 77 | 78 | # Don't go to homedir when we use cd without arguments 79 | set noimplicithome 80 | 81 | # Set the histchars to empty (default: !^), since I never use this feature, and 82 | # it's only annoying (since the ! has special escaping needs) 83 | set histchars 84 | -------------------------------------------------------------------------------- /_old/tcsh/tcsh/tcshrc: -------------------------------------------------------------------------------- 1 | # vim:syntax=tcsh 2 | # 3 | # tcsh configuration 4 | # Martin Tournoij 5 | # Should work on: FreeBSD, OpenBSD, Linux (CentOS, Ubuntu, Arch), OpenSolaris, Windows 7 6 | # 7 | 8 | # NetBSD 9 | if (-d /usr/pkg/bin) then 10 | set prefix = /usr/pkg 11 | # OpenSolaris 12 | else if (-d /opt/csw/bin) then 13 | set prefix = /opt/csw 14 | # FreeBSD, OpenBSD 15 | else if (-d /usr/local/bin) then 16 | set prefix = /usr/local 17 | else 18 | set prefix = 0 19 | endif 20 | 21 | if (-X uname) then 22 | set uname = `uname` 23 | # uname part of msysgit 24 | if ($uname == MINGW32_NT-6.1) set uname = win32 25 | else 26 | set uname = win32 27 | endif 28 | 29 | umask 022 30 | 31 | source ~/.tcsh/env.tcsh 32 | source ~/.tcsh/aliases.tcsh 33 | 34 | # Only load these for interactive shells 35 | if ($?prompt) then 36 | # Disable ^S/^Q - I never use them and I can use those keys in Vim now 37 | stty -ixon 38 | 39 | source ~/.tcsh/settings.tcsh 40 | source ~/.tcsh/keybinds.tcsh 41 | source ~/.tcsh/completions.tcsh 42 | 43 | # We're ssh-ing into vagrant 44 | if (-d /vagrant) then 45 | cd /vagrant 46 | setenv TERM xterm 47 | # Don't logout too easily 48 | bindkey -r ^D 49 | endif 50 | endif 51 | -------------------------------------------------------------------------------- /_old/x11/Xdefaults: -------------------------------------------------------------------------------- 1 | ! Hide pointer when typing. 2 | XTerm*pointerMode: 2 3 | 4 | ! Lines of scrollback. 5 | XTerm*saveLines: 4096 6 | 7 | ! Run as login shell. 8 | !XTerm*loginShell: True 9 | 10 | ! No scollbar 11 | XTerm*scrollBar: False 12 | 13 | ! Use UTF-8 14 | XTerm*locale: UTF-8 15 | 16 | ! Nice font 17 | XTerm*faceName: DejaVu Sans Mono 18 | !XTerm*faceName: Go Mono 19 | XTerm*faceSize: 12 20 | XTerm*faceSize1: 12 21 | XTerm*faceSize2: 12 22 | XTerm*faceSize3: 12 23 | 24 | ! Medium 25 | XTerm*faceSize4: 14 26 | ! Large 27 | XTerm*faceSize5: 16 28 | ! Huge 29 | XTerm*faceSize6: 18 30 | 31 | ! Do not clear terminals after {man,vim,etc.} 32 | XTerm*titeInhibit: true 33 | 34 | ! Triple-clicking a line does *not* copy the newline 35 | XTerm*cutNewline: off 36 | 37 | ! + key also works (and not just key) 38 | XTerm*metaSendsEscape: true 39 | 40 | ! https://lukas.zapletalovi.com/2013/07/hidden-gems-of-xterm.html 41 | ! XTerm*on3Clicks: regex ([[:alpha:]]+://)?([[:alnum:]!#+,./=?@_~-]|(%[[:xdigit:]][[:xdigit:]]))+ 42 | ! XTerm*translations: #override Shift : exec-formatted("chromium '%t'", PRIMARY) 43 | 44 | ! TODO: Messes up backgrounds... But the problem is that braindead applications 45 | ! set color7 as the foreground, which is nigh-unreadable with a white bg. 46 | ! However, this will do the reverse: make black on color7 unreadable :-/ 47 | ! XTerm*color7: gray20 48 | ! XTerm*color8: gray40 49 | 50 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 51 | 52 | ! rxvt-unicode 53 | 54 | ! Hide pointer when typing. 55 | urxvt*pointerBlank: true 56 | 57 | ! Lines of scrollback. 58 | urxvt*saveLines: 4096 59 | 60 | ! Run as login shell. 61 | !urxvt*loginShell: True 62 | 63 | ! No scollbar 64 | urxvt*scrollBar: False 65 | 66 | ! Nice font 67 | urxvt*font: xft:DejaVu Sans Mono:pixelsize=16 68 | 69 | ! Do not clear terminals after {man,vim,etc.} 70 | urxvt*secondaryScreen: false 71 | -------------------------------------------------------------------------------- /bash/bashrc: -------------------------------------------------------------------------------- 1 | # Don't do anything if not running interactively 2 | [[ $- != *i* ]] && return 3 | 4 | # Just the cwd in the prompt 5 | export PS1="[\w]$ " 6 | 7 | # Sane colours and not retarded x-mas tree syndrome 8 | export LS_COLORS="no=00:fi=00:di=34:ln=01;31:pi=34;43:so=31;43:bd=30;43:cd=30;43:or=01;35:ex=31:" 9 | 10 | # Use vi/vim 11 | export EDITOR=vi 12 | if [ -x vim ]; then 13 | export EDITOR=vim 14 | alias vim='vim -p' 15 | alias vi=vim 16 | fi 17 | 18 | # Aliases 19 | alias ls='ls -NF --color' 20 | alias l='ls' 21 | alias la='ls -a' 22 | alias lc='ls -lh' 23 | alias lac='ls -alh' 24 | -------------------------------------------------------------------------------- /bash/inputrc: -------------------------------------------------------------------------------- 1 | # Complete on 1 tab 2 | set show-all-if-ambiguous on 3 | 4 | # Don't use pager 5 | set page-completions off 6 | 7 | # Don't match hidden files 8 | set match-hidden-files off 9 | 10 | # Never bug me for confirmation 11 | set completion-query-items 999999 12 | 13 | # Color completions as ls 14 | set colored-stats on 15 | 16 | # Fixes some problems with DEL key and such (see st FAQ) 17 | set enable-keypad off 18 | 19 | # Up/down arrows 20 | "\e[A": history-search-backward 21 | "\e[B": history-search-forward 22 | 23 | # C-o is C-p 24 | C-O: history-search-backward 25 | 26 | # Make C-w actually kill a "word", rather than until the previous whitespace. 27 | # NOTE: needs "stty werase undef", otherwise readline will say "fuck you and 28 | # your keybinding I will silently ignore them and do whatever made sense 29 | # in 1987 hahah lol kthxfuckyoubye". 30 | # TODO: ideally I'd also like to add - and _ to the word characters, like in 31 | # zsh, but I don't know if that's possible; probably too modern of a 32 | # thing for the GNU folks. 33 | C-w: backward-kill-word 34 | 35 | # Home 36 | "\e[H": beginning-of-line 37 | "\e[1~": beginning-of-line 38 | 39 | # End 40 | "\e[F": end-of-line 41 | "\e[4~": end-of-line 42 | 43 | # Unbind Page Up, Page Down 44 | "\e[5~": 45 | "\e[6~": 46 | -------------------------------------------------------------------------------- /bash/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.bashrc': 'bashrc', 3 | '~/.config/inputrc': 'inputrc' 4 | } 5 | -------------------------------------------------------------------------------- /diffexpr.vim: -------------------------------------------------------------------------------- 1 | fun DotDiff() 2 | silent execute "!diff --text --binary " 3 | \ . "-I '\\$dotignore\\$' -I '\\$dotid' " 4 | \ . v:fname_in . " " . v:fname_new . " > " . v:fname_out 5 | endfun 6 | set diffexpr=DotDiff() 7 | 8 | nnoremap dr 1GV0Gy1GV0Gp:wqa 9 | -------------------------------------------------------------------------------- /doas/doas.conf: -------------------------------------------------------------------------------- 1 | permit setenv { -ENV PS1=$DOAS_PS1 SSH_AUTH_SOCK } :wheel 2 | permit nopass root 3 | -------------------------------------------------------------------------------- /doas/module.py: -------------------------------------------------------------------------------- 1 | requires_root = True 2 | 3 | dirs = { 4 | '.': '/etc', 5 | } 6 | -------------------------------------------------------------------------------- /git/config: -------------------------------------------------------------------------------- 1 | # /usr/share/doc/git-jump/README 2 | 3 | 4 | ### General settings 5 | #################### 6 | 7 | [user] 8 | name = Martin Tournoij 9 | email = martin@arp242.net 10 | signingKey = ~/.ssh/id_ed25519 11 | 12 | [include] 13 | path = ~/code/Misc/git-color-schemes/light-minimal 14 | 15 | [init] 16 | defaultBranch = master # Just keep the master branch for now. 17 | 18 | [gpg] 19 | format = ssh # Sign with SSH key. 20 | [gpg.ssh] 21 | allowedSignersFile = "~/.config/git/keys" 22 | 23 | [core] 24 | eol = lf # Always use \n, even on Windows. 25 | pager = less -F # Quit pager if the contents can fit on the screen. 26 | commentChar = "!" # "#" conflicts with Markdown headers, Github #123 issues 27 | 28 | [http] # Send cookes (e.g. to signal Google SLA signage). 29 | cookiefile = ~/.config/git/cookies 30 | 31 | [url "git@github.com:"] # Prefer git protocol over http for GitHub. 32 | insteadOf = https://github.com/ 33 | [url "git@gitlab.com:"] 34 | insteadOf = https://gitlab.com/ 35 | 36 | [pretty] 37 | #myname=fmt 38 | # Alias for a --pretty= format string, as specified in git-log(1). 39 | # Any aliases defined here can be used just as the built-in pretty 40 | # formats could. For example, running git config pretty.changelog 41 | # "format:* %H %s" would cause the invocation git log 42 | # --pretty=changelog to be equivalent to running git log 43 | # "--pretty=format:* %H %s". Note that an alias with the same name as 44 | # a built-in format will be silently ignored. 45 | 46 | 47 | #### Command settings 48 | ##################### 49 | [commit] 50 | gpgsign = true # Sign commits. 51 | 52 | [diff] 53 | algorithm = histogram # Better quality diffs (but slower). 54 | noprefix = true # Don't show prefixes in file paths. 55 | colorMoved = plain # Highlight chunks of text that moved unchanged different. 56 | colorMovedWS = no # Got bad results with ignoring whitespace. 57 | 58 | [fetch] 59 | prune = true # Automatically remove remote tracking that no longer exists. 60 | pruneTags = true 61 | 62 | [grep] 63 | lineNumber = true # Add line and column number. 64 | column = true 65 | 66 | [help] 67 | autoCorrect = 10 # Run guessed command after 1s if there's only one guess result. 68 | 69 | [log] 70 | abbrevCommit = true # Short commits hashes. 71 | follow = true # Include commits from before renames. 72 | 73 | [merge] 74 | #ff = false # Disable fast-forward merges. 75 | stat = false # Don't print diffstat after merge. 76 | verbosity = 1 # Only show conflicts. 77 | 78 | [pull] 79 | #rebase=false 80 | ff = only # fast-forward instead of merge commits. 81 | 82 | [push] 83 | default = current # Update a branch with the same name on the receiving end. 84 | followTags = true # Automatically push annotated tags. 85 | 86 | [rebase] 87 | missingCommitsCheck = error # Don't drop removed lines in rebase -i; need explicit drop. 88 | 89 | [status] 90 | short = true # Always use short CVS-ish output. 91 | branch = true # Show branch on status. 92 | showUntrackedFiles = all # Show untracked files in untracked dirs too. 93 | 94 | [stash] 95 | showPatch = true # Show patch in git stash show. 96 | 97 | ### Aliases 98 | ########### 99 | 100 | [alias] 101 | st = status # Simple shortcuts. 102 | co = checkout 103 | ci = commit 104 | diffh = diff HEAD 105 | undolast = reset HEAD~ # Undo last commit. 106 | sl = show HEAD # Show last commit. 107 | 108 | # Use draft message for commit. 109 | draft = !git commit --edit -F $(git rev-parse --git-dir)/draft 110 | 111 | # Reuse last commit message. 112 | # TODO: --cleanup to remove # lines? 113 | lastci = !git commit --edit -F $(git rev-parse --git-dir)/COMMIT_EDITMSG 114 | 115 | # Edit git-status files in git. 116 | edit = !vim -p $(git diff --name-only) 117 | 118 | # Show nice overview of tags and branches sorted by date. 119 | t = tag --sort=creatordate --format \ 120 | '%(creatordate:short) %(HEAD)%(align:width=20)%(refname:short)%(end) → %(upstream:track)%(subject)' 121 | b = branch --sort=creatordate --format \ 122 | '%(creatordate:short) %(HEAD)%(align:width=20)%(refname:short)%(end) → %(upstream:track)%(subject)' 123 | 124 | # Like --oneline, but with date. 125 | # TODO: add some colours 126 | l = log --format=format:'%cs %h %s%d' 127 | 128 | # Just merge files with regular Vim; I don't like using vimdiff. 129 | mergeit = ![ -z "$(git diff --diff-filter=U)" ] \ 130 | && echo "No unmerged files" \ 131 | || vim \ 132 | +'/^\\(<<<<<<<\\|=======\\|>>>>>>>\\)' \ 133 | +':silent tabdo :1 | normal! n' \ 134 | +':tabfirst' \ 135 | -p $(git diff --name-only --diff-filter=U) 136 | 137 | # Figure out who works on this. 138 | authors = !git log --format='%an <%ae>' | sort | uniq -c | sort -rn 139 | -------------------------------------------------------------------------------- /git/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | './config': '~/.config/git/config', 3 | } 4 | -------------------------------------------------------------------------------- /htop/htoprc: -------------------------------------------------------------------------------- 1 | # Beware! This file is rewritten by htop when settings are changed in the interface. 2 | # The parser is also very primitive, and not human-friendly. 3 | htop_version=3.2.1 4 | config_reader_min_version=3 5 | fields=0 48 17 2 18 38 39 40 119 2 46 47 49 1 6 | hide_kernel_threads=1 7 | hide_userland_threads=1 8 | shadow_other_users=0 9 | show_thread_names=0 10 | show_program_path=0 11 | highlight_base_name=1 12 | highlight_deleted_exe=1 13 | highlight_megabytes=1 14 | highlight_threads=0 15 | highlight_changes=0 16 | highlight_changes_delay_secs=5 17 | find_comm_in_cmdline=1 18 | strip_exe_from_cmdline=1 19 | show_merged_command=0 20 | header_margin=0 21 | screen_tabs=0 22 | detailed_cpu_time=0 23 | cpu_count_from_one=0 24 | show_cpu_usage=1 25 | show_cpu_frequency=1 26 | show_cpu_temperature=1 27 | degree_fahrenheit=0 28 | update_process_names=0 29 | account_guest_in_cpu_meter=0 30 | color_scheme=1 31 | enable_mouse=0 32 | delay=20 33 | hide_function_bar=2 34 | header_layout=two_50_50 35 | column_meters_0=AllCPUs Memory Swap 36 | column_meter_modes_0=1 1 1 37 | column_meters_1=Tasks LoadAverage Uptime DiskIO NetworkIO 38 | column_meter_modes_1=2 2 2 1 1 39 | tree_view=0 40 | sort_key=47 41 | tree_sort_key=0 42 | sort_direction=-1 43 | tree_sort_direction=1 44 | tree_view_always_by_pid=0 45 | all_branches_collapsed=0 46 | screen:Main=PID USER PRIORITY STATE NICE M_VIRT M_RESIDENT M_SHARE M_SWAP STATE PERCENT_CPU PERCENT_MEM TIME Command 47 | .sort_key=PERCENT_MEM 48 | .tree_sort_key=PID 49 | .tree_view=0 50 | .tree_view_always_by_pid=0 51 | .sort_direction=-1 52 | .tree_sort_direction=1 53 | .all_branches_collapsed=0 54 | screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE Command 55 | .sort_key=IO_RATE 56 | .tree_sort_key=PID 57 | .tree_view=0 58 | .tree_view_always_by_pid=0 59 | .sort_direction=-1 60 | .tree_sort_direction=1 61 | .all_branches_collapsed=0 62 | -------------------------------------------------------------------------------- /htop/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/htop/htoprc': 'htoprc', 3 | } 4 | -------------------------------------------------------------------------------- /less/less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arp242/dotfiles/9ade6749548e9c16e5ede1c176e58c33f4e2371f/less/less -------------------------------------------------------------------------------- /less/lesskey: -------------------------------------------------------------------------------- 1 | #command 2 | / forw-search ^R 3 | -------------------------------------------------------------------------------- /less/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.config/less': '.', 3 | } 4 | 5 | -------------------------------------------------------------------------------- /local/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.local': '.', 3 | } 4 | 5 | # link: 6 | # tpad.zsh 7 | # ff-hist 8 | 9 | -------------------------------------------------------------------------------- /local/script/bl-connect: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Connect to paired bluetooth devices. 4 | # 5 | # Just bl-connect will ask for a device to connect to; use 'bl-connect $dev' (as 6 | # number or name) to connect to that device without asking. 7 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 8 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 9 | setopt err_exit no_unset no_clobber pipefail 10 | 11 | connect() { 12 | local mac=$(cut -d ' ' -f2 <<<$argv[1]) 13 | 14 | # Otherwise audio devices can't connect; usually started on the first audio 15 | # application, but this may not have happened yet. 16 | pulseaudio --start 17 | 18 | bluetoothctl <<<'power on' 19 | bluetoothctl <<<"connect $mac" 20 | } 21 | 22 | IFS=$'\n' devs=($(<< 9 | # 10 | # The first argument is processed with printf; so "\n" (or \t, etc.) will work. 11 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 12 | 13 | list=$1; shift 14 | exec $(printf "$list" | dmenu -i "$@") & 15 | -------------------------------------------------------------------------------- /local/script/dmenu-uni: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # List emojis in dmenu. 4 | # 5 | # Requires xclip and the "uni" tool from https://github.com/arp242/uni 6 | # 7 | # Usage: 8 | # 9 | # dmenu-uni all All codepoints, won't include ZWJ emoji sequences. 10 | # dmenu-uni emoji All emojis. 11 | # dmenu-uni emoji-common Common emojis 12 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 13 | set -euC 14 | 15 | dmenu="dmenu -x -i -l 20 -fn monospace:size=20 -sb #dddddd -sf #000000" 16 | copy="xclip -rmlastnl -selection clipboard" 17 | common="-or g:smileys g:hand-fingers-open g:hand-fingers-partial g:hand-single-finger g:hand-fingers-closed g:hands g:body-parts g:person-gesture" 18 | 19 | case "${1:-all}" in 20 | all) uni -q p all | $dmenu | grep -o "^'.'" | tr -d "'" | $copy ;; 21 | emoji) uni -q e all | $dmenu | cut -d ' ' -f1 | $copy ;; 22 | emoji-common) uni -q e $common | $dmenu | cut -d ' ' -f1 | $copy ;; 23 | *) uni -q e $@ | $dmenu | cut -d ' ' -f1 | $copy ;; 24 | #*) echo >&2 "dmenu-uni: unknown '$1'" ;; 25 | esac 26 | -------------------------------------------------------------------------------- /local/script/flac2v0: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Convert all FLAC files in a directory to MP3 V0. 4 | # 5 | # Requires the "flac" and "lame" tools; MP3 files will be placed in a mp3 6 | # subdirectory. Usage: 7 | # 8 | # flac2v0 [flac-dir] [flac-dir] 9 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 10 | setopt err_exit no_unset no_clobber pipefail 11 | 12 | _tag() { 13 | metaflac "$1" --show-tag="$2" | cut -d= -f2- 14 | } 15 | 16 | if [[ -z $1 ]]; then 17 | print >&2 'flac2v0: need directory; use -h for help.' 18 | exit 2 19 | fi 20 | 21 | for flacdir in $@; do 22 | outdir="$flacdir/mp3" 23 | mkdir -p "$outdir" 24 | 25 | for f in $flacdir/*.flac; do 26 | [[ ! -e $f ]] && continue 27 | 28 | basename "$f" 29 | flac -dcs "$f" | 30 | lame --quiet --vbr-new -V0 --replaygain-accurate --id3v2-only \ 31 | --tt "$(_tag "$f" TITLE)" \ 32 | --tn "$(_tag "$f" TRACKNUMBER)" \ 33 | --tg "$(_tag "$f" GENRE)" \ 34 | --ty "$(_tag "$f" DATE)" \ 35 | --ta "$(_tag "$f" ARTIST)" \ 36 | --tl "$(_tag "$f" ALBUM)" \ 37 | - "$outdir/$(basename "${f%.flac}").mp3" 38 | done 39 | 40 | # Copy additional files 41 | for f in "$flacdir"/*~*.flac; cp "$f" "$outdir" 42 | done 43 | -------------------------------------------------------------------------------- /local/script/game: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Disable xbanish and xcape while a command is running. 4 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 5 | set -euC 6 | 7 | trap 'sv start ~/.config/service/xcape ~/.config/service/xbanish' EXIT 8 | sv stop ~/.config/service/xcape ~/.config/service/xbanish 9 | "$@" 10 | -------------------------------------------------------------------------------- /local/script/git: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # 3 | # Frob with git to rewrite "main" to "master" and vice versa. 4 | # 5 | # The "real" git is assumed to be in /usr/bin/git. 6 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 7 | setopt err_exit no_unset no_clobber pipefail 8 | 9 | def=${$(/usr/bin/git symbolic-ref refs/remotes/origin/HEAD >&/dev/null ||:):t} 10 | if [[ $def = 'master' && $argv[(i)main] -le $#argv ]] then 11 | print >&2 "Using 'main' instead of 'master'" 12 | argv[$argv[(i)main]]=master 13 | elif [[ $def = 'main' && $argv[(i)master] -le $#argv ]] then 14 | print >&2 "Using 'master' instead of 'main'" 15 | argv[$argv[(i)master]]=main 16 | fi 17 | 18 | exec /usr/bin/git $argv 19 | -------------------------------------------------------------------------------- /local/script/git-prunebranches: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Remove local branches that no longer exist on remote. 4 | # 5 | # https://www.reddit.com/r/commandline/comments/blcttq/i_got_tired_of_manually_cleaning_up_stale_local/ 6 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 7 | set -euC 8 | 9 | git fetch origin --prune 10 | git branch --merged master | grep -v 'master$' | xargs git branch -d 11 | -------------------------------------------------------------------------------- /local/script/git-undolast: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Undo the last git commit. 4 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 5 | set -euC 6 | 7 | git reset HEAD~ 8 | -------------------------------------------------------------------------------- /local/script/go: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # 3 | # Frob a bit with the "go" command to work around some issues. 4 | # 5 | # - Use module name instead of "cmd" for "go install ./cmd" 6 | # - "go help" will highlight flags as bold and pipes to $PAGER 7 | # - Having -h, -help, or --help in any position will run "go help $cmd". 8 | # 9 | # The "real" go is assumed to be in /usr/bin/go. 10 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 11 | setopt err_exit no_unset no_clobber pipefail 12 | 13 | # Special case for projects that have the main package in ./cmd rather than 14 | # ./cmd/dir; go install compiles that to $GOBIN/cmd, which isn't very useful. 15 | # Frob so that it installs as $GOBIN/$module instead. 16 | if [[ ${1:-} = 'install' && $argv[-1]:t = 'cmd' ]]; then 17 | argv=(build -o $(go env GOBIN)/${$(go list -m):t} $argv[2,-1]) 18 | [[ -z ${VIM:-} ]] && print >&2 "rewrite: go $argv" # Bit annoying when using :make 19 | fi 20 | 21 | # Always show help for command if -h, -help, or --help is in the command line at 22 | # any position. 23 | if (( $argv[(i)-h] <= $#argv || $argv[(i)-help] <= $#argv || $argv[(i)--help] <= $#argv )); then 24 | for p in $argv; do 25 | if [[ $p[1] != '-' ]]; then 26 | argv=(help $p) 27 | break 28 | fi 29 | done 30 | fi 31 | 32 | # Automatically pipe go test -bench output for nicer alignment and numbers. 33 | # if (( $argv[(i)-bench] <= $#argv && $+commands[gobench.awk] )); then 34 | # exec /usr/bin/go $argv | gobench.awk 35 | # fi 36 | 37 | # Show flags as bold in go help, and pipe to $PAGER. 38 | if [[ ${1:-} = 'help' ]]; then 39 | /usr/bin/go $argv | sed -E 's/(^|\s)-[a-z0-9=]+/\x1b[1m\0\x1b[0m/g' |& $PAGER 40 | exit $? 41 | fi 42 | 43 | exec /usr/bin/go $argv 44 | -------------------------------------------------------------------------------- /local/script/gorun: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run Go "scripts", with cache. 4 | # 5 | # "go run" will compile things on every invocation, which is kinda slow. This 6 | # will cache the results in GOPATH: 7 | # 8 | # % time ./jsonfmt <<<{} 9 | # ./jsonfmt <<< {} 0.21s user 0.07s system 122% cpu 0.291 total 10 | # 11 | # % time ./jsonfmt <<<{} 12 | # ./jsonfmt <<< {} 0.00s user 0.01s system 93% cpu 0.016 total 13 | # 14 | # To use it, set the hashbang as: 15 | # 16 | # #!/usr/bin/env gorun 17 | # 18 | # Unfortunately, this isn't valid Go syntax; on Linux at least you can also use: 19 | # 20 | # ///usr/bin/true; exec /usr/bin/env gorun "$0" "$@" 21 | # 22 | # TODO: automatically print help of the program similar to: 23 | # echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } 24 | 25 | name="$(basename "$1")" 26 | sum="$(sha256sum <"$1")" 27 | cache="$(go env GOPATH)/gorun/$name/$name" 28 | 29 | mkdir -p "$(dirname "$cache")" 30 | 31 | if [ "$sum" != "$(cat "$cache.sum" 2>/dev/null)" ]; then 32 | tail -n+2 "$1" >"$cache.go" 33 | go build -o "$cache" "$cache.go" || exit $? 34 | echo "$sum" >$cache.sum 35 | fi 36 | 37 | shift 38 | exec "$cache" "$@" 39 | -------------------------------------------------------------------------------- /local/script/jsonfmt: -------------------------------------------------------------------------------- 1 | ///usr/bin/true; exec /usr/bin/env gorun "$0" "$@" 2 | // 3 | // Format JSON. 4 | 5 | package main 6 | 7 | import ( 8 | "encoding/json" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "os" 13 | "regexp" 14 | ) 15 | 16 | func main() { 17 | if err := main2(); err != nil { 18 | fmt.Fprintln(os.Stderr, "jsonfmt:", err) 19 | os.Exit(1) 20 | } 21 | } 22 | 23 | func main2() error { 24 | if len(os.Args) == 1 { 25 | return do(os.Stdin, os.Stdout) 26 | } 27 | 28 | wFlag := false 29 | for i := range os.Args { 30 | if os.Args[i] == "-w" { 31 | wFlag = true 32 | os.Args = append(os.Args[:i], os.Args[i+1:]...) 33 | break 34 | } 35 | } 36 | 37 | for _, f := range os.Args[1:] { 38 | fp, err := os.Open(f) 39 | if err != nil { 40 | return err 41 | } 42 | 43 | out := os.Stdout 44 | if wFlag { 45 | return errors.New("-w not implemented") 46 | } 47 | 48 | err = do(fp, out) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | fp.Close() 54 | } 55 | return nil 56 | } 57 | 58 | var reComma = regexp.MustCompile(`,\s*([}\]])`) 59 | 60 | func do(fp io.Reader, out io.Writer) error { 61 | // Read data and replace trailing commads in maps and arrays first; just 62 | // makes it easier to edit stuff. 63 | data, err := io.ReadAll(fp) 64 | if err != nil { 65 | return nil 66 | } 67 | data = reComma.ReplaceAll(data, []byte("$1")) 68 | 69 | var j interface{} 70 | err = json.Unmarshal(data, &j) 71 | if err != nil { 72 | return err 73 | } 74 | 75 | enc := json.NewEncoder(out) 76 | enc.SetIndent("", " ") 77 | enc.SetEscapeHTML(false) 78 | return enc.Encode(j) 79 | } 80 | -------------------------------------------------------------------------------- /local/script/pa-mv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Move application to different pulseaudio sink. 4 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 5 | set -euC 6 | 7 | # No arguments: list sinks and inputs. 8 | if [ -z "${1:-}" ]; then 9 | pactl list sinks | 10 | grep -E '(^Sink|Description:)' | 11 | cut -d ':' -f2- | 12 | sed 's/^\s\+/ /' | 13 | sed -E 's/#([0-9]+)/\x1b[91;1m\1\x1b[0m/' 14 | echo 15 | 16 | pactl list sink-inputs | 17 | grep -E '(^Sink|application.name =|Sink:)' | 18 | cut -d= -f2 | 19 | sed 's/^\s\+/ /' | 20 | sed -E 's/Sink: ([0-9]+)/Sink: \x1b[91;1m\1\x1b[0m/' 21 | echo 22 | 23 | echo 'Move PulseAudio inputs to a different output ("sink"):' 24 | echo " ${0##*/} [input] to move to the next sink (wraps around)." 25 | echo " ${0##*/} [input] [sink] to move to a specific sink." 26 | # One argument: move input to next sink. 27 | elif [ -z "${2:-}" ]; then 28 | cur="$(pactl list short sink-inputs | grep "^$1" | awk '{print $2}')" 29 | if [ -z "$cur" ]; then 30 | >&2 echo "${0##*/}: no suck input: $1" 31 | exit 1 32 | fi 33 | sinks=$(pactl list short sinks | awk '{print $1}') 34 | 35 | use=0 36 | for s in $sinks; do 37 | [ "$use" -eq 1 ] && exec $0 $1 $s 38 | [ "$s" = "$cur" ] && use=1 39 | done 40 | [ "$use" -eq 1 ] && exec $0 $1 "$(echo "$sinks" | head -n1)" 41 | 42 | >&2 echo "${0##*/}: only one sink?" 43 | exit 1 44 | # Two arguments: move specific input to specific sink. 45 | elif [ -z "${3:-}" ]; then 46 | pactl move-sink-input "$1" "$2" 47 | else 48 | >&2 echo "${0##*/}: that's wrong; try again" 49 | exec $0 50 | fi 51 | -------------------------------------------------------------------------------- /local/script/set-meta: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Set tags for an audio file. 4 | # 5 | # Useful after downloading video/albums from YouTube to copy to phone etc. 6 | # 7 | # Usage: 8 | # 9 | # set-meta mediafile artist-name album-name 10 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 11 | set -euC 12 | 13 | if [ -z "${3:-}" ]; then 14 | echo >&2 'Usage: set-meta mediafile artist-name album-name' 15 | exit 1 16 | fi 17 | 18 | out="tmp.${1##*.}" 19 | ffmpeg -loglevel 24 -i "$1" -acodec copy -metadata ARTIST="$2" -metadata ALBUM="$3" "$out" 20 | mv "$out" "$1" 21 | -------------------------------------------------------------------------------- /local/script/set-screen: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Set the active screen. 4 | # 5 | # set-screen laptop 6 | # set-screen hdmi 7 | # set-screen switch 8 | # set-screen clone (or both) # as a mirror/copy 9 | # set-screen laptop-hdmi # Laptop left, HDMI right 10 | # set-screen hdmi-laptop # HDMI left, laptop right 11 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 12 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 13 | setopt err_exit no_unset no_clobber pipefail 14 | 15 | laptop="eDP-1" 16 | laptop_mode=(--auto) 17 | laptop_scale=0.8 18 | 19 | hdmi="HDMI-1" 20 | hdmi_mode=(--auto) 21 | hdmi_scale=1 22 | 23 | laptop_args() { 24 | print -- "--output $laptop $laptop_mode --scale ${laptop_scale}x${laptop_scale}" 25 | } 26 | hdmi_args() { 27 | print -- "--output $hdmi $hdmi_mode --scale ${hdmi_scale}x${hdmi_scale}" 28 | } 29 | active() { 30 | xrandr --query | grep ' connected primary ' | cut -d' ' -f1 31 | } 32 | 33 | case "${1:-}" in 34 | (hdmi) 35 | xrandr \ 36 | $(hdmi_args) --pos 0x0 --primary \ 37 | --output "$laptop" --off 38 | 39 | # Make sure new keyboard has mappings applied. 40 | xmodmap ~/.config/x11/modmap 41 | 42 | #pactl set-card-profile 0 output:hdmi-stereo-extra1 43 | #pactl set-card-profile 0 output:analog-stereo+input:analog-stereo 44 | ;; 45 | (laptop) 46 | xrandr \ 47 | --output "$hdmi" --off \ 48 | $(laptop_args) --pos 0x0 --primary 49 | #pactl set-card-profile 0 output:analog-stereo+input:analog-stereo 50 | ;; 51 | (switch) 52 | case $(active) in 53 | ($laptop) set-screen hdmi ;; 54 | ($hdmi) set-screen laptop ;; 55 | (*) 56 | print >&2 "set-screen: can't get active screen" 57 | exit 1 58 | ;; 59 | esac 60 | ;; 61 | (clone|both) 62 | xrandr \ 63 | $(hdmi_args) --pos 0x0 --primary \ 64 | $(laptop_args) --pos 0x0 65 | #pactl set-card-profile 0 output:hdmi-stereo-extra1 66 | #pactl set-card-profile 0 output:analog-stereo+input:analog-stereo 67 | ;; 68 | (laptop-hdmi) 69 | xrandr \ 70 | $(laptop_args) --pos 0x0 --rotate normal \ 71 | $(hdmi_args) --pos 1920x0 --rotate normal --primary 72 | ;; 73 | (hdmi-laptop) 74 | xrandr \ 75 | $(hdmi_args) --pos 0x0 --rotate normal --primary \ 76 | $(laptop_args) --pos 1920x0 --rotate normal 77 | ;; 78 | (*) 79 | # TODO: print status instead? 80 | print >&2 "${0##*/}: unknown screen; use -h for help" 81 | exit 1 82 | esac 83 | -------------------------------------------------------------------------------- /local/script/sleep-until: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Sleep until a specific time. 4 | # 5 | # This takes a time in 24-hour clock format and sleeps until the next instance 6 | # of this time is reached. 7 | # 8 | # % sleep-until 15:30:45 9 | # % sleep-until 15:30 # Until 15:30:00 10 | # % sleep-until 15 # Until 15:00:00 11 | # 12 | # Or to sleep until a specific date: 13 | # 14 | # % sleep-until 2023-01-01T15:00:00 15 | # 16 | # Or space instead of T; can abbreviate time like above. 17 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 18 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 19 | setopt err_exit no_unset no_clobber pipefail 20 | 21 | if [[ -z ${1:-} ]]; then 22 | print >&2 "sleep-until: need target time; use -h for help." 23 | exit 1 24 | fi 25 | 26 | s=$(( $(date -d "$1" +%s) - $(date +%s) )) 27 | if [[ $s -lt 0 ]]; then 28 | mn=$(( $(date -d 23:59 +%s) - $(date +%s) )) 29 | s=$(( $s + $mn + 60 )) 30 | fi 31 | 32 | print -n 'Sleeping for ' 33 | m=$(($s / 60)) 34 | [[ $m -gt 60 ]] && printf "$(($m / 60)) hours, " 35 | print "$(($m % 60)) minutes ($s seconds)" 36 | sleep $s 37 | -------------------------------------------------------------------------------- /local/script/timeadd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Add times in the format of "1:15". 4 | 5 | import datetime, sys 6 | 7 | args = sys.argv[1:] 8 | if len(args) == 0: 9 | args = sys.stdin.read().split(' ') 10 | 11 | added = datetime.timedelta() 12 | for a in args: 13 | h, m = a.split(':') 14 | added += datetime.timedelta(hours=int(h), minutes=int(m)) 15 | 16 | mins = added.total_seconds() / 60 17 | 18 | print(added) 19 | print(f'{int(mins // 60)}:{int(mins % 60)}') 20 | -------------------------------------------------------------------------------- /local/script/timecalc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Show difference between two times. 4 | # 5 | # TODO: support overflows to next day: timecalc 14:00 08:00 6 | # TODO: support different formats: 14.00, 1400, 14, 2pm 7 | #echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 8 | 9 | import datetime, re, sys 10 | 11 | def to_date(s): 12 | s = list(map(int, re.split('[:.]', s))) 13 | return datetime.datetime.now().replace(hour=s[0], minute=s[1]) 14 | 15 | args = sys.argv[1:] 16 | if len(args) == 0: 17 | args = sys.stdin.read().split(' ') 18 | 19 | d1 = to_date(args[0]) 20 | 21 | if len(args) == 1: 22 | d2 = datetime.datetime.now() 23 | else: 24 | d2 = to_date(args[1]) 25 | 26 | spent = str(d2 - d1).split(':') 27 | spent.pop() 28 | print(':'.join(spent)) 29 | -------------------------------------------------------------------------------- /local/script/tmux-gc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Start or switch to tmux session for goatcounter. 4 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 5 | set -euC 6 | 7 | cd ~/code/goatcounter 8 | s=goatcounter 9 | att() { 10 | if [ -n "${TMUX:-}" ]; then 11 | tmux switch-client -t "=$s" 12 | else 13 | tmux attach-session -t "=$s" 14 | fi 15 | } 16 | if tmux has-session -t "=$s" 2> /dev/null; then 17 | att 18 | exit 0 19 | fi 20 | tmux new-session -d -s "$s" 21 | 22 | tmux new-window -d -t "=$s" -n goatcounter 23 | tmux send-keys -t "=$s:=goatcounter" \ 24 | "goatcounter saas -dev -db 'postgresql+dbname=goatcounter' -listen localhost:8081 -websocket" Enter 25 | 26 | att 27 | -------------------------------------------------------------------------------- /local/script/tmux-site: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Start or switch to tmux session for my site. 4 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 5 | set -euC 6 | 7 | cd ~/code/arp242.net 8 | s=site 9 | att() { 10 | if [ -n "${TMUX:-}" ]; then 11 | tmux switch-client -t "=$s" 12 | else 13 | tmux attach-session -t "=$s" 14 | fi 15 | } 16 | if tmux has-session -t "=$s" 2> /dev/null; then 17 | att 18 | exit 0 19 | fi 20 | tmux new-session -d -s "$s" 21 | 22 | tmux new-window -d -t "=$s" -n server -c ~/code/arp242.net/_site 23 | tmux send-keys -t "=$s:=server" 'python -mhttp.server' Enter 24 | 25 | tmux new-window -d -t "=$s" -n jekyll 26 | tmux send-keys -t "=$s:=jekyll" 'JEKYLL_NO_BUNDLER_REQUIRE=1 jekyll build --strict_front_matter -w' Enter 27 | 28 | att 29 | -------------------------------------------------------------------------------- /local/script/tz: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Show times in various different timezones. 4 | # 5 | # Use "tz 01:00" to set the local time and display all times for that. 6 | # 7 | # Use "tz 01:00 America/Los_Angeles to set the time in that TZ, and display all 8 | # local times for that. 9 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 10 | 11 | tz=${2:-} 12 | if [[ -z ${2:-} ]]; then 13 | zmodload zsh/stat 14 | typeset -A arr 15 | zstat -LH arr /etc/localtime 16 | tz=$arr[link]:h:t/$arr[link]:t 17 | # TODO: allow reversing $1 and $2 18 | fi 19 | 20 | time= 21 | [[ -n ${1:-} ]] && time="-d @$(TZ=$tz date -d "$1" +%s)" 22 | 23 | printf '%-15s' 'US West'; TZ='America/Los_Angeles' date '+%H:%M %z %Z' $time 24 | printf '%-15s' 'US East'; TZ='America/New_York' date '+%H:%M %z %Z' $time 25 | printf '%-15s' 'UTC'; TZ='UTC' date '+%H:%M %z %Z' $time 26 | printf '%-15s' 'Ireland/UK'; TZ='Europe/Dublin' date '+%H:%M %z %Z' $time 27 | printf '%-15s' 'West Europe'; TZ='Europe/Amsterdam' date '+%H:%M %z %Z' $time 28 | printf '%-15s' 'New Zealand'; TZ='NZ' date '+%H:%M %z %Z' $time 29 | 30 | # TODO: just print this is none of the above is in the current TZ; and print the 31 | # above one as bold Also print selected TZ as bold. 32 | printf '\n\x1b[1m%-15s%s\x1b[0m\n' 'Current' "$(date '+%H:%M %z %Z' $time)" 33 | -------------------------------------------------------------------------------- /local/script/wifi: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Manage Wi-Fi connections. 4 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 5 | setopt err_exit no_unset no_clobber pipefail 6 | 7 | dev=${DEV:-} 8 | [[ -z $dev ]] && dev=$(iw dev | grep Interface | head -n1 | cut -d ' ' -f2) 9 | 10 | usage() { 11 | [[ -n ${argv[1]:-} ]] && print >&2 "wifi: error: ${argv[1]}\n" 12 | <<-EOF 13 | wifi [command] [cmd-args] 14 | 15 | Using device $dev; set DEV to change it. 16 | 17 | Commands: 18 | status [refresh] Current status (default is no cmd is given). 19 | Add a number to keep refreshing every n seconds. 20 | scan Scan for networks. 21 | monitor Keep scanning for networks. 22 | connect [id] [pwd] Connect to SSID or BSS; use wpa_supplicant if [pwd] is set. 23 | addr [ip] [route] Manually set IP address with default route. 24 | EOF 25 | [[ -n ${argv[1]:-} ]] && exit 1 26 | return 0 27 | } 28 | 29 | up() { 30 | local f=$(ip link | grep ${dev}:) 31 | [[ -z $f ]] && usage "no such device: $dev" 32 | 33 | err=$(grep -q 'state DOWN' <<<$f && ip link set $dev up 2>&1 ||:) 34 | [[ -n $err ]] && print >&2 "wifi: warning: bringing device up: $err" 35 | return 0 36 | } 37 | 38 | status() { 39 | # Refresh: keep calling this status function (w/o arguments). 40 | if [[ -n ${1:-} ]]; then 41 | while :; do 42 | s=$(status) # Less flicker this way, as running ip/iw takes a few ms. 43 | clear 44 | print $s 45 | sleep $1 46 | done 47 | return 48 | fi 49 | 50 | local link=$(iw dev $dev link) 51 | 52 | # TODO: dev: wlp0s2 (23:23...) 53 | print -f '%-12s %s\n' 'dev' "$dev" 54 | print -f '%-12s %s\n' 'ip' "$(ip addr show dev $dev | grep ' inet ' | cut -d ' ' -f6)" 55 | print -f '%-12s %s\n' 'route' "$(ip route list dev $dev | sed '2,0s/^/ /')" 56 | print -f '%-12s %s\n' 'bss' "$(head -n1 <<<$link | cut -d ' ' -f3)" 57 | 58 | iw dev $dev info | tail -n+2 | awk -F ' ' \ 59 | '/(addr|ssid|channel|txpower) / { printf("%-12s", $1); $1=""; print $0 }' 60 | 61 | print $link | awk -F ':' \ 62 | '/(signal|[rt]x bitrate):/ { printf("%-12s", gensub(/^\s/, "", "g", $1)); $1=""; print gensub(/^\s/, "", "g", $0) }' 63 | 64 | print -f '%-12s %sM\n' 'total RX' $(( ${$(grep -o 'RX: [0-9]*' <<<$link || print 0)#*:} / 1048576)) 65 | print -f '%-12s %sM\n' 'total TX' $(( ${$(grep -o 'TX: [0-9]*' <<<$link || print 0)#*:} / 1048576)) 66 | } 67 | 68 | scan() { 69 | local connected=$(iw dev $dev link | head -n1 | cut -d ' ' -f3) 70 | iw dev $dev scan | awk -F: "$(<<-'EOF' 71 | /^BSS / { 72 | if (ssid != "") 73 | printf(" %-10s %s %-30s (%s)\n", signal, bss, ssid, ciphers) 74 | bss = sprintf("%s:%s:%s:%s:%s:%s", substr($1, 5, 6), $2, $3, $4, $5, substr($6, 0, 2)) 75 | } 76 | /^\tsignal:/ { signal = gensub(/^ /, "", "g", $2) } 77 | /^\tSSID:/ { ssid = gensub(/^ /, "", "g", $2) } 78 | /Pairwise ciphers:/ { ciphers = gensub(/^ /, "", "g", $2) } 79 | EOF 80 | )" | sort -nr | sed -E "s/ (.*?$connected)/→ \1/" 81 | } 82 | 83 | connect() { 84 | local ssid=${argv[1]:-} 85 | local pass=${argv[2]:-} 86 | [[ -z $ssid ]] && usage 'need a SSID' 87 | 88 | iw dev $dev disconnect 89 | if grep -Eq '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' <<<$ssid; then 90 | iw dev $dev connect -w bssid $ssid 91 | else 92 | iw dev $dev connect -w $ssid 93 | fi 94 | 95 | [[ -n $pass ]] && wpa_cli passphrase $ssid $pass 96 | # wpa_cli save_config 97 | } 98 | 99 | addr() { 100 | local ip=${argv[1]:-} 101 | local route=${argv[2]:-} 102 | [[ -z $ip ]] && usage 'need an IP address\n' 103 | 104 | ip addr add $ip dev $dev 105 | [[ -n $route ]] && ip route add default via 10.0.1.1 dev $dev 106 | } 107 | 108 | monitor() { 109 | while :; do 110 | s=$(scan) 111 | clear 112 | print $s 113 | sleep 2 114 | done 115 | } 116 | 117 | cmd=status 118 | if [[ -n ${argv[1]:-} ]]; then 119 | cmd=$argv[1] 120 | shift 121 | fi 122 | 123 | case $cmd in 124 | (help|-h|-help) usage ;; 125 | (scan) up; scan $argv[@] ;; 126 | (connect) up; connect $argv[@] ;; 127 | (addr) up; addr $argv[@] ;; 128 | (monitor) up; monitor $argv[@] ;; 129 | (status) up; status $argv[@] ;; 130 | (*) 131 | print >&2 "unknown command: $cmd\n" 132 | usage 133 | exit 1 134 | esac 135 | -------------------------------------------------------------------------------- /local/script/wm-brightness: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Set screen brightness. Only works for built-in laptop screens on Linux. 4 | # 5 | # Usage: 6 | # 7 | # wm-brightness Show current brightness. 8 | # wm-brightness print Idem. 9 | # wm-brightness 42 Set brightness to 42. 10 | # wm-brightness up Raise brightness 11 | # wm-brightness down Lower brightness 12 | # wm-brightness scale Use a more fine-grained resolution at lower 13 | # brightnesses. 14 | # 15 | # All arguments can be combined; e.g. "wm-brightness up up print" will raise it 16 | # twice and then print the current value, "wm-brightness scale up" will used a 17 | # "scaled" value. 18 | # 19 | # Note: The scale depends on the driver; it doesn't need to be 1-100%. 20 | # Note: It seems the xbacklight utility is broken on many systems; it hasn't 21 | # worked well on my last two laptops anyway. 22 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 23 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 24 | setopt err_exit no_unset pipefail 25 | 26 | if [[ -f /sys/class/backlight/intel_backlight/brightness ]]; then 27 | step=20; min=1; dev=/sys/class/backlight/intel_backlight/brightness 28 | elif [[ -f /sys/class/backlight/amdgpu_bl0/brightness ]]; then 29 | step=5; min=0; dev=/sys/class/backlight/amdgpu_bl0/brightness 30 | else 31 | print >&2 'wm-brightness: no device found in /sys/class/backlight' 32 | exit 1 33 | fi 34 | 35 | cur=$(< $dev) 36 | if [ -z "$cur" ]; then 37 | print >&2 "wm-brightness: could not read current value from $dev" 38 | exit 1 39 | fi 40 | 41 | [ $# -eq 0 ] && { print "$cur"; exit 0; } 42 | 43 | # Process the scale parameter first so it won't matter where it appears. 44 | for a in "$@"; do 45 | [[ $a != "scale" ]] && continue 46 | 47 | if [[ $cur -le $(( $step * 3 )) ]]; then 48 | step=$(( $step / 5 )) 49 | [[ $step -eq 0 ]] && step=1 50 | fi 51 | break 52 | done 53 | 54 | for a in $argv; do 55 | cur=$(< $dev) 56 | case "$a" in 57 | (scale) ;; 58 | (up) print $(( $cur + $step )) > "$dev" ;; 59 | (down) [ $(( $cur - $step )) -le $min ] && print $min > "$dev" || print $(( $cur - $step )) > "$dev" ;; 60 | (print) cat "$dev" ;; 61 | (*) print "$1" > "$dev" 62 | esac 63 | done 64 | -------------------------------------------------------------------------------- /local/script/wm-media: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Volume and media controls. 4 | # 5 | # System-global (with pactl): 6 | # vol-up Raise volume. 7 | # vol-down Lower volume. 8 | # mute Toggle mute for all speakers. 9 | # micmute Toggle mute for all microphones. 10 | # 11 | # For applications (supported: mpv, Firefox): 12 | # pause Toggle play/pause. 13 | # next Next track/file. 14 | # prev Previous track/file. 15 | # forward Seek forward 1 minute. 16 | # rewind Seek backwards 1 minute. 17 | # 18 | # For mpv, start mpv with "--input-ipc-server=/tmp/.mpv". You can stick this in 19 | # your ~/.config/mpv/mpv.conf. See mpv(1) 20 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 21 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 22 | setopt err_exit no_unset no_clobber pipefail 23 | 24 | control-mpv() { 25 | local mpv_sock=/tmp/.mpv 26 | if [[ ! -e $mpv_sock ]]; then 27 | print >&2 "wm-media: $mpv_sock doesn't exist" 28 | exit 1 29 | fi 30 | 31 | case $1 in 32 | (pause) print '{"command": ["cycle", "pause"]}' | socat - $mpv_sock ;; 33 | (next) print '{"command": ["playlist-next"]}' | socat - $mpv_sock ;; 34 | (prev) print '{"command": ["playlist-prev"]}' | socat - $mpv_sock ;; 35 | (forward) print '{"command": ["seek", "60"]}' | socat - $mpv_sock ;; 36 | (rewind) print '{"command": ["seek", "60"]}' | socat - $mpv_sock ;; 37 | (*) 38 | print >&2 "wm-media: unknown action: '$1'" 39 | exit 1 40 | esac 41 | } 42 | 43 | control-firefox() { 44 | # https://specifications.freedesktop.org/mpris-spec/2.2/ 45 | # https://github.com/acrisci/playerctl 46 | # https://wiki.archlinux.org/title/MPRIS 47 | # dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames 48 | # dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next 49 | # dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous 50 | 51 | # TODO: need instance name. 52 | case $1 in 53 | (pause) 54 | dbus-send \ 55 | --print-reply \ 56 | --dest=org.mpris.MediaPlayer2.firefox.instance23725 \ 57 | /org/mpris/MediaPlayer2 \ 58 | org.mpris.MediaPlayer2.Player.PlayPause 59 | ;; 60 | (*) 61 | print >&2 "wm-media: unknown action: '$1'" 62 | exit 1 63 | esac 64 | } 65 | 66 | # Get the currently active/connected sink. 67 | get-sink() { 68 | local sink=$(pactl list sinks short | grep RUNNING | head -n1) 69 | [ -z "$sink" ] && sink=$(pactl list sinks short | head -n1) 70 | print "$sink" | cut -f1 71 | } 72 | 73 | status() { 74 | : 75 | # TODO: print status 76 | # TODO: this lists all sinks, not the first. Can't seem to get one sink from 77 | # pactl? ffs. 78 | # vol=$(pactl list sinks | grep 'Base Volume:' | cut -d / -f 2 | tr -d ' %') 79 | # [ $vol -gt 100 ] && return 80 | # echo $vol 81 | # 82 | # print >&2 'wm-media: no command; use -h for help.' 83 | # exit 1 84 | } 85 | 86 | case ${1:-} in 87 | ("") status ;; 88 | (vol-up) pactl set-sink-volume $(get-sink) +5% ;; 89 | (vol-down) pactl set-sink-volume $(get-sink) -5% ;; 90 | (mute) pactl set-sink-mute $(get-sink) toggle ;; 91 | (micmute) pactl set-source-mute $(get-sink) toggle ;; 92 | (*) 93 | IFS=$'\n' 94 | 95 | # TODO: pass more information: 96 | # 97 | # application.process.id = "6116" 98 | # application.process.binary = "mpv" 99 | # application.name = "mpv Media Player" 100 | # media.name = "Earthless - Red Dragon.opus - mpv" 101 | # 102 | # application.process.id = "30080" 103 | # application.process.binary = "firefox-bin" 104 | # application.name = "Firefox" 105 | # media.name = "TempleOS - Terry Responds to the Haters-mBgIBF9Y6PE.webm" 106 | for a in $(pactl list sink-inputs | awk -F '"' '/application\.name =/ {print $2}'); do 107 | case $a in 108 | (mpv *) control-mpv $@ ;; 109 | (Firefox) control-firefox $@ ;; 110 | (*) 111 | print >&2 "wm-media: warning: unsupported application: $a" 112 | esac 113 | done 114 | esac 115 | -------------------------------------------------------------------------------- /local/script/wm-scratch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Toggle show/hide for a window. 4 | # 5 | # Without arguments it will open a new terminal on first innovation, and 6 | # show/hide it on subsequent invocations. Useful for a "scratch" terminal to 7 | # quickly write down some things or whatnot. 8 | # 9 | # If the first argument is set to any non-empty value it will make the currently 10 | # active window the scratch window. 11 | # 12 | # The second argument is the window class name; if this is the default 13 | # ("scratchwin") then it will spawn a terminal if no such window exists, 14 | # otherwise it won't do anything if it can't find the window. 15 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 16 | set -euC 17 | 18 | name=${2:-scratchwin} 19 | scratch=$(xdotool search --classname $name ||:) 20 | 21 | if [ -n "${1:-}" ]; then 22 | if [ -n "$scratch" ]; then 23 | xdotool set_window --classname '' "$scratch" 24 | xdotool windowmap "$scratch" 25 | fi 26 | xdotool getactivewindow set_window --classname "$name" 27 | exit 0 28 | fi 29 | 30 | if [ -z "$scratch" ]; then 31 | # Only launch a terminal with the default argument; this allows us to do 32 | # things like "wm-scratch '' Devtools" to show/hide Firefox devtools if it 33 | # exists. 34 | if [ "$name" = 'scratchwin' ]; then 35 | st -n "$name" -g 80x25-2-2 & 36 | fi 37 | 38 | # Hack to open Firefox devtools ("K" makes it always start on the console 39 | # tab, rather than the last active tab like with "I" or F12). 40 | # 41 | # Should probably add some arguments for this: 42 | # 43 | # wm-scratch toggle scratchwin "st -n scratchwin -g 80x25-2-2" 44 | # wm-scratch toggle Devtools "xdotool search --classname 'Navigator' key 'Control_L+Shift_L+K'" 45 | # wm-scratch set-active 46 | if [ "$name" = 'Devtools' ]; then 47 | xdotool search --classname 'Navigator' key 'Control_L+Shift_L+K' & 48 | fi 49 | 50 | exit 0 51 | fi 52 | 53 | c=windowmap 54 | if xdotool search --onlyvisible "$name" >/dev/null 2>&1; then 55 | c=windowunmap 56 | fi 57 | xdotool "$c" "$scratch" 58 | -------------------------------------------------------------------------------- /local/script/wm-screenshot: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # Take a screenshot. 4 | # 5 | # Depends on "cap" from https://github.com/arp242/cap 6 | # 7 | # "copy" uses xclip, and "open" sxiv. 8 | # 9 | # Usage: 10 | # 11 | # wm-screenshot Select region. 12 | # wm-screenshot full Take screenshot of entire screen. 13 | # wm-screenshot copy Copy to clipboard 14 | # wm-screenshot open Open in image viewer 15 | # wm-screenshot rm Remove file after we're done. 16 | # wm-screenshot border Add a border around the image. 17 | # wm-screenshot a.png Store as a specific filename. 18 | # 19 | # These can be combined; e.g. "wm-screenshot full open copy a.png" to store a 20 | # fullscreen screenshot in a.png, copy it to the clipboard, and open it with 21 | # sxiv. 22 | # 23 | # Note: files are stored in the current directory. If you launched your WM from 24 | # some odd directory then they're stored there. 25 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 26 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 27 | setopt err_exit no_unset no_clobber pipefail 28 | 29 | full=0; copy=0; open=0; rm=0; border=0; file="" 30 | for a in $@; do 31 | case "$a" in 32 | (full) full=1 ;; 33 | (open) open=1 ;; 34 | (copy) copy=1 ;; 35 | (rm) rm=1 ;; 36 | (border) border=1 ;; 37 | (*.png) file=$a ;; 38 | (*) 39 | print >&2 "wm-screenshot: unknown argument '$a'" 40 | exit 1 41 | esac 42 | done 43 | 44 | args="o" 45 | [[ $full -eq 0 ]] && args="s$args" 46 | [[ $border -eq 1 ]] && args="b$args" 47 | [[ -n "$file" ]] && args="$args $file" 48 | file="$(cap -$args)" 49 | 50 | [[ $copy -eq 1 ]] && xclip -selection clipboard -target image/png -in "$file" 51 | [[ $open -eq 1 ]] && sxiv "$file" 52 | [[ $rm -eq 1 ]] && rm "$file" 53 | -------------------------------------------------------------------------------- /local/script/xdg-open: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # xdg-open, without suckage. 4 | echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs 5 | [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 6 | setopt err_exit no_unset pipefail 7 | 8 | (( $+1 )) || { print >&2 'need a parameter'; exit 1 } 9 | 10 | # Open URL. 11 | if [[ -z "${1:#*://*}" ]]; then 12 | proto=${(L)1%%://*} 13 | case $proto in 14 | (http|https) exec firefox $1 ;; 15 | (*) 16 | print >&2 "xdg-open: no URL handler for protocol '$proto://' (for: $1)" 17 | exit 1 18 | esac 19 | fi 20 | 21 | # Open file. 22 | ext=${(L)1:e} 23 | case $ext in 24 | (html|pdf) exec firefox $1 ;; 25 | (png|webp|jpg|jpeg|heic) exec sxiv $1 ;; 26 | (mp?|ogg|flac|m4v|mkv|avi|mov) exec mpv $1 ;; 27 | (md|markdown|txt|sh) exec st -e vim $1 ;; 28 | (*) 29 | print >&2 "xdg-open: don't know how to open '.$ext' files (for: $1)" 30 | exit 1 31 | esac 32 | -------------------------------------------------------------------------------- /local/script/yaml2json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Convert YAML to JSON. 4 | # 5 | # Use Ruby as that has yaml in the stdlib. 6 | 7 | require 'yaml' 8 | require 'json' 9 | puts JSON.pretty_generate(YAML.load_file(ARGV[0])) 10 | -------------------------------------------------------------------------------- /manage-dotfiles.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding:utf-8 3 | # 4 | 5 | import glob, hashlib, os, pprint, re, shutil, subprocess, sys, tempfile, time 6 | 7 | if sys.argv[0] in ['', '-']: 8 | sys.argv[0] = 'stdin' 9 | root = os.path.dirname(os.path.realpath(sys.argv[0])) 10 | 11 | # TODO: These should all be commandline arguments 12 | verbose = True 13 | difftool = ['vimdiff', '-c source {}/diffexpr.vim'.format(root)] 14 | clobber_it_all = False 15 | 16 | 17 | def dbg(msg): 18 | if verbose: print(msg) 19 | 20 | 21 | def install_file(src, dest): 22 | """ Install (copy) the 'src' file to the 'dest'. Do sane things on 23 | unexpected cases (such as 'dest' being a symlink). """ 24 | 25 | # The destination is a symlink, this is rather unexpected 26 | # TODO: Ask what to do 27 | if os.path.islink(dest): 28 | print("`{} is a symlink".format(dest)) 29 | return 30 | 31 | # Make dirs if required 32 | if not os.path.exists(os.path.dirname(dest)): 33 | os.makedirs(os.path.dirname(dest)) 34 | 35 | # Check for write access 36 | if os.path.exists(dest) and not os.access(dest, os.W_OK): 37 | print("`{}' not writable; skipping".format(dest)) 38 | return 39 | 40 | # Copy! 41 | dbg('{} -> {}'.format(src, dest)) 42 | shutil.copy2(src, dest) 43 | 44 | 45 | def runcmd(cmd): 46 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 47 | return p.communicate()[0].decode() 48 | 49 | 50 | def ask(question, options=['y', 'n'], default=None): 51 | if default is None: default = options[0] 52 | opt_str = '/'.join([ o.upper() if o == default else o for o in options ]) 53 | answer = input('{} [{}]? '.format(question, opt_str)).strip().lower() 54 | 55 | if answer == '': return default 56 | if answer in options: return answer 57 | elif len(answer) == 1: 58 | for o in options: 59 | if o == answer or o[0] == answer[0]: 60 | return o 61 | return ask(question, options, default) 62 | 63 | 64 | def expand_dict(d): 65 | """ Expand pathnames in key => value of a dict to full paths """ 66 | # TODO: os.path.normpath? 67 | e = lambda p: os.path.realpath(os.path.expanduser(p)) 68 | return { e(k): e(v) for (k, v) in d.items() } 69 | 70 | 71 | def manage_dirs(dirs): 72 | mp = lambda a, b: '{}/{}'.format(a, b) 73 | 74 | for dest, src in dirs.items(): 75 | # Destination exsists, but isn't a directory! 76 | if os.path.exists(dest) and not os.path.isdir(dest): 77 | print("Warning: `{}' exists, but is not a directory".format(dest)) 78 | action = ask('What shall we do', ['ignore', 'remove']) 79 | if action == 'ignore': 80 | continue 81 | if action == 'remove': 82 | # TODO: What if dest is a dir? 83 | os.unlink(dest) 84 | 85 | # mkdir -p if required 86 | if not os.path.exists(dest): 87 | os.makedirs(dest) 88 | 89 | # Get list of all files we want to install and run manage_files() on that 90 | for src_root, _, srcfiles in os.walk(src): 91 | dest_root = src_root.replace(src, dest) 92 | srcfiles = { mp(dest_root, f): mp(src_root, f) for f in srcfiles if f != 'module.py' } 93 | manage_files(srcfiles) 94 | 95 | # Get a list of files in the destination that's *not* already in the 96 | # source and ask what we want to do with these files 97 | for root, _, destfiles in os.walk(dest): 98 | # TODO: Doesn't seem to work? (module vim) 99 | continue 100 | for f in destfiles: 101 | full_f = mp(dest, f) 102 | if full_f in srcfiles.keys(): 103 | continue 104 | 105 | # TODO: Make sure dirs end with / 106 | # TODO: Add option "view" and/or "manual merge" 107 | print("The file `{}' exists in `{}', but is not in `{}'".format( 108 | f, dest, src)) 109 | action = ask('What shall we do', ['ignore', 'remove', 'copy']) 110 | if action == 'ignore': 111 | continue 112 | if action == 'remove': 113 | os.unlink(full_f) 114 | if action == 'copy': 115 | shutil.copy2(full_f, mp(src, f)) 116 | 117 | 118 | 119 | def manage_files(files): 120 | for dest, src in files.items(): 121 | # User asked to clobber it all 122 | if clobber_it_all: 123 | install_file(src, dest) 124 | continue 125 | 126 | # src is a binary file (we don't check dest); don't do anything 127 | # TODO: ask what to do where 128 | if os.path.exists(src): 129 | with open(src, 'rb') as fp: 130 | is_binary = False 131 | if os.path.exists(dest): 132 | try: 133 | with open(dest, 'r') as testfp: 134 | testfp.read() 135 | except UnicodeDecodeError: 136 | is_binary = True 137 | 138 | if is_binary or b'\x00' in fp.read(2048) and os.path.exists(dest): 139 | h1 = hashlib.sha256(open(src, 'rb').read()).hexdigest() 140 | h2 = hashlib.sha256(open(dest, 'rb').read()).hexdigest() 141 | if h1 != h2: 142 | print("`{}' is modified but looks like a binary file; skipping".format(src)) 143 | continue 144 | 145 | # File doesn't exist -> install 146 | if not os.path.exists(dest): 147 | install_file(src, dest) 148 | continue 149 | 150 | # Larger than 1 MiB -> don't manually merge 151 | if os.stat(src).st_size > 1048576 or os.stat(dest).st_size > 1048576: 152 | print("Skipping merge of `{}' because it is larger than 1MiB".format(src)) 153 | continue 154 | 155 | # TODO: temporarily until I implement font-scale 156 | # Check again if the files differ, but this time ignoring lines with 157 | # $dotignore$; this test is comparatively slow, which is why we do it 158 | # here 159 | #dest_data = [ l for l in open(dest, 'r').readlines() if not 'dot-ignore' in l] 160 | #src_data = [ l for l in open(src, 'r').readlines() if not 'dot-ignore' in l ] 161 | #if src_data == dest_data: 162 | # continue 163 | # End temp code 164 | 165 | h1 = hashlib.sha256(open(src, 'rb').read()).hexdigest() 166 | h2 = hashlib.sha256(open(dest, 'rb').read()).hexdigest() 167 | 168 | # Files are the same. 169 | if h1 == h2: 170 | continue 171 | 172 | run_diff(src, dest) 173 | 174 | 175 | def run_diff(src, dest): 176 | subprocess.call(difftool + [dest, src]) 177 | 178 | def manage_symlinks(symlinks): 179 | # TODO 180 | # If link exist and point to something else -> ask 181 | # If link exists, and is not a file -> ask 182 | # Else -> make link 183 | for dest, link in symlinks.items(): 184 | pass 185 | #if os.path.exists(link) and not os.path.islink(link): 186 | # print("The link `{}' already exists and is not a symlink; skipping".format(link)) 187 | # continue 188 | 189 | #print(os.getcwd()) 190 | #if os.path.exists(link) and os.lstat(link): 191 | #continue 192 | #print(link, ' -> ', dest) 193 | 194 | 195 | def proc_module(module, code): 196 | """ exec() module code, do something with it """ 197 | assigns = {} 198 | exec(code, assigns) 199 | 200 | if assigns.get('requires_root', False): 201 | # TODO 202 | # print('{} requires root -> skiping'.format(module)) 203 | return 204 | 205 | os.chdir(os.path.dirname(module)) 206 | if assigns.get('files'): 207 | manage_files(expand_dict(assigns['files'])) 208 | if assigns.get('dirs'): 209 | manage_dirs(expand_dict(assigns['dirs'])) 210 | if assigns.get('symlinks'): 211 | manage_symlinks(expand_dict(assigns['symlinks'])) 212 | if assigns.get('run'): 213 | try: 214 | assigns['run']() 215 | except: 216 | print('Error in:', module) 217 | raise 218 | os.chdir(root) 219 | 220 | 221 | if __name__ == '__main__': 222 | if 'CLOBBER_IT_ALL' in sys.argv: 223 | clobber_it_all = True 224 | sys.argv.remove('CLOBBER_IT_ALL') 225 | 226 | if len(sys.argv) > 1: 227 | modules = [ '{}/{}/module.py'.format(root, m) for m in sys.argv[1:] ] 228 | else: 229 | modules = glob.glob(root + '/*/module.py') 230 | 231 | try: 232 | for module in modules: 233 | try: 234 | with open(module, 'r') as fp: code = fp.read() 235 | except FileNotFoundError: 236 | print("Module `{}' doesn't exist".format(module)) 237 | sys.exit(1) 238 | 239 | proc_module(module, code) 240 | except KeyboardInterrupt: 241 | print() 242 | sys.exit(0) 243 | -------------------------------------------------------------------------------- /mpv/input.conf: -------------------------------------------------------------------------------- 1 | # https://raw.githubusercontent.com/mpv-player/mpv/master/etc/input.conf 2 | 3 | MBTN_LEFT ignore 4 | MBTN_LEFT_DBL cycle fullscreen 5 | MBTN_RIGHT cycle pause 6 | 7 | Right seek 5 # In seconds; these are limited by keyframes 8 | Left seek -5 9 | Up seek 60 10 | Down seek -60 11 | KP6 seek 5 12 | KP4 seek -5 13 | KP8 seek 60 14 | KP2 seek -60 15 | 16 | Shift+Right no-osd seek 2 exact # Smaller non-keyframe-limited, seeks with shift 17 | Shift+Left no-osd seek -2 exact 18 | Shift+Up no-osd seek 5 exact 19 | Shift+Down no-osd seek -5 exact 20 | WHEEL_UP seek 2 exact 21 | WHEEL_DOWN seek -2 exact 22 | Ctrl+Right frame-step # advance one frame and pause 23 | Ctrl+Left frame-back-step 24 | 25 | 1 set speed 1.0 # Set playback speed. 26 | 2 set speed 2.0 27 | 3 set speed 4.0 28 | 4 set speed 8.0 29 | 30 | p show-text ${playlist} # show the playlist 31 | t show-text ${track-list} # show the list of video, audio and sub tracks 32 | 33 | 34 | q quit 35 | #Q delete-watch-later-config; quit # TODO 36 | f cycle fullscreen 37 | Esc set fullscreen no 38 | Space cycle pause 39 | > playlist-next # Next file 40 | < playlist-prev # Previous file 41 | i script-binding stats/display-stats-toggle 42 | ` script-binding console/enable 43 | s screenshot video # Take screenshot, w/o OSD and subs 44 | Ctrl+s screenshot each-frame # Screenshot every frame 45 | 46 | ### Sound 47 | m cycle mute 48 | 9 add volume -2 49 | 0 add volume 2 50 | = add audio-delay 0.010 # Change A/V sync 51 | - add audio-delay -0.010 52 | 53 | ### Subs 54 | v cycle sub-visibility 55 | z add sub-delay +0.01 # Subtitle sync 56 | Z add sub-delay -0.01 57 | x add sub-scale +0.05 # Subtitle font size 58 | X add sub-scale -0.05 59 | c add sub-pos +1 # Subtitle position 60 | C add sub-pos -1 61 | j cycle sub # Cycle through subtitles 62 | J cycle sub down 63 | 64 | 65 | # loudnorm=I=-30: loudnorm setting with I=-30, soft volume, might be suitable for background music 66 | # loudnorm=I=-15: louder volume, might be good for the video currently in view 67 | # anull: reset audio filter to null, i.e., disable the audio filter 68 | # n cycle_values af loudnorm=I=-30 loudnorm=I=-15 anull 69 | 70 | ### encode.lua 71 | 72 | # Extract part without recoding. 73 | # 74 | # ffmpeg 75 | # -ss 34:09.005 76 | # -i 'The Expanse/The Expanse S3/The EXPANSE - S03 E08 - It Reaches Out (1080p - AMZN Web-DL).mp4' 77 | # -to 2.1062652772112 78 | # -map 0:0 -map 0:1 79 | # -c copy 'The Expanse/The Expanse S3/The EXPANSE - S03 E08 - It Reaches Out (1080p - AMZN Web-DL)_1.mp4' 80 | e script-message-to encode set-timestamp encode_slice 81 | 82 | # Extract and recode to webm. 83 | # 84 | # Argument name must correspond to an existing script-opts/.conf file 85 | # 86 | # ffmpeg 87 | # -ss 34:03.332 88 | # -i 'The Expanse/The Expanse S3/The EXPANSE - S03 E08 - It Reaches Out (1080p - AMZN Web-DL).srt' 89 | # -ss 34:03.332 90 | # -i 'The Expanse/The Expanse S3/The EXPANSE - S03 E08 - It Reaches Out (1080p - AMZN Web-DL).mp4' 91 | # -to 4.0665652772109 92 | # -map 0 -map 1 93 | # -sn 94 | # -c:v libvpx 95 | # -crf 10 96 | # -b:v 1000k 97 | # 'The Expanse/The Expanse S3/The EXPANSE - S03 E08 - It Reaches Out (1080p - AMZN Web-DL)_2.webm' 98 | E script-message-to encode set-timestamp encode_webm 99 | -------------------------------------------------------------------------------- /mpv/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.config/mpv': '.', 3 | } 4 | -------------------------------------------------------------------------------- /mpv/mpv.conf: -------------------------------------------------------------------------------- 1 | #profile=gpu-hq # Better but slower quality; even on my Celeron laptop it's only a few % of CPU difference. 2 | no-input-default-bindings # I have my own input.conf 3 | save-position-on-quit # Remember position. 4 | write-filename-in-watch-later-config # Write comment with filename in the ~/.config/mpv/watch_later/… file. 5 | cursor-autohide-fs-only # Don't autohide cursor if not fullscreen. 6 | volume-max=150 # My laptop speakers suck. 7 | autofit-larger=95%x95% # Never make the window larger than the screen. 8 | msg-level=auto_profiles=warn,file=warn # Bit less verbose. 9 | sub-scale=0.4 # Smaller subtitles by default. 10 | sub-margin-y=8 # Less margin at the bottom. 11 | sub-border-size=4 # Fairly large text shadow; makes subs easier to read in all backgrounds. 12 | sub-shadow-offset=4 13 | sub-shadow-color='#333333' 14 | osd-font-size=30 # Smaller font in OSD 15 | image-display-duration=inf # Display images forever 16 | screenshot-format=webp # Screenshots as lossless webp. 17 | screenshot-webp-lossless=yes 18 | screenshot-webp-compression=0 # Don't compress; we can do it later if need be. 19 | 20 | # TODO: add username here properly 21 | input-ipc-server=/tmp/run-martin/mpv 22 | 23 | # - add `--resume-playback-check-mtime` to check consistent mtime when 24 | # restoring playback state. 25 | # --keep-open= 26 | 27 | # Cache network stuff a bit more 28 | #[cache] 29 | # profile-desc = 'large cache size' 30 | # demuxer-max-bytes=1GiB 31 | # demuxer-max-back-bytes=1GiB 32 | 33 | # Audio files. 34 | [audio] 35 | profile-desc = 'audio only' 36 | # profile-cond = not vo_configured 37 | # profile-restore = copy 38 | no-save-position-on-quit 39 | no-resume-playback 40 | display-tags= 41 | term-osd-bar 42 | term-osd-bar-chars=┣━╉─┤ 43 | 44 | 45 | 46 | # https://iamscum.wordpress.com/guides/videoplayback-guide/mpv-conf/ 47 | # https://mpv.io/manual/master/#property-list 48 | # https://github.com/Argon-/mpv-config/blob/master/mpv.conf 49 | # https://github.com/bamos/dotfiles/blob/master/.mpv/scripts.old/music.lua 50 | # https://github.com/mpv-player/mpv/tree/master/TOOLS/lua 51 | # https://www.programmersought.com/article/37104856925/ 52 | 53 | # https://github.com/mpv-player/mpv/wiki/User-Scripts 54 | # https://github.com/jonniek/mpv-scripts 55 | # https://github.com/occivink/mpv-scripts 56 | -------------------------------------------------------------------------------- /mpv/script-opts/console.conf: -------------------------------------------------------------------------------- 1 | # font 2 | font_size=24 3 | -------------------------------------------------------------------------------- /mpv/script-opts/encode_slice.conf: -------------------------------------------------------------------------------- 1 | # profile to slice the current video without reencoding it 2 | # watch out that the extract will be snapped to keyframes; this is unavoidable when copying streams 3 | # see encode_webm.conf for a detailed explanations of all the options 4 | 5 | only_active_tracks=yes 6 | preserve_filters=no 7 | append_filter= 8 | codec=-c copy 9 | output_format=$f_$n.$x 10 | output_directory=. 11 | detached=yes 12 | ffmpeg_command=ffmpeg 13 | print=yes 14 | -------------------------------------------------------------------------------- /mpv/script-opts/encode_webm.conf: -------------------------------------------------------------------------------- 1 | # if yes, only encode the currently active tracks 2 | # 3 | # for example, mute the player / hide the subtitles if you don't want audio / 4 | # subs to be part of the extract 5 | only_active_tracks=no 6 | 7 | # whether to preserve some of the applied filters (crop, rotate, flip and mirror) into the extract 8 | # this is pretty useful in combination with crop.lua 9 | # note that you cannot copy video streams and apply filters at the same time 10 | preserve_filters=yes 11 | 12 | # apply another filter after the ones from the previous option if any 13 | # can be used to limit the resolution of the output, for example with 14 | # append_filter=scale=2*trunc(iw/max(1\,sqrt((iw*ih)/(960*540)))/2):-2 15 | append_filter= 16 | 17 | # additional parameters passed to ffmpeg 18 | #codec=-an -sn -c:v libvpx -crf 10 -b:v 1000k 19 | codec=-sn -c:v libvpx -crf 10 -b:v 1000k 20 | 21 | # format of the output filename 22 | # Does basic interpolation on the following variables: $f, $x, $t, $s, $e, $d, $p, $n which respectively represent 23 | # input filename, input extension, title, start timestamp, end timestamp, duration, profile name and an incrementing number in case of conflicts 24 | # if the extension is not among the recognized ones, it will default to mkv 25 | output_format=$f_$n.webm 26 | 27 | # the directory in which to create the extract 28 | # empty means the same directory as the input file 29 | # relative paths are relative to mpv's working directory, absolute ones work like you would expect 30 | output_directory= 31 | 32 | # if yes, the ffmpeg process will run detached from mpv and we won't know if it succeeded or not 33 | # if no, we know the result of calling ffmpeg, but we can only encode one extract at a time and mpv will block on exit 34 | detached=yes 35 | 36 | # executable to run when encoding (or its full path if not in PATH) 37 | # for example, this can be used with a wrapper script that calls ffmpeg and triggers a notification when finished 38 | # note that the executable gets the ffmpeg arguments as-is, and is expected to call ffmpeg itself 39 | ffmpeg_command=ffmpeg 40 | 41 | # if yes, print the ffmpeg call before executing it 42 | print=yes 43 | -------------------------------------------------------------------------------- /mpv/script-opts/osc.conf: -------------------------------------------------------------------------------- 1 | # https://mpv.io/manual/stable/#configurable-options 2 | # layout=box 3 | # minmousemove=3 4 | 5 | # Show OSD if mouse moves anywhere. 6 | deadzonesize=0 7 | 8 | hidetimeout=1000 9 | 10 | # timetotal=yes 11 | 12 | boxmaxchars=140 13 | 14 | # String that supports property expansion that will be displayed as OSC title. 15 | # ASS tags are escaped, and newlines and trailing slashes are stripped. 16 | title=${media-title} 17 | -------------------------------------------------------------------------------- /mpv/scripts/encode.lua: -------------------------------------------------------------------------------- 1 | -- https://github.com/occivink/mpv-scripts/tree/master/scripts 2 | local utils = require "mp.utils" 3 | local msg = require "mp.msg" 4 | local options = require "mp.options" 5 | 6 | local ON_WINDOWS = (package.config:sub(1,1) ~= "/") 7 | 8 | local start_timestamp = nil 9 | local profile_start = "" 10 | 11 | -- implementation detail of the osd message 12 | local timer = nil 13 | local timer_duration = 2 14 | 15 | function append_table(lhs, rhs) 16 | for i = 1,#rhs do 17 | lhs[#lhs+1] = rhs[i] 18 | end 19 | return lhs 20 | end 21 | 22 | function file_exists(name) 23 | local f = io.open(name, "r") 24 | if f ~= nil then 25 | io.close(f) 26 | return true 27 | else 28 | return false 29 | end 30 | end 31 | 32 | function get_extension(path) 33 | local candidate = string.match(path, "%.([^.]+)$") 34 | if candidate then 35 | for _, ext in ipairs({ "mkv", "webm", "mp4", "avi" }) do 36 | if candidate == ext then 37 | return candidate 38 | end 39 | end 40 | end 41 | return "mkv" 42 | end 43 | 44 | function get_output_string(dir, format, input, extension, title, from, to, profile) 45 | local res = utils.readdir(dir) 46 | if not res then 47 | return nil 48 | end 49 | local files = {} 50 | for _, f in ipairs(res) do 51 | files[f] = true 52 | end 53 | local output = format 54 | output = string.gsub(output, "$f", input) 55 | output = string.gsub(output, "$t", title) 56 | output = string.gsub(output, "$s", seconds_to_time_string(from, true)) 57 | output = string.gsub(output, "$e", seconds_to_time_string(to, true)) 58 | output = string.gsub(output, "$d", seconds_to_time_string(to-from, true)) 59 | output = string.gsub(output, "$x", extension) 60 | output = string.gsub(output, "$p", profile) 61 | if ON_WINDOWS then 62 | output = string.gsub(output, "[/\\|<>?:\"*]", "_") 63 | end 64 | if not string.find(output, "$n") then 65 | return files[output] and nil or output 66 | end 67 | local i = 1 68 | while true do 69 | local potential_name = string.gsub(output, "$n", tostring(i)) 70 | if not files[potential_name] then 71 | return potential_name 72 | end 73 | i = i + 1 74 | end 75 | end 76 | 77 | function get_video_filters() 78 | local filters = {} 79 | for _, vf in ipairs(mp.get_property_native("vf")) do 80 | local name = vf["name"] 81 | local filter 82 | if name == "crop" then 83 | local p = vf["params"] 84 | filter = string.format("crop=%d:%d:%d:%d", p.w, p.h, p.x, p.y) 85 | elseif name == "mirror" then 86 | filter = "hflip" 87 | elseif name == "flip" then 88 | filter = "vflip" 89 | elseif name == "rotate" then 90 | local rotation = vf["params"]["angle"] 91 | -- rotate is NOT the filter we want here 92 | if rotation == "90" then 93 | filter = "transpose=clock" 94 | elseif rotation == "180" then 95 | filter = "transpose=clock,transpose=clock" 96 | elseif rotation == "270" then 97 | filter = "transpose=cclock" 98 | end 99 | end 100 | filters[#filters + 1] = filter 101 | end 102 | return filters 103 | end 104 | 105 | function get_input_info(default_path, only_active) 106 | local accepted = { 107 | video = true, 108 | audio = not mp.get_property_bool("mute"), 109 | sub = mp.get_property_bool("sub-visibility") 110 | } 111 | local ret = {} 112 | for _, track in ipairs(mp.get_property_native("track-list")) do 113 | local track_path = track["external-filename"] or default_path 114 | if not only_active or (track["selected"] and accepted[track["type"]]) then 115 | local tracks = ret[track_path] 116 | if not tracks then 117 | ret[track_path] = { track["ff-index"] } 118 | else 119 | tracks[#tracks + 1] = track["ff-index"] 120 | end 121 | end 122 | end 123 | return ret 124 | end 125 | 126 | function seconds_to_time_string(seconds, full) 127 | local ret = string.format("%02d:%02d.%03d" 128 | , math.floor(seconds / 60) % 60 129 | , math.floor(seconds) % 60 130 | , seconds * 1000 % 1000 131 | ) 132 | if full or seconds > 3600 then 133 | ret = string.format("%d:%s", math.floor(seconds / 3600), ret) 134 | end 135 | return ret 136 | end 137 | 138 | function start_encoding(from, to, settings) 139 | local args = { 140 | settings.ffmpeg_command, 141 | "-loglevel", "panic", "-hide_banner", 142 | } 143 | local append_args = function(table) args = append_table(args, table) end 144 | 145 | local path = mp.get_property("path") 146 | local is_stream = not file_exists(path) 147 | if is_stream then 148 | path = mp.get_property("stream-path") 149 | end 150 | 151 | local track_args = {} 152 | local start = seconds_to_time_string(from, false) 153 | local input_index = 0 154 | for input_path, tracks in pairs(get_input_info(path, settings.only_active_tracks)) do 155 | append_args({ 156 | "-ss", start, 157 | "-i", input_path, 158 | }) 159 | if settings.only_active_tracks then 160 | for _, track_index in ipairs(tracks) do 161 | track_args = append_table(track_args, { "-map", string.format("%d:%d", input_index, track_index)}) 162 | end 163 | else 164 | track_args = append_table(track_args, { "-map", tostring(input_index)}) 165 | end 166 | input_index = input_index + 1 167 | end 168 | 169 | append_args({"-to", tostring(to-from)}) 170 | append_args(track_args) 171 | 172 | -- apply some of the video filters currently in the chain 173 | local filters = {} 174 | if settings.preserve_filters then 175 | filters = get_video_filters() 176 | end 177 | if settings.append_filter ~= "" then 178 | filters[#filters + 1] = settings.append_filter 179 | end 180 | if #filters > 0 then 181 | append_args({ "-filter:v", table.concat(filters, ",") }) 182 | end 183 | 184 | -- split the user-passed settings on whitespace 185 | for token in string.gmatch(settings.codec, "[^%s]+") do 186 | args[#args + 1] = token 187 | end 188 | 189 | -- path of the output 190 | local output_directory = settings.output_directory 191 | if output_directory == "" then 192 | if is_stream then 193 | output_directory = "." 194 | else 195 | output_directory, _ = utils.split_path(path) 196 | end 197 | else 198 | output_directory = string.gsub(output_directory, "^~", os.getenv("HOME") or "~") 199 | end 200 | local input_name = mp.get_property("filename/no-ext") or "encode" 201 | local title = mp.get_property("media-title") 202 | local extension = get_extension(path) 203 | local output_name = get_output_string(output_directory, settings.output_format, input_name, extension, title, from, to, settings.profile) 204 | if not output_name then 205 | mp.osd_message("Invalid path " .. output_directory) 206 | return 207 | end 208 | args[#args + 1] = utils.join_path(output_directory, output_name) 209 | 210 | if settings.print then 211 | local o = "" 212 | -- fuck this is ugly 213 | for i = 1, #args do 214 | local fmt = "" 215 | if i == 1 then 216 | fmt = "%s%s" 217 | elseif i >= 2 and i <= 4 then 218 | fmt = "%s" 219 | elseif args[i-1] == "-i" or i == #args or args[i-1] == "-filter:v" then 220 | fmt = "%s '%s'" 221 | else 222 | fmt = "%s %s" 223 | end 224 | o = string.format(fmt, o, args[i]) 225 | end 226 | print(o) 227 | end 228 | if settings.detached then 229 | utils.subprocess_detached({ args = args }) 230 | else 231 | local res = utils.subprocess({ args = args, max_size = 0, cancellable = false }) 232 | if res.status == 0 then 233 | mp.osd_message("Finished encoding succesfully") 234 | else 235 | mp.osd_message("Failed to encode, check the log") 236 | end 237 | end 238 | end 239 | 240 | function clear_timestamp() 241 | timer:kill() 242 | start_timestamp = nil 243 | profile_start = "" 244 | mp.remove_key_binding("encode-ESC") 245 | mp.remove_key_binding("encode-ENTER") 246 | mp.osd_message("", 0) 247 | end 248 | 249 | function set_timestamp(profile) 250 | if not mp.get_property("path") then 251 | mp.osd_message("No file currently playing") 252 | return 253 | end 254 | if not mp.get_property_bool("seekable") then 255 | mp.osd_message("Cannot encode non-seekable media") 256 | return 257 | end 258 | 259 | if not start_timestamp or profile ~= profile_start then 260 | profile_start = profile 261 | start_timestamp = mp.get_property_number("time-pos") 262 | local msg = function() 263 | mp.osd_message( 264 | string.format("encode [%s]: waiting for end timestamp", profile or "default"), 265 | timer_duration 266 | ) 267 | end 268 | msg() 269 | timer = mp.add_periodic_timer(timer_duration, msg) 270 | mp.add_forced_key_binding("ESC", "encode-ESC", clear_timestamp) 271 | mp.add_forced_key_binding("ENTER", "encode-ENTER", function() set_timestamp(profile) end) 272 | else 273 | local from = start_timestamp 274 | local to = mp.get_property_number("time-pos") 275 | if to <= from then 276 | mp.osd_message("Second timestamp cannot be before the first", timer_duration) 277 | timer:kill() 278 | timer:resume() 279 | return 280 | end 281 | clear_timestamp() 282 | mp.osd_message(string.format("Encoding from %s to %s" 283 | , seconds_to_time_string(from, false) 284 | , seconds_to_time_string(to, false) 285 | ), timer_duration) 286 | -- include the current frame into the extract 287 | local fps = mp.get_property_number("container-fps") or 30 288 | to = to + 1 / fps / 2 289 | local settings = { 290 | detached = true, 291 | container = "", 292 | only_active_tracks = false, 293 | preserve_filters = true, 294 | append_filter = "", 295 | codec = "-an -sn -c:v libvpx -crf 10 -b:v 1000k", 296 | output_format = "$f_$n.webm", 297 | output_directory = "", 298 | ffmpeg_command = "ffmpeg", 299 | print = true, 300 | } 301 | if profile then 302 | options.read_options(settings, profile) 303 | if settings.container ~= "" then 304 | msg.warn("The 'container' setting is deprecated, use 'output_format' now") 305 | settings.output_format = settings.output_format .. "." .. settings.container 306 | end 307 | settings.profile = profile 308 | else 309 | settings.profile = "default" 310 | end 311 | start_encoding(from, to, settings) 312 | end 313 | end 314 | 315 | mp.add_key_binding(nil, "set-timestamp", set_timestamp) 316 | -------------------------------------------------------------------------------- /mpv/scripts/martin.lua: -------------------------------------------------------------------------------- 1 | local io = require "io" 2 | local utils = require "mp.utils" 3 | 4 | -- Use io.write as we don't want mpv to show a [martin]: message. 5 | 6 | -- Hide cursor, and show it again on shutdown. 7 | io.write("\x1b[?25l") 8 | mp.register_event("shutdown", function() io.write("\x1b[?25h") end) 9 | 10 | -- Pause before suspending; otherwise mpv will half-read some frame (or some 11 | -- such) and audio/video is corrupted for a second on resume. Also show cursor 12 | -- on suspend, and hide it again on resume. 13 | -- 14 | -- Also need to disable ^Z signal with function wrapper: 15 | -- mpv() { stty susp '' &>/dev/null; =mpv $@; stty susp '^Z' &>/dev/null; } 16 | mp.add_forced_key_binding("ctrl+z", "c-z", function() 17 | mp.command('set pause yes') 18 | io.write("\x1b[?25h\n") 19 | 20 | mp.add_timeout(1, function() 21 | io.write("\x1b[?25l\n") 22 | mp.command('set pause no') 23 | end) 24 | 25 | utils.subprocess({args = {'kill', '-TSTP', tostring(utils.getpid())}}) 26 | end) 27 | -------------------------------------------------------------------------------- /psql/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/psqlrc': 'psqlrc', 3 | } 4 | -------------------------------------------------------------------------------- /psql/psqlrc: -------------------------------------------------------------------------------- 1 | -- Show row count of last query in prompt. 2 | -- Gosh, why did I do it like this...? There was a reason for it and it fixes 3 | -- something, but I forgot what. 4 | select :'PROMPT1'='%/%R%x%# ' as default_prompt \gset 5 | \if :default_prompt 6 | \set PROMPT1 '(%:ROW_COUNT:)%R%# ' 7 | \endif 8 | 9 | \set QUIET \\-- Don't print welcome message etc. 10 | \set HISTFILE ~/.cache/psql-history- :DBNAME \\-- Keep history per database 11 | \set HISTSIZE -1 \\-- Infinite history 12 | \set HISTCONTROL ignoredups \\-- Don't store duplicates in history 13 | \set PROMPT2 '%R%# ' \\-- No database name in the line continuation prompt. 14 | \set COMP_KEYWORD_CASE lower \\-- Complete keywords to lower case. 15 | \pset linestyle unicode \\-- Nicely formatted tables. 16 | \pset footer off \\-- Don't display "(n rows)" at the end of the table. 17 | \pset null 'NULL' \\-- Display null values as NULL 18 | \timing on \\-- Show query timings 19 | 20 | \set pretty '\\pset numericlocale' \\-- Toggle between thousands separators in numbers 21 | 22 | -- \set IGNOREEOF 2 \\-- Press ^D twice to exit. 23 | 24 | -- \set ECHO_HIDDEN ON \\-- Show "internal" queries 25 | -- \set SINGLELINE on \\-- Run query on enter 26 | -- 27 | -- TODO: Don't show ↵ for newlines 28 | 29 | -- \echo 'Using database' :DBNAME 30 | -------------------------------------------------------------------------------- /pubkey/id_ed25519.pub: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOsOVgdZ4bxWJjiHP4cS49nZLjBOKEHEKy7NaELEXWev martin@x270.arp242.net 2 | -------------------------------------------------------------------------------- /pubkey/module.py: -------------------------------------------------------------------------------- 1 | # Append public key to ~/.ssh/authorized_keys 2 | def run(): 3 | import os 4 | d = os.path.expanduser('~/.ssh') 5 | if not os.path.exists(d): 6 | os.makedirs(d) 7 | 8 | path = '{}/authorized_keys'.format(d) 9 | key = open('id_ed25519.pub', 'r').read().strip() 10 | if os.path.exists(path): 11 | if key in open(d + '/authorized_keys', 'r').read(): 12 | return 13 | 14 | with open(d + '/authorized_keys', 'a+') as fp: 15 | fp.write(key) 16 | fp.write('\n') 17 | -------------------------------------------------------------------------------- /redshift/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/redshift.conf': 'redshift.conf', 3 | } 4 | -------------------------------------------------------------------------------- /redshift/redshift.conf: -------------------------------------------------------------------------------- 1 | [redshift] 2 | temp-day=6500 3 | temp-night=4500 4 | brightness-day=1 5 | brightness-night=1 6 | 7 | ; Set the screen gamma (for all colors, or each color channel individually) 8 | ;gamma=0.8 9 | ;gamma=0.8:0.7:0.8 10 | 11 | location-provider=manual 12 | 13 | [manual] 14 | lat=51.50 15 | lon=5.45 16 | -------------------------------------------------------------------------------- /rg/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/ripgrep': 'ripgrep', 3 | } 4 | 5 | -------------------------------------------------------------------------------- /rg/ripgrep: -------------------------------------------------------------------------------- 1 | --colors=line:none 2 | --colors=match:none 3 | --colors=path:none 4 | 5 | --colors=match:fg:red 6 | --colors=line:fg:magenta 7 | --colors=path:style:bold 8 | --colors=path:style:underline 9 | 10 | --smart-case 11 | --sort=path 12 | -------------------------------------------------------------------------------- /service/xbanish/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export DISPLAY=:0 3 | export XAUTHORITY=/home/martin/.Xauthority 4 | exec xbanish -i mod4 5 | -------------------------------------------------------------------------------- /service/xcape/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export DISPLAY=:0 3 | export XAUTHORITY=/home/martin/.Xauthority 4 | exec xcape -de 'Shift_L=KP_Add' 5 | -------------------------------------------------------------------------------- /sqlite/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.sqliterc': 'sqliterc', 3 | } 4 | -------------------------------------------------------------------------------- /sqlite/sqliterc: -------------------------------------------------------------------------------- 1 | .headers on 2 | .mode box 3 | .nullvalue NULL 4 | .bail on 5 | 6 | -- .width 100 7 | -- .changes on 8 | -- pragma foreign_keys = on; 9 | -- pragma case_sensitive_like = on; 10 | -- pragma journal_mode = wal; 11 | -------------------------------------------------------------------------------- /tmux/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/tmux/tmux.conf': 'tmux.conf', 3 | } 4 | -------------------------------------------------------------------------------- /tmux/tmux.conf: -------------------------------------------------------------------------------- 1 | set -g status-keys vi # Use vi-style keys 2 | setw -g mode-keys vi 3 | set -g history-limit 10000 # Longer history 4 | set -g status-right "#h %H:%M" # Right text in status bar (short host, short time) 5 | set -g status-left "#{?client_prefix,#[bold]-P-, }" # Show "-P-" after prefix key was pressed on the right. 6 | set -g base-index 1 # Start pane & window indexing at 1 instead of 0 7 | set -g pane-base-index 1 8 | setw -g status-bg green # Status bar colours 9 | setw -g status-fg black 10 | 11 | setw -g window-status-format "#[bg=green,fg=black] #I:#W " 12 | setw -g window-status-current-format "#[bg=yellow,fg=black] #I:#W " 13 | set -g default-terminal "tmux-256color" # Make italics work; bit odd since this is already the TERM, but ah well. 14 | set -ga terminal-overrides ",*256col*:Tc" # More magic to make italics work. 15 | 16 | unbind C-b # Remove default prefix key and set prefix key to ^P 17 | set -g prefix C-p 18 | bind-key C-p send-prefix 19 | bind-key k confirm kill-window # Confirm before killing a window or the server. 20 | bind-key K confirm kill-server 21 | bind-key > swap-window -t +1\; next-window # Move window to left/right 22 | bind-key < swap-window -t -1\; previous-window 23 | bind-key C-f copy-mode\; send-key ? # Search with , instead of awkward [? 24 | bind-key f copy-mode\; send-key ? 25 | bind-key R move-window -r # Renumber windows sequentially 26 | bind-key S capture-pane -S-\; save-buffer tmux-scroll # Save scroll buffer. 27 | bind-key D attach-session -c "#{pane_current_path}" # Set directory for new panes to the current pane's path. 28 | bind-key C new-window -a # New window after the current one, instead of at the end. 29 | bind-key t set -g status # Toggle status. 30 | -------------------------------------------------------------------------------- /vim/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.vim': '.', 3 | } 4 | -------------------------------------------------------------------------------- /vim/packman.conf: -------------------------------------------------------------------------------- 1 | install_dir="$HOME/.cache/vim/pack/plugins" 2 | 3 | want_start=" 4 | godlygeek / tabular 5 | justinmk / vim-dirvish 6 | natebosch / vim-lsc 7 | romainl / vim-qf 8 | machakann / vim-swap 9 | 10 | # Filetypes 11 | daveyarwood / vim-alda # ft=alda 12 | " 13 | 14 | # https://github.com/zirrostig/vim-schlepp 15 | # https://github.com/Shougo/echodoc.vim 16 | # 17 | # vim:ft=sh 18 | -------------------------------------------------------------------------------- /vim/spell/en.utf-8.add: -------------------------------------------------------------------------------- 1 | /encoding=utf-8 2 | # Various spelling additions; added as I encounter them as I write. Not 3 | # comprehensive. Compile with :mkspell! % 4 | 5 | # Some spelling preferences. 6 | Maori/! 7 | naive/! 8 | reusable/! 9 | Māori 10 | reëvaluates 11 | reïmplementing 12 | reüsable 13 | coördinate 14 | reïmplemented 15 | 16 | # Various words that aren't in the main spellfile. 17 | COVID 18 | EULAs/= 19 | Giza 20 | Kristallnacht/= 21 | NDA/= 22 | Nuremburg/= 23 | abhorrible 24 | ableism 25 | ableist 26 | ad-hoc 27 | asshole 28 | assholery 29 | assholes 30 | asterism 31 | blogspam 32 | christmas 33 | clusterfuck 34 | cofounder 35 | coworker 36 | coworkers 37 | cruft 38 | célèbre 39 | decorational 40 | denialism 41 | feck 42 | fecking 43 | fixie 44 | frob 45 | frobbing 46 | fuckery 47 | gung-ho 48 | hackery 49 | handwaved 50 | hardline 51 | hissy 52 | hometown 53 | interpunction 54 | klansmen 55 | kthxbye 56 | math 57 | misfeatures 58 | monocultures 59 | muckery 60 | neurodivergency 61 | neurodivergent 62 | neurodiversity 63 | nondisclosure 64 | ol' 65 | ostracization 66 | paycheck 67 | payoff 68 | pedophilia 69 | predates 70 | roommate 71 | shouty 72 | significand 73 | skeptical 74 | skeptics 75 | smoothes 76 | souped-up 77 | startup 78 | startups 79 | stupidness 80 | tajine 81 | tbsp 82 | tbsp. 83 | timeframe 84 | timeframes 85 | tradeoff 86 | tsp 87 | tsp. 88 | twat 89 | unabstracted 90 | undecoded 91 | unfucking 92 | unpluralized 93 | unsubmitted 94 | watercooler 95 | webshop 96 | worldview 97 | 98 | # Some computer jargon. 99 | BDD/= 100 | CDN/= 101 | CDNs/= 102 | CLDR/= 103 | ChangeLog/= 104 | DKIM/= 105 | Dockerfile/= 106 | Dockerfiles/= 107 | EC2/= 108 | ETag/= 109 | GFDL/= 110 | GOPATH/= 111 | GPG/= 112 | GPL's/= 113 | GoatCounter/= 114 | JSON/= 115 | LSP/= 116 | Linode/= 117 | Matomo/= 118 | OOP/= 119 | PNG/= 120 | PRs/= 121 | RFCs/= 122 | SVG/= 123 | SaaS/= 124 | TOML/= 125 | TOML/= 126 | VT220/= 127 | WYSIWYG 128 | YAGNI/= 129 | YAML/= 130 | adblockers 131 | async 132 | autocmds 133 | autogenerated 134 | autoreply 135 | autowrap 136 | backend 137 | bitmask 138 | bitmasks 139 | blockquote 140 | codepoint 141 | codepoints 142 | commandline 143 | conf 144 | config 145 | crontab 146 | crypto 147 | datetime 148 | dict 149 | dir 150 | docbook 151 | filesystem 152 | filesystems 153 | filetype 154 | filetypes 155 | flexbox 156 | frontend 157 | frontends 158 | frontmatter 159 | fullscreen 160 | glibc/= 161 | globals 162 | globbing 163 | godoc 164 | goroutine 165 | goroutines 166 | hostname 167 | i386/= 168 | keybind 169 | keybinds 170 | keyrings 171 | libre 172 | linebreaks 173 | linter 174 | linters 175 | lowercase 176 | mbox/= 177 | metacharacters 178 | microkernel 179 | microkernels 180 | microservice 181 | microservices 182 | minifier 183 | minifiers 184 | monorepos 185 | monospace 186 | multibyte 187 | multiline 188 | pageview 189 | pageviews 190 | plugin 191 | plugins 192 | png 193 | popup 194 | quickfix 195 | regex 196 | regexp 197 | screensaver 198 | src 199 | stderr 200 | stdin 201 | stdlib 202 | stdout 203 | struct 204 | structs 205 | stylesheet 206 | subtest 207 | subtests 208 | tagsoup 209 | teletype 210 | teletypes 211 | terminfo 212 | timesharing 213 | toolchain 214 | uncropped 215 | unexported 216 | unicode 217 | unkeyed 218 | userbase 219 | varchar 220 | vendored 221 | vendoring 222 | vimrc 223 | webapp 224 | webhook 225 | webhooks 226 | whitespace 227 | wildcard 228 | wildcards 229 | 230 | # Program names. 231 | amixer/= 232 | chmod/= 233 | chown/= 234 | chroot/= 235 | csh/= 236 | dmenu/= 237 | fetchmail/= 238 | gcc/= 239 | gofmt/= 240 | grep/= 241 | httpd/= 242 | ksh/= 243 | makepkg/= 244 | npm/= 245 | openssl/= 246 | pactl/= 247 | pf/= 248 | printf/= 249 | sendmail/= 250 | setopt/= 251 | sftp/= 252 | ssh/= 253 | sxiv/= 254 | systemd/= 255 | tmux/= 256 | xbacklight/= 257 | xbps/= 258 | zsh/= 259 | 260 | # Product and organisation names. 261 | Baskerville/= 262 | Bitbucket/= 263 | CentOS/= 264 | CoffeeScript/= 265 | Debian's/= 266 | Django/= 267 | DragonFly/= 268 | Equifax/= 269 | Ericson/= 270 | FRC/= 271 | FSF/= 272 | GDB/= 273 | GNU's/= 274 | GTK/= 275 | GitHub/= 276 | HN/= 277 | Harvard's/= 278 | Hurd/= 279 | Inkscape/= 280 | Instagram/= 281 | Kubernetes/= 282 | Log4J/= 283 | Lua 284 | MSX/= 285 | Mailgun/= 286 | MariaDB/= 287 | MediaWiki's/= 288 | MediaWiki/= 289 | MessagePack/= 290 | Microsystems/= 291 | Minix/= 292 | MongoDB/= 293 | MySQL/= 294 | Neovim/= 295 | Netlify/= 296 | OSI/= 297 | OpenAPI/= 298 | POSIX/= 299 | Plesk/= 300 | PostgreSQL/= 301 | PowerShell/= 302 | PragerU/= 303 | QNX/= 304 | Quillette/= 305 | RIAA/= 306 | Reddit's/= 307 | Reddit/= 308 | Redis/= 309 | SCO/= 310 | SPLC's/= 311 | SPLC/= 312 | SQLite/= 313 | SecureWorks/= 314 | Symbolics/= 315 | TECO's/= 316 | TECO/= 317 | Tcl/= 318 | ThinkPad/= 319 | Trolltech/= 320 | TypeScript/= 321 | Unilogic/= 322 | UpWork/= 323 | Vim9/= 324 | VimScript/= 325 | Vimeo/= 326 | Vox/= 327 | WebDAV/= 328 | WebKit/= 329 | WhatsApp/= 330 | XFree86/= 331 | iframe 332 | jQuery/= 333 | k8s/= 334 | macOS/= 335 | qutebrowser/= 336 | suckless/= 337 | 338 | # People 339 | Allman/= 340 | Breitbart/= 341 | Breivik/= 342 | Brenton/= 343 | Dmitry/= 344 | Eben/= 345 | Engelbart's/= 346 | Engelbart/= 347 | Geller's/= 348 | Geller/= 349 | Lessig/= 350 | Lippman's/= 351 | Lippman/= 352 | Maajid/= 353 | Moglen's/= 354 | Moglen/= 355 | Multatuli/= 356 | Nawaz/= 357 | Ousterhout's/= 358 | Ousterhout/= 359 | Perens/= 360 | Phillip/= 361 | Prager's/= 362 | Prager/= 363 | RMS/= 364 | Rossum/= 365 | Tanenbaum/= 366 | Tarrant/= 367 | Torvalds/= 368 | Tournoij/= 369 | Vixie/= 370 | Willison/= 371 | 372 | # Unsorted (zg'd). 373 | subpackage 374 | omitempty 375 | uncomparable 376 | fsnotify 377 | accessor 378 | backends 379 | inotify 380 | kqueue 381 | fallbacks 382 | losslessly 383 | filesize 384 | illumos 385 | EPP 386 | Gransy 387 | -------------------------------------------------------------------------------- /vim/spell/en.utf-8.add.spl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arp242/dotfiles/9ade6749548e9c16e5ede1c176e58c33f4e2371f/vim/spell/en.utf-8.add.spl -------------------------------------------------------------------------------- /vim/vimrc: -------------------------------------------------------------------------------- 1 | vim9script 2 | set encoding=utf-8 # Make sure UTF-8 is used. 3 | scriptencoding utf-8 4 | set nocompatible # Ensure it works with 'vim -u' 5 | syntax on # Switch syntax highlighting on. 6 | filetype plugin indent on # Enable filetype detection. 7 | if $TERM =~ '256color' 8 | set termguicolors # Use true colors. 9 | &t_8f = "\[38;2;%lu;%lu;%lum" # Set correct escape codes to make termguicolors work in st. 10 | &t_8b = "\[48;2;%lu;%lu;%lum" 11 | &t_SI = "\[3 q" # Start Insert; set cursor to underline (1=block, 3=underline, 5=bar). 12 | &t_SR = &t_SI # Start Replace. 13 | &t_EI = "\[1 q" # End Insert (or Replace), set back to block cursor. 14 | endif 15 | set background=light # Sometimes gets overridden or changed from the default by distros. 16 | silent! colorscheme default2 # Load my color scheme if it exists. 17 | set backspace=indent,eol,start # Allow backspacing over everything. 18 | set history=500 # Keep 500 lines of command line history. 19 | set incsearch # Jump to match while typing the pattern in /. 20 | set hlsearch # Highlight last used search pattern. 21 | set ignorecase # Case-insensitive searching unless \C is in the pattern… 22 | set smartcase # …or the pattern contains an upper-case letter. 23 | set nowrapscan # Don't wrap search. 24 | set gdefault # Always use the /g flag with :s; add /g to restore the default. 25 | set textwidth=80 # Wrap at at 80 characters. 26 | set linebreak # Wrap at word. 27 | set showbreak=↪ # Display at the start of line for wrapped lines. 28 | set noshowmode # Don't show mode in cmdline. 29 | set breakindent # When wrapping show next line on the same indent level. 30 | set breakindentopt=sbr,list:-1 # sbr → Display showbreak before indent. 31 | # list → indent list if it matches formatlistpat 32 | set autoindent # Copy indent from current line when starting a new line. 33 | set copyindent # Copy indent for new lines when auto-indenting. 34 | set shiftround # Round indent to multiple of shiftwidth when using < and > 35 | set backup # Keep backup file when writing. 36 | set backupext=.bak # Extension for backup files (modified in autocmd below). 37 | set backupskip=/tmp/* # No backup for these files. 38 | set listchars=tab:!·,trail:· # String to use in 'list' mode. 39 | set spelllang=en_gb # Default language for spell check. 40 | set spelloptions=camel # Spellcheck CamelCase words separately. 41 | set helplang=en langmenu=en # Always use English in help and UI. 42 | set scrolloff=2 # Minimum number of lines to keep above/below cursor. 43 | silent! set smoothscroll # Scroll (wrapped) screenlines, rather than actual lines. 44 | set wildmenu # Better tab completion at the command-line. 45 | set wildmode=longest:full # Complete longest match, list other matches in wildmenu. 46 | set wildignorecase # Case is ignored when completing file names and directories. 47 | set wildignore+=*.o,*.png,*.jpg,*.jpeg,*.webp,*.gif # Ignore these files in completion. 48 | set wildoptions=pum # Show pop-up menu. 49 | set wildcharm= # Trigger wild mode from mappings/macros. 50 | set completeopt=menuone,noselect # Insert mode completion: 51 | # menuone → always show menu, even when there is 1 match. 52 | # noselect → don't select an option when starting. 53 | set completepopup=highlight:Pmenu,border:off # Options for preview popup in completion. 54 | set pumheight=10 # Don't make completion menu too high. 55 | set previewheight=6 # Height of preview window. 56 | set infercase # Like smartcase for insert completion. 57 | set tabpagemax=500 # Max. number of tabs to be open with -p argument or :tab all. 58 | set showcmd # Show partial command in the last line of the screen. 59 | set nojoinspaces # Don't add two spaces after interpunction when using J. 60 | set smarttab # Backspace at start of line remove shiftwidith worth of space. 61 | set matchpairs+=<:> # Also match < & > with %. 62 | set switchbuf=useopen,usetab,newtab # Use open tab (if any) when trying to jump to a quickfix error. 63 | set noexpandtab # Real men use real tabs… 64 | set tabstop=4 # …which are 4 spaces wide. 65 | set shiftwidth=0 # Use tabstop value. 66 | set softtabstop=-1 # Use shiftwidth value. 67 | set synmaxcol=500 # Maximum column in which to search for syntax items. 68 | set t_ti= t_te= # Prevent clearing the terminal on exit. 69 | set mouse= # I don't want mouse support. 70 | set nrformats=bin,hex,unsigned # Don't increment octal numbers, and ignore '-' in front of nrs. 71 | set paragraphs= # Don't include nroff stuff. 72 | set tildeop # Use ~ as an operator to switch case. 73 | set clipboard= # Never automatically interface with system clipboard. 74 | set nofoldenable # Disable folds by default. 75 | set undofile # Save undo to file. 76 | set notitle # Don't update term title. 77 | set nowarn # :! doesn't warn if buffer is unsaved. 78 | set shortmess-=S # Show match count on n. 79 | set shortmess+=aFI # a: abbreviate a few things 80 | # F: don't show file info with :edit etc. 81 | # I: don't show :intro message 82 | set virtualedit=block # Allow virtual editing in visual block mode. 83 | &ttyfast = $SSH_CLIENT == '' # Assume the terminal is fast for smoother redrawing. 84 | set display=lastline,uhex # lastline → Show as much of the last line as possible instead of @. 85 | # uhex → Always show unprintable chars as instead of ^C. 86 | set updatecount=50 # Write to swap every 50 characters. 87 | set formatoptions+=ncroqlj # n Recognize numbered lists when formatting (see formatlistpat) 88 | # c Wrap comments with textwidth 89 | # r Insert comment char after enter 90 | # o Insert comment char after o/O 91 | # q Format comments with gq 92 | # l Don't break lines when they were longer than textwidth to start with. 93 | # j Remove comment character when joining lines with J. 94 | &diffopt = [ 95 | 'internal', # Use internal library rather than external shell tool. 96 | 'filler', # Show filler lines. 97 | 'closeoff', # Run :diffoff when closing the other split. 98 | 'indent-heuristic', # Better detection of whitespace diffs. 99 | 'algorithm:histogram', # Better algorithm 100 | 'foldcolumn:0' # Don't reset foldcolumn for diff files. 101 | ]->join(',') 102 | &formatlistpat = '\v^\s*%(\d+[:.\)\t ]|-)\s+' # Indent lines that start with '- ' too. 103 | &fillchars = [ 104 | 'vert: ', # Don't show fill for vsplit or removed diff lines; colour is enough. 105 | 'diff: ', 106 | 'fold: ', 107 | 'foldopen:┌', # text in foldcolumn 108 | 'foldsep:│', 109 | 'stl:━', # Bold line for active statusline 110 | 'stlnc:╌', # And dashed line for inactive 111 | ]->join(',') 112 | 113 | hi StatusLine ctermbg=black ctermfg=white 114 | hi StatusLineNC ctermbg=black ctermfg=white 115 | 116 | # Set/create directory to keep backup, swap, undo files. 117 | set backupdir=~/.cache/vim/backup// |call mkdir(&backupdir, 'p', 0o700) 118 | set directory=~/.cache/vim/swap |call mkdir(&directory, 'p', 0o700) 119 | set undodir=~/.cache/vim/undo |call mkdir(&undodir, 'p', 0o700) 120 | 121 | # Set viminfo file location unless explicitly turned off. 122 | if &viminfofile != 'NONE' | set viminfofile=$HOME/.cache/vim/viminfo | endif 123 | 124 | set laststatus=0 # Never show statusline 125 | &statusline = ' ' # Blank statusline 126 | set showtabline=2 # Always show tabline 127 | 128 | # Use the tabline as 'statusline' by putting the cursor position in there. 129 | def! g:Tabline(): string 130 | # Get list of all tabs, together with the flags and name we want to display. 131 | var tabs = [] 132 | var tabs_len = 0 133 | var sel_len = 0 134 | var sel_idx = 0 135 | var tabinfo = gettabinfo() 136 | 137 | for i in range(0, tabinfo->len() - 1) 138 | var t = tabinfo[i] 139 | 140 | # Get focused window. 141 | var focus = tabpagewinnr(t.tabnr)->win_getid(t.tabnr) 142 | var w = {} 143 | for wid in t.windows 144 | if wid == focus 145 | w = getwininfo(wid)[0] 146 | break 147 | endif 148 | endfor 149 | 150 | var sel = bufwinid(w.bufnr) == w.winid 151 | var is_help = getbufvar(w.bufnr, '&ft') == 'help' 152 | var is_dir = getbufvar(w.bufnr, '&ft') == 'dirvish' 153 | 154 | var n = bufname(w.bufnr)->fnamemodify(':.') ?? '[No Name]' 155 | var f = len(t.windows) > 1 ? len(t.windows)->string() : '' 156 | if is_help 157 | f ..= ':h' 158 | n = fnamemodify(n, ':t') 159 | elseif getbufvar(w.bufnr, '&modified') 160 | f ..= '+' 161 | elseif (!getbufvar(w.bufnr, '&modifiable') || getbufvar(w.bufnr, '&readonly')) && !is_help 162 | if !getbufvar(w.bufnr, 'had_swap')->empty() 163 | f ..= 'S' 164 | endif 165 | f ..= '-' 166 | endif 167 | 168 | if n =~ $HOME # Always using :~ means 'vi file' would become ~/file 169 | n = fnamemodify(n, ':~') 170 | endif 171 | 172 | # Show only first character of every directory entry. 173 | var slash = stridx(n, '/') 174 | #if slash > -1 && slash != len(n) - 1 175 | if !sel && slash > -1 && slash != len(n) - 1 176 | var l = n->split('/') 177 | n = l->map((j, v) => j == len(l) - 1 ? v : v[: (v[0] == '.' ? 1 : 0)])->join('/') 178 | if is_dir # Gets lost otherwise 179 | n ..= '/' 180 | endif 181 | endif 182 | 183 | tabs_len += len(n) 184 | if sel 185 | sel_len = len(n) 186 | sel_idx = i 187 | endif 188 | add(tabs, {name: n, fname: n, flags: f, sel: sel}) 189 | endfor 190 | 191 | # Create string for the right-hand side. 192 | var right = line('.') .. '/' .. line('$') .. ' ' .. virtcol('.') 193 | 194 | var [tr_left, tr_right] = ['', ''] 195 | # TODO: do this better; we want to make sure the active tab is always "in 196 | # view", and show indicators of how many more there are. e.g. 197 | # <4 file1 file2 file3 1> 198 | # Different from how standard tabline works, but makes more sense IMO. 199 | if tabs_len > &columns - len(right) 200 | # tr_left = '%#TabLineMore#…' .. (sel_idx) .. '%#TabLine#' 201 | # tr_right = '%#TabLineMore#' .. (len(tabs) - sel_idx - 1) .. '…%#TabLine#' 202 | # tabs = tabs[sel_idx - 3 : sel_idx + 3] 203 | 204 | # var trim_by = (&columns - 24 - sel_len) / len(tabs) - 1 205 | # for i in range(0, len(tabs) - 1) 206 | # if tabs[i].sel 207 | # continue 208 | # endif 209 | # var l = len(tabs[i].name) - trim_by 210 | # l = [l, len(tabs[i].name) - 4]->min() 211 | 212 | # tabs[i].name = tabs[i].name[l :] 213 | # endfor 214 | endif 215 | 216 | # Create string for statusline 217 | var tabstr = tr_left 218 | for t in tabs 219 | if t.sel 220 | tabstr ..= '%#TabLineSel#' 221 | endif 222 | 223 | if t.flags != '' 224 | tabstr ..= ' ' .. t.flags 225 | endif 226 | 227 | tabstr ..= ' ' .. t.name .. ' ' 228 | if t.sel 229 | tabstr ..= '%#TabLine#' 230 | endif 231 | endfor 232 | tabstr ..= tr_right 233 | 234 | return '%#TabLine#' .. tabstr .. '%#TablineFill#%=' .. right 235 | enddef 236 | set tabline=%!Tabline() 237 | 238 | # Redraw tabline when the cursor moves. 239 | augroup my-tabline 240 | au! 241 | au CursorMoved,CursorMovedI * :redrawtabline 242 | augroup end 243 | 244 | 245 | ### Autocmds 246 | ############ 247 | augroup my-autocmds 248 | au! 249 | 250 | # Don't ask to reload buffers changed on disk; you still get error on write 251 | au FileChangedShell * v:fcs_choice = 0 252 | 253 | au SwapExists * { 254 | v:swapchoice = 'o' # Never bug me if a swap file already exists; just open as read-only 255 | b:had_swap = 1 # For display in the statusline/tabline 256 | } 257 | 258 | # Go to the last cursor location when a file is opened unless this is a git commit. 259 | au BufReadPost * { 260 | if line("'\"") > 1 && line("'\"") <= line("$") && &filetype != 'gitcommit' 261 | exe 'normal! g`"' 262 | endif 263 | } 264 | 265 | # Disable indent in visual block mode; it's often annoying when inserting 266 | # text with I, which changes the alignment of the first line only and 267 | # mucks up the text for the other lines. 268 | au ModeChanged *:[\x16] { 269 | b:save_indent = [&l:indentexpr, &l:autoindent, &l:cindent, &l:smartindent] 270 | setl indentexpr= noautoindent nocindent nosmartindent 271 | } 272 | au ModeChanged [\x16]:* { 273 | if get(b:, 'save_indent', [])->len() > 0 274 | &l:indentexpr = b:save_indent[0] 275 | &l:autoindent = b:save_indent[1] 276 | &l:cindent = b:save_indent[2] 277 | &l:smartindent = b:save_indent[3] 278 | unlet b:save_indent 279 | endif 280 | } 281 | 282 | # Don't spellcheck urls. 283 | au BufReadPost * syn match UrlNoSpell '\w\+:\/\/[^[:space:]]\+' contains=@NoSpell 284 | 285 | # Filetype overrides. 286 | au Filetype awk setl et 287 | au Filetype css setl isk+=- 288 | au Filetype html setl textwidth=100 indentexpr= 289 | au Filetype gotxt { 290 | if expand('%:p')->stridx('/db/') != -1 291 | set ft=sql 292 | endif 293 | } 294 | au Filetype javascript hi def link javaScriptValue Number 295 | au Filetype lua hi link luaTable Normal 296 | au filetype make setl ts=8 297 | au Filetype markdown { 298 | setl expandtab noshiftround 299 | hi markdownError ctermbg=NONE 300 | } 301 | au Filetype python { 302 | setl ts=4 303 | # g:python_indent = {} 304 | # g:pyindent_open_paren = 'shiftwidth()' 305 | # g:pyindent_continue = 'shiftwidth()' 306 | } 307 | au Filetype vim { 308 | setl keywordprg=:tab\ help 309 | silent! syn clear vimCommentString vimCommentTitle 310 | silent! hi vimSep guifg=NONE 311 | } 312 | au Filetype yaml setl expandtab ts=2 313 | au Filetype zsh hi link zshTypes Statement 314 | augroup end 315 | 316 | ### Commands 317 | ############ 318 | 319 | # Convert buffer to and from scratch. 320 | command S { 321 | if &buftype == 'nofile' 322 | setl swapfile buftype= bufhidden= 323 | else 324 | setl noswapfile buftype=nofile bufhidden=hide 325 | endif 326 | echo printf('swapfile=%s buftype=%s bufhidden=%s', &swapfile, &buftype, &bufhidden) 327 | } 328 | 329 | # Clean trailing whitespace. 330 | command TrimWhitespace { 331 | var save = winsaveview() 332 | keeppattern :%s/\s\+$//e 333 | winrestview(save) 334 | } 335 | 336 | # Sort whitespace separated words. 337 | command SortWords { 338 | getline('.')->trim()->split('')->sort()->join(' ')->setline('.') 339 | } 340 | 341 | # Call uni on current character or visual selection. 342 | command -range UnicodeName { 343 | var save = @a 344 | if == -1 345 | @a = strcharpart(strpart(getline('.'), col('.') - 1), 0, 1) 346 | else 347 | exe 'normal! gv"ay' 348 | endif 349 | echo system('uni -q i', @a)[: -2] 350 | @a = save 351 | } 352 | 353 | # Sum up all numbers in a selection. This removes all non-numbers, so that it 354 | # works when summing lines that also contain text, as a "poor man's 355 | # spreadsheet". Use (block) visual mode to only sum one "column". 356 | command -range Sum { 357 | var lines = getline(, )->join(' ') 358 | 359 | # Get visual selection if last visual mode was block. This is far from 360 | # ideal, since "select some text, escape, run :%Sum" will give the wrong 361 | # results, but as far as I can find it's the best we can do. 362 | if visualmode() == "" 363 | var save = @a 364 | exe 'silent normal! gv"ay' 365 | lines = @a->substitute('\n', ' ', 'g') 366 | @a = save 367 | endif 368 | 369 | var t = 0.0 370 | for n in lines->substitute('[^0-9 \t.-]', '', 'g')->split('\s\+') 371 | t += n->str2float() 372 | endfor 373 | echom printf('Total: %f', t)->trim('0', 2)->trim('.', 2) 374 | } 375 | 376 | # Load the output of a command in the current buffer. 377 | command -complete=command -nargs=+ Load call( 378 | \ (getline(1, '$')->filter((_, v) => len(v) > 0)->len() == 0 ? 'setline' : 'append'), 379 | \ ['.', execute()->split('\n')]) 380 | 381 | ### Mappings 382 | ############ 383 | 384 | # Reload config. 385 | nnoremap r :source $MYVIMRC:doautocmd Filetype:echo 'reloaded ' .. $MYVIMRC 386 | 387 | # Some useful-ish toggles. 388 | # TODO: show a menu on just t, and we can add some other options. 389 | # Maybe put in "toggle.vim" plugin. 390 | nnoremap tl :setl list!:setl list? 391 | nnoremap tc :setl cursorcolumn!:setl cursorcolumn? 392 | nnoremap tC :setl cursorline!:setl cursorline? 393 | nnoremap ts :setl shiftround!:setl shiftround? 394 | 395 | # Switch spell check languages 396 | nnoremap ss :setl spell!:setl spell? 397 | nnoremap sn :setl spelllang=nl 398 | nnoremap se :setl spelllang=en_gb 399 | 400 | # Use to clear some highlighting, and make sure it works from insert mode. 401 | nnoremap :nohlsearch:setl nolist nospell:diffupdate 402 | inoremap :exe "normal \" 403 | # Sync syntax too. 404 | nnoremap l :syntax sync fromstart 405 | 406 | # Use ; instead of :, bit easier as you don't need shift. 407 | #nnoremap ; : 408 | 409 | # We don't need ex mode; use it for formatting. 410 | noremap Q gq 411 | 412 | # Bloody annoying. 413 | nnoremap q: :q 414 | 415 | # Interface with system clipboard. 416 | noremap y "*y 417 | noremap p "*p 418 | noremap Y "+y 419 | noremap P "+p 420 | 421 | # Indent in visual and select mode automatically re-selects. 422 | vnoremap > >gv 423 | vnoremap < n 'Nn'[v:searchforward] 427 | nnoremap N 'nN'[v:searchforward] 428 | 429 | # Don't move cursor on * and # 430 | nnoremap * :let @/ = '\<'..expand('')..'\>' \| :call histadd('/', @/) \| :set hlsearch 431 | nmap # * 432 | 433 | # Use visual movement rather than line movement. 434 | nnoremap k gk 435 | nnoremap j gj 436 | nnoremap gk 437 | nnoremap gj 438 | inoremap pumvisible() ? "\" : "\gk" 439 | inoremap pumvisible() ? "\" : "\gj" 440 | 441 | # Suspend also works from insert. 442 | inoremap 443 | 444 | # Doc on in insert. 445 | inoremap :silent! normal! K 446 | 447 | # Use for history, as I use as the tmux prefix key. 448 | cnoremap 449 | 450 | # Readline-y mappings 451 | inoremap ^ 452 | cnoremap 453 | inoremap col('.') > strlen(getline('.')) \|\| pumvisible() ? "\" : "\" 454 | 455 | # Use a reasonable completion. 456 | def guessType(): string 457 | if &completefunc != '' | return "\\" 458 | elseif &omnifunc != '' | return "\\" 459 | else | return "\\" 460 | endif 461 | enddef 462 | inoremap pumvisible() ? "\" : guessType() 463 | nnoremap pumvisible() ? "i\" : 'i' .. guessType() 464 | 465 | # Always insert spaces after non-whitespace, unless colorcolumn is enabled, in 466 | # which case cc_align to align with that. 467 | inoremap &cc == '' ? (getline('.')[: col('.') - 2] =~ '^\s*$' ? "\" : repeat(' ', (virtcol('.') % shiftwidth()) + 1)) : cc_align#tab() 468 | 469 | # Make go to the next entry when using the popupmenu from commandline 470 | # completion. 471 | cnoremap pumvisible() ? '' : "\" 472 | 473 | # Yank without clobbering registers. 474 | nnoremap dD "_dd 475 | 476 | # Replace the current line with the unnamed register. 477 | nnoremap RR "_ddP 478 | 479 | # Write and run :make. 480 | nnoremap MM :silent! :wa:echo &makeprg:silent make:redraw! 481 | 482 | # Close all windows except the current one. 483 | nnoremap OO :silent wincmd o 484 | 485 | # Open tabs faster. 486 | nnoremap TT :tabe 487 | nnoremap HH :tab h 488 | 489 | # Open current directory in new tab. 490 | nnoremap d :tabe %:h 491 | 492 | # Don't do anything on space in insert mode; it's almost always an accident. 493 | nnoremap 494 | 495 | # gf and gF opens in a tab. 496 | nnoremap gf gf 497 | vnoremap gf gf 498 | nnoremap gF gF 499 | vnoremap gF gF 500 | 501 | # Navigate tabs 502 | nnoremap gT 503 | nnoremap gt 504 | inoremap gT 505 | inoremap gt 506 | 507 | # I often mistype this :-/ 508 | cabbr Set set 509 | cabbr Help help 510 | cabbr tane tabe 511 | cabbr ta tabe 512 | iabbr teh the 513 | iabbr hte the 514 | iabbr Teh The 515 | iabbr seperated separated 516 | iabbr seperate separate 517 | iabbr taht that 518 | 519 | # Makes stuff a bit easier to type. 520 | iabbr 1= != 521 | iabbr ;= := 522 | iabbr :+ := 523 | iabbr err1= err != 524 | iabbr err!= err != 525 | 526 | # Add/remove word delimiters in search pattern. 527 | # word → \ → word 528 | def wrap(): string 529 | var l = getcmdline() 530 | var pos = getcmdpos() 531 | # Remove 532 | if l[: 1] == '\<' && l[-2 :] == '\>' 533 | setcmdpos(pos - 2) 534 | return l[2 : len(l) - 3] 535 | endif 536 | # Add 537 | if l[: 1] != '\<' 538 | l = '\<' .. l 539 | pos += 2 540 | endif 541 | if l[-2 :] != '\>' 542 | l ..= '\>' 543 | endif 544 | setcmdpos(pos) 545 | return l 546 | enddef 547 | cnoremap index(['/', '?'], getcmdtype()) == -1 ? "\" : "\ewrap()\" 548 | 549 | ### Plugins 550 | ########### 551 | g:loaded_netrwPlugin = 1 552 | 553 | ### switchy.vim 554 | nnoremap a :call switchy#switch('tabedit', 'sbuf') 555 | 556 | ### lazy.vim 557 | def R(file: string): list 558 | var f = $HOME .. '/.vim/snip/' .. file 559 | return filereadable(f) ? readfile(f) : [] 560 | enddef 561 | g:lazy_snippets = { 562 | go: { 563 | err-simple: "if err != nil {\n\treturn err\n}", 564 | err-wrap: "if err != nil {\n\treturn fmt.Errorf(\"\b: %w\", err)\n}", 565 | err-test: "if have != want {\n\tt.Errorf(\"\\nhave: %s\\nwant: %s\", have, want)\n}", 566 | test: R('/test.go'), 567 | bench: R('/bench.go'), 568 | }, 569 | html: { 570 | doc: R('/base.html'), 571 | }, 572 | } 573 | 574 | ### vim-dirvish 575 | ############### 576 | g:dirvish_relative_paths = 1 # Make paths in the Dirvish buffer relative to getcwd(). 577 | 578 | fun open() abort 579 | let line = getline('.') 580 | let ext = fnamemodify(line, ':e') 581 | if ext =~ '\v^%(mp[34]|mkv|avi|ogg|m4a|opus)$' 582 | exe '!mpv ' .. fnameescape(line) 583 | elseif ext =~ '\v^%(pdf)$' 584 | exe '!firefox ' .. fnameescape(line) .. ' &' 585 | else 586 | call dirvish#open('edit', 0) 587 | endif 588 | endfun 589 | 590 | augroup my-dirvish 591 | au! 592 | au Filetype dirvish { 593 | # Open non-text files. 594 | # n *@:.call dirvish#open("edit", 0) 595 | nnoremap :.call open() 596 | 597 | # Q instead of gq is nicer. 598 | nmap Q (dirvish_quit) 599 | # Add tab mappings 600 | nnoremap t :call dirvish#open('tabedit', 0) 601 | xnoremap t :call dirvish#open('tabedit', 0) 602 | # Make new directory 603 | nnoremap M :let _d=input('mkdir ', '', 'dir'):call mkdir(_d, 'p'):exe 'e ' .. _d:unlet _d 604 | # Make new file 605 | nnoremap C :let _d=input('edit ', '', 'dir'):exe 'e ' .. _d:unlet _d 606 | # Launch shell in cwd 607 | nnoremap ! :lcd %:silent exec '!' .. (has('gui_running') ? 'st -e ' : '') .. $SHELL 608 | } 609 | augroup end 610 | 611 | ### gopher.vim 612 | g:gopher_debug = ['commands', 'setup'] 613 | g:gopher_highlight = ['string-spell', 'string-fmt'] 614 | augroup my-gopher 615 | au! 616 | au Filetype go { 617 | # Make ! stand out a bit more in '!foo'. 618 | syn match goBang /!\ze[^=]/ 619 | hi goBang gui=bold cterm=bold 620 | # Compile without cgo unless explicitly enabled. 621 | if $CGO_ENABLED == '' | $CGO_ENABLED = 0 | endif 622 | } 623 | 624 | # Quick replace for go.mod 625 | au Filetype gomod comm! -nargs=1 Replace append(4, printf('replace zgo.at/%s => ../../Golib/%s', , )) 626 | 627 | # Format buffer on write; https://vi.stackexchange.com/questions/7116 628 | au BufWritePre *.go { 629 | var save = winsaveview() 630 | silent! exe 'undojoin | keepjumps :%!goimports -local exams-api 2>/dev/null || cat /dev/stdin' 631 | winrestview(save) 632 | } 633 | 634 | # Replace tabs in comments. 635 | # au BufWritePre *.go { 636 | # var save = winsaveview() 637 | # keepjumps s!//[\t ]+!\='//' .. substitute('\t', ' ') ! 638 | # winrestview(save) 639 | # } 640 | augroup end 641 | 642 | ### vim-qf 643 | # g:qf_auto_open_quickfix = 1 # Automatically open qfix and loclist. 644 | # g:qf_auto_open_loclist = 1 645 | #g:qf_auto_quit = 0 # Breaks with tabs. 646 | # augroup my-qf 647 | # au! 648 | # # Close list when entering tabs and they're empty. 649 | # au TabEnter * { 650 | # if len(getqflist()) == 0 651 | # cclose 652 | # # else 653 | # # qf#OpenQuickfix() 654 | # # wincmd w 655 | # endif 656 | # } 657 | # augroup end 658 | 659 | # Go to next/prev error; need to use escape codes as isn't reliable. 660 | nmap (qf_qf_previous) 661 | nmap [D > (qf_qf_previous) 662 | nmap [1;5D (qf_qf_previous) 663 | nmap (qf_qf_next) 664 | nmap [C (qf_qf_next) 665 | nmap [1;5C (qf_qf_next) 666 | 667 | # Toggle quickfix list. 668 | nmap (qf_qf_toggle_stay) 669 | nmap [A (qf_qf_toggle_stay) 670 | nmap [1;5A (qf_qf_toggle_stay) 671 | 672 | ### vim-lsc 673 | g:lsc_server_commands = { 674 | go: {command: 'gopls serve', log_level: -1, suppress_stderr: v:true}, 675 | c: {command: 'clangd', log_level: -1, suppress_stderr: v:true}, 676 | cpp: {command: 'clangd', log_level: -1, suppress_stderr: v:true}, 677 | sql: {command: 'sqls', log_level: -1, suppress_stderr: v:true}, 678 | 'sql.runbuf': {command: 'sqls', log_level: -1, suppress_stderr: v:true}, 679 | rust: {command: 'rust-analyzer', log_level: -1, suppress_stderr: v:true}, 680 | zig: {command: 'zls', log_level: -1, suppress_stderr: v:true}, 681 | } 682 | g:lsc_enable_autocomplete = v:false # Don't complete when typing. 683 | g:lsc_enable_diagnostics = v:false # Don't lint code. 684 | g:lsc_reference_highlights = v:false # Don't highlight references. 685 | #g:lsc_enable_incremental_sync = v:false # Don't constantly send diffs to server. 686 | #g:lsc_preview_split_direction = 'below' # Show preview at bottom, rather than top. 687 | 688 | g:lsc_auto_map = {defaults: v:true, GoToDefinitionSplit: ''} 689 | augroup my-lsc 690 | au! 691 | # Open in tab, rather than split. 692 | au BufNewFile,BufReadPost * { 693 | if has_key(get(g:, 'lsc_servers_by_filetype', {}), &filetype) && lsc#server#filetypeActive(&filetype) 694 | nnoremap gd :tab LSClientGoToDefinitionSplit 695 | endif 696 | } 697 | augroup end 698 | 699 | ### runbuf.vim 700 | g:runbuf_commands = {gc: 'psql goatcounter'} 701 | g:runbuf_map = '' 702 | augroup my-runbuf 703 | au! 704 | au Filetype *.runbuf { 705 | nnoremap :echo win_execute(win_getid(bufnr(b:output)), "normal! 3\C-e>") 706 | nnoremap :echo win_execute(win_getid(bufnr(b:output)), "normal! 3\C-y>") 707 | } 708 | augroup end 709 | 710 | ### xdg_open.vim 711 | g:xdg_open_match = '&filetype == "dirvish" ? getline(".") : expand("")' 712 | fun g:MyOpen() 713 | if &filetype == 'dirvish' 714 | return getline(".") 715 | elseif expand('') =~ '^#\d\+' 716 | return 'https://github.com/arp242/' .. expand('%:p:h:t') .. '/issues/' .. expand('') 717 | else 718 | return expand('') 719 | endif 720 | endfun 721 | g:xdg_open_match = 'MyOpen()' 722 | 723 | # g:xdg_open_match = { -> &filetype == "dirvish" ? getline(".") : expand("") } 724 | # g:Xdg_open_match = () => &filetype == "dirvish" ? getline(".") : expand("") 725 | 726 | nnoremap g. :let [@,, @;] = [@;, ''] 727 | 728 | silent! set shortmess+=e! 729 | 730 | 731 | defcompile # Compile functions so we get errors on startup. 732 | # vim: et 733 | -------------------------------------------------------------------------------- /x11/Xmodmap: -------------------------------------------------------------------------------- 1 | ! CapsLock is CTRL 2 | remove Lock = Caps_Lock 3 | keysym Caps_Lock = Control_L 4 | add Control = Control_L 5 | 6 | ! Right Alt is compose 7 | keysym Alt_R = Multi_key 8 | 9 | ! Right Alt is compose 10 | keysym Alt_R = Multi_key 11 | 12 | ! xmodmap -e "Pointer_Button4 = Tab" 13 | 14 | ! keysym KP_Home = minus underscore 15 | ! keysym KP_8 = equal plus 16 | 17 | ! vim:ft=xmodmap 18 | -------------------------------------------------------------------------------- /x11/fonts.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | dmenu 7 | 8 | 9 | Noto Color Emoji 10 | 11 | 12 | 13 | 14 | serif 15 | DejaVu Serif 16 | 17 | 18 | sans-serif 19 | DejaVu Sans 20 | 21 | 22 | 23 | monospace 24 | DejaVu Sans Mono 25 | 26 | 27 | 28 | Bitstream Vera Sans 29 | DejaVu Sans 30 | 31 | 32 | 33 | Arial 34 | DejaVu Sans 35 | 36 | 37 | 38 | Helvetica 39 | DejaVu Sans 40 | 41 | 42 | 43 | Nimbus Sans L 44 | DejaVu Sans 45 | 46 | 47 | 48 | Liberation Sans 49 | DejaVu Sans 50 | 51 | 52 | 53 | FreeSans 54 | DejaVu Sans 55 | 56 | 57 | 58 | Bitstream Vera Serif 59 | DejaVu Serif 60 | 61 | 62 | 63 | Liberation Serif 64 | DejaVu Serif 65 | 66 | 67 | 68 | Bitstream Sans Mono 69 | DejaVu Sans Mono 70 | 71 | 72 | 73 | Liberation Mono 74 | DejaVu Sans Mono 75 | 76 | 77 | 90 | 91 | 101 | 102 | -------------------------------------------------------------------------------- /x11/gtk3-settings.ini: -------------------------------------------------------------------------------- 1 | [Settings] 2 | gtk-cursor-theme-name = hicolor 3 | -------------------------------------------------------------------------------- /x11/icons: -------------------------------------------------------------------------------- 1 | [icon theme] 2 | Inherits=hicolor 3 | -------------------------------------------------------------------------------- /x11/module.py: -------------------------------------------------------------------------------- 1 | files = { 2 | '~/.config/x11/compose': 'XCompose', 3 | '~/.config/x11/modmap': 'Xmodmap', 4 | '~/.config/fontconfig/fonts.conf': 'fonts.conf', 5 | '~/.config/x11/xinitrc': 'xinitrc', 6 | #'~/.icons/default/index.theme': 'icons', 7 | '~/.config/gtk-3.0/settings.ini': 'gtk3-settings.ini', 8 | } 9 | 10 | dirs = { 11 | '~/.config/service': 'service' 12 | } 13 | -------------------------------------------------------------------------------- /x11/service/xbanish/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export DISPLAY=:0 3 | export XAUTHORITY=/home/martin/.config/x11/authority 4 | exec xbanish -i mod4 >/dev/null 2>&1 5 | -------------------------------------------------------------------------------- /x11/service/xcape/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export DISPLAY=:0 3 | export XAUTHORITY=/home/martin/.config/x11/authority 4 | exec xcape -fe 'Shift_L=KP_Add' >/dev/null 2>&1 5 | -------------------------------------------------------------------------------- /x11/xinitrc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd ~ 4 | xset -b 5 | #xset m 1/1 6 | xmodmap ~/.config/x11/modmap 7 | xsetroot -solid "#3a6ea5" 8 | 9 | while :; do 10 | ssh-agent -a /tmp/run-$USER/ssh-agent /home/martin/code/Prog/craicwm/craicwm > /tmp/run-$USER/wm.log 2>&1 11 | sleep 0.5 12 | done 13 | -------------------------------------------------------------------------------- /zsh/module.py: -------------------------------------------------------------------------------- 1 | dirs = { 2 | '~/.zsh': '.', 3 | } 4 | 5 | symlinks = { 6 | '~/.zsh/zshrc': '~/.zsh/zshrc', 7 | } 8 | -------------------------------------------------------------------------------- /zsh/zshrc: -------------------------------------------------------------------------------- 1 | set -u # Undefined variables are an error. 2 | ZDOTDIR=~/.zsh # Store all zsh-related stuff in ~/.zsh/ instead of ~/ 3 | HISTFILE=~/.zsh/history 4 | 5 | ### Setup PATH 6 | ############## 7 | prepath() { for d in $@; [[ -d $d:A ]] && path=($d:A $path) } # Use the full path to prevent dupes. 8 | postpath() { for d in $@; [[ -d $d:A ]] && path+=($d:A) } 9 | have() { (( $+commands[$1] )) } # Check if command exists. 10 | 11 | typeset -U path # No duplicates 12 | path=() 13 | prepath /bin /sbin /usr/bin /usr/sbin /usr/games 14 | prepath /usr/pkg/bin /usr/pkg/sbin # NetBSD 15 | prepath /usr/X11R6/bin /usr/X11R6/sbin # OpenBSD 16 | prepath /opt/ooce/bin # illumos 17 | prepath /usr/local/bin /usr/local/sbin 18 | 19 | prepath ~/.local/gobin # Go 20 | postpath ~/code/Vim/gopher.vim/tools/bin 21 | prepath ~/.local/script # My local stuff. 22 | postpath ~/.gem/ruby/*/bin(N[-1]) # Ruby 23 | postpath ~/.luarocks/bin(N[-1]) # Lua 24 | postpath ~/.dotnet/root ~/.dotnet/tools # .NET 25 | postpath /usr/lib/plan9/bin # Plan 9 from userspace 26 | 27 | ### Various env variables 28 | ######################### 29 | export LANG=en_NZ.UTF-8 # Use Kiwiland for sane date format, metric system, etc. 30 | export LC_COLLATE=C # I prefer this sorting. 31 | if [[ -n ${TMUX:-} ]]; then # Do the TERM dance. 32 | export TERM=tmux-256color 33 | elif [[ -n ${DISPLAY:-} ]]; then 34 | export TERM=st-256color 35 | fi 36 | 37 | have vim && export EDITOR=vim # Default applications. 38 | have firefox && export BROWSER=firefox 39 | have less && export PAGER=less 40 | have clang && export CC=clang 41 | have clang++ && export CXX=clang++ 42 | 43 | # Store stuff in ~/.config and ~/.cache when we can. 44 | # https://github.com/grawity/dotfiles/blob/master/.dotfiles.notes 45 | export LESSHISTFILE=~/.cache/lesshistory 46 | export LESSKEY=~/.config/less/less 47 | export INPUTRC=~/.config/inputrc 48 | export SQLITE_HISTORY=~/.cache/sqlite_history 49 | export PSQLRC=~/.config/psqlrc 50 | export BUNDLE_USER_HOME=~/.cache/bundle 51 | export GNUPGHOME=~/.config/gnupg 52 | export CRAWL_DIR=~/.config/crawl 53 | export XCOMPOSEFILE=~/.config/x11/compose 54 | export XAUTHORITY=~/.config/x11/authority 55 | 56 | # TODO 57 | # Doesn't work? "startx ~/.config/x11/xinitrc"? 58 | # export XINITRC=~/.config/x11/xinitrc 59 | # export VIMINIT=":source ~/.config/vim/vimrc" 60 | 61 | export BUNDLE_PATH=~/.gem # Deal with bundler 62 | export DOTNET_ROOT=~/.dotnet/root # .NET root 63 | export ANDROID_SDK_ROOT=~/android/sdk # Android tools 64 | export PLAN9=/usr/lib/plan9 # Plan 9 from userspace 65 | export GOBIN=~/.local/gobin # Go binaries ('go install'). 66 | export GOPATH=~/.cache/go # GOPATH mostly stores cache stuff these days. 67 | export GOCACHE=$GOPATH/cache # Build and test cache. 68 | export GOTMPDIR=$GOPATH/tmp # tmp files during compile 69 | export GOFLAGS=-modcacherw # Just leave mod cache writable. 70 | mkdir -m0700 -p "$GOTMPDIR" # Make sure it exists as Go won't create it. 71 | 72 | # R Display colours escape chars as-is (so they're displayed). 73 | # i Ignore case unless pattern has upper case chars. 74 | # M Display line numbers and position. 75 | # Q Never ring terminal bell. 76 | # X Don't clear the screen on exit. 77 | # L Ignore LESSOPEN – some Linux distros set this to broken defaults (*cough* Fedora *cough*). 78 | export LESS="RiMQXL" 79 | 80 | export PGHOST=/tmp # PostgreSQL defaults 81 | export LS_COLORS="no=00:fi=00:di=34:ln=01;31:pi=34;43:so=31;43:bd=30;43:cd=30;43:or=01;35:ex=31:" 82 | export GREP_COLOR=31 # Older GNU grep; BSD grep 83 | export GREP_COLORS="ms=31:mc=31:sl=0:cx=0:fn=0:ln=0:bn=0:se=0" # Newer GNU grep. 84 | export RIPGREP_CONFIG_PATH=$HOME/.config/ripgrep 85 | export GH_NO_UPDATE_NOTIFIER=y # Annoying update check. 86 | export BLOCKSIZE=K # Output sizes in K instead of 512b blocks. 87 | export MANWIDTH=80 # Only needed with GNU stuff; use mandoc for better man. 88 | export GTK_IM_MODULE=xim # Make compose key work. 89 | export QT_IM_MODULE=xim 90 | export GTK_OVERLAY_SCROLLING=0 # Disable annoying "overlay scrollbar". 91 | export SYSTEMD_PAGER= # Don't output to a pager. 92 | export _JAVA_AWT_WM_NONREPARENTING=1 # This magic fixes Java applications. 93 | 94 | if [[ -d '/etc/service' ]]; then # Set user service dir for runit. 95 | export SVDIR=/etc/service 96 | elif [[ -d '/var/service' ]]; then 97 | export SVDIR=/var/service 98 | fi 99 | export XDG_RUNTIME_DIR=/tmp/run-$(id -un) # Needed for some programs. 100 | mkdir -m0700 -p "$XDG_RUNTIME_DIR" 101 | export TMUX_TMPDIR=$XDG_RUNTIME_DIR 102 | 103 | # Run commands from this file on interactive session 104 | [[ -f "$HOME/.local/python-startup" ]] && export PYTHONSTARTUP=~/.local/python-startup 105 | 106 | 107 | ### Our work here is done if not an interactive shell 108 | ##################################################### 109 | [[ -o interactive ]] || return 0 110 | 111 | # Load zsh-completions 112 | fpath=(~/.zsh/zsh-completions/src $fpath) 113 | 114 | # Directory shortcuts 115 | hash -d c=~/code 116 | hash -d pack=~c/Vim 117 | hash -d cp=~c/Prog 118 | hash -d cm=~c/Misc 119 | hash -d cg=~c/Golib 120 | hash -d gc=~/code/goatcounter 121 | hash -d d=~/code/arp242.net/_drafts 122 | hash -d p=~/code/arp242.net/_posts 123 | hash -d vim=/usr/share/vim/vim90 124 | hash -d go=$(print -n /usr/go-*(N[-1])) 125 | hash -d epp=~c/epp-server 126 | 127 | setopt no_flow_control # Disable ^S, ^Q, ^\ 128 | stty -ixon quit undef # For Vim etc; above is just for zsh. 129 | stty werase undef # Needed to make C-w do something sane in readlone. 130 | setopt notify # Report status of bg jobs immediately 131 | setopt no_clobber # Don't clobber existing files with > .... 132 | setopt clobber_empty # ... but do allow overwriting empty files. 133 | setopt append_create # Refuse to create new files with >> 134 | setopt short_repeat # Short repeat syntax ("repeat 5; echo x"). 135 | setopt no_beep # Don't beep 136 | setopt no_hup # Don't kill background jobs when exiting 137 | setopt no_bg_nice # Don't frob with nicelevels 138 | setopt auto_continue # Send CONT before disown if job is suspended 139 | setopt no_auto_remove_slash # Don't guess when slashes should be removed (too magic) 140 | setopt no_match # Show error if globbing fails 141 | setopt extended_glob # More globbing characters 142 | disable -p '^' # Disable ^ pattern from extended_glob; it's the same as ~ anyway 143 | LISTMAX=999999 # Disable 'do you wish to see all %d possibilities' 144 | 145 | ### History 146 | setopt append_history # Append to history, rather than overwriting 147 | setopt inc_append_history # Append immediately rather than only at exit 148 | setopt extended_history # Store some metadata as well 149 | setopt hist_no_store # Don't store history and fc commands 150 | setopt no_bang_hist # Don't use ! for history expansion 151 | setopt hist_ignore_dups # Don't add to history if it's the same as previous event. 152 | setopt hist_ignore_all_dups # Remove older event if new event is duplicate. 153 | setopt hist_save_no_dups # Older commands that duplicate newer ones are omitted. 154 | HISTSIZE=11000 # Max. entries to keep in memory 155 | SAVEHIST=10000 # Max. entries to save to file 156 | HISTORY_IGNORE='([bf]g *|[bf]g|disown|cd ..|cd -|up|ww)' # Don't add these to the history file. 157 | 158 | ### Prompt 159 | setopt prompt_subst # Expand parameters commands, and arithmetic in PROMPT 160 | setopt transient_rprompt # Remove rprompt after a command is run. 161 | 162 | PROMPT='%(?..%130(?..%S%?%s))[%~]%# ' 163 | if have git; then 164 | autoload -Uz vcs_info 165 | zstyle ':vcs_info:*' enable git # Enable just git. 166 | zstyle ':vcs_info:*' formats '(%b)' # Show branch. 167 | set_prompt() { 168 | vcs_info >/dev/null 2>&1 169 | print -n "%(?..%130(?..%S%?%s))" # Exit code in "standout" if non-0 and non-130 (^C to clear input) 170 | print -n "[%~]${vcs_info_msg_0_:-}%# " # Directory and VCS info (if any). 171 | } 172 | PROMPT=$'$(set_prompt)' 173 | fi 174 | 175 | _has_bat0=$([[ ! -f /sys/class/power_supply/BAT0/capacity ]]; printf $?) 176 | _has_bat1=$([[ ! -f /sys/class/power_supply/BAT1/capacity ]]; printf $?) 177 | set_rprompt() { 178 | local host= # Show hostname only for ssh connections. 179 | [[ -n "${SSH_CLIENT:-}${SSH2_CLIENT:-}${SSH_CONNECTION:-}" ]] && host="%F{red}%U%B%m%b%u%f:" 180 | 181 | local bat=() # Battery status 182 | (( $_has_bat0 )) && bat+="$(< /sys/class/power_supply/BAT0/capacity)%%" 183 | (( $_has_bat1 )) && bat+="$(< /sys/class/power_supply/BAT1/capacity)%%" 184 | [[ -n $bat ]] && bat=" ${(j!:!)bat}" 185 | 186 | print "${host}%T${bat}" # %T prints the time 187 | } 188 | RPROMPT=$'$(set_rprompt)' 189 | 190 | 191 | ### Completion 192 | ############## 193 | setopt complete_in_word # Allow completion from within a word/phrase. 194 | setopt always_to_end # Move cursor to end of word when when completing from middle. 195 | setopt no_list_ambiguous # Show options on single tab press. 196 | setopt list_packed # Use different column widths if we can; makes it more compact. 197 | 198 | # Load and init 199 | autoload -U compinit && compinit # Load completion system. 200 | zmodload zsh/complist # Load interactive menu. 201 | 202 | autoload -U select-word-style && select-word-style bash # Only alphanumeric characters match a "word". 203 | zstyle ':zle:*' word-chars '-_' # Also match these additional characters as a "word". 204 | 205 | zstyle ':completion:*' menu select # Use menu for selecting. 206 | zstyle ':completion::complete:*' use-cache on # Enable cache (not used by many completions). 207 | zstyle ':completion:*:warnings' format 'No completions' # Warn when there are no completions 208 | zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} # Show ls-like colours in file completion. 209 | zstyle ':completion:*' list-separator '│' # Separator before help; looks nicer than -- 210 | zstyle ':completion:*' squeeze-slashes true # "path//" is "path/" rather than "path/*" 211 | zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' # Make completion case-insensitive. 212 | zstyle ':completion:*:functions' ignored-patterns '_*' # Ignore in completion. 213 | zstyle ':completion:*:*files' ignored-patterns '*?.pyc' '*?.o' 214 | 215 | ### Keys 216 | ######## 217 | bindkey -e # Use the default "emacs" bindings. 218 | export KEYTIMEOUT=10 # Time to wait for another key in multi-character sequences, in 1/100th second. 219 | 220 | autoload -U up-line-or-beginning-search && zle -N up-line-or-beginning-search 221 | autoload -U down-line-or-beginning-search && zle -N down-line-or-beginning-search 222 | autoload -U edit-command-line && zle -N edit-command-line 223 | 224 | bindkey '^[[A' up-line-or-beginning-search # Arrow up 225 | bindkey '^[OA' up-line-or-beginning-search 226 | bindkey '^p' up-line-or-beginning-search 227 | bindkey '^o' up-line-or-beginning-search # ^p is my tmux prefix, so map ^p to ^o 228 | bindkey '^[[B' down-line-or-beginning-search # Arrow down 229 | bindkey '^[OB' down-line-or-beginning-search 230 | bindkey '^n' down-line-or-beginning-search 231 | bindkey '^[[1;5C' forward-char # Ctrl + Arrow Right 232 | bindkey '^[[1;5D' backward-char # Ctrl + Arrow Left 233 | bindkey '^[[1;2C' forward-word # Shift + Arrow Right 234 | bindkey '^[[1;2D' backward-word # Shift + Arrow Left 235 | bindkey '^[[H' beginning-of-line # Home 236 | bindkey '^[[1~' beginning-of-line 237 | bindkey '^[[7~' beginning-of-line 238 | bindkey '^[[F' end-of-line # End 239 | bindkey '^[[4~' end-of-line 240 | bindkey '^[[8~' end-of-line 241 | bindkey '^[[3~' delete-char # Delete 242 | bindkey '^[[P' delete-char 243 | bindkey '^h' backward-delete-char # Backspace 244 | bindkey '^?' backward-delete-char 245 | bindkey '^t' edit-command-line # Edit in Vim. 246 | bindkey '^\' accept-and-hold # Run command without clearing commandline. 247 | bindkey '^[[Z' up-history # Shift+Tab; so it works in completion menu to go back. 248 | bindkey '^[OP' run-help # F1 249 | bindkey -s '^[[5~' '' # Disable Page up/down; on my ThinkPad they're right next to the 250 | bindkey -s '^[[6~' '' # arrow keys and pressing them by accident is annoying. 251 | 252 | # Toggle "doas" at the start. 253 | toggle-doas() { 254 | [[ "${BUFFER:0:4}" = "doas" ]] && 255 | {CURSOR+=-5; BUFFER="${BUFFER:5}";} || 256 | {BUFFER="doas $BUFFER"; CURSOR+=5;} 257 | } 258 | zle -N toggle-doas toggle-doas && bindkey '^s' toggle-doas 259 | 260 | # Replace first word with "rm". 261 | replace-rm() { zle beginning-of-line; zle delete-word; zle -U "rm " } 262 | zle -N replace-rm replace-rm && bindkey '^r' replace-rm 263 | 264 | # Store the current input, and restore it with a second ^q 265 | remember() { 266 | if (( $#BUFFER )); then 267 | stored=$BUFFER 268 | BUFFER= 269 | else 270 | print -ln "${stored:-}" 271 | fi 272 | } 273 | zle -N remember remember && bindkey '^q' remember 274 | 275 | 276 | ### Commands 277 | ############ 278 | alias cp='cp -i' # Ask for confirmation when overwriting existing files. 279 | alias mv='mv -i' 280 | alias make='nice -n 20 make' # Make can always be very nice. 281 | alias free='free -m' # MB is more useful. 282 | alias du='du -h' 283 | alias cal='cal -m' # Week starts on Monday. 284 | alias ps='ps axu' # These are pretty much the only flags I use. 285 | alias td='echo $(date +%Y-%m-%d)' # "today" 286 | alias now='echo $(date +%Y-%m-%d\ %T)' 287 | alias hub='NO_COLOR=y gh' # "git" and "go" already start with "g"; this is easier. 288 | alias df='df -h | grep -Ev "(cgroup|devtmpfs|/run|/shm)"' 289 | mkcd() { mkdir -p $@ && cd $1 } # Create directories and cd to first one. 290 | 291 | # Disable this ridiculous banner and colours. 292 | alias ffmpeg='AV_LOG_FORCE_NOCOLOR=1 ffmpeg -hide_banner' 293 | alias ffprobe='AV_LOG_FORCE_NOCOLOR=1 ffprobe -hide_banner' 294 | alias ffplay='AV_LOG_FORCE_NOCOLOR=1 ffplay -hide_banner' 295 | 296 | if [[ $(uname) = Linux ]]; then 297 | if [[ -h /bin/ls ]]; then # Assume busybox; the colours don't work on light bg. 298 | alias ls='ls -F --color=never' 299 | else 300 | alias ls='ls -FN --color=auto' # -F adds trailing / etc; -N avoids adding quotes 301 | fi 302 | alias lc='ls -lh' # "List Complete" 303 | alias la='ls -A' # "List All" 304 | alias lac='ls -lhA' # "List All Complete" 305 | alias lh='ls -d .*' # "List Hidden" 306 | alias lsd='ls -ld *(-/DN)' # "List Directories" 307 | else 308 | alias ls='ls -Fh' 309 | alias lc='ls -l' 310 | alias la='ls -a' 311 | alias lac='ls -la' 312 | fi 313 | 314 | if have systemctl; then 315 | alias zzz='systemctl suspend' 316 | alias ZZZ='systemctl hibernate' 317 | elif have pm-suspend; then 318 | alias zzz='pm-suspend' 319 | alias ZZZ='pm-hibernate' 320 | fi 321 | 322 | have bsdtar && alias tar='bsdtar' 323 | have htop && alias top='htop' 324 | alias youtube-dl='noglob yt-dlp --no-colors --no-part -o "%(title)s-%(id)s.%(ext)s"' 325 | alias youtube-dl-audio='youtube-dl --extract-audio --format "bestaudio*"' 326 | alias youtube-dl-chan='noglob yt-dlp --no-colors --no-part -o "%(upload_date)s %(title)s-%(id)s.%(ext)s"' 327 | youtube-dl-select() { 328 | # Select two: 1+2 329 | # Ideally want to select av1; much smaller! 330 | youtube-dl -F --quiet $1 | grep -Ev '(storyboard|(video|audio) only)' | 331 | sed -E 's/\|/│/g; 2s/-/─/g; s/[~0-9.]+[MG]iB/\x1b[1m\0\x1b[0m/' 332 | print -n 'Which? ' 333 | read -n s 334 | youtube-dl -f $s $1 335 | } 336 | alias sqlite=sqlite3 337 | alias ag='rg' # I'm so used to typing "ag". 338 | alias vim="vim -p --ttyfail" # Open in tabs, and refuse to open if output is not a terminal. 339 | alias vi="vim" 340 | alias scc='scc --min-gen --no-complexity --no-cocomo --no-size' 341 | alias batchy='vim +":Batchy echo" +:S +":setl nowrap"' 342 | runbuf() { vim +":Runbuf $@" } 343 | 344 | unfunction have # Unset helpers. 345 | unfunction prepath 346 | unfunction postpath 347 | 348 | alias sl='ls' # Typos 349 | alias l='ls' 350 | alias c='cd' 351 | alias vo='vi' 352 | alias ci='vi' 353 | alias iv='vi' 354 | alias grpe='grep' 355 | alias Grep='grep' 356 | alias les='less' 357 | alias les='less' 358 | alias Less='less' 359 | alias cd.='cd .' 360 | alias cd..='cd ..' 361 | 362 | autoload -U run-help run-help-git run-help-ip # Smarter run-help 363 | alias run-help >/dev/null && unalias run-help # Unset the default 364 | 365 | alias curl='noglob curl' # Disable globbing for some commands where we rarely want it; 366 | alias find='noglob find' 367 | alias pharod='noglob pharod' 368 | 369 | autoload -U zcalc # Get quick results for "zc 6 * 6", or just use "zc" to get zcalc 370 | alias zc >/dev/null && unalias zc 371 | zc() { if (( $# )); then zcalc -e ${(j: :)argv}; else zcalc; fi } 372 | alias zc='noglob zc' 373 | 374 | alias -g VV=' |& vim +S -' # Global aliases to pipe output. 375 | alias -g LL=' |& less' 376 | alias -g LLl=' |& less' # Typo after using ^l 377 | alias -g LLS=' |& less -S' # No wrapping. 378 | alias -g GG=' |& grep' 379 | alias -g HH=' |& head -n20' 380 | alias -g SS=' |& sort' 381 | alias -g SSH=' |& sort -h' 382 | alias -g CC=' |& xclip -in' # TODO: ideally I'd like to copy to both, but xclip doesn't support that 383 | 384 | # Diff two directories 385 | diffdir() { vim ${@[3,-1]} +":Diffdir $1 $2" } 386 | 387 | # So I can map ^Z in mpv 388 | mpv() { stty susp '' &>/dev/null; =mpv $@; stty susp '^Z' &>/dev/null; } 389 | 390 | # "ag edit" and "grep edit". 391 | age() { 392 | local IFS=$'\n' files=($(=rg -l "$@")) 393 | (( $#files )) || return 1 394 | vim --ttyfail -p $files \ 395 | +':silent! /\v'"${@[-1]/\//\\/}" \ 396 | +':silent! tabdo :1 | normal! n' \ 397 | +':tabfirst' 398 | } 399 | grepe() { 400 | local IFS=$'\n' files=($(=grep -l "$@")) 401 | (( $#files )) || return 1 402 | vim --ttyfail -p $files \ 403 | +':silent! /\v'"${@[-1]/\//\\/}" \ 404 | +':silent! tabdo :1 | normal! n' \ 405 | +':tabfirst' 406 | } 407 | 408 | # Restart ssh-agent after restarting WM or x11 (may be old env var in tmux). 409 | ssh-reagent() { 410 | export SSH_AUTH_SOCK=$(print $XDG_RUNTIME_DIR/ssh-*/agent.*) 411 | ssh-add -l >/dev/null || ssh-add 412 | } 413 | 414 | # Get random string; first parameter is length (default: 20), if the second is 415 | # set to any value it will only include alphanumeric characters. 416 | rnd() { 417 | [[ -n ${2:-} ]] && filter='[:punct:][:space:][:cntrl]' || filter='[:space:]' 418 | strings -n1 "$tmp/main.go" 429 | printf 'package main\n\nimport "testing"\n\nfunc TestA(t *testing.T) {\n\n}\n\n' > "$tmp/main_test.go" 430 | printf 'func BenchmarkA(b *testing.B) {\n\tb.ReportAllocs()\n\tfor n := 0; n < b.N; n++ {\n\t}\n}\n' >> "$tmp/main_test.go" 431 | printf 'go %s\n\nmodule %s\n' $(go version | grep -o '1\.[0-9][0-9]') $(basename $tmp) > "$tmp/go.mod" 432 | ( 433 | cd "$tmp" 434 | vim -p main.go main_test.go 435 | print "$tmp" 436 | ) 437 | } 438 | 439 | # Run sql files or commands. 440 | sql() { 441 | local cmd="psql -X -P linestyle=unicode -P null=NULL goatcounter" 442 | local f="$HOME/docs/sql/scripts/$1" 443 | if [[ -f "$f" ]]; then 444 | eval "$cmd" <"$HOME/docs/sql/scripts/$1" | less -S 445 | else 446 | eval "$cmd" <<<"$1" | less -S 447 | fi 448 | } 449 | _sql() { _files -W ~/docs/sql/scripts } 450 | compdef _sql sql 451 | 452 | # sman, or "SQL man"; list completions just for the PostgreSQL manpages on SQL syntax. 453 | sman() { 454 | if [[ ${@[(i)-w]} -le ${#@} ]]; then 455 | local page=("${(@)@:#-w}") 456 | ${BROWSER:-firefox} "https://www.postgresql.org/docs/current/sql-${${(L)page%-??}//_/}.html" 457 | return 458 | fi 459 | man $@ 460 | } 461 | _sman() { 462 | local x=() 463 | for f in /usr/share/man/man7/[A-Z]*.7; do 464 | f=${f%.7} 465 | f=${f%-13} 466 | x+=(${f##*/}) 467 | done 468 | _arguments "1: :{_describe 'page' x}" 469 | } 470 | compdef _sman sman 471 | 472 | # Find outdated modules. 473 | go-mod-update() { 474 | go list -u -m -mod=readonly \ 475 | $(go list -m -f '{{.Indirect}} {{.}}' -mod=readonly all | 476 | awk '/^false/ {print $2}') | grep '\[' 477 | } 478 | 479 | # - Automatically set PGDATABASE to the first path part that matches a database. 480 | # - Add -S to LESS to not wrap. 481 | psql() { 482 | local db=${PGDATABASE:-} 483 | if [[ -z $db && -z ${1:-} ]]; then 484 | local paths=(${(s,/,)PWD}) 485 | local dbs=($(=psql -qtAX postgres -c 'select datname from pg_catalog.pg_database')) 486 | for p in ${(Oa)paths}; do 487 | if [[ ${dbs[(r)$p]:-} = $p ]]; then 488 | db=$p 489 | break 490 | fi 491 | done 492 | fi 493 | #db=${db:-goatcounter} 494 | LESS=S$LESS PGDATABASE=$db =psql $@ 495 | } 496 | 497 | # "up 3" to go up 3 directories, or "up name" to go up until that directory. 498 | up() { 499 | if [[ ${1:-1} =~ '[0-9]+' ]]; then 500 | local d='./' 501 | repeat ${1:-1}; d+='../' 502 | cd $d 503 | else 504 | local d=(${(s:/:Oa)PWD}) 505 | for (( i=1; i<=$#d; i++ )); do 506 | if [[ $d[$i] = $1 ]]; then 507 | up $(( i - 1 )) 508 | return 509 | fi 510 | done 511 | print >&2 'not found' 512 | return 1 513 | fi 514 | } 515 | _up() { 516 | local d=(${(s:/:Oa)PWD}) 517 | _arguments "1: :{_describe 'dir' d}" 518 | } 519 | compdef _up up 520 | # Easier to type than "up"; "ww" doesn't stand for anything, other than being 521 | # easy to type and not being a common command already. 522 | alias ww=up 523 | --------------------------------------------------------------------------------