summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--.gitmodules99
-rw-r--r--.stowrc5
-rw-r--r--Brewfile67
-rw-r--r--EXTERNAL39
-rw-r--r--Makefile158
-rw-r--r--Makefile.hush68
-rw-r--r--Makefile.include12
-rw-r--r--Makefile.mail8
-rw-r--r--Makefile.partofme8
-rw-r--r--Makefile.st-doy214
-rw-r--r--Makefile.tozt10
-rw-r--r--Xmodmap39
-rw-r--r--abook/abookrc39
-rw-r--r--agignore7
-rw-r--r--alacritty/.config/alacritty/alacritty.toml.PL578
-rw-r--r--alacritty/.gitignore1
-rw-r--r--alacritty/Makefile6
-rw-r--r--archlinux-packages70
-rw-r--r--bash/.bash_profile4
-rw-r--r--bash/.bashrc48
-rw-r--r--bash_profile4
-rw-r--r--bashrc73
-rwxr-xr-xbat/.bin/batman3
-rw-r--r--bat/.config/sh/rc.d/bat2
-rwxr-xr-xbin/.bin/cryptdir (renamed from bin/cryptdir)2
-rwxr-xr-xbin/.bin/cryptoloop30
-rwxr-xr-xbin/.bin/files-between14
-rwxr-xr-xbin/.bin/fm22avi (renamed from bin/fm22avi)0
-rwxr-xr-xbin/.bin/history-stats (renamed from bin/history-stats)0
-rwxr-xr-xbin/.bin/hostcert8
-rwxr-xr-xbin/.bin/mem-usage (renamed from bin/mem-usage)0
-rwxr-xr-xbin/.bin/pacman-dump6
-rwxr-xr-xbin/.bin/pdfcat (renamed from bin/pdfcat)0
-rwxr-xr-xbin/.bin/reply28
-rwxr-xr-xbin/.bin/scanpdf4
-rwxr-xr-xbin/.bin/scratch (renamed from services/available/watch-kbd/run)2
-rwxr-xr-xbin/.bin/set-mac10
-rwxr-xr-xbin/.bin/show-colors (renamed from bin/show-colors)2
-rwxr-xr-xbin/.bin/smt22
-rwxr-xr-xbin/.bin/sum (renamed from bin/sum)0
-rwxr-xr-xbin/.bin/web (renamed from bin/web)0
-rw-r--r--bin/.gitignore1
-rwxr-xr-xbin/clean-vim-undo13
-rw-r--r--bin/git/git-imerge4135
-rwxr-xr-xbin/hostcert8
-rwxr-xr-xbin/hush/p5
-rwxr-xr-xbin/hush/setup-inputs16
-rwxr-xr-xbin/hush/ssh-askpass5
-rwxr-xr-xbin/hush/sudo-askpass5
-rwxr-xr-xbin/hush/svdn29
-rwxr-xr-xbin/hush/svget5
-rwxr-xr-xbin/hush/svkill6
-rwxr-xr-xbin/hush/svlog5
-rwxr-xr-xbin/hush/svnuke11
-rwxr-xr-xbin/hush/svstop6
-rwxr-xr-xbin/hush/svup6
-rwxr-xr-xbin/hush/update-mail11
-rwxr-xr-xbin/hush/volume17
-rwxr-xr-xbin/hush/watch-kbd11
-rwxr-xr-xbin/hush/wifi38
-rw-r--r--bin/local/.gitignore2
-rwxr-xr-xbin/nopaste37
-rwxr-xr-xbin/pacman-dump7
-rwxr-xr-xbin/pick-music6
-rwxr-xr-xbin/pt9
-rwxr-xr-xbin/rand-music13
-rwxr-xr-xbin/ringtone20
-rwxr-xr-xbin/scratch5
-rwxr-xr-xbin/setfont5
-rwxr-xr-xbin/st-doy2/power-usage10
-rwxr-xr-xbin/t9
-rwxr-xr-xbin/tozt/learn_spam38
-rwxr-xr-xbin/update-addressbook276
-rwxr-xr-xbin/vimmanpager15
-rwxr-xr-xbin/watch-lock37
-rwxr-xr-xbin/weechat-config29
-rwxr-xr-xbuild8
-rwxr-xr-xclean9
-rw-r--r--config/alacritty/alacritty.yml.hush167
-rw-r--r--config/alacritty/alacritty.yml.st-doy2172
-rw-r--r--config/darksky/location1
-rw-r--r--config/git/ignore9
-rw-r--r--config/i3/browser-workspace.json16
-rw-r--r--config/i3/signal-workspace.json16
-rw-r--r--config/i3status/config44
-rw-r--r--config/karabiner/assets/complex_modifications/command-escape.json54
-rw-r--r--config/karabiner/assets/complex_modifications/number-row.json390
-rw-r--r--config/karabiner/assets/complex_modifications/other-remapping.json200
-rw-r--r--config/karabiner/assets/complex_modifications/terminal-overrides.json140
-rw-r--r--config/karabiner/karabiner.json1018
-rw-r--r--config/mpd/mpd.conf5
-rw-r--r--config/ncmpcpp/bindings591
-rw-r--r--config/offlineimap/config34
-rw-r--r--config/offlineimap/pass.py5
-rw-r--r--config/perspektiv/config.toml15
-rw-r--r--config/sh/aliases41
-rw-r--r--config/sh/cdhist.sh174
-rw-r--r--config/sh/env26
-rw-r--r--config/sh/functions20
m---------config/sh/fzf0
-rw-r--r--config/touchegg/touchegg.conf16
-rw-r--r--config/weechat/extra24
-rw-r--r--config/weechat/saved263
-rw-r--r--config/zsh/local-completions/hush/_sv10
m---------config/zsh/zsh-autosuggestions0
m---------config/zsh/zsh-completions0
m---------config/zsh/zsh-syntax-highlighting0
-rw-r--r--crawl/.config/sh/rc.d/crawl2
-rw-r--r--crawl/.crawlrc (renamed from crawlrc)0
-rw-r--r--crawl/.ssh/cao_key (renamed from ssh/cao_key)0
-rw-r--r--crawl/Makefile4
-rw-r--r--crontab1
-rw-r--r--docker/.config/systemd/user/docker-prune.service3
-rw-r--r--docker/.config/systemd/user/docker-prune.timer6
-rw-r--r--docker/Makefile9
-rw-r--r--dzil/config.ini7
-rw-r--r--dzil/profiles/default/Module.pm0
-rw-r--r--dzil/profiles/default/profile.ini8
-rw-r--r--dzil/profiles/default/root/.gitignore18
-rw-r--r--dzil/profiles/default/root/.travis.yml13
-rw-r--r--dzil/profiles/default/root/Changes4
-rw-r--r--dzil/profiles/default/root/dist.ini11
-rw-r--r--eza/.config/sh/rc.d/exa1
-rw-r--r--fortune-mod/.gitignore1
-rw-r--r--fortune-mod/.local/share/fortune/buffy (renamed from local/share/fortune/buffy)0
-rw-r--r--fortune-mod/.local/share/fortune/calvin (renamed from local/share/fortune/calvin)0
-rw-r--r--fortune-mod/.local/share/fortune/chapterhouse-dune (renamed from local/share/fortune/chapterhouse-dune)0
-rw-r--r--fortune-mod/.local/share/fortune/children-of-dune (renamed from local/share/fortune/children-of-dune)0
-rw-r--r--fortune-mod/.local/share/fortune/dune (renamed from local/share/fortune/dune)0
-rw-r--r--fortune-mod/.local/share/fortune/dune-messiah (renamed from local/share/fortune/dune-messiah)0
-rw-r--r--fortune-mod/.local/share/fortune/firefly (renamed from local/share/fortune/firefly)0
-rw-r--r--fortune-mod/.local/share/fortune/god-emperor (renamed from local/share/fortune/god-emperor)0
-rw-r--r--fortune-mod/.local/share/fortune/heretics-of-dune (renamed from local/share/fortune/heretics-of-dune)0
-rw-r--r--fortune-mod/.local/share/fortune/hitchhiker (renamed from local/share/fortune/hitchhiker)0
-rw-r--r--fortune-mod/.local/share/fortune/house-atreides (renamed from local/share/fortune/house-atreides)0
-rw-r--r--fortune-mod/.local/share/fortune/house-harkonnen (renamed from local/share/fortune/house-harkonnen)0
-rw-r--r--fortune-mod/.local/share/fortune/ideas (renamed from local/share/fortune/ideas)0
-rw-r--r--fortune-mod/.local/share/fortune/kernelcookies (renamed from local/share/fortune/kernelcookies)0
-rw-r--r--fortune-mod/.local/share/fortune/perl (renamed from local/share/fortune/perl)0
-rw-r--r--fortune-mod/.local/share/fortune/song-of-ice-and-fire (renamed from local/share/fortune/song-of-ice-and-fire)0
-rw-r--r--fortune-mod/.local/share/fortune/yasd-fortune (renamed from local/share/fortune/yasd-fortune)0
-rw-r--r--fortune-mod/Makefile9
-rw-r--r--fzf/.config/sh/rc.d/fzf2
-rw-r--r--gdb/.config/gdb/gdbinit (renamed from gdbinit)0
-rwxr-xr-xgit/.bin/git/git-amend13
-rwxr-xr-xgit/.bin/git/git-blame-stats (renamed from bin/git/git-blame-stats)0
-rwxr-xr-xgit/.bin/git/git-default-branch4
-rwxr-xr-xgit/.bin/git/git-file-size (renamed from bin/git/git-file-size)0
-rwxr-xr-xgit/.bin/git/git-pr5
-rwxr-xr-xgit/.bin/git/git-record13
-rwxr-xr-xgit/.bin/git/git-root9
-rw-r--r--git/.config/git/config (renamed from config/git/config)56
-rw-r--r--git/.config/git/ignore1
-rw-r--r--git/.config/sh/rc.d/git1
-rw-r--r--gnupg/gpg-agent.conf3
-rw-r--r--gnupg/gpg.conf15
-rw-r--r--hammerspoon/Spoons/ReloadConfiguration.spoon/docs.json90
-rw-r--r--hammerspoon/Spoons/ReloadConfiguration.spoon/init.lua49
-rw-r--r--hammerspoon/Spoons/SpeedMenu.spoon/docs.json39
-rw-r--r--hammerspoon/Spoons/SpeedMenu.spoon/init.lua111
-rw-r--r--hammerspoon/init.lua173
-rw-r--r--helix/.config/helix/config.toml34
-rw-r--r--helix/.config/helix/languages.toml14
-rw-r--r--helix/.config/sh/rc.d/helix2
-rwxr-xr-xi3/.bin/i3-switch-workspace (renamed from bin/hush/i3-switch-workspace)78
-rwxr-xr-xi3/.bin/kill-focused (renamed from bin/hush/kill-focused)0
-rw-r--r--i3/.config/i3/config (renamed from config/i3/config)20
-rw-r--r--i3/.config/i3/terminal-workspace.json (renamed from config/i3/terminal-workspace.json)30
-rwxr-xr-xi3status/.bin/status (renamed from bin/hush/status)25
-rwxr-xr-xi3status/.bin/update-weather (renamed from bin/hush/update-weather)3
-rwxr-xr-xi3status/.bin/weather (renamed from bin/hush/weather)126
-rw-r--r--i3status/.config/i3status/config32
-rw-r--r--i3status/.config/systemd/user/weather.service3
-rw-r--r--i3status/.config/systemd/user/weather.timer6
-rw-r--r--i3status/Makefile9
-rwxr-xr-xinstall10
-rwxr-xr-xlaptop/.bin/backlight47
-rwxr-xr-xlaptop/.bin/import11
-rwxr-xr-xlaptop/.bin/numkeys (renamed from bin/hush/numkeys)11
-rwxr-xr-xlaptop/.bin/sc19
-rwxr-xr-xlaptop/.bin/setup-inputs18
-rwxr-xr-xlaptop/.bin/tv15
-rwxr-xr-xlaptop/.bin/volume45
-rwxr-xr-xlaptop/.bin/vscreen16
-rwxr-xr-xlaptop/.bin/watch-kbd14
-rwxr-xr-xlaptop/.bin/webcam (renamed from bin/hush/webcam)0
-rw-r--r--laptop/.config/sh/rc.d/laptop1
-rw-r--r--laptop/.config/systemd/user/watch-kbd.service6
-rw-r--r--laptop/Makefile9
-rw-r--r--ledgerrc1
-rw-r--r--less/.config/lesskey (renamed from lesskey)0
-rw-r--r--less/.config/sh/rc.d/less1
-rw-r--r--mbsync/.mbsyncrc21
-rwxr-xr-xmbsyncloop/.bin/mbsyncloop312
-rw-r--r--mbsyncloop/.config/mbsyncloop/config.json4
-rw-r--r--mbsyncloop/.config/systemd/user/mbsyncloop.service6
-rw-r--r--mbsyncloop/Makefile9
-rw-r--r--mpdscribble/mpdscribble.conf.tmpl7
-rw-r--r--msmtp/.config/msmtp/config (renamed from config/msmtp/config)2
-rw-r--r--msmtp/Makefile4
-rwxr-xr-xmutt/.config/mutt/choose-muttrc-type12
-rw-r--r--mutt/.config/mutt/imap (renamed from mutt/imap)0
-rw-r--r--mutt/.config/mutt/local (renamed from mutt/offlineimap)3
-rw-r--r--mutt/.config/mutt/mailcap (renamed from mutt/mailcap)0
-rw-r--r--mutt/.config/mutt/muttrc (renamed from mutt/muttrc)11
-rw-r--r--mutt/Makefile5
-rwxr-xr-xmutt/choose-muttrc-type12
-rw-r--r--nethack/.config/sh/rc.d/nethack1
-rw-r--r--nethack/.nethackrc176
-rw-r--r--nethackrc59
-rwxr-xr-xnotmuch/.cache/notmuch/hooks/post-new (renamed from notmuch/hooks/post-new)0
-rw-r--r--notmuch/.config/notmuch/default/config (renamed from notmuch-config)5
-rw-r--r--notmuch/Makefile4
-rw-r--r--packages.hornet42
-rw-r--r--packages.mail21
-rw-r--r--packages.mz-doy132
-rw-r--r--packages.partofme21
-rw-r--r--packages.root20
-rw-r--r--packages.tozt21
-rw-r--r--perlcriticrc1
-rw-r--r--picom/.config/systemd/user/picom.service6
-rw-r--r--picom/Makefile9
-rw-r--r--plists/com.amethyst.Amethyst.plistbin12811 -> 0 bytes
-rw-r--r--podman/.config/sh/rc.d/podman4
-rw-r--r--procmail/mark_as_read20
-rw-r--r--procmailrc12
-rw-r--r--proverc1
-rw-r--r--ra-multiplex/.config/systemd/user/ra-multiplex.service6
-rw-r--r--ra-multiplex/Makefile9
-rwxr-xr-xrbw/.bin/p5
l---------rbw/.bin/scp (renamed from bin/hush/scp)0
l---------rbw/.bin/sftp (renamed from bin/hush/sftp)0
-rwxr-xr-xrbw/.bin/ssh (renamed from bin/hush/ssh)2
-rwxr-xr-xrbw/.bin/ssh-askpass (renamed from bin/hush/svre)3
-rwxr-xr-xrbw/.bin/sudo (renamed from bin/hush/sudo)0
-rwxr-xr-xrbw/.bin/sudo-askpass (renamed from bin/hush/svst)2
-rw-r--r--rbw/.config/sh/rc.d/rbw5
-rw-r--r--readline/.inputrc (renamed from inputrc)0
-rwxr-xr-xredshift/.bin/redshift4
-rw-r--r--redshift/.config/systemd/user/redshift.service6
-rw-r--r--redshift/Makefile9
-rw-r--r--reply/.replyrc (renamed from replyrc)0
-rwxr-xr-xripgrep/.bin/rg7
-rw-r--r--screenrc28
-rwxr-xr-xservices/available/compton/log/run3
-rwxr-xr-xservices/available/compton/run3
-rwxr-xr-xservices/available/duplicati/log/run3
-rwxr-xr-xservices/available/duplicati/run2
-rwxr-xr-xservices/available/kuake/log/run3
-rwxr-xr-xservices/available/kuake/run4
-rwxr-xr-xservices/available/light-locker/log/run3
-rwxr-xr-xservices/available/light-locker/run2
-rwxr-xr-xservices/available/mpd/log/run3
-rwxr-xr-xservices/available/mpd/run3
-rwxr-xr-xservices/available/mpdscribble/log/run3
-rwxr-xr-xservices/available/mpdscribble/run3
-rwxr-xr-xservices/available/offlineimap/log/run3
-rwxr-xr-xservices/available/offlineimap/run3
-rwxr-xr-xservices/available/perspektiv/log/run3
-rwxr-xr-xservices/available/perspektiv/run3
-rwxr-xr-xservices/available/redshift/log/run3
-rwxr-xr-xservices/available/redshift/run3
-rwxr-xr-xservices/available/touchegg/log/run3
-rwxr-xr-xservices/available/touchegg/run2
-rwxr-xr-xservices/available/unclutter/log/run3
-rwxr-xr-xservices/available/unclutter/run3
-rwxr-xr-xservices/available/urxvtd/log/run3
-rwxr-xr-xservices/available/urxvtd/run3
-rwxr-xr-xservices/available/watch-kbd/log/run3
-rwxr-xr-xservices/available/watch-lock/log/run3
-rwxr-xr-xservices/available/watch-lock/run5
-rwxr-xr-xservices/available/xbindkeys/run4
-rwxr-xr-xservices/available/xcape/log/run3
-rwxr-xr-xservices/available/xcape/run3
m---------sh/.config/sh/fzf0
-rw-r--r--sh/.config/sh/rc.d/00path1
-rw-r--r--sh/.config/sh/rc.d/sh10
-rw-r--r--sh/.profile (renamed from profile)0
-rw-r--r--ssh/.ssh/authorized_keys1
-rw-r--r--ssh/authorized_keys1
-rw-r--r--starship/.config/starship.toml.PL159
-rw-r--r--starship/.gitignore1
-rw-r--r--starship/Makefile6
-rw-r--r--tex/.config/sh/rc.d/tex1
-rw-r--r--tex/.config/tex/jesse.sty (renamed from config/tex/jesse.sty)0
-rw-r--r--tex/.config/tex/jesse_essay.sty (renamed from config/tex/jesse_essay.sty)0
-rw-r--r--tex/.config/tex/jesse_letter.sty (renamed from config/tex/jesse_letter.sty)0
-rw-r--r--tex/.config/tex/jesse_macros.sty (renamed from config/tex/jesse_macros.sty)0
-rw-r--r--tex/.config/tex/jesse_resume.sty (renamed from config/tex/jesse_resume.sty)0
-rw-r--r--tex/.config/tex/sarah_resume.sty (renamed from config/tex/sarah_resume.sty)21
-rw-r--r--tig/.config/tig/config (renamed from config/tig/config)0
-rwxr-xr-xtmux/.bin/tmux-clipboard (renamed from bin/tmux-clipboard)0
-rw-r--r--tmux/.config/sh/rc.d/tmux5
-rw-r--r--tmux/.config/tmux/tmux.conf (renamed from tmux.conf)2
-rw-r--r--unclutter/.config/systemd/user/unclutter.service6
-rw-r--r--unclutter/Makefile9
-rwxr-xr-xuninstall9
-rw-r--r--vim/after/ftplugin/rust.vim1
-rw-r--r--vim/colors/local.vim126
-rw-r--r--vim/ftdetect/c.vim1
-rw-r--r--vim/ftdetect/levdes.vim1
-rw-r--r--vim/ftdetect/nhdes.vim1
-rw-r--r--vim/ftplugin/c.vim1
-rw-r--r--vim/ftplugin/cpp.vim2
-rw-r--r--vim/ftplugin/gitcommit.vim9
-rw-r--r--vim/ftplugin/go.vim3
-rw-r--r--vim/ftplugin/help.vim3
-rw-r--r--vim/ftplugin/javascript.vim3
-rw-r--r--vim/ftplugin/perl.vim25
-rw-r--r--vim/ftplugin/puppet.vim1
-rw-r--r--vim/ftplugin/python.vim13
-rw-r--r--vim/ftplugin/ruby.vim25
-rw-r--r--vim/ftplugin/rust.vim12
-rw-r--r--vim/ftplugin/sh.vim1
-rw-r--r--vim/ftplugin/terraform.vim3
-rw-r--r--vim/ftplugin/tex.vim96
-rw-r--r--vim/ftplugin/vim.vim3
-rw-r--r--vim/ftplugin/xs.vim10
m---------vim/pack/filetype/start/ledger0
m---------vim/pack/filetype/start/polyglot0
m---------vim/pack/plugins/start/airline0
m---------vim/pack/plugins/start/ale0
m---------vim/pack/plugins/start/autobrace0
m---------vim/pack/plugins/start/commentary0
m---------vim/pack/plugins/start/diff-changes0
m---------vim/pack/plugins/start/editorconfig0
m---------vim/pack/plugins/start/fzf0
m---------vim/pack/plugins/start/fzf.vim0
m---------vim/pack/plugins/start/gundo0
m---------vim/pack/plugins/start/history-sync0
m---------vim/pack/plugins/start/neosnippet0
m---------vim/pack/plugins/start/startify0
m---------vim/pack/plugins/start/textobj0
-rw-r--r--vim/plugin/dircreate.vim31
-rw-r--r--vim/plugin/eolws.vim6
-rw-r--r--vim/plugin/keywordprg.vim33
-rw-r--r--vim/plugin/nopaste.vim19
-rw-r--r--vim/plugin/opinionated-defaults.vim157
-rw-r--r--vim/plugin/rainbow_paren.vim96
-rw-r--r--vim/snippets/_.snippets4
-rw-r--r--vim/snippets/c.snippets12
-rw-r--r--vim/snippets/perl.snippets123
-rw-r--r--vim/snippets/python.snippets8
-rw-r--r--vim/snippets/ruby.snippets22
-rw-r--r--vim/snippets/rust.snippets16
-rw-r--r--vim/snippets/sh.snippets6
-rw-r--r--vim/snippets/tex.snippets13
-rw-r--r--vim/snippets/xs.snippets16
-rw-r--r--vim/spell/en.utf-8.add111
-rw-r--r--vim/syntax/levdes.vim304
-rw-r--r--vim/syntax/nhdes.vim99
-rw-r--r--vim/syntax/perl.vim1
-rw-r--r--vimrc194
-rw-r--r--weechat/perl/autoload/beep.pl257
-rw-r--r--weechat/perl/autoload/buffers.pl1292
-rw-r--r--weechat/perl/autoload/chanmon.pl1154
-rw-r--r--weechat/perl/autoload/chatters.pl287
-rw-r--r--xbindkeys/.config/systemd/user/xbindkeys.service9
-rw-r--r--xbindkeys/.xbindkeysrc (renamed from xbindkeysrc)21
-rw-r--r--xbindkeys/Makefile9
-rw-r--r--xcape/.config/systemd/user/xcape.service7
-rw-r--r--xcape/Makefile9
-rw-r--r--xorg/.Xdefaults (renamed from Xdefaults)0
-rw-r--r--xorg/.Xmodmap38
-rw-r--r--xorg/.xinitrc (renamed from xinitrc)2
-rw-r--r--xorg/.xprofile10
-rw-r--r--xprofile9
-rwxr-xr-xxss-lock/.bin/on-lock (renamed from bin/on-lock)1
-rw-r--r--xss-lock/.config/systemd/user/xss-lock.service6
-rw-r--r--xss-lock/Makefile9
m---------zsh/.config/zsh/zsh-autosuggestions0
m---------zsh/.config/zsh/zsh-completions0
m---------zsh/.config/zsh/zsh-syntax-highlighting0
-rw-r--r--zsh/.zshcomplete (renamed from zshcomplete)5
-rw-r--r--zsh/.zshinput (renamed from zshinput)16
-rw-r--r--zsh/.zshrc77
-rw-r--r--zshrc103
378 files changed, 2755 insertions, 14552 deletions
diff --git a/.gitignore b/.gitignore
index 47de586..b5173bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1 @@
-/config/alacritty/alacritty.yml
-/config/darksky/api
-/local/share/fortune/*.dat
-/less
-/mpdscribble/mpdscribble.conf
-/vim/spell/*.spl
+supervise \ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index 1b1a149..6ce12d7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,87 +1,12 @@
-[submodule "vim/bundle/fuzzyfinder"]
- path = vim/bundle/fuzzyfinder
- url = git://github.com/vim-scripts/FuzzyFinder
-[submodule "vim/bundle/gundo"]
- path = vim/pack/plugins/start/gundo
- url = git://github.com/sjl/gundo.vim
-[submodule "vim/bundle/l9"]
- path = vim/bundle/l9
- url = git://github.com/vim-scripts/L9
-[submodule "vim/bundle/snipmate"]
- path = vim/bundle/snipmate
- url = git://github.com/garbas/vim-snipmate
-[submodule "vim/bundle/supertab"]
- path = vim/bundle/supertab
- url = git://github.com/ervandew/supertab
-[submodule "vim/bundle/textobj"]
- path = vim/pack/plugins/start/textobj
- url = git://github.com/doy/vim-textobj
-[submodule "zsh/zsh-syntax-highlighting"]
- path = config/zsh/zsh-syntax-highlighting
- url = git://github.com/zsh-users/zsh-syntax-highlighting
-[submodule "vim/bundle/tlib"]
- path = vim/bundle/tlib
- url = git://github.com/tomtom/tlib_vim
-[submodule "vim/bundle/addon-mw-utils"]
- path = vim/bundle/addon-mw-utils
- url = git://github.com/MarcWeber/vim-addon-mw-utils
-[submodule "vim/bundle/startify"]
- path = vim/pack/plugins/start/startify
- url = git://github.com/mhinz/vim-startify
-[submodule "vim/bundle/airline"]
- path = vim/pack/plugins/start/airline
- url = git://github.com/bling/vim-airline
-[submodule "vim/bundle/neocomplete"]
- path = vim/bundle/neocomplete
- url = git://github.com/Shougo/neocomplete.vim
-[submodule "vim/bundle/neosnippet"]
- path = vim/pack/plugins/start/neosnippet
- url = git://github.com/Shougo/neosnippet.vim
-[submodule "vim/bundle/typescript"]
- path = vim/bundle/typescript
- url = git://github.com/leafgarland/typescript-vim
-[submodule "vim/bundle/julia"]
- path = vim/bundle/julia
- url = git://github.com/JuliaLang/julia-vim
-[submodule "zsh/zsh-autosuggestions"]
- path = config/zsh/zsh-autosuggestions
- url = git://github.com/zsh-users/zsh-autosuggestions
-[submodule "zsh/zsh-completions"]
- path = config/zsh/zsh-completions
- url = git://github.com/zsh-users/zsh-completions
-[submodule "vim/bundle/ledger"]
- path = vim/pack/filetype/start/ledger
- url = git://github.com/ledger/vim-ledger
-[submodule "vim/pack/local/start/ale"]
- path = vim/pack/plugins/start/ale
- url = git://github.com/w0rp/ale
-[submodule "vim/pack/local/start/commentary"]
- path = vim/pack/plugins/start/commentary
- url = git://github.com/tpope/vim-commentary
-[submodule "vim/pack/plugins/start/editorconfig"]
- path = vim/pack/plugins/start/editorconfig
- url = git://github.com/editorconfig/editorconfig-vim
-[submodule "zsh/fzf"]
- path = config/sh/fzf
- url = git://github.com/junegunn/fzf
-[submodule "vim/pack/plugins/start/fzf.vim"]
- path = vim/pack/plugins/start/fzf.vim
- url = git://github.com/junegunn/fzf.vim
-[submodule "vim/pack/plugins/start/fzf"]
- path = vim/pack/plugins/start/fzf
- url = git://github.com/junegunn/fzf
-[submodule "vim/pack/plugins/start/history-sync"]
- path = vim/pack/plugins/start/history-sync
- url = git://github.com/doy/vim-history-sync
-[submodule "vim/pack/plugins/start/diff-changes"]
- path = vim/pack/plugins/start/diff-changes
- url = git://github.com/doy/vim-diff-changes
-[submodule "vim/pack/plugins/start/autobrace"]
- path = vim/pack/plugins/start/autobrace
- url = git://github.com/doy/vim-autobrace
-[submodule "vim/pack/filetype/start/polyglot"]
- path = vim/pack/filetype/start/polyglot
- url = git://github.com/sheerun/vim-polyglot
-[submodule "vim/pack/filetype/start/terraform"]
- path = vim/pack/filetype/start/terraform
- url = git://github.com/hashivim/vim-terraform
+[submodule "sh/.config/sh/fzf"]
+ path = sh/.config/sh/fzf
+ url = https://github.com/junegunn/fzf
+[submodule "zsh/.config/zsh/zsh-autosuggestions"]
+ path = zsh/.config/zsh/zsh-autosuggestions
+ url = https://github.com/zsh-users/zsh-autosuggestions
+[submodule "zsh/.config/zsh/zsh-completions"]
+ path = zsh/.config/zsh/zsh-completions
+ url = https://github.com/zsh-users/zsh-completions
+[submodule "zsh/.config/zsh/zsh-syntax-highlighting"]
+ path = zsh/.config/zsh/zsh-syntax-highlighting
+ url = https://github.com/zsh-users/zsh-syntax-highlighting
diff --git a/.stowrc b/.stowrc
new file mode 100644
index 0000000..a8b39ca
--- /dev/null
+++ b/.stowrc
@@ -0,0 +1,5 @@
+-t ~
+--ignore=Makefile
+--ignore=.gitignore
+--ignore=.PL
+--ignore=.stowskip
diff --git a/Brewfile b/Brewfile
deleted file mode 100644
index fda8c13..0000000
--- a/Brewfile
+++ /dev/null
@@ -1,67 +0,0 @@
-tap "homebrew/bundle"
-tap "homebrew/cask"
-tap "homebrew/core"
-tap "wata727/tflint"
-brew "openssl"
-brew "readline"
-brew "python"
-brew "awscli"
-brew "bash"
-brew "bash-completion"
-brew "bazel"
-brew "binutils"
-brew "cloc"
-brew "cmake"
-brew "coreutils"
-brew "curl"
-brew "diffutils"
-brew "exa"
-brew "findutils"
-brew "flake8"
-brew "fortune"
-brew "fzf"
-brew "git"
-brew "gnu-sed", args: ["with-default-names"]
-brew "gsl"
-brew "htop"
-brew "hyperfine"
-brew "jq"
-brew "less"
-brew "libu2f-host"
-brew "libxml2"
-brew "libxmlsec1"
-brew "libxslt"
-brew "mongodb"
-brew "mtr"
-brew "ncdu"
-brew "node"
-brew "parallel"
-brew "postgresql"
-brew "ruby-build"
-brew "rbenv"
-brew "rbspy"
-brew "rename"
-brew "rsync"
-brew "ruby"
-brew "rustup-init"
-brew "shellcheck"
-brew "smartmontools"
-brew "ssss"
-brew "task"
-brew "tealdeer"
-brew "telnet"
-brew "terraform"
-brew "the_silver_searcher"
-brew "thrift"
-brew "tig"
-brew "tmux"
-brew "vim"
-brew "watchman"
-brew "wget"
-brew "wireshark", link: false
-brew "yamllint"
-brew "yarn"
-brew "zsh"
-brew "wata727/tflint/tflint"
-cask "amethyst"
-cask "wireshark"
diff --git a/EXTERNAL b/EXTERNAL
index 5b7766d..53ae26e 100644
--- a/EXTERNAL
+++ b/EXTERNAL
@@ -1,36 +1,17 @@
-bin/git/git-blame-stats
-- from perigrin at some point, but all relevant links are now dead
-bin/git/git-imerge
-- https://github.com/mhagger/git-imerge
-bin/ringtone
-- http://uselessdiaries.blogspot.com/2008/04/converting-audio-files-to-mp3-using.html
-bin/show_colors
-- http://www.linuxfocus.org/English/May2004/article335.shtml
-bin/vimmanpager
-- gentoo vim ebuild, somewhere in the middle
-local/share/fortune/*
+fortune/.local/share/fortune/*
- ideas, and yasd-fortune compiled by sartak
- perl from the base fortune-mod distribution
- calvin, kernelcookies, firefly, hitchhiker, and various dune quotes from the corresponding gentoo packages
- song-of-ice-and-fire and buffy compiled by me
-nethackrc
+git/.bin/git/git-blame-stats
+- from perigrin at some point, but all relevant links are now dead
+local/.bin/show_colors
+- http://www.linuxfocus.org/English/May2004/article335.shtml
+local/.bin/vimmanpager
+- gentoo vim ebuild, somewhere in the middle
+nethack/.nethackrc
- based on https://github.com/TAEB/TAEB/blob/master/lib/TAEB/Config.pm#L192 by sartak
-procmail/mark_as_read
-- http://www.mhonarc.org/archive/html/procmail/2005-08/msg00176.html
-config/sh/cdhist.sh
-- git://github.com/kana/config.git
-ssh/cao_key
+ssh/.ssh/cao_key
- http://crawl.akrasiac.org/cao_key
-config/tex/jesse_resume.sty
+tex/.config/tex/jesse_resume.sty
- based on http://www.courtesan.com/todd/resume.html
-vimrc
-- originally based on http://sartak.org/conf/vimrc
-vim/syntax/levdes.vim
-- Darshan Shaligram
-vim/syntax/nhdes.vim
-- http://bilious.alt.org/~paxed/nethack/nhdes.vim
-weechat/perl/autoload/*
-- http://www.weechat.org/scripts/source/beep.pl.html/
-- http://www.weechat.org/scripts/source/buffers.pl.html/
-- http://www.weechat.org/scripts/source/chanmon.pl.html/
-- http://www.weechat.org/scripts/source/chatters.pl.html/
diff --git a/Makefile b/Makefile
index d49a917..303b645 100644
--- a/Makefile
+++ b/Makefile
@@ -1,149 +1,25 @@
-INTO := $(HOME)
+ifeq ($(USER),root)
+PACKAGES=$(shell cat packages.root)
+else
+PACKAGES=$(shell cat packages.$$(hostname))
+endif
-all : build
+build: submodules
+ @for package in $(PACKAGES); do ./build $${package}; done
-include Makefile.$(shell hostname | cut -d. -f1)
+install: submodules
+ @for package in $(PACKAGES); do ./install $${package}; done
-INSTALL := \
- $(INSTALL) \
- .abook/abookrc \
- .agignore \
- .bash_profile \
- .bashrc \
- .config/git/config \
- .config/git/ignore \
- .config/mpd/mpd.conf \
- .config/ncmpcpp/bindings \
- .config/sh/aliases \
- .config/sh/cdhist.sh \
- .config/sh/env \
- .config/sh/functions \
- .config/sh/fzf \
- .config/tex/jesse_essay.sty \
- .config/tex/jesse_letter.sty \
- .config/tex/jesse_macros.sty \
- .config/tex/jesse_resume.sty \
- .config/tex/jesse.sty \
- .config/tex/sarah_resume.sty \
- .config/tig/config \
- .config/weechat/saved \
- .config/weechat/extra \
- .config/zsh/local-completions \
- .config/zsh/zsh-autosuggestions \
- .config/zsh/zsh-completions \
- .config/zsh/zsh-syntax-highlighting \
- .crawlrc \
- .gdbinit \
- .inputrc \
- .ledgerrc \
- .less \
- .local/share/fortune \
- .mutt/choose-muttrc-type \
- .mutt/imap \
- .mutt/mailcap \
- .mutt/muttrc \
- .mutt/offlineimap \
- .nethackrc \
- .perlcriticrc \
- .profile \
- .proverc \
- .replyrc \
- .screenrc \
- .ssh/cao_key \
- .tmux.conf \
- .vimrc \
- .zshcomplete \
- .zshinput \
- .zshrc \
- .bin \
- .dzil \
- .vim \
- .weechat/perl \
+uninstall:
+ @for package in $(PACKAGES); do ./uninstall $${package}; done
-EMPTYDIRS := \
- $(EMPTYDIRS) \
- .cache/mutt/headers \
- .cache/mutt/bodies \
- .cache/vim/hist \
- .cache/vim/undo \
+clean:
+ @for package in $(PACKAGES); do ./clean $${package}; done
-INSTALL_CUSTOM := \
- $(INSTALL_CUSTOM)
-
-BUILD := \
- $(BUILD) \
- $(addsuffix .dat,$(filter-out %.dat,$(wildcard local/share/fortune/*))) \
- $(addsuffix tags,$(wildcard vim/pack/*/start/*/doc/)) \
- vim/spell/en.utf-8.add.spl \
- less
-
-INSTALLED_SYMLINKS := \
- $(patsubst %,$(INTO)/%,$(INSTALL)) \
- $(INSTALL_CUSTOM)
-
-INSTALLED_DIRS := \
- $(patsubst %,$(INTO)/%,$(EMPTYDIRS))
-
-INSTALLED := \
- $(INSTALLED_SYMLINKS) \
- $(INSTALLED_DIRS)
-
-ECHO = @echo
-LN = @ln -sf
-MKDIR = @mkdir -p
-RM = @rm -f
-RMDIR = @rmdir -p --ignore-fail-on-non-empty
-
-# named targets
-
-build : submodules $(BUILD)
-
-submodules :
+submodules:
@git submodule update --init --recursive
-install :: all $(INSTALLED)
- @chmod 600 ssh/cao_key
- @chmod 700 gnupg
- $(ECHO) Installed into $(INTO)
-
-clean ::
- $(ECHO) Cleaning from $(INTO)
- $(RM) $(BUILD)
- $(RM) $(INSTALLED_SYMLINKS)
- $(RMDIR) $(INSTALLED_DIRS)
-
-update :
- @git submodule foreach '(if [ $$path == "vim/pack/filetype/start/perl" ]; then git checkout dev; else git checkout master; fi) && git pull'
-
-versions :
- @git submodule foreach -q 'printf "%-53s" " $$path" && GIT_PAGER=cat git show -s --format=format:%cI%n $$sha1'
-
-updates :
- @git submodule foreach -q 'if [ $$path == "vim/pack/filetype/start/perl" ]; then if [ $$(git rev-parse dev) != $$sha1 ]; then git lg dev...$$sha1; fi; else if [ $$(git rev-parse master) != $$sha1 ]; then git lg master...$$sha1; fi; fi'
-
-.PHONY: submodules build install clean update versions updates
-
-# installation targets
-
-$(patsubst %,$(INTO)/%,$(EMPTYDIRS)) :
- $(MKDIR) $@
-
-$(patsubst %,$(INTO)/%,$(INSTALL)) : $(INTO)/.% : %
- @[ ! -e $@ ] || [ -h $@ ] || mv -f $@ $@.bak
- $(MKDIR) $(dir $@)
- $(LN) $(PWD)/$< $@
-
-# build targets
-
-local/share/fortune/%.dat : local/share/fortune/%
- $(ECHO) "Compiling $@"
- @strfile -s $(basename $@)
-
-%/doc/tags: %/doc
- @vim -u NONE -c':helptags $< | :q'
-
-%.spl : %
- @vim -u NONE -c':mkspell! $< | :q'
+update:
+ @git submodule foreach 'git checkout master && git pull'
-less : lesskey
- lesskey -o $@ $<
+.PHONY: build install uninstall clean submodules update
diff --git a/Makefile.hush b/Makefile.hush
deleted file mode 100644
index 9d7a996..0000000
--- a/Makefile.hush
+++ /dev/null
@@ -1,68 +0,0 @@
-INSTALL := \
- .config/alacritty/alacritty.yml \
- .config/darksky/api \
- .config/darksky/location \
- .config/i3/browser-workspace.json \
- .config/i3/config \
- .config/i3/signal-workspace.json \
- .config/i3/terminal-workspace.json \
- .config/i3status/config \
- .config/msmtp/config \
- .config/offlineimap/config \
- .config/offlineimap/pass.py \
- .config/perspektiv/config.toml \
- .config/touchegg/touchegg.conf \
- .gnupg/gpg.conf \
- .gnupg/gpg-agent.conf \
- .notmuch-config \
- .xbindkeysrc \
- .Xdefaults \
- .xinitrc \
- .xprofile \
- .Xmodmap \
- .mpdscribble \
- $(patsubst %,.%,$(wildcard services/available/*/run)) \
- $(patsubst %,.%,$(wildcard services/available/*/log/run))
-
-EMPTYDIRS := \
- $(patsubst services/available/%,.log/%,$(wildcard services/available/*)) \
- Maildir \
- .cache/mpd \
- .config/mpd/playlists
-
-INSTALL_CUSTOM := \
- $(patsubst services/available/%,$(INTO)/.services/enabled/%,$(wildcard services/available/*)) \
- /var/spool/cron/$(USER) \
- $(INTO)/Maildir/.notmuch/hooks/post-new
-
-BUILD := \
- config/alacritty/alacritty.yml \
- mpdscribble/mpdscribble.conf
-
-install ::
- @chmod 600 config/msmtp/config
-
-clean ::
- @crontab -r
-
-/var/spool/cron/$(USER) : crontab
- @crontab $<
-
-$(INTO)/Maildir/.notmuch/hooks/post-new: notmuch/hooks/post-new
- @[ ! -e $@ ] || [ -h $@ ] || mv -f $@ $@.bak
- $(MKDIR) $(INTO)/Maildir/.notmuch/hooks
- $(LN) $(PWD)/$< $@
-
-$(INTO)/.services/enabled/% : services/available/%
- $(MKDIR) $(dir $<)
- $(LN) ../available/$(notdir $<) $@
-
-config/alacritty/alacritty.yml : config/alacritty/alacritty.yml.hush
- $(LN) $(notdir $<) $@
-
-config/darksky/api :
- pass show websites/darksky.net/api > $@
-
-mpdscribble/mpdscribble.conf : mpdscribble/mpdscribble.conf.tmpl
- pass="$$(pass show websites/last.fm/doyster)" &&\
- perl -E'while (<STDIN>) { if (/^password =/) { say "password = $$ARGV[0]" } else { print } }' "$$pass" < $< > $@
diff --git a/Makefile.include b/Makefile.include
new file mode 100644
index 0000000..6d8ce6e
--- /dev/null
+++ b/Makefile.include
@@ -0,0 +1,12 @@
+build:
+install:
+uninstall:
+clean:
+.PHONY: build install uninstall clean
+
+% : %.PL
+ @perl $< > $@
+
+$(HOME)/.services/enabled/% : $(HOME)/.services/available/%
+ @mkdir -p $(dir $@)
+ @ln -sf ../available/$(notdir $<) $@
diff --git a/Makefile.mail b/Makefile.mail
deleted file mode 100644
index 94da815..0000000
--- a/Makefile.mail
+++ /dev/null
@@ -1,8 +0,0 @@
-INSTALL := \
- .ssh/authorized_keys
-
-EMPTYDIRS := \
-
-INSTALL_CUSTOM := \
-
-BUILD := \
diff --git a/Makefile.partofme b/Makefile.partofme
deleted file mode 100644
index 94da815..0000000
--- a/Makefile.partofme
+++ /dev/null
@@ -1,8 +0,0 @@
-INSTALL := \
- .ssh/authorized_keys
-
-EMPTYDIRS := \
-
-INSTALL_CUSTOM := \
-
-BUILD := \
diff --git a/Makefile.st-doy2 b/Makefile.st-doy2
deleted file mode 100644
index 46f430d..0000000
--- a/Makefile.st-doy2
+++ /dev/null
@@ -1,14 +0,0 @@
-INSTALL := \
- .config/alacritty/alacritty.yml \
- .config/karabiner \
- .hammerspoon
-
-EMPTYDIRS := \
-
-INSTALL_CUSTOM := \
-
-BUILD := \
- config/alacritty/alacritty.yml
-
-config/alacritty/alacritty.yml : config/alacritty/alacritty.yml.st-doy2
- $(LN) $(notdir $<) $@
diff --git a/Makefile.tozt b/Makefile.tozt
deleted file mode 100644
index b028300..0000000
--- a/Makefile.tozt
+++ /dev/null
@@ -1,10 +0,0 @@
-INSTALL := \
- .procmailrc \
- .procmail \
- .ssh/authorized_keys
-
-EMPTYDIRS := \
-
-INSTALL_CUSTOM := \
-
-BUILD := \
diff --git a/Xmodmap b/Xmodmap
deleted file mode 100644
index 3a3b6ad..0000000
--- a/Xmodmap
+++ /dev/null
@@ -1,39 +0,0 @@
-! reset state
-clear control
-clear mod1
-clear mod4
-
-! swap alt and control
-keycode 37 = Alt_L Meta_L
-keycode 64 = Control_L
-keycode 105 = Alt_R Meta_R
-keycode 108 = Control_R
-
-! map prtsc to super, because the thinkpad layout puts it in that location
-keycode 107 = Super_R
-
-! set the values for control, mod1 (meta), and mod4 (super) now that they have
-! been assigned to keycodes
-add control = Control_L Control_R
-add mod1 = Alt_L Alt_R Meta_L Meta_R
-add mod4 = Super_L Super_R
-
-! map home and end to insert, because the thinkpad layout puts them where
-! insert should be
-keycode 110 = Insert
-keycode 115 = Insert
-
-! map function keys to their appropriate values (thinkpad does this in
-! hardware, but other keyboards don't)
-keycode 67 = XF86AudioMute F1 XF86AudioMute F1 F1 F1 XF86Switch_VT_1
-keycode 68 = XF86AudioLowerVolume F2 XF86AudioLowerVolume F2 F2 F2 XF86Switch_VT_2
-keycode 69 = XF86AudioRaiseVolume F3 XF86AudioRaiseVolume F3 F3 F3 XF86Switch_VT_3
-keycode 70 = XF86AudioMicMute F4 XF86AudioMicMute F4 F4 F4 XF86Switch_VT_4
-keycode 71 = XF86MonBrightnessDown F5 XF86MonBrightnessDown F5 F5 F5 XF86Switch_VT_5
-keycode 72 = XF86MonBrightnessUp F6 XF86MonBrightnessUp F6 F6 F6 XF86Switch_VT_6
-keycode 73 = XF86Display F7 XF86Display F7 F7 F7 XF86Switch_VT_7
-keycode 74 = XF86WLAN F8 XF86WLAN F8 F8 F8 XF86Switch_VT_8
-keycode 75 = XF86Tools F9 XF86Tools F9 F9 F9 XF86Switch_VT_9
-keycode 76 = XF86Search F10 XF86Search F10 F10 F10 XF86Switch_VT_10
-keycode 95 = XF86LaunchA F11 XF86LaunchA F11 F11 F11 XF86Switch_VT_11
-keycode 96 = XF86Explorer F12 XF86Explorer F12 F12 F12 XF86Switch_VT_12
diff --git a/abook/abookrc b/abook/abookrc
deleted file mode 100644
index 671efa9..0000000
--- a/abook/abookrc
+++ /dev/null
@@ -1,39 +0,0 @@
-field aim = AIM
-field irc = IRC, list
-field twitter = Twitter
-field skype = Skype
-field birthday = Birthday, date
-
-field 2address = Address
-field 2address2 = Address2
-field 2city = City
-field 2state = State/Province
-field 2zip = "ZIP/Postal Code"
-field 2country = Country
-
-field textphone = Text
-
-view Contact = name, email, birthday, nick
-view Phone = mobile, textphone, phone, workphone
-view Internet = irc, aim, skype, twitter, url
-view Address = address, address2, city, state, zip, country
-view Address2 = 2address, 2address2, 2city, 2state, 2zip, 2country
-view Other = notes
-
-set index_format=" {name:23} {email:34} {mobile:12|phone|workphone} {birthday:10} {nick}"
-
-set preserve_fields=all
-set show_all_emails=false
-set www_command=firefox
-set address_style=us
-set sort_field=name
-
-set use_colors=true
-set color_header_bg=default
-set color_header_fg=green
-set color_footer_bg=default
-set color_footer_fg=green
-set color_list_header_bg=default
-set color_list_highlight_bg=cyan
-set color_list_even_fg=yellow
-set color_list_odd_fg=yellow
diff --git a/agignore b/agignore
deleted file mode 100644
index 8c348f8..0000000
--- a/agignore
+++ /dev/null
@@ -1,7 +0,0 @@
-node_modules/
-*.min.css
-*.min.js
-*.d
-*.pdf
-*.map
-/.git/
diff --git a/alacritty/.config/alacritty/alacritty.toml.PL b/alacritty/.config/alacritty/alacritty.toml.PL
new file mode 100644
index 0000000..f580ac4
--- /dev/null
+++ b/alacritty/.config/alacritty/alacritty.toml.PL
@@ -0,0 +1,578 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.016;
+
+chomp(my $hostname = `hostname`);
+
+while (<DATA>) {
+ if ($hostname eq 'mz-doy1') {
+ s/^family = .*/family = "Fixed Fallback"/;
+ s/^size = .*/size = 10.5/;
+ }
+ print;
+}
+
+__DATA__
+[colors]
+draw_bold_text_with_bright_colors = true
+
+[colors.bright]
+black = "0x697386"
+blue = "0x9fcdff"
+cyan = "0x7fd3ed"
+green = "0x85d996"
+magenta = "0xf0b4e4"
+red = "0xfbb5b2"
+white = "0xffffff"
+yellow = "0xefc078"
+
+[colors.cursor]
+cursor = "0x00ff00"
+text = "0x000000"
+
+[colors.normal]
+black = "0x000000"
+blue = "0x688ef1"
+cyan = "0x3a97d4"
+green = "0x1ea672"
+magenta = "0xc96ed0"
+red = "0xed5f74"
+white = "0xe3e8ee"
+yellow = "0xd97917"
+
+[colors.primary]
+background = "0x000000"
+foreground = "0xc1c9d2"
+
+[env]
+TERM = "alacritty-direct"
+
+[font]
+size = 11
+
+[font.bold]
+family = "FiraMono"
+style = "Regular"
+
+[font.italic]
+family = "FiraMono"
+
+[font.normal]
+family = "FiraMono"
+
+[[keyboard.bindings]]
+action = "Paste"
+key = "V"
+mods = "Control|Shift"
+
+[[keyboard.bindings]]
+action = "Copy"
+key = "C"
+mods = "Control|Shift"
+
+[[keyboard.bindings]]
+action = "Quit"
+key = "Q"
+mods = "Command"
+
+[[keyboard.bindings]]
+action = "Quit"
+key = "W"
+mods = "Command"
+
+[[keyboard.bindings]]
+action = "PasteSelection"
+key = "Insert"
+mods = "Shift"
+
+[[keyboard.bindings]]
+action = "ResetFontSize"
+key = "Key0"
+mods = "Control"
+
+[[keyboard.bindings]]
+action = "IncreaseFontSize"
+key = "Equals"
+mods = "Control"
+
+[[keyboard.bindings]]
+action = "DecreaseFontSize"
+key = "Minus"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001BOH"
+key = "Home"
+mode = "AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001B[H"
+key = "Home"
+mode = "~AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001BOF"
+key = "End"
+mode = "AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001B[F"
+key = "End"
+mode = "~AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001B[5;2~"
+key = "PageUp"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[5;5~"
+key = "PageUp"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[5~"
+key = "PageUp"
+
+[[keyboard.bindings]]
+chars = "\u001B[6;2~"
+key = "PageDown"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[6;5~"
+key = "PageDown"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[6~"
+key = "PageDown"
+
+[[keyboard.bindings]]
+chars = "\u001B[Z"
+key = "Tab"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u007F"
+key = "Back"
+
+[[keyboard.bindings]]
+chars = "\u001B\u007F"
+key = "Back"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[2~"
+key = "Insert"
+
+[[keyboard.bindings]]
+chars = "\u001B[3~"
+key = "Delete"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2D"
+key = "Left"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5D"
+key = "Left"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3D"
+key = "Left"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[D"
+key = "Left"
+mode = "~AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001BOD"
+key = "Left"
+mode = "AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2C"
+key = "Right"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5C"
+key = "Right"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3C"
+key = "Right"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[C"
+key = "Right"
+mode = "~AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001BOC"
+key = "Right"
+mode = "AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2A"
+key = "Up"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5A"
+key = "Up"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3A"
+key = "Up"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[A"
+key = "Up"
+mode = "~AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001BOA"
+key = "Up"
+mode = "AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2B"
+key = "Down"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5B"
+key = "Down"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3B"
+key = "Down"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[B"
+key = "Down"
+mode = "~AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001BOB"
+key = "Down"
+mode = "AppCursor"
+
+[[keyboard.bindings]]
+chars = "\u001BOP"
+key = "F1"
+
+[[keyboard.bindings]]
+chars = "\u001BOQ"
+key = "F2"
+
+[[keyboard.bindings]]
+chars = "\u001BOR"
+key = "F3"
+
+[[keyboard.bindings]]
+chars = "\u001BOS"
+key = "F4"
+
+[[keyboard.bindings]]
+chars = "\u001B[15~"
+key = "F5"
+
+[[keyboard.bindings]]
+chars = "\u001B[17~"
+key = "F6"
+
+[[keyboard.bindings]]
+chars = "\u001B[18~"
+key = "F7"
+
+[[keyboard.bindings]]
+chars = "\u001B[19~"
+key = "F8"
+
+[[keyboard.bindings]]
+chars = "\u001B[20~"
+key = "F9"
+
+[[keyboard.bindings]]
+chars = "\u001B[21~"
+key = "F10"
+
+[[keyboard.bindings]]
+chars = "\u001B[23~"
+key = "F11"
+
+[[keyboard.bindings]]
+chars = "\u001B[24~"
+key = "F12"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2P"
+key = "F1"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2Q"
+key = "F2"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2R"
+key = "F3"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;2S"
+key = "F4"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[15;2~"
+key = "F5"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[17;2~"
+key = "F6"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[18;2~"
+key = "F7"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[19;2~"
+key = "F8"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[20;2~"
+key = "F9"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[21;2~"
+key = "F10"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[23;2~"
+key = "F11"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[24;2~"
+key = "F12"
+mods = "Shift"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5P"
+key = "F1"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5Q"
+key = "F2"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5R"
+key = "F3"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;5S"
+key = "F4"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[15;5~"
+key = "F5"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[17;5~"
+key = "F6"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[18;5~"
+key = "F7"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[19;5~"
+key = "F8"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[20;5~"
+key = "F9"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[21;5~"
+key = "F10"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[23;5~"
+key = "F11"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[24;5~"
+key = "F12"
+mods = "Control"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;6P"
+key = "F1"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;6Q"
+key = "F2"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;6R"
+key = "F3"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;6S"
+key = "F4"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[15;6~"
+key = "F5"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[17;6~"
+key = "F6"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[18;6~"
+key = "F7"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[19;6~"
+key = "F8"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[20;6~"
+key = "F9"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[21;6~"
+key = "F10"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[23;6~"
+key = "F11"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[24;6~"
+key = "F12"
+mods = "Alt"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3P"
+key = "F1"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3Q"
+key = "F2"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3R"
+key = "F3"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[1;3S"
+key = "F4"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[15;3~"
+key = "F5"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[17;3~"
+key = "F6"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[18;3~"
+key = "F7"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[19;3~"
+key = "F8"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[20;3~"
+key = "F9"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[21;3~"
+key = "F10"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[23;3~"
+key = "F11"
+mods = "Super"
+
+[[keyboard.bindings]]
+chars = "\u001B[24;3~"
+key = "F12"
+mods = "Super"
+
+[[mouse.bindings]]
+action = "PasteSelection"
+mouse = "Middle"
+
+[selection]
+semantic_escape_chars = " "
+
+[window]
+decorations = "full"
+
+[window.dimensions]
+columns = 80
+lines = 24
+
+[window.padding]
+x = 2
+y = 2
diff --git a/alacritty/.gitignore b/alacritty/.gitignore
new file mode 100644
index 0000000..816fb45
--- /dev/null
+++ b/alacritty/.gitignore
@@ -0,0 +1 @@
+/.config/alacritty/alacritty.toml
diff --git a/alacritty/Makefile b/alacritty/Makefile
new file mode 100644
index 0000000..391be12
--- /dev/null
+++ b/alacritty/Makefile
@@ -0,0 +1,6 @@
+include ../Makefile.include
+
+build: .config/alacritty/alacritty.toml
+
+clean:
+ @rm -f .config/alacritty/alacritty.toml
diff --git a/archlinux-packages b/archlinux-packages
index aeaf2e3..5f0032d 100644
--- a/archlinux-packages
+++ b/archlinux-packages
@@ -1,27 +1,30 @@
-base
base-devel
abook
accountsservice
alacritty
-alacritty-terminfo
ansible-lint
apache-tools
+arenatracker-bin
+base
bc
-bear
bind-tools
browserpass
ccache
chars
+chromium
clang
cloc
cmake
-compton
consolas-font
cronie
+ctags
cups
daemontools
+dhcpcd
diceware
+diffutils
dmenu
+docker-compose
doctl
duplicati-latest
efibootmgr
@@ -30,6 +33,7 @@ ethtool
exa
firefox
flashplugin
+flips
foomatic-db
foomatic-db-engine
foomatic-db-gutenprint-ppds
@@ -40,10 +44,13 @@ gdb
ghostscript
gimp
git
+gnome-terminal
+gnu-netcat
go
grub
gutenprint
-gvim
+higan
+hplip
htop
hugo
hyperfine
@@ -51,41 +58,60 @@ i3status
i3-wm
iftop
imagemagick
+inetutils
inotify-tools
intel-ucode
iotop
iw
jq
-jrnl
ledger
+lib32-gnutls
+lib32-libldap
libreoffice-fresh
libva-intel-driver
libva-utils
lightdm
lightdm-gtk-greeter
light-locker
+linux
+lld
+logrotate
lsof
+lvm2
+man-db
+man-pages
+mdadm
mesa-demos
+minisign
mpd
mpdscribble
mpv
msmtp-mta
mtr
-mutt
+munin-node
+namcap
ncdu
ncmpcpp
+neomutt
+netctl
+nethack
nmap
+nodejs-terser
notmuch
ntp
offlineimap
+openapi-generator-cli
openssh
+openssl-1.0
package-query
+pacman-contrib
pass
pavucontrol
perf
perlbrew
perl-io-socket-ssl
perl-rename
+picom
powertop
pulseaudio
puppet
@@ -93,26 +119,39 @@ puppet-lint
python2-virtualenv
python-pycryptodome
python-virtualenv
+rbw-bin
redshift
+ripgrep
rsync
rtorrent
+ruby
+ruby-bundler
+ruby-irb
rustup
rxvt-unicode
+sane
+screen
shellcheck
-signal
+signal-desktop
smartmontools
+snes9x-gtk
+socat
sshfs
steam
strace
sxiv
syncthing
+tarsnap
+tcpdump
+teleterm
+terraform
texlive-bin
texlive-core
texlive-latexextra
the_silver_searcher
tig
tmux
-touchegg
+touchegg-qt5
tpacpi-bat
ttf-dejavu
ttf-font-awesome
@@ -120,10 +159,17 @@ unclutter-xfixes-git
unzip
upower
valgrind
+wabt
+wasm-pack
weechat
whois
-wireguard-arch
+wine-gecko
+wine-mono
+wine-staging
+winetricks
wireguard-tools
+wireshark-cli
+wireshark-qt
wpa_actiond
xbindkeys
xcape
@@ -134,13 +180,17 @@ xorg-server
xorg-xbacklight
xorg-xev
xorg-xinput
+xorg-xmag
xorg-xmodmap
xorg-xprop
xorg-xset
xorg-xwininfo
+xsecurelock
+xss-lock
xterm
xzoom
yaourt
zathura
zathura-pdf-poppler
+zoom
zsh
diff --git a/bash/.bash_profile b/bash/.bash_profile
new file mode 100644
index 0000000..e8c96d8
--- /dev/null
+++ b/bash/.bash_profile
@@ -0,0 +1,4 @@
+# shellcheck source=bash/.bashrc
+. "$HOME"/.bashrc
+
+# vim:ft=sh:
diff --git a/bash/.bashrc b/bash/.bashrc
new file mode 100644
index 0000000..3422362
--- /dev/null
+++ b/bash/.bashrc
@@ -0,0 +1,48 @@
+if [[ $- != *i* ]]; then
+ return
+fi
+for file in ~/.config/sh/rc.d/*; do
+ # shellcheck disable=SC1090
+ source "$file"
+done
+# completion {{{
+#shellcheck disable=SC1091
+[ -f /etc/bash_completion ] && source /etc/bash_completion
+#shellcheck disable=SC1091
+[ -f /etc/profile.d/bash-completion ] && source /etc/profile.d/bash-completion
+#shellcheck disable=SC1091
+[ -f /usr/share/bash-completion/bash_completion ] && source /usr/share/bash-completion/bash_completion
+# }}}
+# bash configuration {{{
+shopt -s extglob
+shopt -s no_empty_cmd_completion
+shopt -s checkwinsize
+shopt -s histappend
+if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
+ shopt -s globstar
+fi
+set -o vi
+export HISTCONTROL=ignoredups
+export HISTFILESIZE=1000000000
+export HISTSIZE=1000000000
+if [[ -z "$PROMPT_COMMAND" ]]; then
+ export PROMPT_COMMAND='history -a'
+else
+ export PROMPT_COMMAND="${PROMPT_COMMAND};history -a"
+fi
+# plugins {{{
+# shellcheck source=sh/.config/sh/fzf/shell/completion.bash
+source ~/.config/sh/fzf/shell/completion.bash
+# shellcheck source=sh/.config/sh/fzf/shell/key-bindings.bash
+source ~/.config/sh/fzf/shell/key-bindings.bash
+# }}}
+# prompt {{{
+if type starship > /dev/null 2>&1; then
+ eval "$(starship init bash)"
+fi
+# }}}
+# }}}
+# fortune {{{
+fortune -n600 -s ~/.local/share/fortune | grep -v -E "^$"
+# }}}
+# vim: fdm=marker
diff --git a/bash_profile b/bash_profile
deleted file mode 100644
index b200eb1..0000000
--- a/bash_profile
+++ /dev/null
@@ -1,4 +0,0 @@
-# shellcheck source=bashrc
-. "$HOME"/.bashrc
-
-# vim:ft=sh:
diff --git a/bashrc b/bashrc
deleted file mode 100644
index c6015cf..0000000
--- a/bashrc
+++ /dev/null
@@ -1,73 +0,0 @@
-# language environments {{{
-# shellcheck disable=1090
-test -f "$HOME"/perl5/perlbrew/etc/bashrc && source "$HOME"/perl5/perlbrew/etc/bashrc
-test -f "$HOME"/python/bin/activate && source "$HOME"/python/bin/activate
-type rbenv > /dev/null 2>&1 && eval "$(rbenv init -)"
-test -d "$HOME"/.cargo/bin && export PATH="$HOME/.cargo/bin:$PATH"
-# }}}
-# environment {{{
-[ -d /usr/share/git/diff-highlight ] && export PATH="/usr/share/git/diff-highlight:${PATH}"
-[ -d /usr/local/share/git-core/contrib/diff-highlight ] && export PATH="/usr/local/share/git-core/contrib/diff-highlight:${PATH}"
-PATH="${HOME}/.bin/local:${HOME}/.bin/$(hostname):${HOME}/.bin:/usr/lib/ccache/bin:$PATH"
-export PATH
-[ -f "$HOME/.config/sh/env" ] && source "$HOME"/.config/sh/env
-# }}}
-# Test for an interactive shell. {{{
-# There is no need to set anything past this point for scp and rcp, and it's
-# important to refrain from outputting anything in those cases.
-if [[ $- != *i* ]] ; then
- # Shell is non-interactive. Be done now!
- return
-fi
-[ -z "$PS1" ] && return # }}}
-# Change the window title of X terminals {{{
-case ${TERM} in
- xterm*|rxvt*|Eterm|aterm|kterm|gnome|screen*)
- PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\007"'
- ;;
-esac # }}}
-# aliases {{{
-[ -f "$HOME/.config/sh/aliases" ] && source "$HOME"/.config/sh/aliases
-[ -f "$HOME/.config/sh/functions" ] && source "$HOME"/.config/sh/functions
-# }}}
-# completion {{{
-#shellcheck disable=SC1091
-[ -f /etc/bash_completion ] && source /etc/bash_completion
-#shellcheck disable=SC1091
-[ -f /etc/profile.d/bash-completion ] && source /etc/profile.d/bash-completion
-#shellcheck disable=SC1091
-[ -f /usr/share/bash-completion/bash_completion ] && source /usr/share/bash-completion/bash_completion
-# }}}
-# bash configuration {{{
-shopt -s extglob
-shopt -s no_empty_cmd_completion
-shopt -s checkwinsize
-shopt -s histappend
-if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
- shopt -s globstar
-fi
-set -o vi
-export HISTCONTROL=ignoredups
-export HISTFILESIZE=1000000000
-export HISTSIZE=1000000000
-if [[ -z "$PROMPT_COMMAND" ]]; then
- export PROMPT_COMMAND='history -a'
-else
- export PROMPT_COMMAND="${PROMPT_COMMAND};history -a"
-fi
-# plugins {{{
-source ~/.config/sh/cdhist.sh
-source ~/.config/sh/fzf/shell/completion.bash
-source ~/.config/sh/fzf/shell/key-bindings.bash
-# }}}
-# prompt {{{
-if type fancy-prompt > /dev/null 2>&1; then
- __err=0
- export PROMPT_COMMAND="__err=\$?;$PROMPT_COMMAND;PS1=\"\$(fancy-prompt --prompt-escape bash \$__err)\""
-fi
-# }}}
-# }}}
-# fortune {{{
-fortune -n600 -s ~/.local/share/fortune | grep -v -E "^$"
-# }}}
-# vim: fdm=marker
diff --git a/bat/.bin/batman b/bat/.bin/batman
new file mode 100755
index 0000000..5e328a3
--- /dev/null
+++ b/bat/.bin/batman
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+col -bx | bat --color=always -l man -pp | less +Gg
diff --git a/bat/.config/sh/rc.d/bat b/bat/.config/sh/rc.d/bat
new file mode 100644
index 0000000..f02d505
--- /dev/null
+++ b/bat/.config/sh/rc.d/bat
@@ -0,0 +1,2 @@
+export MANPAGER=batman
+export MANROFFOPT=-c
diff --git a/bin/cryptdir b/bin/.bin/cryptdir
index 3fb858f..eb63300 100755
--- a/bin/cryptdir
+++ b/bin/.bin/cryptdir
@@ -19,7 +19,7 @@ cryptfile=$(mktemp)
cryptdir=$(mktemp -d)
pass=$(dd if=/dev/urandom bs=1 count=80 | base64)
-cleanup () {
+cleanup() {
set +e
cd
sudo umount "$cryptdir"
diff --git a/bin/.bin/cryptoloop b/bin/.bin/cryptoloop
new file mode 100755
index 0000000..493c74e
--- /dev/null
+++ b/bin/.bin/cryptoloop
@@ -0,0 +1,30 @@
+#!/bin/sh
+set -eu
+
+command="$1"
+name="$2"
+file="${HOME}/crypt/${name}.luks"
+dev="/dev/mapper/$name"
+
+case "$command" in
+create)
+ size=$3
+ count=${4:-1}
+ dd if=/dev/urandom of="$file" bs="$size" count="$count" iflag=fullblock
+ sudo cryptsetup luksFormat "$file"
+ sudo cryptsetup open "$file" "$name"
+ sudo mkfs.ext4 "$dev"
+ sudo mount "$dev" /mnt
+ sudo chown "$USER" /mnt
+ sudo umount /mnt
+ sudo cryptsetup close "$name"
+ ;;
+open)
+ sudo cryptsetup open "$file" "$name"
+ sudo mount "$dev" /mnt
+ ;;
+close)
+ sudo umount /mnt
+ sudo cryptsetup close "$name"
+ ;;
+esac
diff --git a/bin/.bin/files-between b/bin/.bin/files-between
new file mode 100755
index 0000000..634b61c
--- /dev/null
+++ b/bin/.bin/files-between
@@ -0,0 +1,14 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.014;
+
+use File::Basename;
+
+my $first = $ARGV[0];
+my $second = $ARGV[1];
+
+my $dirname = dirname($first);
+die unless $dirname eq dirname($second);
+
+say for grep { /^\Q$first\E$/../^\Q$second\E$/ } sort <$dirname/*>;
diff --git a/bin/fm22avi b/bin/.bin/fm22avi
index eebfb4f..eebfb4f 100755
--- a/bin/fm22avi
+++ b/bin/.bin/fm22avi
diff --git a/bin/history-stats b/bin/.bin/history-stats
index 0fead1f..0fead1f 100755
--- a/bin/history-stats
+++ b/bin/.bin/history-stats
diff --git a/bin/.bin/hostcert b/bin/.bin/hostcert
new file mode 100755
index 0000000..61f519d
--- /dev/null
+++ b/bin/.bin/hostcert
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -eu
+set -o pipefail
+
+host="$1"
+port="${2:-443}"
+
+openssl s_client -connect "$host:$port" </dev/null 2>/dev/null | perl -nle 'print if /BEGIN CERTIFICATE/../END CERTIFICATE/' | openssl x509 -text | perl -nle 'print unless /BEGIN CERTIFICATE/../END CERTIFICATE/'
diff --git a/bin/mem-usage b/bin/.bin/mem-usage
index 19e8c32..19e8c32 100755
--- a/bin/mem-usage
+++ b/bin/.bin/mem-usage
diff --git a/bin/.bin/pacman-dump b/bin/.bin/pacman-dump
new file mode 100755
index 0000000..b32ed16
--- /dev/null
+++ b/bin/.bin/pacman-dump
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -eu
+set -o pipefail
+
+echo base-devel
+comm -23 <(pacman -Qeq | sort) <(pacman -Qgq base-devel | sort)
diff --git a/bin/pdfcat b/bin/.bin/pdfcat
index ff4edaa..ff4edaa 100755
--- a/bin/pdfcat
+++ b/bin/.bin/pdfcat
diff --git a/bin/.bin/reply b/bin/.bin/reply
new file mode 100755
index 0000000..412189f
--- /dev/null
+++ b/bin/.bin/reply
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -eu
+
+DOCKERFILE="$(cat <<EOF
+FROM docker.io/debian:stable-slim
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ cpanminus \
+ make \
+ gcc \
+ libreadline-dev
+RUN cpanm -n \
+ Reply \
+ B::Keywords \
+ Data::Dump \
+ Carp::Always \
+ Term::ReadLine::Gnu
+EOF
+)"
+IMAGE="$(basename "$0"):$(echo "$DOCKERFILE" | sha256sum | cut -d' ' -f1)"
+
+if [ -z "$(podman images -q "$IMAGE")" ]; then
+ echo "$DOCKERFILE" | podman build -t "$IMAGE" -f - .
+fi
+
+podman run --rm -it \
+ -v "$HOME"/.replyrc:/root/.replyrc \
+ "$IMAGE" \
+ reply "$@"
diff --git a/bin/.bin/scanpdf b/bin/.bin/scanpdf
new file mode 100755
index 0000000..31ebb14
--- /dev/null
+++ b/bin/.bin/scanpdf
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -eu
+
+scanimage --format=png --device=pixma --resolution=150 | convert - scan.pdf
diff --git a/services/available/watch-kbd/run b/bin/.bin/scratch
index 10816ec..0cca01c 100755
--- a/services/available/watch-kbd/run
+++ b/bin/.bin/scratch
@@ -2,4 +2,4 @@
set -eu
set -o pipefail
-exec watch-kbd
+cat >/dev/null
diff --git a/bin/.bin/set-mac b/bin/.bin/set-mac
new file mode 100755
index 0000000..986d333
--- /dev/null
+++ b/bin/.bin/set-mac
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -eu
+
+link() {
+ sudo ip link set dev wlp0s20f3 "$@"
+}
+
+link down
+link address "$1"
+link up
diff --git a/bin/show-colors b/bin/.bin/show-colors
index be1a489..47e0d32 100755
--- a/bin/show-colors
+++ b/bin/.bin/show-colors
@@ -7,7 +7,7 @@ set -o pipefail
# Last change: Mon Feb 16 16:24:41 CET 2004
############################################################
-for attr in 0 1 2 3 4 5 6 7 ; do
+for attr in 0 1 2 3 4 5 6 7; do
echo "----------------------------------------------------------------"
printf 'ESC[%s;Foreground;Background - \n' $attr
for fore in 30 31 32 33 34 35 36 37; do
diff --git a/bin/.bin/smt b/bin/.bin/smt
new file mode 100755
index 0000000..446197d
--- /dev/null
+++ b/bin/.bin/smt
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -eu
+
+DOCKERFILE="$(cat <<EOF
+FROM docker.io/debian:stable-slim
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ cpanminus \
+ make \
+ gcc \
+ libreadline-dev
+RUN cpanm -n Games::SMTNocturne::Demons
+EOF
+)"
+IMAGE="$(basename "$0"):$(echo "$DOCKERFILE" | sha256sum | cut -d' ' -f1)"
+
+if [ -z "$(podman images -q "$IMAGE")" ]; then
+ echo "$DOCKERFILE" | podman build -t "$IMAGE" -f - .
+fi
+
+podman run --rm -it \
+ "$IMAGE" \
+ smt "$@"
diff --git a/bin/sum b/bin/.bin/sum
index cf21bfd..cf21bfd 100755
--- a/bin/sum
+++ b/bin/.bin/sum
diff --git a/bin/web b/bin/.bin/web
index f8484c0..f8484c0 100755
--- a/bin/web
+++ b/bin/.bin/web
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000..550df27
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1 @@
+/.bin/local/*
diff --git a/bin/clean-vim-undo b/bin/clean-vim-undo
deleted file mode 100755
index efcd3aa..0000000
--- a/bin/clean-vim-undo
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-
-my $undodir = "$ENV{HOME}/.cache/vim/undo";
-opendir my $undo, $undodir
- or die "can't open $undodir: $!";
-
-for my $undofile (readdir($undo)) {
- next unless -f "$undodir/$undofile";
- (my $file = $undofile) =~ s{%}{/}g;
- unlink "$undodir/$undofile" unless -e $file && $file =~ m{^/};
-}
diff --git a/bin/git/git-imerge b/bin/git/git-imerge
deleted file mode 100644
index b903539..0000000
--- a/bin/git/git-imerge
+++ /dev/null
@@ -1,4135 +0,0 @@
-#! /usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# Copyright 2012-2013 Michael Haggerty <mhagger@alum.mit.edu>
-#
-# This file is part of git-imerge.
-#
-# git-imerge is free software: you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation, either version 2 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see
-# <http://www.gnu.org/licenses/>.
-
-r"""Git incremental merge
-
-Perform the merge between two branches incrementally. If conflicts
-are encountered, figure out exactly which pairs of commits conflict,
-and present the user with one pairwise conflict at a time for
-resolution.
-
-Multiple incremental merges can be in progress at the same time. Each
-incremental merge has a name, and its progress is recorded in the Git
-repository as references under 'refs/imerge/NAME'.
-
-An incremental merge can be interrupted and resumed arbitrarily, or
-even pushed to a server to allow somebody else to work on it.
-
-
-Instructions:
-
-To start an incremental merge or rebase, use one of the following
-commands:
-
- git-imerge merge BRANCH
- Analogous to "git merge BRANCH"
-
- git-imerge rebase BRANCH
- Analogous to "git rebase BRANCH"
-
- git-imerge drop [commit | commit1..commit2]
- Drop the specified commit(s) from the current branch
-
- git-imerge revert [commit | commit1..commit2]
- Revert the specified commits by adding new commits that
- reverse their effects
-
- git-imerge start --name=NAME --goal=GOAL BRANCH
- Start a general imerge
-
-Then the tool will present conflicts to you one at a time, similar to
-"git rebase --incremental". Resolve each conflict, and then
-
- git add FILE...
- git-imerge continue
-
-You can view your progress at any time with
-
- git-imerge diagram
-
-When you have resolved all of the conflicts, simplify and record the
-result by typing
-
- git-imerge finish
-
-To get more help about any git-imerge subcommand, type
-
- git-imerge SUBCOMMAND --help
-
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-from __future__ import unicode_literals
-
-import locale
-import sys
-import re
-import subprocess
-from subprocess import CalledProcessError
-from subprocess import check_call
-import itertools
-import argparse
-from io import StringIO
-import json
-import os
-
-
-PREFERRED_ENCODING = locale.getpreferredencoding()
-
-
-# Define check_output() for ourselves, including decoding of the
-# output into PREFERRED_ENCODING:
-def check_output(*popenargs, **kwargs):
- if 'stdout' in kwargs:
- raise ValueError('stdout argument not allowed, it will be overridden.')
- process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
- output = communicate(process)[0]
- retcode = process.poll()
- if retcode:
- cmd = kwargs.get("args")
- if cmd is None:
- cmd = popenargs[0]
- # We don't store output in the CalledProcessError because
- # the "output" keyword parameter was not supported in
- # Python 2.6:
- raise CalledProcessError(retcode, cmd)
- return output
-
-
-STATE_VERSION = (1, 3, 0)
-
-ZEROS = '0' * 40
-
-ALLOWED_GOALS = [
- 'full',
- 'rebase',
- 'rebase-with-history',
- 'border',
- 'border-with-history',
- 'border-with-history2',
- 'merge',
- 'drop',
- 'revert',
- ]
-DEFAULT_GOAL = 'merge'
-
-
-class Failure(Exception):
- """An exception that indicates a normal failure of the script.
-
- Failures are reported at top level via sys.exit(str(e)) rather
- than via a Python stack dump."""
-
- pass
-
-
-class AnsiColor:
- BLACK = '\033[0;30m'
- RED = '\033[0;31m'
- GREEN = '\033[0;32m'
- YELLOW = '\033[0;33m'
- BLUE = '\033[0;34m'
- MAGENTA = '\033[0;35m'
- CYAN = '\033[0;36m'
- B_GRAY = '\033[0;37m'
- D_GRAY = '\033[1;30m'
- B_RED = '\033[1;31m'
- B_GREEN = '\033[1;32m'
- B_YELLOW = '\033[1;33m'
- B_BLUE = '\033[1;34m'
- B_MAGENTA = '\033[1;35m'
- B_CYAN = '\033[1;36m'
- WHITE = '\033[1;37m'
- END = '\033[0m'
-
- @classmethod
- def disable(cls):
- cls.BLACK = ''
- cls.RED = ''
- cls.GREEN = ''
- cls.YELLOW = ''
- cls.BLUE = ''
- cls.MAGENTA = ''
- cls.CYAN = ''
- cls.B_GRAY = ''
- cls.D_GRAY = ''
- cls.B_RED = ''
- cls.B_GREEN = ''
- cls.B_YELLOW = ''
- cls.B_BLUE = ''
- cls.B_MAGENTA = ''
- cls.B_CYAN = ''
- cls.WHITE = ''
- cls.END = ''
-
-
-def iter_neighbors(iterable):
- """For an iterable (x0, x1, x2, ...) generate [(x0,x1), (x1,x2), ...]."""
-
- i = iter(iterable)
-
- try:
- last = next(i)
- except StopIteration:
- return
-
- for x in i:
- yield (last, x)
- last = x
-
-
-def find_first_false(f, lo, hi):
- """Return the smallest i in lo <= i < hi for which f(i) returns False using bisection.
-
- If there is no such i, return hi.
-
- """
-
- # Loop invariant: f(i) returns True for i < lo; f(i) returns False
- # for i >= hi.
-
- while lo < hi:
- mid = (lo + hi) // 2
- if f(mid):
- lo = mid + 1
- else:
- hi = mid
-
- return lo
-
-
-def call_silently(cmd):
- try:
- NULL = open(os.devnull, 'w')
- except (IOError, AttributeError):
- NULL = subprocess.PIPE
-
- p = subprocess.Popen(cmd, stdout=NULL, stderr=NULL)
- p.communicate()
- retcode = p.wait()
- if retcode:
- raise CalledProcessError(retcode, cmd)
-
-
-def communicate(process, input=None):
- """Return decoded output from process."""
- if input is not None:
- input = input.encode(PREFERRED_ENCODING)
-
- output, error = process.communicate(input)
-
- output = None if output is None else output.decode(PREFERRED_ENCODING)
- error = None if error is None else error.decode(PREFERRED_ENCODING)
-
- return (output, error)
-
-
-if sys.hexversion < 0x03000000:
- # In Python 2.x, os.environ keys and values must be byte
- # strings:
- def env_encode(s):
- """Encode unicode keys or values for use in os.environ."""
-
- return s.encode(PREFERRED_ENCODING)
-
-else:
- # In Python 3.x, os.environ keys and values must be unicode
- # strings:
- def env_encode(s):
- """Use unicode keys or values unchanged in os.environ."""
-
- return s
-
-
-class UncleanWorkTreeError(Failure):
- pass
-
-
-class AutomaticMergeFailed(Exception):
- def __init__(self, commit1, commit2):
- Exception.__init__(
- self, 'Automatic merge of %s and %s failed' % (commit1, commit2,)
- )
- self.commit1, self.commit2 = commit1, commit2
-
-
-class InvalidBranchNameError(Failure):
- pass
-
-
-class NotFirstParentAncestorError(Failure):
- def __init__(self, commit1, commit2):
- Failure.__init__(
- self,
- 'Commit "%s" is not a first-parent ancestor of "%s"'
- % (commit1, commit2),
- )
-
-
-class NonlinearAncestryError(Failure):
- def __init__(self, commit1, commit2):
- Failure.__init__(
- self,
- 'The history "%s..%s" is not linear'
- % (commit1, commit2),
- )
-
-
-class NothingToDoError(Failure):
- def __init__(self, src_tip, dst_tip):
- Failure.__init__(
- self,
- 'There are no commits on "%s" that are not already in "%s"'
- % (src_tip, dst_tip),
- )
-
-
-class GitTemporaryHead(object):
- """A context manager that records the current HEAD state then restores it.
-
- This should only be used when the working copy is clean. message
- is used for the reflog.
-
- """
-
- def __init__(self, git, message):
- self.git = git
- self.message = message
-
- def __enter__(self):
- self.head_name = self.git.get_head_refname()
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- if self.head_name:
- try:
- self.git.restore_head(self.head_name, self.message)
- except CalledProcessError as e:
- raise Failure(
- 'Could not restore HEAD to %r!: %s\n'
- % (self.head_name, e.message,)
- )
-
- return False
-
-
-class GitRepository(object):
- BRANCH_PREFIX = 'refs/heads/'
-
- MERGE_STATE_REFNAME_RE = re.compile(
- r"""
- ^
- refs\/imerge\/
- (?P<name>.+)
- \/state
- $
- """,
- re.VERBOSE,
- )
-
- def __init__(self):
- self.git_dir_cache = None
-
- def git_dir(self):
- if self.git_dir_cache is None:
- self.git_dir_cache = check_output(
- ['git', 'rev-parse', '--git-dir']
- ).rstrip('\n')
-
- return self.git_dir_cache
-
- def check_imerge_name_format(self, name):
- """Check that name is a valid imerge name."""
-
- try:
- call_silently(
- ['git', 'check-ref-format', 'refs/imerge/%s' % (name,)]
- )
- except CalledProcessError:
- raise Failure('Name %r is not a valid refname component!' % (name,))
-
- def check_branch_name_format(self, name):
- """Check that name is a valid branch name."""
-
- try:
- call_silently(
- ['git', 'check-ref-format', 'refs/heads/%s' % (name,)]
- )
- except CalledProcessError:
- raise InvalidBranchNameError('Name %r is not a valid branch name!' % (name,))
-
- def iter_existing_imerge_names(self):
- """Iterate over the names of existing MergeStates in this repo."""
-
- for line in check_output(['git', 'for-each-ref', 'refs/imerge']).splitlines():
- (sha1, type, refname) = line.split()
- if type == 'blob':
- m = GitRepository.MERGE_STATE_REFNAME_RE.match(refname)
- if m:
- yield m.group('name')
-
- def set_default_imerge_name(self, name):
- """Set the default merge to the specified one.
-
- name can be None to cause the default to be cleared."""
-
- if name is None:
- try:
- check_call(['git', 'config', '--unset', 'imerge.default'])
- except CalledProcessError as e:
- if e.returncode == 5:
- # Value was not set
- pass
- else:
- raise
- else:
- check_call(['git', 'config', 'imerge.default', name])
-
- def get_default_imerge_name(self):
- """Get the name of the default merge, or None if it is currently unset."""
-
- try:
- return check_output(['git', 'config', 'imerge.default']).rstrip()
- except CalledProcessError:
- return None
-
- def get_default_edit(self):
- """Should '--edit' be used when committing intermediate user merges?
-
- When 'git imerge continue' or 'git imerge record' finds a user
- merge that can be committed, should it (by default) ask the user
- to edit the commit message? This behavior can be configured via
- 'imerge.editmergemessages'. If it is not configured, return False.
-
- Please note that this function is only used to choose the default
- value. It can be overridden on the command line using '--edit' or
- '--no-edit'.
-
- """
-
- try:
- return {'true' : True, 'false' : False}[
- check_output(
- ['git', 'config', '--bool', 'imerge.editmergemessages']
- ).rstrip()
- ]
- except CalledProcessError:
- return False
-
- def unstaged_changes(self):
- """Return True iff there are unstaged changes in the working copy"""
-
- try:
- check_call(['git', 'diff-files', '--quiet', '--ignore-submodules'])
- return False
- except CalledProcessError:
- return True
-
- def uncommitted_changes(self):
- """Return True iff the index contains uncommitted changes."""
-
- try:
- check_call([
- 'git', 'diff-index', '--cached', '--quiet',
- '--ignore-submodules', 'HEAD', '--',
- ])
- return False
- except CalledProcessError:
- return True
-
- def get_commit_sha1(self, arg):
- """Convert arg into a SHA1 and verify that it refers to a commit.
-
- If not, raise ValueError."""
-
- try:
- return self.rev_parse('%s^{commit}' % (arg,))
- except CalledProcessError:
- raise ValueError('%r does not refer to a valid git commit' % (arg,))
-
- def refresh_index(self):
- process = subprocess.Popen(
- ['git', 'update-index', '-q', '--ignore-submodules', '--refresh'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- )
- out, err = communicate(process)
- retcode = process.poll()
- if retcode:
- raise UncleanWorkTreeError(err.rstrip() or out.rstrip())
-
- def verify_imerge_name_available(self, name):
- self.check_imerge_name_format(name)
- if check_output(['git', 'for-each-ref', 'refs/imerge/%s' % (name,)]):
- raise Failure('Name %r is already in use!' % (name,))
-
- def check_imerge_exists(self, name):
- """Verify that a MergeState with the given name exists.
-
- Just check for the existence, readability, and compatible
- version of the 'state' reference. If the reference doesn't
- exist, just return False. If it exists but is unusable for
- some other reason, raise an exception."""
-
- self.check_imerge_name_format(name)
- state_refname = 'refs/imerge/%s/state' % (name,)
- for line in check_output(['git', 'for-each-ref', state_refname]).splitlines():
- (sha1, type, refname) = line.split()
- if refname == state_refname and type == 'blob':
- self.read_imerge_state_dict(name)
- # If that didn't throw an exception:
- return True
- else:
- return False
-
- def read_imerge_state_dict(self, name):
- state_string = check_output(
- ['git', 'cat-file', 'blob', 'refs/imerge/%s/state' % (name,)],
- )
- state = json.loads(state_string)
-
- # Convert state['version'] to a tuple of integers, and verify
- # that it is compatible with this version of the script:
- version = tuple(int(i) for i in state['version'].split('.'))
- if version[0] != STATE_VERSION[0] or version[1] > STATE_VERSION[1]:
- raise Failure(
- 'The format of imerge %s (%s) is not compatible with this script version.'
- % (name, state['version'],)
- )
- state['version'] = version
-
- return state
-
- def read_imerge_state(self, name):
- """Read the state associated with the specified imerge.
-
- Return the tuple
-
- (state_dict, {(i1, i2) : (sha1, source), ...})
-
- , where source is 'auto' or 'manual'. Validity is checked only
- lightly.
-
- """
-
- merge_ref_re = re.compile(
- r"""
- ^
- refs\/imerge\/
- """ + re.escape(name) + r"""
- \/(?P<source>auto|manual)\/
- (?P<i1>0|[1-9][0-9]*)
- \-
- (?P<i2>0|[1-9][0-9]*)
- $
- """,
- re.VERBOSE,
- )
-
- state_ref_re = re.compile(
- r"""
- ^
- refs\/imerge\/
- """ + re.escape(name) + r"""
- \/state
- $
- """,
- re.VERBOSE,
- )
-
- state = None
-
- # A map {(i1, i2) : (sha1, source)}:
- merges = {}
-
- # refnames that were found but not understood:
- unexpected = []
-
- for line in check_output([
- 'git', 'for-each-ref', 'refs/imerge/%s' % (name,)
- ]).splitlines():
- (sha1, type, refname) = line.split()
- m = merge_ref_re.match(refname)
- if m:
- if type != 'commit':
- raise Failure('Reference %r is not a commit!' % (refname,))
- i1, i2 = int(m.group('i1')), int(m.group('i2'))
- source = m.group('source')
- merges[i1, i2] = (sha1, source)
- continue
-
- m = state_ref_re.match(refname)
- if m:
- if type != 'blob':
- raise Failure('Reference %r is not a blob!' % (refname,))
- state = self.read_imerge_state_dict(name)
- continue
-
- unexpected.append(refname)
-
- if state is None:
- raise Failure(
- 'No state found; it should have been a blob reference at '
- '"refs/imerge/%s/state"' % (name,)
- )
-
- if unexpected:
- raise Failure(
- 'Unexpected reference(s) found in "refs/imerge/%s" namespace:\n %s\n'
- % (name, '\n '.join(unexpected),)
- )
-
- return (state, merges)
-
- def write_imerge_state_dict(self, name, state):
- state_string = json.dumps(state, sort_keys=True) + '\n'
-
- cmd = ['git', 'hash-object', '-t', 'blob', '-w', '--stdin']
- p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
- out = communicate(p, input=state_string)[0]
- retcode = p.poll()
- if retcode:
- raise CalledProcessError(retcode, cmd)
- sha1 = out.strip()
- check_call([
- 'git', 'update-ref',
- '-m', 'imerge %r: Record state' % (name,),
- 'refs/imerge/%s/state' % (name,),
- sha1,
- ])
-
- def is_ancestor(self, commit1, commit2):
- """Return True iff commit1 is an ancestor (or equal to) commit2."""
-
- if commit1 == commit2:
- return True
- else:
- return int(
- check_output([
- 'git', 'rev-list', '--count', '--ancestry-path',
- '%s..%s' % (commit1, commit2,),
- ]).strip()
- ) != 0
-
- def is_ff(self, refname, commit):
- """Would updating refname to commit be a fast-forward update?
-
- Return True iff refname is not currently set or it points to an
- ancestor of commit.
-
- """
-
- try:
- ref_oldval = self.get_commit_sha1(refname)
- except ValueError:
- # refname doesn't already exist; no problem.
- return True
- else:
- return self.is_ancestor(ref_oldval, commit)
-
- def automerge(self, commit1, commit2, msg=None):
- """Attempt an automatic merge of commit1 and commit2.
-
- Return the SHA1 of the resulting commit, or raise
- AutomaticMergeFailed on error. This must be called with a clean
- worktree."""
-
- call_silently(['git', 'checkout', '-f', commit1])
- cmd = ['git', '-c', 'rerere.enabled=false', 'merge']
- if msg is not None:
- cmd += ['-m', msg]
- cmd += [commit2]
- try:
- call_silently(cmd)
- except CalledProcessError:
- self.abort_merge()
- raise AutomaticMergeFailed(commit1, commit2)
- else:
- return self.get_commit_sha1('HEAD')
-
- def manualmerge(self, commit, msg):
- """Initiate a merge of commit into the current HEAD."""
-
- check_call(['git', 'merge', '--no-commit', '-m', msg, commit,])
-
- def require_clean_work_tree(self, action):
- """Verify that the current tree is clean.
-
- The code is a Python translation of the git-sh-setup(1) function
- of the same name."""
-
- process = subprocess.Popen(
- ['git', 'rev-parse', '--verify', 'HEAD'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- )
- err = communicate(process)[1]
- retcode = process.poll()
- if retcode:
- raise UncleanWorkTreeError(err.rstrip())
-
- self.refresh_index()
-
- error = []
- if self.unstaged_changes():
- error.append('Cannot %s: You have unstaged changes.' % (action,))
-
- if self.uncommitted_changes():
- if not error:
- error.append('Cannot %s: Your index contains uncommitted changes.' % (action,))
- else:
- error.append('Additionally, your index contains uncommitted changes.')
-
- if error:
- raise UncleanWorkTreeError('\n'.join(error))
-
- def simple_merge_in_progress(self):
- """Return True iff a merge (of a single branch) is in progress."""
-
- try:
- with open(os.path.join(self.git_dir(), 'MERGE_HEAD')) as f:
- heads = [line.rstrip() for line in f]
- except IOError:
- return False
-
- return len(heads) == 1
-
- def commit_user_merge(self, edit_log_msg=None):
- """If a merge is in progress and ready to be committed, commit it.
-
- If a simple merge is in progress and any changes in the working
- tree are staged, commit the merge commit and return True.
- Otherwise, return False.
-
- """
-
- if not self.simple_merge_in_progress():
- return False
-
- # Check if all conflicts are resolved and everything in the
- # working tree is staged:
- self.refresh_index()
- if self.unstaged_changes():
- raise UncleanWorkTreeError(
- 'Cannot proceed: You have unstaged changes.'
- )
-
- # A merge is in progress, and either all changes have been staged
- # or no changes are necessary. Create a merge commit.
- cmd = ['git', 'commit', '--no-verify']
-
- if edit_log_msg is None:
- edit_log_msg = self.get_default_edit()
-
- if edit_log_msg:
- cmd += ['--edit']
- else:
- cmd += ['--no-edit']
-
- try:
- check_call(cmd)
- except CalledProcessError:
- raise Failure('Could not commit staged changes.')
-
- return True
-
- def create_commit_chain(self, base, path):
- """Point refname at the chain of commits indicated by path.
-
- path is a list [(commit, metadata), ...]. Create a series of
- commits corresponding to the entries in path. Each commit's tree
- is taken from the corresponding old commit, and each commit's
- metadata is taken from the corresponding metadata commit. Use base
- as the parent of the first commit, or make the first commit a root
- commit if base is None. Reuse existing commits from the list
- whenever possible.
-
- Return a commit object corresponding to the last commit in the
- chain.
-
- """
-
- reusing = True
- if base is None:
- if not path:
- raise ValueError('neither base nor path specified')
- parents = []
- else:
- parents = [base]
-
- for (commit, metadata) in path:
- if reusing:
- if commit == metadata and self.get_commit_parents(commit) == parents:
- # We can reuse this commit, too.
- parents = [commit]
- continue
- else:
- reusing = False
-
- # Create a commit, copying the old log message and author info
- # from the metadata commit:
- tree = self.get_tree(commit)
- new_commit = self.commit_tree(
- tree, parents,
- msg=self.get_log_message(metadata),
- metadata=self.get_author_info(metadata),
- )
- parents = [new_commit]
-
- [commit] = parents
- return commit
-
- def rev_parse(self, arg):
- return check_output(['git', 'rev-parse', '--verify', '--quiet', arg]).strip()
-
- def rev_list(self, *args):
- cmd = ['git', 'rev-list'] + list(args)
- return [
- l.strip()
- for l in check_output(cmd).splitlines()
- ]
-
- def rev_list_with_parents(self, *args):
- """Iterate over (commit, [parent,...])."""
-
- cmd = ['git', 'log', '--format=%H %P'] + list(args)
- for line in check_output(cmd).splitlines():
- commits = line.strip().split()
- yield (commits[0], commits[1:])
-
- def summarize_commit(self, commit):
- """Summarize `commit` to stdout."""
-
- check_call(['git', '--no-pager', 'log', '--no-walk', commit])
-
- def get_author_info(self, commit):
- """Return environment settings to set author metadata.
-
- Return a map {str : str}."""
-
- # We use newlines as separators here because msysgit has problems
- # with NUL characters; see
- #
- # https://github.com/mhagger/git-imerge/pull/71
- a = check_output([
- 'git', '--no-pager', 'log', '-n1',
- '--format=%an%n%ae%n%ai', commit
- ]).strip().splitlines()
-
- return {
- 'GIT_AUTHOR_NAME': env_encode(a[0]),
- 'GIT_AUTHOR_EMAIL': env_encode(a[1]),
- 'GIT_AUTHOR_DATE': env_encode(a[2]),
- }
-
- def get_log_message(self, commit):
- contents = check_output([
- 'git', 'cat-file', 'commit', commit,
- ]).splitlines(True)
- contents = contents[contents.index('\n') + 1:]
- if contents and contents[-1][-1:] != '\n':
- contents.append('\n')
- return ''.join(contents)
-
- def get_commit_parents(self, commit):
- """Return a list containing the parents of commit."""
-
- return check_output(
- ['git', '--no-pager', 'log', '--no-walk', '--pretty=format:%P', commit]
- ).strip().split()
-
- def get_tree(self, arg):
- return self.rev_parse('%s^{tree}' % (arg,))
-
- def update_ref(self, refname, value, msg, deref=True):
- if deref:
- opt = []
- else:
- opt = ['--no-deref']
-
- check_call(['git', 'update-ref'] + opt + ['-m', msg, refname, value])
-
- def delete_ref(self, refname, msg, deref=True):
- if deref:
- opt = []
- else:
- opt = ['--no-deref']
-
- check_call(['git', 'update-ref'] + opt + ['-m', msg, '-d', refname])
-
- def delete_imerge_refs(self, name):
- stdin = ''.join(
- 'delete %s\n' % (refname,)
- for refname in check_output([
- 'git', 'for-each-ref',
- '--format=%(refname)',
- 'refs/imerge/%s' % (name,)
- ]).splitlines()
- )
-
- process = subprocess.Popen(
- [
- 'git', 'update-ref',
- '-m', 'imerge: remove merge %r' % (name,),
- '--stdin',
- ],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- )
- out = communicate(process, input=stdin)[0]
- retcode = process.poll()
- if retcode:
- sys.stderr.write(
- 'Warning: error removing references:\n%s' % (out,)
- )
-
- def detach(self, msg):
- """Detach HEAD. msg is used for the reflog."""
-
- self.update_ref('HEAD', 'HEAD^0', msg, deref=False)
-
- def reset_hard(self, commit):
- check_call(['git', 'reset', '--hard', commit])
-
- def amend(self):
- check_call(['git', 'commit', '--amend'])
-
- def abort_merge(self):
- # We don't use "git merge --abort" here because it was
- # only added in git version 1.7.4.
- check_call(['git', 'reset', '--merge'])
-
- def compute_best_merge_base(self, tip1, tip2):
- try:
- merge_bases = check_output(['git', 'merge-base', '--all', tip1, tip2]).splitlines()
- except CalledProcessError:
- raise Failure('Cannot compute merge base for %r and %r' % (tip1, tip2))
- if not merge_bases:
- raise Failure('%r and %r do not have a common merge base' % (tip1, tip2))
- if len(merge_bases) == 1:
- return merge_bases[0]
-
- # There are multiple merge bases. The "best" one is the one that
- # is the "closest" to the tips, which we define to be the one with
- # the fewest non-merge commits in "merge_base..tip". (It can be
- # shown that the result is independent of which tip is used in the
- # computation.)
- best_base = best_count = None
- for merge_base in merge_bases:
- cmd = ['git', 'rev-list', '--no-merges', '--count', '%s..%s' % (merge_base, tip1)]
- count = int(check_output(cmd).strip())
- if best_base is None or count < best_count:
- best_base = merge_base
- best_count = count
-
- return best_base
-
- def linear_ancestry(self, commit1, commit2, first_parent):
- """Compute a linear ancestry between commit1 and commit2.
-
- Our goal is to find a linear series of commits connecting
- `commit1` and `commit2`. We do so as follows:
-
- * If all of the commits in
-
- git rev-list --ancestry-path commit1..commit2
-
- are on a linear chain, return that.
-
- * If there are multiple paths between `commit1` and `commit2` in
- that list of commits, then
-
- * If `first_parent` is not set, then raise an
- `NonlinearAncestryError` exception.
-
- * If `first_parent` is set, then, at each merge commit, follow
- the first parent that is in that list of commits.
-
- Return a list of SHA-1s in 'chronological' order.
-
- Raise NotFirstParentAncestorError if commit1 is not an ancestor of
- commit2.
-
- """
-
- oid1 = self.rev_parse(commit1)
- oid2 = self.rev_parse(commit2)
-
- parentage = {oid1 : []}
- for (commit, parents) in self.rev_list_with_parents(
- '--ancestry-path', '--topo-order', '%s..%s' % (oid1, oid2)
- ):
- parentage[commit] = parents
-
- commits = []
-
- commit = oid2
- while commit != oid1:
- parents = parentage.get(commit, [])
-
- # Only consider parents that are in the ancestry path:
- included_parents = [
- parent
- for parent in parents
- if parent in parentage
- ]
-
- if not included_parents:
- raise NotFirstParentAncestorError(commit1, commit2)
- elif len(included_parents) == 1 or first_parent:
- parent = included_parents[0]
- else:
- raise NonlinearAncestryError(commit1, commit2)
-
- commits.append(commit)
- commit = parent
-
- commits.reverse()
-
- return commits
-
- def get_boundaries(self, tip1, tip2, first_parent):
- """Get the boundaries of an incremental merge.
-
- Given the tips of two branches that should be merged, return
- (merge_base, commits1, commits2) describing the edges of the
- imerge. Raise Failure if there are any problems."""
-
- merge_base = self.compute_best_merge_base(tip1, tip2)
-
- commits1 = self.linear_ancestry(merge_base, tip1, first_parent)
- if not commits1:
- raise NothingToDoError(tip1, tip2)
-
- commits2 = self.linear_ancestry(merge_base, tip2, first_parent)
- if not commits2:
- raise NothingToDoError(tip2, tip1)
-
- return (merge_base, commits1, commits2)
-
- def get_head_refname(self, short=False):
- """Return the name of the reference that is currently checked out.
-
- If `short` is set, return it as a branch name. If HEAD is
- currently detached, return None."""
-
- cmd = ['git', 'symbolic-ref', '--quiet']
- if short:
- cmd += ['--short']
- cmd += ['HEAD']
- try:
- return check_output(cmd).strip()
- except CalledProcessError:
- return None
-
- def restore_head(self, refname, message):
- check_call(['git', 'symbolic-ref', '-m', message, 'HEAD', refname])
- check_call(['git', 'reset', '--hard'])
-
- def checkout(self, refname, quiet=False):
- cmd = ['git', 'checkout']
- if quiet:
- cmd += ['--quiet']
- if refname.startswith(GitRepository.BRANCH_PREFIX):
- target = refname[len(GitRepository.BRANCH_PREFIX):]
- else:
- target = '%s^0' % (refname,)
- cmd += [target]
- check_call(cmd)
-
- def commit_tree(self, tree, parents, msg, metadata=None):
- """Create a commit containing the specified tree.
-
- metadata can be author or committer information to be added to the
- environment, as str objects; e.g., {'GIT_AUTHOR_NAME' : 'me'}.
-
- Return the SHA-1 of the new commit object."""
-
- cmd = ['git', 'commit-tree', tree]
- for parent in parents:
- cmd += ['-p', parent]
-
- if metadata is not None:
- env = os.environ.copy()
- env.update(metadata)
- else:
- env = os.environ
-
- process = subprocess.Popen(
- cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
- )
- out = communicate(process, input=msg)[0]
- retcode = process.poll()
-
- if retcode:
- # We don't store the output in the CalledProcessError because
- # the "output" keyword parameter was not supported in Python
- # 2.6:
- raise CalledProcessError(retcode, cmd)
-
- return out.strip()
-
- def revert(self, commit):
- """Apply the inverse of commit^..commit to HEAD and commit."""
-
- cmd = ['git', 'revert', '--no-edit']
- if len(self.get_commit_parents(commit)) > 1:
- cmd += ['-m', '1']
- cmd += [commit]
- check_call(cmd)
-
- def reparent(self, commit, parent_sha1s, msg=None):
- """Create a new commit object like commit, but with the specified parents.
-
- commit is the SHA1 of an existing commit and parent_sha1s is a
- list of SHA1s. Create a new commit exactly like that one, except
- that it has the specified parent commits. Return the SHA1 of the
- resulting commit object, which is already stored in the object
- database but is not yet referenced by anything.
-
- If msg is set, then use it as the commit message for the new
- commit."""
-
- old_commit = check_output(['git', 'cat-file', 'commit', commit])
- separator = old_commit.index('\n\n')
- headers = old_commit[:separator + 1].splitlines(True)
- rest = old_commit[separator + 2:]
-
- new_commit = StringIO()
- for i in range(len(headers)):
- line = headers[i]
- if line.startswith('tree '):
- new_commit.write(line)
- for parent_sha1 in parent_sha1s:
- new_commit.write('parent %s\n' % (parent_sha1,))
- elif line.startswith('parent '):
- # Discard old parents:
- pass
- else:
- new_commit.write(line)
-
- new_commit.write('\n')
- if msg is None:
- new_commit.write(rest)
- else:
- new_commit.write(msg)
- if not msg.endswith('\n'):
- new_commit.write('\n')
-
- process = subprocess.Popen(
- ['git', 'hash-object', '-t', 'commit', '-w', '--stdin'],
- stdin=subprocess.PIPE, stdout=subprocess.PIPE,
- )
- out = communicate(process, input=new_commit.getvalue())[0]
- retcode = process.poll()
- if retcode:
- raise Failure('Could not reparent commit %s' % (commit,))
- return out.strip()
-
- def temporary_head(self, message):
- """Return a context manager to manage a temporary HEAD.
-
- On entry, record the current HEAD state. On exit, restore it.
- message is used for the reflog.
-
- """
-
- return GitTemporaryHead(self, message)
-
-
-class MergeRecord(object):
- # Bits for the flags field:
-
- # There is a saved successful auto merge:
- SAVED_AUTO = 0x01
-
- # An auto merge (which may have been unsuccessful) has been done:
- NEW_AUTO = 0x02
-
- # There is a saved successful manual merge:
- SAVED_MANUAL = 0x04
-
- # A manual merge (which may have been unsuccessful) has been done:
- NEW_MANUAL = 0x08
-
- # A merge that is currently blocking the merge frontier:
- BLOCKED = 0x10
-
- # Some useful bit combinations:
- SAVED = SAVED_AUTO | SAVED_MANUAL
- NEW = NEW_AUTO | NEW_MANUAL
-
- AUTO = SAVED_AUTO | NEW_AUTO
- MANUAL = SAVED_MANUAL | NEW_MANUAL
-
- ALLOWED_INITIAL_FLAGS = [
- SAVED_AUTO,
- SAVED_MANUAL,
- NEW_AUTO,
- NEW_MANUAL,
- ]
-
- def __init__(self, sha1=None, flags=0):
- # The currently believed correct merge, or None if it is
- # unknown or the best attempt was unsuccessful.
- self.sha1 = sha1
-
- if self.sha1 is None:
- if flags != 0:
- raise ValueError('Initial flags (%s) for sha1=None should be 0' % (flags,))
- elif flags not in self.ALLOWED_INITIAL_FLAGS:
- raise ValueError('Initial flags (%s) is invalid' % (flags,))
-
- # See bits above.
- self.flags = flags
-
- def record_merge(self, sha1, source):
- """Record a merge at this position.
-
- source must be SAVED_AUTO, SAVED_MANUAL, NEW_AUTO, or NEW_MANUAL."""
-
- if source == self.SAVED_AUTO:
- # SAVED_AUTO is recorded in any case, but only used if it
- # is the only info available.
- if self.flags & (self.MANUAL | self.NEW) == 0:
- self.sha1 = sha1
- self.flags |= source
- elif source == self.NEW_AUTO:
- # NEW_AUTO is silently ignored if any MANUAL value is
- # already recorded.
- if self.flags & self.MANUAL == 0:
- self.sha1 = sha1
- self.flags |= source
- elif source == self.SAVED_MANUAL:
- # SAVED_MANUAL is recorded in any case, but only used if
- # no NEW_MANUAL is available.
- if self.flags & self.NEW_MANUAL == 0:
- self.sha1 = sha1
- self.flags |= source
- elif source == self.NEW_MANUAL:
- # NEW_MANUAL is always used, and also causes NEW_AUTO to
- # be forgotten if present.
- self.sha1 = sha1
- self.flags = (self.flags | source) & ~self.NEW_AUTO
- else:
- raise ValueError('Undefined source: %s' % (source,))
-
- def record_blocked(self, blocked):
- if blocked:
- self.flags |= self.BLOCKED
- else:
- self.flags &= ~self.BLOCKED
-
- def is_known(self):
- return self.sha1 is not None
-
- def is_blocked(self):
- return self.flags & self.BLOCKED != 0
-
- def is_manual(self):
- return self.flags & self.MANUAL != 0
-
- def save(self, git, name, i1, i2):
- """If this record has changed, save it."""
-
- def set_ref(source):
- git.update_ref(
- 'refs/imerge/%s/%s/%d-%d' % (name, source, i1, i2),
- self.sha1,
- 'imerge %r: Record %s merge' % (name, source,),
- )
-
- def clear_ref(source):
- git.delete_ref(
- 'refs/imerge/%s/%s/%d-%d' % (name, source, i1, i2),
- 'imerge %r: Remove obsolete %s merge' % (name, source,),
- )
-
- if self.flags & self.MANUAL:
- if self.flags & self.AUTO:
- # Any MANUAL obsoletes any AUTO:
- if self.flags & self.SAVED_AUTO:
- clear_ref('auto')
-
- self.flags &= ~self.AUTO
-
- if self.flags & self.NEW_MANUAL:
- # Convert NEW_MANUAL to SAVED_MANUAL.
- if self.sha1:
- set_ref('manual')
- self.flags |= self.SAVED_MANUAL
- elif self.flags & self.SAVED_MANUAL:
- # Delete any existing SAVED_MANUAL:
- clear_ref('manual')
- self.flags &= ~self.SAVED_MANUAL
- self.flags &= ~self.NEW_MANUAL
-
- elif self.flags & self.NEW_AUTO:
- # Convert NEW_AUTO to SAVED_AUTO.
- if self.sha1:
- set_ref('auto')
- self.flags |= self.SAVED_AUTO
- elif self.flags & self.SAVED_AUTO:
- # Delete any existing SAVED_AUTO:
- clear_ref('auto')
- self.flags &= ~self.SAVED_AUTO
- self.flags &= ~self.NEW_AUTO
-
-
-class UnexpectedMergeFailure(Exception):
- def __init__(self, msg, i1, i2):
- Exception.__init__(self, msg)
- self.i1, self.i2 = i1, i2
-
-
-class BlockCompleteError(Exception):
- pass
-
-
-class FrontierBlockedError(Exception):
- def __init__(self, msg, i1, i2):
- Exception.__init__(self, msg)
- self.i1 = i1
- self.i2 = i2
-
-
-class NotABlockingCommitError(Exception):
- pass
-
-
-def find_frontier_blocks(block):
- """Iterate over the frontier blocks for the specified block.
-
- Use bisection to find the blocks. Iterate over the blocks starting
- in the bottom left and ending at the top right. Record in block
- any blockers that we find.
-
- We make the following assumptions (using Python subscript
- notation):
-
- 0. All of the merges in block[1:,0] and block[0,1:] are
- already known. (This is an invariant of the Block class.)
-
- 1. If a direct merge can be done between block[i1-1,0] and
- block[0,i2-1], then all of the pairwise merges in
- block[1:i1, 1:i2] can also be done.
-
- 2. If a direct merge fails between block[i1-1,0] and
- block[0,i2-1], then all of the pairwise merges in
- block[i1-1:,i2-1:] would also fail.
-
- Under these assumptions, the merge frontier is a stepstair
- pattern going from the bottom-left to the top-right, and
- bisection can be used to find the transition between mergeable
- and conflicting in any row or column.
-
- Of course these assumptions are not rigorously true, so the
- MergeFrontier returned by this function is only an
- approximation of the real merge diagram. We check for and
- correct such inconsistencies later.
-
- """
-
- # Given that these diagrams typically have few blocks, check
- # the end of a range first to see if the whole range can be
- # determined, and fall back to bisection otherwise. We
- # determine the frontier block by block, starting in the lower
- # left.
-
- if block.len1 <= 1 or block.len2 <= 1 or block.is_blocked(1, 1):
- return
-
- if block.is_mergeable(block.len1 - 1, block.len2 - 1):
- # The whole block is mergable!
- yield block
- return
-
- if not block.is_mergeable(1, 1):
- # There are no mergeable blocks in block; therefore,
- # block[1,1] must itself be unmergeable. Record that
- # fact:
- block[1, 1].record_blocked(True)
- return
-
- # At this point, we know that there is at least one mergeable
- # commit in the first column. Find the height of the success
- # block in column 1:
- i1 = 1
- i2 = find_first_false(
- lambda i: block.is_mergeable(i1, i),
- 2, block.len2,
- )
-
- # Now we know that (1,i2-1) is mergeable but (1,i2) is not;
- # e.g., (i1, i2) is like 'A' (or maybe 'B') in the following
- # diagram (where '*' means mergeable, 'x' means not mergeable,
- # and '?' means indeterminate) and that the merge under 'A' is
- # not mergeable:
- #
- # i1
- #
- # 0123456
- # 0 *******
- # 1 **?????
- # i2 2 **?????
- # 3 **?????
- # 4 *Axxxxx
- # 5 *xxxxxx
- # B
-
- while True:
- if i2 == 1:
- break
-
- # At this point in the loop, we know that any blocks to
- # the left of 'A' have already been recorded, (i1, i2-1)
- # is mergeable but (i1, i2) is not; e.g., we are at a
- # place like 'A' in the following diagram:
- #
- # i1
- #
- # 0123456
- # 0 **|****
- # 1 **|*???
- # i2 2 **|*???
- # 3 **|Axxx
- # 4 --+xxxx
- # 5 *xxxxxx
- #
- # This implies that (i1, i2) is the first unmergeable
- # commit in a blocker block (though blocker blocks are not
- # recorded explicitly). It also implies that a mergeable
- # block has its last mergeable commit somewhere in row
- # i2-1; find its width.
- if (
- i1 == block.len1 - 1
- or block.is_mergeable(block.len1 - 1, i2 - 1)
- ):
- yield block[:block.len1, :i2]
- break
- else:
- i1 = find_first_false(
- lambda i: block.is_mergeable(i, i2 - 1),
- i1 + 1, block.len1 - 1,
- )
- yield block[:i1, :i2]
-
- # At this point in the loop, (i1-1, i2-1) is mergeable but
- # (i1, i2-1) is not; e.g., 'A' in the following diagram:
- #
- # i1
- #
- # 0123456
- # 0 **|*|**
- # 1 **|*|??
- # i2 2 --+-+xx
- # 3 **|xxAx
- # 4 --+xxxx
- # 5 *xxxxxx
- #
- # The block ending at (i1-1,i2-1) has just been recorded.
- # Now find the height of the conflict rectangle at column
- # i1 and fill it in:
- if i2 - 1 == 1 or not block.is_mergeable(i1, 1):
- break
- else:
- i2 = find_first_false(
- lambda i: block.is_mergeable(i1, i),
- 2, i2 - 1,
- )
-
-
-class MergeFrontier(object):
- """Represents the merge frontier within a Block.
-
- A MergeFrontier is represented by a list of SubBlocks, each of
- which is thought to be completely mergeable. The list is kept in
- normalized form:
-
- * Only non-empty blocks are retained
-
- * Blocks are sorted from bottom left to upper right
-
- * No redundant blocks
-
- """
-
- @staticmethod
- def map_known_frontier(block):
- """Return the MergeFrontier describing existing successful merges in block.
-
- The return value only includes the part that is fully outlined
- and whose outline consists of rectangles reaching back to
- (0,0).
-
- A blocked commit is *not* considered to be within the
- frontier, even if a merge is registered for it. Such merges
- must be explicitly unblocked."""
-
- # FIXME: This algorithm can take combinatorial time, for
- # example if there is a big block of merges that is a dead
- # end:
- #
- # +++++++
- # +?+++++
- # +?+++++
- # +?+++++
- # +?*++++
- #
- # The problem is that the algorithm will explore all of the
- # ways of getting to commit *, and the number of paths grows
- # like a binomial coefficient. The solution would be to
- # remember dead-ends and reject any curves that visit a point
- # to the right of a dead-end.
- #
- # For now we don't intend to allow a situation like this to be
- # created, so we ignore the problem.
-
- # A list (i1, i2, down) of points in the path so far. down is
- # True iff the attempted step following this one was
- # downwards.
- path = []
-
- def create_frontier(path):
- blocks = []
- for ((i1old, i2old, downold), (i1new, i2new, downnew)) in iter_neighbors(path):
- if downold is True and downnew is False:
- blocks.append(block[:i1new + 1, :i2new + 1])
- return MergeFrontier(block, blocks)
-
- # Loop invariants:
- #
- # * path is a valid path
- #
- # * (i1, i2) is in block but it not yet added to path
- #
- # * down is True if a step downwards from (i1, i2) has not yet
- # been attempted
- (i1, i2) = (block.len1 - 1, 0)
- down = True
- while True:
- if down:
- if i2 == block.len2 - 1:
- # Hit edge of block; can't move down:
- down = False
- elif (i1, i2 + 1) in block and not block.is_blocked(i1, i2 + 1):
- # Can move down
- path.append((i1, i2, True))
- i2 += 1
- else:
- # Can't move down.
- down = False
- else:
- if i1 == 0:
- # Success!
- path.append((i1, i2, False))
- return create_frontier(path)
- elif (i1 - 1, i2) in block and not block.is_blocked(i1 - 1, i2):
- # Can move left
- path.append((i1, i2, False))
- down = True
- i1 -= 1
- else:
- # There's no way to go forward; backtrack until we
- # find a place where we can still try going left:
- while True:
- try:
- (i1, i2, down) = path.pop()
- except IndexError:
- # This shouldn't happen because, in the
- # worst case, there is a valid path across
- # the top edge of the merge diagram.
- raise RuntimeError('Block is improperly formed!')
- if down:
- down = False
- break
-
- @staticmethod
- def compute_by_bisection(block):
- """Return a MergeFrontier instance for block.
-
- Compute the blocks making up the boundary using bisection. See
- find_frontier_blocks() for more information.
-
- """
-
- return MergeFrontier(block, list(find_frontier_blocks(block)))
-
- def __init__(self, block, blocks=None):
- self.block = block
- self.blocks = self._normalized_blocks(blocks or [])
-
- def __iter__(self):
- """Iterate over blocks from bottom left to upper right."""
-
- return iter(self.blocks)
-
- def __bool__(self):
- """Return True iff this frontier has no completed parts."""
-
- return bool(self.blocks)
-
- def __nonzero__(self):
- """Return True iff this frontier has no completed parts."""
-
- return bool(self.blocks)
-
- def is_complete(self):
- """Return True iff the frontier covers the whole block."""
-
- return (
- len(self.blocks) == 1
- and self.blocks[0].len1 == self.block.len1
- and self.blocks[0].len2 == self.block.len2
- )
-
- # Additional codes used in the 2D array returned from create_diagram()
- FRONTIER_WITHIN = 0x10
- FRONTIER_RIGHT_EDGE = 0x20
- FRONTIER_BOTTOM_EDGE = 0x40
- FRONTIER_MASK = 0x70
-
- @classmethod
- def default_formatter(cls, node, legend=None):
- def color(node, within):
- if within:
- return AnsiColor.B_GREEN + node + AnsiColor.END
- else:
- return AnsiColor.B_RED + node + AnsiColor.END
-
- if legend is None:
- legend = ['?', '*', '.', '#', '@', '-', '|', '+']
- merge = node & Block.MERGE_MASK
- within = merge == Block.MERGE_MANUAL or (node & cls.FRONTIER_WITHIN)
- skip = [Block.MERGE_MANUAL, Block.MERGE_BLOCKED, Block.MERGE_UNBLOCKED]
- if merge not in skip:
- vertex = (cls.FRONTIER_BOTTOM_EDGE | cls.FRONTIER_RIGHT_EDGE)
- edge_status = node & vertex
- if edge_status == vertex:
- return color(legend[-1], within)
- elif edge_status == cls.FRONTIER_RIGHT_EDGE:
- return color(legend[-2], within)
- elif edge_status == cls.FRONTIER_BOTTOM_EDGE:
- return color(legend[-3], within)
- return color(legend[merge], within)
-
- def create_diagram(self):
- """Generate a diagram of this frontier.
-
- The returned diagram is a nested list of integers forming a 2D array,
- representing the merge frontier embedded in the diagram of commits
- returned from Block.create_diagram().
-
- At each node in the returned diagram is an integer whose value is a
- bitwise-or of existing MERGE_* constant from Block.create_diagram()
- and zero or more of the FRONTIER_* constants defined in this class."""
-
- diagram = self.block.create_diagram()
-
- try:
- next_block = self.blocks[0]
- except IndexError:
- next_block = None
-
- diagram[0][-1] |= self.FRONTIER_BOTTOM_EDGE
- for i2 in range(1, self.block.len2):
- if next_block is None or i2 >= next_block.len2:
- diagram[0][i2] |= self.FRONTIER_RIGHT_EDGE
-
- prev_block = None
- for n in range(len(self.blocks)):
- block = self.blocks[n]
- try:
- next_block = self.blocks[n + 1]
- except IndexError:
- next_block = None
-
- for i1 in range(block.len1):
- for i2 in range(block.len2):
- v = self.FRONTIER_WITHIN
- if i1 == block.len1 - 1 and (
- next_block is None or i2 >= next_block.len2
- ):
- v |= self.FRONTIER_RIGHT_EDGE
- if i2 == block.len2 - 1 and (
- prev_block is None or i1 >= prev_block.len1
- ):
- v |= self.FRONTIER_BOTTOM_EDGE
- diagram[i1][i2] |= v
- prev_block = block
-
- try:
- prev_block = self.blocks[-1]
- except IndexError:
- prev_block = None
-
- for i1 in range(1, self.block.len1):
- if prev_block is None or i1 >= prev_block.len1:
- diagram[i1][0] |= self.FRONTIER_BOTTOM_EDGE
- diagram[-1][0] |= self.FRONTIER_RIGHT_EDGE
-
- return diagram
-
- def format_diagram(self, formatter=None, diagram=None):
- if formatter is None:
- formatter = self.default_formatter
- if diagram is None:
- diagram = self.create_diagram()
- return [
- [formatter(diagram[i1][i2]) for i2 in range(self.block.len2)]
- for i1 in range(self.block.len1)]
-
- def write(self, f):
- """Write this frontier to file-like object f."""
- diagram = self.format_diagram()
- for i2 in range(self.block.len2):
- for i1 in range(self.block.len1):
- f.write(diagram[i1][i2])
- f.write('\n')
-
- def write_html(self, f, name, cssfile='imerge.css', abbrev_sha1=7):
- class_map = {
- Block.MERGE_UNKNOWN: 'merge_unknown',
- Block.MERGE_MANUAL: 'merge_manual',
- Block.MERGE_AUTOMATIC: 'merge_automatic',
- Block.MERGE_BLOCKED: 'merge_blocked',
- Block.MERGE_UNBLOCKED: 'merge_unblocked',
- self.FRONTIER_WITHIN: 'frontier_within',
- self.FRONTIER_RIGHT_EDGE: 'frontier_right_edge',
- self.FRONTIER_BOTTOM_EDGE: 'frontier_bottom_edge',
- }
-
- def map_to_classes(i1, i2, node):
- merge = node & Block.MERGE_MASK
- ret = [class_map[merge]]
- for bit in [self.FRONTIER_WITHIN, self.FRONTIER_RIGHT_EDGE,
- self.FRONTIER_BOTTOM_EDGE]:
- if node & bit:
- ret.append(class_map[bit])
- if not (node & self.FRONTIER_WITHIN):
- ret.append('frontier_without')
- elif (node & Block.MERGE_MASK) == Block.MERGE_UNKNOWN:
- ret.append('merge_skipped')
- if i1 == 0 or i2 == 0:
- ret.append('merge_initial')
- if i1 == 0:
- ret.append('col_left')
- if i1 == self.block.len1 - 1:
- ret.append('col_right')
- if i2 == 0:
- ret.append('row_top')
- if i2 == self.block.len2 - 1:
- ret.append('row_bottom')
- return ret
-
- f.write("""\
-<html>
-<head>
-<title>git-imerge: %s</title>
-<link rel="stylesheet" href="%s" type="text/css" />
-</head>
-<body>
-<table id="imerge">
-""" % (name, cssfile))
-
- diagram = self.create_diagram()
-
- f.write(' <tr>\n')
- f.write(' <th class="indexes">&nbsp;</td>\n')
- for i1 in range(self.block.len1):
- f.write(' <th class="indexes">%d-*</td>\n' % (i1,))
- f.write(' </tr>\n')
-
- for i2 in range(self.block.len2):
- f.write(' <tr>\n')
- f.write(' <th class="indexes">*-%d</td>\n' % (i2,))
- for i1 in range(self.block.len1):
- classes = map_to_classes(i1, i2, diagram[i1][i2])
- record = self.block.get_value(i1, i2)
- sha1 = record.sha1 or ''
- td_id = record.sha1 and ' id="%s"' % (record.sha1) or ''
- td_class = classes and ' class="' + ' '.join(classes) + '"' or ''
- f.write(' <td%s%s>%.*s</td>\n' % (
- td_id, td_class, abbrev_sha1, sha1))
- f.write(' </tr>\n')
- f.write('</table>\n</body>\n</html>\n')
-
- @staticmethod
- def _normalized_blocks(blocks):
- """Return a normalized list of blocks from the argument.
-
- * Remove empty blocks.
-
- * Remove redundant blocks.
-
- * Sort the blocks according to their len1 members.
-
- """
-
- def contains(block1, block2):
- """Return true if block1 contains block2."""
-
- return block1.len1 >= block2.len1 and block1.len2 >= block2.len2
-
- blocks = sorted(blocks, key=lambda block: block.len1)
- ret = []
-
- for block in blocks:
- if block.len1 == 0 or block.len2 == 0:
- continue
- while True:
- if not ret:
- ret.append(block)
- break
-
- last = ret[-1]
- if contains(last, block):
- break
- elif contains(block, last):
- ret.pop()
- else:
- ret.append(block)
- break
-
- return ret
-
- def remove_failure(self, i1, i2):
- """Refine the merge frontier given that the specified merge fails."""
-
- newblocks = []
- shrunk_block = False
-
- for block in self.blocks:
- if i1 < block.len1 and i2 < block.len2:
- if i1 > 1:
- newblocks.append(block[:i1, :])
- if i2 > 1:
- newblocks.append(block[:, :i2])
- shrunk_block = True
- else:
- newblocks.append(block)
-
- if shrunk_block:
- self.blocks = self._normalized_blocks(newblocks)
-
- def partition(self, block):
- """Return two MergeFrontier instances partitioned by block.
-
- Return (frontier1, frontier2), where each frontier is limited
- to each side of the argument.
-
- block must be contained in this MergeFrontier and already be
- outlined."""
-
- # Remember that the new blocks have to include the outlined
- # edge of the partitioning block to satisfy the invariant that
- # the left and upper edge of a block has to be known.
-
- left = []
- right = []
- for b in self.blocks:
- if b.len1 == block.len1 and b.len2 == block.len2:
- # That's the block we're partitioning on; just skip it.
- pass
- elif b.len1 < block.len1 and b.len2 > block.len2:
- left.append(b[:, block.len2 - 1:])
- elif b.len1 > block.len1 and b.len2 < block.len2:
- right.append(b[block.len1 - 1:, :])
- else:
- raise ValueError(
- 'MergeFrontier partitioned with inappropriate block'
- )
- return (
- MergeFrontier(self.block[:block.len1, block.len2 - 1:], left),
- MergeFrontier(self.block[block.len1 - 1:, :block.len2], right),
- )
-
- def iter_blocker_blocks(self):
- """Iterate over the blocks on the far side of this frontier.
-
- This must only be called for an outlined frontier."""
-
- if not self:
- yield self.block
- return
-
- blockruns = []
- if self.blocks[0].len2 < self.block.len2:
- blockruns.append([self.block[0, :]])
- blockruns.append(self)
- if self.blocks[-1].len1 < self.block.len1:
- blockruns.append([self.block[:, 0]])
-
- for block1, block2 in iter_neighbors(itertools.chain(*blockruns)):
- yield self.block[block1.len1 - 1:block2.len1, block2.len2 - 1: block1.len2]
-
- def get_affected_blocker_block(self, i1, i2):
- """Return the blocker block that a successful merge (i1,i2) would unblock.
-
- If there is no such block, raise NotABlockingCommitError."""
-
- for block in self.iter_blocker_blocks():
- try:
- (block_i1, block_i2) = block.convert_original_indexes(i1, i2)
- except IndexError:
- pass
- else:
- if (block_i1, block_i2) == (1, 1):
- # That's the one we need to improve this block:
- return block
- else:
- # An index pair can only be in a single blocker
- # block, which we've already found:
- raise NotABlockingCommitError(
- 'Commit %d-%d was not blocking the frontier.'
- % self.block.get_original_indexes(i1, i2)
- )
- else:
- raise NotABlockingCommitError(
- 'Commit %d-%d was not on the frontier.'
- % self.block.get_original_indexes(i1, i2)
- )
-
- def auto_expand(self):
- """Try pushing out one of the blocks on this frontier.
-
- Raise BlockCompleteError if the whole block has already been
- solved. Raise FrontierBlockedError if the frontier is blocked
- everywhere. This method does *not* update self; if it returns
- successfully you should recompute the frontier from
- scratch."""
-
- blocks = list(self.iter_blocker_blocks())
- if not blocks:
- raise BlockCompleteError('The block is already complete')
-
- # Try blocks from left to right:
- blocks.sort(key=lambda block: block.get_original_indexes(0, 0))
-
- for block in blocks:
- if block.auto_expand_frontier():
- return
- else:
- # None of the blocks could be expanded. Suggest that the
- # caller do a manual merge of the commit that is blocking
- # the leftmost blocker block.
- i1, i2 = blocks[0].get_original_indexes(1, 1)
- raise FrontierBlockedError(
- 'Conflict; suggest manual merge of %d-%d' % (i1, i2),
- i1, i2
- )
-
-
-class NoManualMergeError(Exception):
- pass
-
-
-class ManualMergeUnusableError(Exception):
- def __init__(self, msg, commit):
- Exception.__init__(self, 'Commit %s is not usable; %s' % (commit, msg))
- self.commit = commit
-
-
-class CommitNotFoundError(Exception):
- def __init__(self, commit):
- Exception.__init__(
- self,
- 'Commit %s was not found among the known merge commits' % (commit,),
- )
- self.commit = commit
-
-
-class Block(object):
- """A rectangular range of commits, indexed by (i1,i2).
-
- The commits block[0,1:] and block[1:,0] are always all known.
- block[0,0] may or may not be known; it is usually unneeded (except
- maybe implicitly).
-
- Members:
-
- name -- the name of the imerge of which this block is part.
-
- len1, len2 -- the dimensions of the block.
-
- """
-
- def __init__(self, git, name, len1, len2):
- self.git = git
- self.name = name
- self.len1 = len1
- self.len2 = len2
-
- def get_merge_state(self):
- """Return the MergeState instance containing this Block."""
-
- raise NotImplementedError()
-
- def get_area(self):
- """Return the area of this block, ignoring the known edges."""
-
- return (self.len1 - 1) * (self.len2 - 1)
-
- def _check_indexes(self, i1, i2):
- if not (0 <= i1 < self.len1):
- raise IndexError('first index (%s) is out of range 0:%d' % (i1, self.len1,))
- if not (0 <= i2 < self.len2):
- raise IndexError('second index (%s) is out of range 0:%d' % (i2, self.len2,))
-
- def _normalize_indexes(self, index):
- """Return a pair of non-negative integers (i1, i2)."""
-
- try:
- (i1, i2) = index
- except TypeError:
- raise IndexError('Block indexing requires exactly two indexes')
-
- if i1 < 0:
- i1 += self.len1
- if i2 < 0:
- i2 += self.len2
-
- self._check_indexes(i1, i2)
- return (i1, i2)
-
- def get_original_indexes(self, i1, i2):
- """Return the original indexes corresponding to (i1,i2) in this block.
-
- This function supports negative indexes."""
-
- return self._normalize_indexes((i1, i2))
-
- def convert_original_indexes(self, i1, i2):
- """Return the indexes in this block corresponding to original indexes (i1,i2).
-
- raise IndexError if they are not within this block. This
- method does not support negative indices."""
-
- return (i1, i2)
-
- def _set_value(self, i1, i2, value):
- """Set the MergeRecord for integer indexes (i1, i2).
-
- i1 and i2 must be non-negative."""
-
- raise NotImplementedError()
-
- def get_value(self, i1, i2):
- """Return the MergeRecord for integer indexes (i1, i2).
-
- i1 and i2 must be non-negative."""
-
- raise NotImplementedError()
-
- def __getitem__(self, index):
- """Return the MergeRecord at (i1, i2) (requires two indexes).
-
- If i1 and i2 are integers but the merge is unknown, return
- None. If either index is a slice, return a SubBlock."""
-
- try:
- (i1, i2) = index
- except TypeError:
- raise IndexError('Block indexing requires exactly two indexes')
- if isinstance(i1, slice) or isinstance(i2, slice):
- return SubBlock(self, i1, i2)
- else:
- return self.get_value(*self._normalize_indexes((i1, i2)))
-
- def __contains__(self, index):
- return self[index].is_known()
-
- def is_blocked(self, i1, i2):
- """Return True iff the specified commit is blocked."""
-
- (i1, i2) = self._normalize_indexes((i1, i2))
- return self[i1, i2].is_blocked()
-
- def is_mergeable(self, i1, i2):
- """Determine whether (i1,i2) can be merged automatically.
-
- If we already have a merge record for (i1,i2), return True.
- Otherwise, attempt a merge (discarding the result)."""
-
- (i1, i2) = self._normalize_indexes((i1, i2))
- if (i1, i2) in self:
- return True
- else:
- sys.stderr.write(
- 'Attempting automerge of %d-%d...' % self.get_original_indexes(i1, i2)
- )
- try:
- self.git.automerge(self[i1, 0].sha1, self[0, i2].sha1)
- sys.stderr.write('success.\n')
- return True
- except AutomaticMergeFailed:
- sys.stderr.write('failure.\n')
- return False
-
- def auto_outline(self):
- """Complete the outline of this Block.
-
- raise UnexpectedMergeFailure if automerging fails."""
-
- # Check that all of the merges go through before recording any
- # of them permanently.
- merges = []
-
- def do_merge(i1, commit1, i2, commit2, msg='Autofilling %d-%d...', record=True):
- if (i1, i2) in self:
- return self[i1, i2].sha1
- (i1orig, i2orig) = self.get_original_indexes(i1, i2)
- sys.stderr.write(msg % (i1orig, i2orig))
- logmsg = 'imerge \'%s\': automatic merge %d-%d' % (self.name, i1orig, i2orig)
- try:
- merge = self.git.automerge(commit1, commit2, msg=logmsg)
- sys.stderr.write('success.\n')
- except AutomaticMergeFailed as e:
- sys.stderr.write('unexpected conflict. Backtracking...\n')
- raise UnexpectedMergeFailure(str(e), i1, i2)
- if record:
- merges.append((i1, i2, merge))
- return merge
-
- i2 = self.len2 - 1
- left = self[0, i2].sha1
- for i1 in range(1, self.len1 - 1):
- left = do_merge(i1, self[i1, 0].sha1, i2, left)
-
- i1 = self.len1 - 1
- above = self[i1, 0].sha1
- for i2 in range(1, self.len2 - 1):
- above = do_merge(i1, above, i2, self[0, i2].sha1)
-
- i1, i2 = self.len1 - 1, self.len2 - 1
- if i1 > 1 and i2 > 1:
- # We will compare two ways of doing the final "vertex" merge:
- # as a continuation of the bottom edge, or as a continuation
- # of the right edge. We only accept it if both approaches
- # succeed and give identical trees.
- vertex_v1 = do_merge(
- i1, self[i1, 0].sha1, i2, left,
- msg='Autofilling %d-%d (first way)...',
- record=False,
- )
- vertex_v2 = do_merge(
- i1, above, i2, self[0, i2].sha1,
- msg='Autofilling %d-%d (second way)...',
- record=False,
- )
- if self.git.get_tree(vertex_v1) == self.git.get_tree(vertex_v2):
- sys.stderr.write(
- 'The two ways of autofilling %d-%d agree.\n'
- % self.get_original_indexes(i1, i2)
- )
- # Everything is OK. Now reparent the actual vertex merge to
- # have above and left as its parents:
- merges.append(
- (i1, i2, self.git.reparent(vertex_v1, [above, left]))
- )
- else:
- sys.stderr.write(
- 'The two ways of autofilling %d-%d do not agree. Backtracking...\n'
- % self.get_original_indexes(i1, i2)
- )
- raise UnexpectedMergeFailure('Inconsistent vertex merges', i1, i2)
- else:
- do_merge(
- i1, above, i2, left,
- msg='Autofilling %d-%d...',
- )
-
- # Done! Now we can record the results:
- sys.stderr.write('Recording autofilled block %s.\n' % (self,))
- for (i1, i2, merge) in merges:
- self[i1, i2].record_merge(merge, MergeRecord.NEW_AUTO)
-
- def auto_fill_micromerge(self):
- """Try to fill the very first micromerge in this block.
-
- Return True iff the attempt was successful."""
-
- assert (1, 1) not in self
- if self.len1 <= 1 or self.len2 <= 1 or self.is_blocked(1, 1):
- return False
-
- i1, i2 = 1, 1
- (i1orig, i2orig) = self.get_original_indexes(i1, i2)
- sys.stderr.write('Attempting to merge %d-%d...' % (i1orig, i2orig))
- logmsg = 'imerge \'%s\': automatic merge %d-%d' % (self.name, i1orig, i2orig)
- try:
- merge = self.git.automerge(
- self[i1, i2 - 1].sha1,
- self[i1 - 1, i2].sha1,
- msg=logmsg,
- )
- sys.stderr.write('success.\n')
- except AutomaticMergeFailed:
- sys.stderr.write('conflict.\n')
- self[i1, i2].record_blocked(True)
- return False
- else:
- self[i1, i2].record_merge(merge, MergeRecord.NEW_AUTO)
- return True
-
- def auto_outline_frontier(self, merge_frontier=None):
- """Try to outline the merge frontier of this block.
-
- Return True iff some progress was made."""
-
- if merge_frontier is None:
- merge_frontier = MergeFrontier.compute_by_bisection(self)
-
- if not merge_frontier:
- # Nothing to do.
- return False
-
- best_block = max(merge_frontier, key=lambda block: block.get_original_indexes(0, 0))
-
- try:
- best_block.auto_outline()
- except UnexpectedMergeFailure as e:
- # One of the merges that we expected to succeed in
- # fact failed.
- merge_frontier.remove_failure(e.i1, e.i2)
- return self.auto_outline_frontier(merge_frontier)
- else:
- f1, f2 = merge_frontier.partition(best_block)
- if f1:
- f1.block.auto_outline_frontier(f1)
- if f2:
- f2.block.auto_outline_frontier(f2)
- return True
-
- def auto_expand_frontier(self):
- merge_state = self.get_merge_state()
- if merge_state.manual:
- return False
- elif merge_state.goal == 'full':
- return self.auto_fill_micromerge()
- else:
- return self.auto_outline_frontier()
-
- # The codes in the 2D array returned from create_diagram()
- MERGE_UNKNOWN = 0
- MERGE_MANUAL = 1
- MERGE_AUTOMATIC = 2
- MERGE_BLOCKED = 3
- MERGE_UNBLOCKED = 4
- MERGE_MASK = 7
-
- # A map {(is_known(), manual, is_blocked()) : integer constant}
- MergeState = {
- (False, False, False): MERGE_UNKNOWN,
- (False, False, True): MERGE_BLOCKED,
- (True, False, True): MERGE_UNBLOCKED,
- (True, True, True): MERGE_UNBLOCKED,
- (True, False, False): MERGE_AUTOMATIC,
- (True, True, False): MERGE_MANUAL,
- }
-
- def create_diagram(self):
- """Generate a diagram of this Block.
-
- The returned diagram, is a nested list of integers forming a 2D array,
- where the integer at diagram[i1][i2] is one of MERGE_UNKNOWN,
- MERGE_MANUAL, MERGE_AUTOMATIC, MERGE_BLOCKED, or MERGE_UNBLOCKED,
- representing the state of the commit at (i1, i2)."""
-
- diagram = [[None for i2 in range(self.len2)] for i1 in range(self.len1)]
-
- for i2 in range(self.len2):
- for i1 in range(self.len1):
- rec = self.get_value(i1, i2)
- c = self.MergeState[
- rec.is_known(), rec.is_manual(), rec.is_blocked()]
- diagram[i1][i2] = c
-
- return diagram
-
- def format_diagram(self, legend=None, diagram=None):
- if legend is None:
- legend = [
- AnsiColor.D_GRAY + '?' + AnsiColor.END,
- AnsiColor.B_GREEN + '*' + AnsiColor.END,
- AnsiColor.B_GREEN + '.' + AnsiColor.END,
- AnsiColor.B_RED + '#' + AnsiColor.END,
- AnsiColor.B_YELLOW + '@' + AnsiColor.END,
- ]
- if diagram is None:
- diagram = self.create_diagram()
- return [
- [legend[diagram[i1][i2]] for i2 in range(self.len2)]
- for i1 in range(self.len1)]
-
- def write(self, f, legend=None, sep='', linesep='\n'):
- diagram = self.format_diagram(legend)
- for i2 in range(self.len2):
- f.write(sep.join(diagram[i1][i2] for i1 in range(self.len1)) + linesep)
-
- def writeppm(self, f):
- f.write('P3\n')
- f.write('%d %d 255\n' % (self.len1, self.len2,))
- legend = ['127 127 0', '0 255 0', '0 127 0', '255 0 0', '127 0 0']
- self.write(f, legend, sep=' ')
-
-
-class SubBlock(Block):
- @staticmethod
- def _convert_to_slice(i, len):
- """Return (start, len) for the specified index.
-
- i may be an integer or a slice with step equal to 1."""
-
- if isinstance(i, int):
- if i < 0:
- i += len
- i = slice(i, i + 1)
- elif isinstance(i, slice):
- if i.step is not None and i.step != 1:
- raise ValueError('Index has a non-zero step size')
- else:
- raise ValueError('Index cannot be converted to a slice')
-
- (start, stop, step) = i.indices(len)
- return (start, stop - start)
-
- def __init__(self, block, slice1, slice2):
- (start1, len1) = self._convert_to_slice(slice1, block.len1)
- (start2, len2) = self._convert_to_slice(slice2, block.len2)
- Block.__init__(self, block.git, block.name, len1, len2)
- if isinstance(block, SubBlock):
- # Peel away one level of indirection:
- self._merge_state = block._merge_state
- self._start1 = start1 + block._start1
- self._start2 = start2 + block._start2
- else:
- assert(isinstance(block, MergeState))
- self._merge_state = block
- self._start1 = start1
- self._start2 = start2
-
- def get_merge_state(self):
- return self._merge_state
-
- def get_original_indexes(self, i1, i2):
- i1, i2 = self._normalize_indexes((i1, i2))
- return self._merge_state.get_original_indexes(
- i1 + self._start1,
- i2 + self._start2,
- )
-
- def convert_original_indexes(self, i1, i2):
- (i1, i2) = self._merge_state.convert_original_indexes(i1, i2)
- if not (
- self._start1 <= i1 < self._start1 + self.len1
- and self._start2 <= i2 < self._start2 + self.len2
- ):
- raise IndexError('Indexes are not within block')
- return (i1 - self._start1, i2 - self._start2)
-
- def _set_value(self, i1, i2, sha1, flags):
- self._check_indexes(i1, i2)
- self._merge_state._set_value(
- i1 + self._start1,
- i2 + self._start2,
- sha1, flags,
- )
-
- def get_value(self, i1, i2):
- self._check_indexes(i1, i2)
- return self._merge_state.get_value(i1 + self._start1, i2 + self._start2)
-
- def __str__(self):
- return '%s[%d:%d,%d:%d]' % (
- self._merge_state,
- self._start1, self._start1 + self.len1,
- self._start2, self._start2 + self.len2,
- )
-
-
-class MissingMergeFailure(Failure):
- def __init__(self, i1, i2):
- Failure.__init__(self, 'Merge %d-%d is not yet done' % (i1, i2))
- self.i1 = i1
- self.i2 = i2
-
-
-class MergeState(Block):
- SOURCE_TABLE = {
- 'auto': MergeRecord.SAVED_AUTO,
- 'manual': MergeRecord.SAVED_MANUAL,
- }
-
- @staticmethod
- def get_scratch_refname(name):
- return 'refs/heads/imerge/%s' % (name,)
-
- @staticmethod
- def _check_no_merges(git, commits):
- multiparent_commits = [
- commit
- for commit in commits
- if len(git.get_commit_parents(commit)) > 1
- ]
- if multiparent_commits:
- raise Failure(
- 'The following commits on the to-be-merged branch are merge commits:\n'
- ' %s\n'
- '--goal=\'rebase\' is not yet supported for branches that include merges.\n'
- % ('\n '.join(multiparent_commits),)
- )
-
- @staticmethod
- def initialize(
- git, name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal=DEFAULT_GOAL, goalopts=None,
- manual=False, branch=None,
- ):
- """Create and return a new MergeState object."""
-
- git.verify_imerge_name_available(name)
- if branch:
- git.check_branch_name_format(branch)
- else:
- branch = name
-
- if goal == 'rebase':
- MergeState._check_no_merges(git, commits2)
-
- return MergeState(
- git, name, merge_base,
- tip1, commits1,
- tip2, commits2,
- MergeRecord.NEW_MANUAL,
- goal=goal, goalopts=goalopts,
- manual=manual,
- branch=branch,
- )
-
- @staticmethod
- def read(git, name):
- (state, merges) = git.read_imerge_state(name)
-
- # Translate sources from strings into MergeRecord constants
- # SAVED_AUTO or SAVED_MANUAL:
- merges = dict((
- ((i1, i2), (sha1, MergeState.SOURCE_TABLE[source]))
- for ((i1, i2), (sha1, source)) in merges.items()
- ))
-
- blockers = state.get('blockers', [])
-
- # Find merge_base, commits1, and commits2:
- (merge_base, source) = merges.pop((0, 0))
- if source != MergeRecord.SAVED_MANUAL:
- raise Failure('Merge base should be manual!')
- commits1 = []
- for i1 in itertools.count(1):
- try:
- (sha1, source) = merges.pop((i1, 0))
- if source != MergeRecord.SAVED_MANUAL:
- raise Failure('Merge %d-0 should be manual!' % (i1,))
- commits1.append(sha1)
- except KeyError:
- break
-
- commits2 = []
- for i2 in itertools.count(1):
- try:
- (sha1, source) = merges.pop((0, i2))
- if source != MergeRecord.SAVED_MANUAL:
- raise Failure('Merge (0,%d) should be manual!' % (i2,))
- commits2.append(sha1)
- except KeyError:
- break
-
- tip1 = state.get('tip1', commits1[-1])
- tip2 = state.get('tip2', commits2[-1])
-
- goal = state['goal']
- if goal not in ALLOWED_GOALS:
- raise Failure('Goal %r, read from state, is not recognized.' % (goal,))
-
- goalopts = state['goalopts']
-
- manual = state['manual']
- branch = state.get('branch', name)
-
- state = MergeState(
- git, name, merge_base,
- tip1, commits1,
- tip2, commits2,
- MergeRecord.SAVED_MANUAL,
- goal=goal, goalopts=goalopts,
- manual=manual,
- branch=branch,
- )
-
- # Now write the rest of the merges to state:
- for ((i1, i2), (sha1, source)) in merges.items():
- if i1 == 0 and i2 >= state.len2:
- raise Failure('Merge 0-%d is missing!' % (state.len2,))
- if i1 >= state.len1 and i2 == 0:
- raise Failure('Merge %d-0 is missing!' % (state.len1,))
- if i1 >= state.len1 or i2 >= state.len2:
- raise Failure(
- 'Merge %d-%d is out of range [0:%d,0:%d]'
- % (i1, i2, state.len1, state.len2)
- )
- state[i1, i2].record_merge(sha1, source)
-
- # Record any blockers:
- for (i1, i2) in blockers:
- state[i1, i2].record_blocked(True)
-
- return state
-
- @staticmethod
- def remove(git, name):
- # If HEAD is the scratch refname, abort any in-progress
- # commits and detach HEAD:
- scratch_refname = MergeState.get_scratch_refname(name)
- if git.get_head_refname() == scratch_refname:
- try:
- git.abort_merge()
- except CalledProcessError:
- pass
- # Detach head so that we can delete scratch_refname:
- git.detach('Detach HEAD from %s' % (scratch_refname,))
-
- # Delete the scratch refname:
- git.delete_ref(
- scratch_refname, 'imerge %s: remove scratch reference' % (name,),
- )
-
- # Remove any references referring to intermediate merges:
- git.delete_imerge_refs(name)
-
- # If this merge was the default, unset the default:
- if git.get_default_imerge_name() == name:
- git.set_default_imerge_name(None)
-
- def __init__(
- self, git, name, merge_base,
- tip1, commits1,
- tip2, commits2,
- source,
- goal=DEFAULT_GOAL, goalopts=None,
- manual=False,
- branch=None,
- ):
- Block.__init__(self, git, name, len(commits1) + 1, len(commits2) + 1)
- self.tip1 = tip1
- self.tip2 = tip2
- self.goal = goal
- self.goalopts = goalopts
- self.manual = bool(manual)
- self.branch = branch or name
-
- # A simulated 2D array. Values are None or MergeRecord instances.
- self._data = [[None] * self.len2 for i1 in range(self.len1)]
-
- self.get_value(0, 0).record_merge(merge_base, source)
- for (i1, commit) in enumerate(commits1, 1):
- self.get_value(i1, 0).record_merge(commit, source)
- for (i2, commit) in enumerate(commits2, 1):
- self.get_value(0, i2).record_merge(commit, source)
-
- def get_merge_state(self):
- return self
-
- def set_goal(self, goal):
- if goal not in ALLOWED_GOALS:
- raise ValueError('%r is not an allowed goal' % (goal,))
-
- if goal == 'rebase':
- self._check_no_merges(
- self.git,
- [self[0, i2].sha1 for i2 in range(1, self.len2)],
- )
-
- self.goal = goal
-
- def _set_value(self, i1, i2, value):
- self._data[i1][i2] = value
-
- def get_value(self, i1, i2):
- value = self._data[i1][i2]
- # Missing values spring to life on first access:
- if value is None:
- value = MergeRecord()
- self._data[i1][i2] = value
- return value
-
- def __contains__(self, index):
- # Avoid creating new MergeRecord objects here.
- (i1, i2) = self._normalize_indexes(index)
- value = self._data[i1][i2]
- return (value is not None) and value.is_known()
-
- def auto_complete_frontier(self):
- """Complete the frontier using automerges.
-
- If progress is blocked before the frontier is complete, raise
- a FrontierBlockedError. Save the state as progress is
- made."""
-
- progress_made = False
- try:
- while True:
- frontier = MergeFrontier.map_known_frontier(self)
- frontier.auto_expand()
- self.save()
- progress_made = True
- except BlockCompleteError:
- return
- except FrontierBlockedError as e:
- self.save()
- if not progress_made:
- # Adjust the error message:
- raise FrontierBlockedError(
- 'No progress was possible; suggest manual merge of %d-%d'
- % (e.i1, e.i2),
- e.i1, e.i2,
- )
- else:
- raise
-
- def find_index(self, commit):
- """Return (i1,i2) for the specified commit.
-
- Raise CommitNotFoundError if it is not known."""
-
- for i2 in range(0, self.len2):
- for i1 in range(0, self.len1):
- if (i1, i2) in self:
- record = self[i1, i2]
- if record.sha1 == commit:
- return (i1, i2)
- raise CommitNotFoundError(commit)
-
- def request_user_merge(self, i1, i2):
- """Prepare the working tree for the user to do a manual merge.
-
- It is assumed that the merges above and to the left of (i1, i2)
- are already done."""
-
- above = self[i1, i2 - 1]
- left = self[i1 - 1, i2]
- if not above.is_known() or not left.is_known():
- raise RuntimeError('The parents of merge %d-%d are not ready' % (i1, i2))
- refname = MergeState.get_scratch_refname(self.name)
- self.git.update_ref(
- refname, above.sha1,
- 'imerge %r: Prepare merge %d-%d' % (self.name, i1, i2,),
- )
- self.git.checkout(refname)
- logmsg = 'imerge \'%s\': manual merge %d-%d' % (self.name, i1, i2)
- try:
- self.git.manualmerge(left.sha1, logmsg)
- except CalledProcessError:
- # We expect an error (otherwise we would have automerged!)
- pass
- sys.stderr.write(
- '\n'
- 'Original first commit:\n'
- )
- self.git.summarize_commit(self[i1, 0].sha1)
- sys.stderr.write(
- '\n'
- 'Original second commit:\n'
- )
- self.git.summarize_commit(self[0, i2].sha1)
- sys.stderr.write(
- '\n'
- 'There was a conflict merging commit %d-%d, shown above.\n'
- 'Please resolve the conflict, commit the result, then type\n'
- '\n'
- ' git-imerge continue\n'
- % (i1, i2)
- )
-
- def incorporate_manual_merge(self, commit):
- """Record commit as a manual merge of its parents.
-
- Return the indexes (i1,i2) where it was recorded. If the
- commit is not usable for some reason, raise
- ManualMergeUnusableError."""
-
- parents = self.git.get_commit_parents(commit)
- if len(parents) < 2:
- raise ManualMergeUnusableError('it is not a merge', commit)
- if len(parents) > 2:
- raise ManualMergeUnusableError('it is an octopus merge', commit)
- # Find the parents among our contents...
- try:
- (i1first, i2first) = self.find_index(parents[0])
- (i1second, i2second) = self.find_index(parents[1])
- except CommitNotFoundError:
- raise ManualMergeUnusableError(
- 'its parents are not known merge commits', commit,
- )
- swapped = False
- if i1first < i1second:
- # Swap parents to make the parent from above the first parent:
- (i1first, i2first, i1second, i2second) = (i1second, i2second, i1first, i2first)
- swapped = True
- if i1first != i1second + 1 or i2first != i2second - 1:
- raise ManualMergeUnusableError(
- 'it is not a pairwise merge of adjacent parents', commit,
- )
- if swapped:
- # Create a new merge with the parents in the conventional order:
- commit = self.git.reparent(commit, [parents[1], parents[0]])
-
- i1, i2 = i1first, i2second
- self[i1, i2].record_merge(commit, MergeRecord.NEW_MANUAL)
- return (i1, i2)
-
- def incorporate_user_merge(self, edit_log_msg=None):
- """If the user has done a merge for us, incorporate the results.
-
- If the scratch reference refs/heads/imerge/NAME exists and is
- checked out, first check if there are staged changes that can
- be committed. Then try to incorporate the current commit into
- this MergeState, delete the reference, and return (i1,i2)
- corresponding to the merge. If the scratch reference does not
- exist, raise NoManualMergeError(). If the scratch reference
- exists but cannot be used, raise a ManualMergeUnusableError.
- If there are unstaged changes in the working tree, emit an
- error message and raise UncleanWorkTreeError.
-
- """
-
- refname = MergeState.get_scratch_refname(self.name)
-
- try:
- commit = self.git.get_commit_sha1(refname)
- except ValueError:
- raise NoManualMergeError('Reference %s does not exist.' % (refname,))
-
- head_name = self.git.get_head_refname()
- if head_name is None:
- raise NoManualMergeError('HEAD is currently detached.')
- elif head_name != refname:
- # This should not usually happen. The scratch reference
- # exists, but it is not current. Perhaps the user gave up on
- # an attempted merge then switched to another branch. We want
- # to delete refname, but only if it doesn't contain any
- # content that we don't already know.
- try:
- self.find_index(commit)
- except CommitNotFoundError:
- # It points to a commit that we don't have in our records.
- raise Failure(
- 'The scratch reference, %(refname)s, already exists but is not\n'
- 'checked out. If it points to a merge commit that you would like\n'
- 'to use, please check it out using\n'
- '\n'
- ' git checkout %(refname)s\n'
- '\n'
- 'and then try to continue again. If it points to a commit that is\n'
- 'unneeded, then please delete the reference using\n'
- '\n'
- ' git update-ref -d %(refname)s\n'
- '\n'
- 'and then continue.'
- % dict(refname=refname)
- )
- else:
- # It points to a commit that is already recorded. We can
- # delete it without losing any information.
- self.git.delete_ref(
- refname,
- 'imerge %r: Remove obsolete scratch reference' % (self.name,),
- )
- sys.stderr.write(
- '%s did not point to a new merge; it has been deleted.\n'
- % (refname,)
- )
- raise NoManualMergeError(
- 'Reference %s was not checked out.' % (refname,)
- )
-
- # If we reach this point, then the scratch reference exists and is
- # checked out. Now check whether there is staged content that
- # can be committed:
- if self.git.commit_user_merge(edit_log_msg=edit_log_msg):
- commit = self.git.get_commit_sha1('HEAD')
-
- self.git.require_clean_work_tree('proceed')
-
- merge_frontier = MergeFrontier.map_known_frontier(self)
-
- # This might throw ManualMergeUnusableError:
- (i1, i2) = self.incorporate_manual_merge(commit)
-
- # Now detach head so that we can delete refname.
- self.git.detach('Detach HEAD from %s' % (refname,))
-
- self.git.delete_ref(
- refname, 'imerge %s: remove scratch reference' % (self.name,),
- )
-
- try:
- # This might throw NotABlockingCommitError:
- unblocked_block = merge_frontier.get_affected_blocker_block(i1, i2)
- unblocked_block[1, 1].record_blocked(False)
- sys.stderr.write(
- 'Merge has been recorded for merge %d-%d.\n'
- % unblocked_block.get_original_indexes(1, 1)
- )
- except NotABlockingCommitError:
- raise
- finally:
- self.save()
-
- def _set_refname(self, refname, commit, force=False):
- try:
- ref_oldval = self.git.get_commit_sha1(refname)
- except ValueError:
- # refname doesn't already exist; simply point it at commit:
- self.git.update_ref(refname, commit, 'imerge: recording final merge')
- self.git.checkout(refname, quiet=True)
- else:
- # refname already exists. This has two ramifications:
- # 1. HEAD might point at it
- # 2. We may only fast-forward it (unless force is set)
- head_refname = self.git.get_head_refname()
-
- if not force and not self.git.is_ancestor(ref_oldval, commit):
- raise Failure(
- '%s cannot be fast-forwarded to %s!' % (refname, commit)
- )
-
- if head_refname == refname:
- self.git.reset_hard(commit)
- else:
- self.git.update_ref(
- refname, commit, 'imerge: recording final merge',
- )
- self.git.checkout(refname, quiet=True)
-
- def simplify_to_full(self, refname, force=False):
- for i1 in range(1, self.len1):
- for i2 in range(1, self.len2):
- if not (i1, i2) in self:
- raise Failure(
- 'Cannot simplify to "full" because '
- 'merge %d-%d is not yet done'
- % (i1, i2)
- )
-
- self._set_refname(refname, self[-1, -1].sha1, force=force)
-
- def simplify_to_rebase_with_history(self, refname, force=False):
- i1 = self.len1 - 1
- for i2 in range(1, self.len2):
- if not (i1, i2) in self:
- raise Failure(
- 'Cannot simplify to rebase-with-history because '
- 'merge %d-%d is not yet done'
- % (i1, i2)
- )
-
- commit = self[i1, 0].sha1
- for i2 in range(1, self.len2):
- orig = self[0, i2].sha1
- tree = self.git.get_tree(self[i1, i2].sha1)
-
- # Create a commit, copying the old log message:
- msg = (
- self.git.get_log_message(orig).rstrip('\n')
- + '\n\n(rebased-with-history from commit %s)\n' % orig
- )
- commit = self.git.commit_tree(tree, [commit, orig], msg=msg)
-
- self._set_refname(refname, commit, force=force)
-
- def simplify_to_border(
- self, refname,
- with_history1=False, with_history2=False, force=False,
- ):
- i1 = self.len1 - 1
- for i2 in range(1, self.len2):
- if not (i1, i2) in self:
- raise Failure(
- 'Cannot simplify to border because '
- 'merge %d-%d is not yet done'
- % (i1, i2)
- )
-
- i2 = self.len2 - 1
- for i1 in range(1, self.len1):
- if not (i1, i2) in self:
- raise Failure(
- 'Cannot simplify to border because '
- 'merge %d-%d is not yet done'
- % (i1, i2)
- )
-
- i1 = self.len1 - 1
- commit = self[i1, 0].sha1
- for i2 in range(1, self.len2 - 1):
- orig = self[0, i2].sha1
- tree = self.git.get_tree(self[i1, i2].sha1)
-
- # Create a commit, copying the old log message:
- if with_history2:
- parents = [commit, orig]
- msg = (
- self.git.get_log_message(orig).rstrip('\n')
- + '\n\n(rebased-with-history from commit %s)\n' % (orig,)
- )
- else:
- parents = [commit]
- msg = (
- self.git.get_log_message(orig).rstrip('\n')
- + '\n\n(rebased from commit %s)\n' % (orig,)
- )
-
- commit = self.git.commit_tree(tree, parents, msg=msg)
- commit1 = commit
-
- i2 = self.len2 - 1
- commit = self[0, i2].sha1
- for i1 in range(1, self.len1 - 1):
- orig = self[i1, 0].sha1
- tree = self.git.get_tree(self[i1, i2].sha1)
-
- # Create a commit, copying the old log message:
- if with_history1:
- parents = [orig, commit]
- msg = (
- self.git.get_log_message(orig).rstrip('\n')
- + '\n\n(rebased-with-history from commit %s)\n' % (orig,)
- )
- else:
- parents = [commit]
- msg = (
- self.git.get_log_message(orig).rstrip('\n')
- + '\n\n(rebased from commit %s)\n' % (orig,)
- )
-
- commit = self.git.commit_tree(tree, parents, msg=msg)
- commit2 = commit
-
- # Construct the apex commit:
- tree = self.git.get_tree(self[-1, -1].sha1)
- msg = (
- 'Merge %s into %s (using imerge border)'
- % (self.tip2, self.tip1)
- )
-
- commit = self.git.commit_tree(tree, [commit1, commit2], msg=msg)
-
- # Update the reference:
- self._set_refname(refname, commit, force=force)
-
- def _simplify_to_path(self, refname, base, path, force=False):
- """Simplify based on path and set refname to the result.
-
- The base and path arguments are defined similarly to
- create_commit_chain(), except that instead of SHA-1s they may
- optionally represent commits via (i1, i2) tuples.
-
- """
-
- def to_sha1(arg):
- if type(arg) is tuple:
- commit_record = self[arg]
- if not commit_record.is_known():
- raise MissingMergeFailure(*arg)
- return commit_record.sha1
- else:
- return arg
-
- base_sha1 = to_sha1(base)
- path_sha1 = []
- for (commit, metadata) in path:
- commit_sha1 = to_sha1(commit)
- metadata_sha1 = to_sha1(metadata)
- path_sha1.append((commit_sha1, metadata_sha1))
-
- # A path simplification is allowed to discard history, as long
- # as the *pre-simplification* apex commit is a descendant of
- # the branch to be moved.
- if path:
- apex = path_sha1[-1][0]
- else:
- apex = base_sha1
-
- if not force and not self.git.is_ff(refname, apex):
- raise Failure(
- '%s cannot be updated to %s without discarding history.\n'
- 'Use --force if you are sure, or choose a different reference'
- % (refname, apex,)
- )
-
- # The update is OK, so here we can set force=True:
- self._set_refname(
- refname,
- self.git.create_commit_chain(base_sha1, path_sha1),
- force=True,
- )
-
- def simplify_to_rebase(self, refname, force=False):
- i1 = self.len1 - 1
- path = [
- ((i1, i2), (0, i2))
- for i2 in range(1, self.len2)
- ]
-
- try:
- self._simplify_to_path(refname, (i1, 0), path, force=force)
- except MissingMergeFailure as e:
- raise Failure(
- 'Cannot simplify to %s because merge %d-%d is not yet done'
- % (self.goal, e.i1, e.i2)
- )
-
- def simplify_to_drop(self, refname, force=False):
- try:
- base = self.goalopts['base']
- except KeyError:
- raise Failure('Goal "drop" was not initialized correctly')
-
- i2 = self.len2 - 1
- path = [
- ((i1, i2), (i1, 0))
- for i1 in range(1, self.len1)
- ]
-
- try:
- self._simplify_to_path(refname, base, path, force=force)
- except MissingMergeFailure as e:
- raise Failure(
- 'Cannot simplify to rebase because merge %d-%d is not yet done'
- % (e.i1, e.i2)
- )
-
- def simplify_to_revert(self, refname, force=False):
- self.simplify_to_rebase(refname, force=force)
-
- def simplify_to_merge(self, refname, force=False):
- if not (-1, -1) in self:
- raise Failure(
- 'Cannot simplify to merge because merge %d-%d is not yet done'
- % (self.len1 - 1, self.len2 - 1)
- )
- tree = self.git.get_tree(self[-1, -1].sha1)
- parents = [self[-1, 0].sha1, self[0, -1].sha1]
-
- # Create a preliminary commit with a generic commit message:
- sha1 = self.git.commit_tree(
- tree, parents,
- msg='Merge %s into %s (using imerge)' % (self.tip2, self.tip1),
- )
-
- self._set_refname(refname, sha1, force=force)
-
- # Now let the user edit the commit log message:
- self.git.amend()
-
- def simplify(self, refname, force=False):
- """Simplify this MergeState and save the result to refname.
-
- The merge must be complete before calling this method."""
-
- if self.goal == 'full':
- self.simplify_to_full(refname, force=force)
- elif self.goal == 'rebase':
- self.simplify_to_rebase(refname, force=force)
- elif self.goal == 'rebase-with-history':
- self.simplify_to_rebase_with_history(refname, force=force)
- elif self.goal == 'border':
- self.simplify_to_border(refname, force=force)
- elif self.goal == 'border-with-history':
- self.simplify_to_border(refname, with_history2=True, force=force)
- elif self.goal == 'border-with-history2':
- self.simplify_to_border(
- refname, with_history1=True, with_history2=True, force=force,
- )
- elif self.goal == 'drop':
- self.simplify_to_drop(refname, force=force)
- elif self.goal == 'revert':
- self.simplify_to_revert(refname, force=force)
- elif self.goal == 'merge':
- self.simplify_to_merge(refname, force=force)
- else:
- raise ValueError('Invalid value for goal (%r)' % (self.goal,))
-
- def save(self):
- """Write the current MergeState to the repository."""
-
- blockers = []
- for i2 in range(0, self.len2):
- for i1 in range(0, self.len1):
- record = self[i1, i2]
- if record.is_known():
- record.save(self.git, self.name, i1, i2)
- if record.is_blocked():
- blockers.append((i1, i2))
-
- state = dict(
- version='.'.join(str(i) for i in STATE_VERSION),
- blockers=blockers,
- tip1=self.tip1, tip2=self.tip2,
- goal=self.goal,
- goalopts=self.goalopts,
- manual=self.manual,
- branch=self.branch,
- )
- self.git.write_imerge_state_dict(self.name, state)
-
- def __str__(self):
- return 'MergeState(\'%s\', tip1=\'%s\', tip2=\'%s\', goal=\'%s\')' % (
- self.name, self.tip1, self.tip2, self.goal,
- )
-
-
-def choose_merge_name(git, name):
- names = list(git.iter_existing_imerge_names())
-
- # If a name was specified, try to use it and fail if not possible:
- if name is not None:
- if name not in names:
- raise Failure('There is no incremental merge called \'%s\'!' % (name,))
- if len(names) > 1:
- # Record this as the new default:
- git.set_default_imerge_name(name)
- return name
-
- # A name was not specified. Try to use the default name:
- default_name = git.get_default_imerge_name()
- if default_name:
- if git.check_imerge_exists(default_name):
- return default_name
- else:
- # There's no reason to keep the invalid default around:
- git.set_default_imerge_name(None)
- raise Failure(
- 'Warning: The default incremental merge \'%s\' has disappeared.\n'
- '(The setting imerge.default has been cleared.)\n'
- 'Please try again.'
- % (default_name,)
- )
-
- # If there is exactly one imerge, set it to be the default and use it.
- if len(names) == 1 and git.check_imerge_exists(names[0]):
- return names[0]
-
- raise Failure('Please select an incremental merge using --name')
-
-
-def read_merge_state(git, name=None):
- return MergeState.read(git, choose_merge_name(git, name))
-
-
-def cmd_list(parser, options):
- git = GitRepository()
- names = list(git.iter_existing_imerge_names())
- default_merge = git.get_default_imerge_name()
- if not default_merge and len(names) == 1:
- default_merge = names[0]
- for name in names:
- if name == default_merge:
- sys.stdout.write('* %s\n' % (name,))
- else:
- sys.stdout.write(' %s\n' % (name,))
-
-
-def cmd_init(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
-
- if not options.name:
- parser.error(
- 'Please specify the --name to be used for this incremental merge'
- )
- tip1 = git.get_head_refname(short=True) or 'HEAD'
- tip2 = options.tip2
- try:
- (merge_base, commits1, commits2) = git.get_boundaries(
- tip1, tip2, options.first_parent,
- )
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
-
- merge_state = MergeState.initialize(
- git, options.name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal=options.goal, manual=options.manual,
- branch=(options.branch or options.name),
- )
- merge_state.save()
- if len(list(git.iter_existing_imerge_names())) > 1:
- git.set_default_imerge_name(options.name)
-
-
-def cmd_start(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
-
- if not options.name:
- parser.error(
- 'Please specify the --name to be used for this incremental merge'
- )
- tip1 = git.get_head_refname(short=True) or 'HEAD'
- tip2 = options.tip2
-
- try:
- (merge_base, commits1, commits2) = git.get_boundaries(
- tip1, tip2, options.first_parent,
- )
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
-
- merge_state = MergeState.initialize(
- git, options.name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal=options.goal, manual=options.manual,
- branch=(options.branch or options.name),
- )
- merge_state.save()
- if len(list(git.iter_existing_imerge_names())) > 1:
- git.set_default_imerge_name(options.name)
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- merge_state.request_user_merge(e.i1, e.i2)
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_merge(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
-
- tip2 = options.tip2
-
- if options.name:
- name = options.name
- else:
- # By default, name the imerge after the branch being merged:
- name = tip2
- git.check_imerge_name_format(name)
-
- tip1 = git.get_head_refname(short=True)
- if tip1:
- if not options.branch:
- # See if we can store the result to the checked-out branch:
- try:
- git.check_branch_name_format(tip1)
- except InvalidBranchNameError:
- pass
- else:
- options.branch = tip1
- else:
- tip1 = 'HEAD'
-
- if not options.branch:
- if options.name:
- options.branch = options.name
- else:
- parser.error(
- 'HEAD is not a simple branch. '
- 'Please specify --branch for storing results.'
- )
-
- try:
- (merge_base, commits1, commits2) = git.get_boundaries(
- tip1, tip2, options.first_parent,
- )
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
- except NothingToDoError as e:
- sys.stdout.write('Already up-to-date.\n')
- sys.exit(0)
-
- merge_state = MergeState.initialize(
- git, name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal=options.goal, manual=options.manual,
- branch=options.branch,
- )
- merge_state.save()
- if len(list(git.iter_existing_imerge_names())) > 1:
- git.set_default_imerge_name(name)
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- merge_state.request_user_merge(e.i1, e.i2)
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_rebase(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
-
- tip1 = options.tip1
-
- tip2 = git.get_head_refname(short=True)
- if tip2:
- if not options.branch:
- # See if we can store the result to the current branch:
- try:
- git.check_branch_name_format(tip2)
- except InvalidBranchNameError:
- pass
- else:
- options.branch = tip2
- if not options.name:
- # By default, name the imerge after the branch being rebased:
- options.name = tip2
- else:
- tip2 = git.rev_parse('HEAD')
-
- if not options.name:
- parser.error(
- 'The checked-out branch could not be used as the imerge name.\n'
- 'Please use the --name option.'
- )
-
- if not options.branch:
- if options.name:
- options.branch = options.name
- else:
- parser.error(
- 'HEAD is not a simple branch. '
- 'Please specify --branch for storing results.'
- )
-
- try:
- (merge_base, commits1, commits2) = git.get_boundaries(
- tip1, tip2, options.first_parent,
- )
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
- except NothingToDoError as e:
- sys.stdout.write('Already up-to-date.\n')
- sys.exit(0)
-
- merge_state = MergeState.initialize(
- git, options.name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal=options.goal, manual=options.manual,
- branch=options.branch,
- )
- merge_state.save()
- if len(list(git.iter_existing_imerge_names())) > 1:
- git.set_default_imerge_name(options.name)
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- merge_state.request_user_merge(e.i1, e.i2)
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_drop(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
-
- m = re.match(r'^(?P<start>.*[^\.])(?P<sep>\.{2,})(?P<end>[^\.].*)$', options.range)
- if m:
- if m.group('sep') != '..':
- parser.error(
- 'Range must either be a single commit '
- 'or in the form "commit..commit"'
- )
- start = git.rev_parse(m.group('start'))
- end = git.rev_parse(m.group('end'))
- else:
- end = git.rev_parse(options.range)
- start = git.rev_parse('%s^' % (end,))
-
- try:
- to_drop = git.linear_ancestry(start, end, options.first_parent)
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
-
- # Suppose we want to drop commits 2 and 3 in the branch below.
- # Then we set up an imerge as follows:
- #
- # o - 0 - 1 - 2 - 3 - 4 - 5 - 6 ← tip1
- # |
- # 3⁻¹
- # |
- # 2⁻¹
- #
- # ↑
- # tip2
- #
- # We first use imerge to rebase tip1 onto tip2, then we simplify
- # by discarding the sequence (2, 3, 3⁻¹, 2⁻¹) (which together are
- # a NOOP). In this case, goalopts would have the following
- # contents:
- #
- # goalopts['base'] = rev_parse(commit1)
-
- tip1 = git.get_head_refname(short=True)
- if tip1:
- if not options.branch:
- # See if we can store the result to the current branch:
- try:
- git.check_branch_name_format(tip1)
- except InvalidBranchNameError:
- pass
- else:
- options.branch = tip1
- if not options.name:
- # By default, name the imerge after the branch being rebased:
- options.name = tip1
- else:
- tip1 = git.rev_parse('HEAD')
-
- if not options.name:
- parser.error(
- 'The checked-out branch could not be used as the imerge name.\n'
- 'Please use the --name option.'
- )
-
- if not options.branch:
- if options.name:
- options.branch = options.name
- else:
- parser.error(
- 'HEAD is not a simple branch. '
- 'Please specify --branch for storing results.'
- )
-
- # Create a branch based on end that contains the inverse of the
- # commits that we want to drop. This will be tip2:
-
- git.checkout(end)
- for commit in reversed(to_drop):
- git.revert(commit)
-
- tip2 = git.rev_parse('HEAD')
-
- try:
- (merge_base, commits1, commits2) = git.get_boundaries(
- tip1, tip2, options.first_parent,
- )
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
- except NothingToDoError as e:
- sys.stdout.write('Already up-to-date.\n')
- sys.exit(0)
-
- merge_state = MergeState.initialize(
- git, options.name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal='drop', goalopts={'base' : start},
- manual=options.manual,
- branch=options.branch,
- )
- merge_state.save()
- if len(list(git.iter_existing_imerge_names())) > 1:
- git.set_default_imerge_name(options.name)
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- merge_state.request_user_merge(e.i1, e.i2)
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_revert(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
-
- m = re.match(r'^(?P<start>.*[^\.])(?P<sep>\.{2,})(?P<end>[^\.].*)$', options.range)
- if m:
- if m.group('sep') != '..':
- parser.error(
- 'Range must either be a single commit '
- 'or in the form "commit..commit"'
- )
- start = git.rev_parse(m.group('start'))
- end = git.rev_parse(m.group('end'))
- else:
- end = git.rev_parse(options.range)
- start = git.rev_parse('%s^' % (end,))
-
- try:
- to_revert = git.linear_ancestry(start, end, options.first_parent)
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
-
- # Suppose we want to revert commits 2 and 3 in the branch below.
- # Then we set up an imerge as follows:
- #
- # o - 0 - 1 - 2 - 3 - 4 - 5 - 6 ← tip1
- # |
- # 3⁻¹
- # |
- # 2⁻¹
- #
- # ↑
- # tip2
- #
- # Then we use imerge to rebase tip2 onto tip1.
-
- tip1 = git.get_head_refname(short=True)
- if tip1:
- if not options.branch:
- # See if we can store the result to the current branch:
- try:
- git.check_branch_name_format(tip1)
- except InvalidBranchNameError:
- pass
- else:
- options.branch = tip1
- if not options.name:
- # By default, name the imerge after the branch being rebased:
- options.name = tip1
- else:
- tip1 = git.rev_parse('HEAD')
-
- if not options.name:
- parser.error(
- 'The checked-out branch could not be used as the imerge name.\n'
- 'Please use the --name option.'
- )
-
- if not options.branch:
- if options.name:
- options.branch = options.name
- else:
- parser.error(
- 'HEAD is not a simple branch. '
- 'Please specify --branch for storing results.'
- )
-
- # Create a branch based on end that contains the inverse of the
- # commits that we want to drop. This will be tip2:
-
- git.checkout(end)
- for commit in reversed(to_revert):
- git.revert(commit)
-
- tip2 = git.rev_parse('HEAD')
-
- try:
- (merge_base, commits1, commits2) = git.get_boundaries(
- tip1, tip2, options.first_parent,
- )
- except NonlinearAncestryError as e:
- if options.first_parent:
- parser.error(str(e))
- else:
- parser.error('%s\nPerhaps use "--first-parent"?' % (e,))
- except NothingToDoError as e:
- sys.stdout.write('Already up-to-date.\n')
- sys.exit(0)
-
- merge_state = MergeState.initialize(
- git, options.name, merge_base,
- tip1, commits1,
- tip2, commits2,
- goal='revert',
- manual=options.manual,
- branch=options.branch,
- )
- merge_state.save()
- if len(list(git.iter_existing_imerge_names())) > 1:
- git.set_default_imerge_name(options.name)
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- merge_state.request_user_merge(e.i1, e.i2)
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_remove(parser, options):
- git = GitRepository()
- MergeState.remove(git, choose_merge_name(git, options.name))
-
-
-def cmd_continue(parser, options):
- git = GitRepository()
- merge_state = read_merge_state(git, options.name)
- try:
- merge_state.incorporate_user_merge(edit_log_msg=options.edit)
- except NoManualMergeError:
- pass
- except NotABlockingCommitError as e:
- raise Failure(str(e))
- except ManualMergeUnusableError as e:
- raise Failure(str(e))
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- merge_state.request_user_merge(e.i1, e.i2)
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_record(parser, options):
- git = GitRepository()
- merge_state = read_merge_state(git, options.name)
- try:
- merge_state.incorporate_user_merge(edit_log_msg=options.edit)
- except NoManualMergeError as e:
- raise Failure(str(e))
- except NotABlockingCommitError:
- raise Failure(str(e))
- except ManualMergeUnusableError as e:
- raise Failure(str(e))
-
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- pass
- else:
- sys.stderr.write('Merge is complete!\n')
-
-
-def cmd_autofill(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
- merge_state = read_merge_state(git, options.name)
- with git.temporary_head(message='imerge: restoring'):
- try:
- merge_state.auto_complete_frontier()
- except FrontierBlockedError as e:
- raise Failure(str(e))
-
-
-def cmd_simplify(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
- merge_state = read_merge_state(git, options.name)
- merge_frontier = MergeFrontier.map_known_frontier(merge_state)
- if not merge_frontier.is_complete():
- raise Failure('Merge %s is not yet complete!' % (merge_state.name,))
- refname = 'refs/heads/%s' % ((options.branch or merge_state.branch),)
- if options.goal is not None:
- merge_state.set_goal(options.goal)
- merge_state.save()
- merge_state.simplify(refname, force=options.force)
-
-
-def cmd_finish(parser, options):
- git = GitRepository()
- git.require_clean_work_tree('proceed')
- merge_state = read_merge_state(git, options.name)
- merge_frontier = MergeFrontier.map_known_frontier(merge_state)
- if not merge_frontier.is_complete():
- raise Failure('Merge %s is not yet complete!' % (merge_state.name,))
- refname = 'refs/heads/%s' % ((options.branch or merge_state.branch),)
- if options.goal is not None:
- merge_state.set_goal(options.goal)
- merge_state.save()
- merge_state.simplify(refname, force=options.force)
- MergeState.remove(git, merge_state.name)
-
-
-def cmd_diagram(parser, options):
- git = GitRepository()
- if not (options.commits or options.frontier):
- options.frontier = True
- if not (options.color or (options.color is None and sys.stdout.isatty())):
- AnsiColor.disable()
-
- merge_state = read_merge_state(git, options.name)
- if options.commits:
- merge_state.write(sys.stdout)
- sys.stdout.write('\n')
- if options.frontier:
- merge_frontier = MergeFrontier.map_known_frontier(merge_state)
- merge_frontier.write(sys.stdout)
- sys.stdout.write('\n')
- if options.html:
- merge_frontier = MergeFrontier.map_known_frontier(merge_state)
- html = open(options.html, 'w')
- merge_frontier.write_html(html, merge_state.name)
- html.close()
- sys.stdout.write(
- 'Key:\n'
- )
- if options.frontier:
- sys.stdout.write(
- ' |,-,+ = rectangles forming current merge frontier\n'
- )
- sys.stdout.write(
- ' * = merge done manually\n'
- ' . = merge done automatically\n'
- ' # = conflict that is currently blocking progress\n'
- ' @ = merge was blocked but has been resolved\n'
- ' ? = no merge recorded\n'
- '\n'
- )
-
-
-def reparent_recursively(git, start_commit, parents, end_commit):
- """Change the parents of start_commit and its descendants.
-
- Change start_commit to have the specified parents, and reparent
- all commits on the ancestry path between start_commit and
- end_commit accordingly. Return the replacement end_commit.
- start_commit, parents, and end_commit must all be resolved OIDs.
-
- """
-
- # A map {old_oid : new_oid} keeping track of which replacements
- # have to be made:
- replacements = {}
-
- # Reparent start_commit:
- replacements[start_commit] = git.reparent(start_commit, parents)
-
- for (commit, parents) in git.rev_list_with_parents(
- '--ancestry-path', '--topo-order', '--reverse',
- '%s..%s' % (start_commit, end_commit)
- ):
- parents = [replacements.get(p, p) for p in parents]
- replacements[commit] = git.reparent(commit, parents)
-
- try:
- return replacements[end_commit]
- except KeyError:
- raise ValueError(
- "%s is not an ancestor of %s" % (start_commit, end_commit),
- )
-
-
-def cmd_reparent(parser, options):
- git = GitRepository()
- try:
- commit = git.get_commit_sha1(options.commit)
- except ValueError:
- sys.exit('%s is not a valid commit', options.commit)
-
- try:
- head = git.get_commit_sha1('HEAD')
- except ValueError:
- sys.exit('HEAD is not a valid commit')
-
- try:
- parents = [git.get_commit_sha1(p) for p in options.parents]
- except ValueError as e:
- sys.exit(e.message)
-
- sys.stderr.write('Reparenting %s..HEAD\n' % (options.commit,))
-
- try:
- new_head = reparent_recursively(git, commit, parents, head)
- except ValueError as e:
- sys.exit(e.message)
-
- sys.stdout.write('%s\n' % (new_head,))
-
-
-def main(args):
- NAME_INIT_HELP = 'name to use for this incremental merge'
-
- def add_name_argument(subparser, help=None):
- if help is None:
- subcommand = subparser.prog.split()[1]
- help = 'name of incremental merge to {0}'.format(subcommand)
-
- subparser.add_argument(
- '--name', action='store', default=None, help=help,
- )
-
- def add_goal_argument(subparser, default=DEFAULT_GOAL):
- help = 'the goal of the incremental merge'
- if default is None:
- help = (
- 'the type of simplification to be made '
- '(default is the value provided to "init" or "start")'
- )
- subparser.add_argument(
- '--goal',
- action='store', default=default,
- choices=ALLOWED_GOALS,
- help=help,
- )
-
- def add_branch_argument(subparser):
- subcommand = subparser.prog.split()[1]
- help = 'the name of the branch to which the result will be stored'
- if subcommand in ['simplify', 'finish']:
- help = (
- 'the name of the branch to which to store the result '
- '(default is the value provided to "init" or "start" if any; '
- 'otherwise the name of the merge). '
- 'If BRANCH already exists then it must be able to be '
- 'fast-forwarded to the result unless the --force option is '
- 'specified.'
- )
- subparser.add_argument(
- '--branch',
- action='store', default=None,
- help=help,
- )
-
- def add_manual_argument(subparser):
- subparser.add_argument(
- '--manual',
- action='store_true', default=False,
- help=(
- 'ask the user to complete all merges manually, even when they '
- 'appear conflict-free. This option disables the usual bisection '
- 'algorithm and causes the full incremental merge diagram to be '
- 'completed.'
- ),
- )
-
- def add_first_parent_argument(subparser, default=None):
- subcommand = subparser.prog.split()[1]
- help = (
- 'handle only the first parent commits '
- '(this option is currently required if the history is nonlinear)'
- )
- if subcommand in ['merge', 'rebase']:
- help = argparse.SUPPRESS
- subparser.add_argument(
- '--first-parent', action='store_true', default=default, help=help,
- )
-
- def add_tip2_argument(subparser):
- subparser.add_argument(
- 'tip2', action='store', metavar='branch',
- help='the tip of the branch to be merged into HEAD',
- )
-
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- )
- subparsers = parser.add_subparsers(dest='subcommand', help='sub-command')
-
- subparser = subparsers.add_parser(
- 'start',
- help=(
- 'start a new incremental merge '
- '(equivalent to "init" followed by "continue")'
- ),
- )
- add_name_argument(subparser, help=NAME_INIT_HELP)
- add_goal_argument(subparser)
- add_branch_argument(subparser)
- add_manual_argument(subparser)
- add_first_parent_argument(subparser)
- add_tip2_argument(subparser)
-
- subparser = subparsers.add_parser(
- 'merge',
- help='start a simple merge via incremental merge',
- )
- add_name_argument(subparser, help=NAME_INIT_HELP)
- add_goal_argument(subparser, default='merge')
- add_branch_argument(subparser)
- add_manual_argument(subparser)
- add_first_parent_argument(subparser, default=True)
- add_tip2_argument(subparser)
-
- subparser = subparsers.add_parser(
- 'rebase',
- help='start a simple rebase via incremental merge',
- )
- add_name_argument(subparser, help=NAME_INIT_HELP)
- add_goal_argument(subparser, default='rebase')
- add_branch_argument(subparser)
- add_manual_argument(subparser)
- add_first_parent_argument(subparser, default=True)
- subparser.add_argument(
- 'tip1', action='store', metavar='branch',
- help=(
- 'the tip of the branch onto which the current branch should '
- 'be rebased'
- ),
- )
-
- subparser = subparsers.add_parser(
- 'drop',
- help='drop one or more commits via incremental merge',
- )
- add_name_argument(subparser, help=NAME_INIT_HELP)
- add_branch_argument(subparser)
- add_manual_argument(subparser)
- add_first_parent_argument(subparser, default=True)
- subparser.add_argument(
- 'range', action='store', metavar='[commit | commit..commit]',
- help=(
- 'the commit or range of commits that should be dropped'
- ),
- )
-
- subparser = subparsers.add_parser(
- 'revert',
- help='revert one or more commits via incremental merge',
- )
- add_name_argument(subparser, help=NAME_INIT_HELP)
- add_branch_argument(subparser)
- add_manual_argument(subparser)
- add_first_parent_argument(subparser, default=True)
- subparser.add_argument(
- 'range', action='store', metavar='[commit | commit..commit]',
- help=(
- 'the commit or range of commits that should be reverted'
- ),
- )
-
- subparser = subparsers.add_parser(
- 'continue',
- help=(
- 'record the merge at branch imerge/NAME '
- 'and start the next step of the merge '
- '(equivalent to "record" followed by "autofill" '
- 'and then sets up the working copy with the next '
- 'conflict that has to be resolved manually)'
- ),
- )
- add_name_argument(subparser)
- subparser.set_defaults(edit=None)
- subparser.add_argument(
- '--edit', '-e', dest='edit', action='store_true',
- help='commit staged changes with the --edit option',
- )
- subparser.add_argument(
- '--no-edit', dest='edit', action='store_false',
- help='commit staged changes with the --no-edit option',
- )
-
- subparser = subparsers.add_parser(
- 'finish',
- help=(
- 'simplify then remove a completed incremental merge '
- '(equivalent to "simplify" followed by "remove")'
- ),
- )
- add_name_argument(subparser)
- add_goal_argument(subparser, default=None)
- add_branch_argument(subparser)
- subparser.add_argument(
- '--force',
- action='store_true', default=False,
- help='allow the target branch to be updated in a non-fast-forward manner',
- )
-
- subparser = subparsers.add_parser(
- 'diagram',
- help='display a diagram of the current state of a merge',
- )
- add_name_argument(subparser)
- subparser.add_argument(
- '--commits', action='store_true', default=False,
- help='show the merges that have been made so far',
- )
- subparser.add_argument(
- '--frontier', action='store_true', default=False,
- help='show the current merge frontier',
- )
- subparser.add_argument(
- '--html', action='store', default=None,
- help='generate HTML diagram showing the current merge frontier',
- )
- subparser.add_argument(
- '--color', dest='color', action='store_true', default=None,
- help='draw diagram with colors',
- )
- subparser.add_argument(
- '--no-color', dest='color', action='store_false',
- help='draw diagram without colors',
- )
-
- subparser = subparsers.add_parser(
- 'list',
- help=(
- 'list the names of incremental merges that are currently in progress. '
- 'The active merge is shown with an asterisk next to it.'
- ),
- )
-
- subparser = subparsers.add_parser(
- 'init',
- help='initialize a new incremental merge',
- )
- add_name_argument(subparser, help=NAME_INIT_HELP)
- add_goal_argument(subparser)
- add_branch_argument(subparser)
- add_manual_argument(subparser)
- add_first_parent_argument(subparser)
- add_tip2_argument(subparser)
-
- subparser = subparsers.add_parser(
- 'record',
- help='record the merge at branch imerge/NAME',
- )
- # record:
- add_name_argument(
- subparser,
- help='name of merge to which the merge should be added',
- )
- subparser.set_defaults(edit=None)
- subparser.add_argument(
- '--edit', '-e', dest='edit', action='store_true',
- help='commit staged changes with the --edit option',
- )
- subparser.add_argument(
- '--no-edit', dest='edit', action='store_false',
- help='commit staged changes with the --no-edit option',
- )
-
- subparser = subparsers.add_parser(
- 'autofill',
- help='autofill non-conflicting merges',
- )
- add_name_argument(subparser)
-
- subparser = subparsers.add_parser(
- 'simplify',
- help=(
- 'simplify a completed incremental merge by discarding unneeded '
- 'intermediate merges and cleaning up the ancestry of the commits '
- 'that are retained'
- ),
- )
- add_name_argument(subparser)
- add_goal_argument(subparser, default=None)
- add_branch_argument(subparser)
- subparser.add_argument(
- '--force',
- action='store_true', default=False,
- help='allow the target branch to be updated in a non-fast-forward manner',
- )
-
- subparser = subparsers.add_parser(
- 'remove',
- help='irrevocably remove an incremental merge',
- )
- add_name_argument(subparser)
-
- subparser = subparsers.add_parser(
- 'reparent',
- help=(
- 'change the parents of the specified commit and propagate the '
- 'change to HEAD'
- ),
- )
- subparser.add_argument(
- '--commit', metavar='COMMIT', default='HEAD',
- help=(
- 'target commit to reparent. Create a new commit identical to '
- 'this one, but having the specified parents. Then create '
- 'new versions of all descendants of this commit all the way to '
- 'HEAD, incorporating the modified commit. Output the SHA-1 of '
- 'the replacement HEAD commit.'
- ),
- )
- subparser.add_argument(
- 'parents', nargs='*', metavar='PARENT',
- help='a list of commits',
- )
-
- options = parser.parse_args(args)
-
- # Set an environment variable GIT_IMERGE=1 while we are running.
- # This makes it possible for hook scripts etc. to know that they
- # are being run within git-imerge, and should perhaps behave
- # differently. In the future we might make the value more
- # informative, like GIT_IMERGE=[automerge|autofill|...].
- os.environ[str('GIT_IMERGE')] = str('1')
-
- if options.subcommand == 'list':
- cmd_list(parser, options)
- elif options.subcommand == 'init':
- cmd_init(parser, options)
- elif options.subcommand == 'start':
- cmd_start(parser, options)
- elif options.subcommand == 'merge':
- cmd_merge(parser, options)
- elif options.subcommand == 'rebase':
- cmd_rebase(parser, options)
- elif options.subcommand == 'drop':
- cmd_drop(parser, options)
- elif options.subcommand == 'revert':
- cmd_revert(parser, options)
- elif options.subcommand == 'remove':
- cmd_remove(parser, options)
- elif options.subcommand == 'continue':
- cmd_continue(parser, options)
- elif options.subcommand == 'record':
- cmd_record(parser, options)
- elif options.subcommand == 'autofill':
- cmd_autofill(parser, options)
- elif options.subcommand == 'simplify':
- cmd_simplify(parser, options)
- elif options.subcommand == 'finish':
- cmd_finish(parser, options)
- elif options.subcommand == 'diagram':
- cmd_diagram(parser, options)
- elif options.subcommand == 'reparent':
- cmd_reparent(parser, options)
- else:
- parser.error('Unrecognized subcommand')
-
-
-if __name__ == '__main__':
- try:
- main(sys.argv[1:])
- except Failure as e:
- sys.exit(str(e))
-
-
-# vim: set expandtab ft=python:
diff --git a/bin/hostcert b/bin/hostcert
deleted file mode 100755
index 545167a..0000000
--- a/bin/hostcert
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-host="$1"
-port="${2:-443}"
-
-openssl s_client -connect "$host:$port" < /dev/null 2>/dev/null | perl -nle 'print if /BEGIN CERTIFICATE/../END CERTIFICATE/' | openssl x509 -text | perl -nle 'print unless /BEGIN CERTIFICATE/../END CERTIFICATE/'
diff --git a/bin/hush/p b/bin/hush/p
deleted file mode 100755
index c2cbc9a..0000000
--- a/bin/hush/p
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-pass git ls-files | grep '\.gpg$' | sed 's/\.gpg$//' | fzf | xargs pass "$@"
diff --git a/bin/hush/setup-inputs b/bin/hush/setup-inputs
deleted file mode 100755
index 63d9c5d..0000000
--- a/bin/hush/setup-inputs
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-# key bindings
-setxkbmap -option ctrl:nocaps
-setxkbmap -option compose:caps
-xmodmap "$HOME"/.Xmodmap
-"$(dirname "$0")"/numkeys on
-
-# trackpad settings
-xinput set-prop "SynPS/2 Synaptics TouchPad" "libinput Accel Speed" 0.4
-xinput set-prop "SynPS/2 Synaptics TouchPad" "libinput Tapping Enabled" 1
-
-# needs to happen after xmodmap stuff
-svre xcape
diff --git a/bin/hush/ssh-askpass b/bin/hush/ssh-askpass
deleted file mode 100755
index 8088c8f..0000000
--- a/bin/hush/ssh-askpass
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-exec pass "ssh/$(hostname)"
diff --git a/bin/hush/sudo-askpass b/bin/hush/sudo-askpass
deleted file mode 100755
index 2f487be..0000000
--- a/bin/hush/sudo-askpass
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-exec pass "system/$(hostname)/doy"
diff --git a/bin/hush/svdn b/bin/hush/svdn
deleted file mode 100755
index 6687879..0000000
--- a/bin/hush/svdn
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-svst "$1" || exit 0
-
-svstop "$1"
-svst "$1" || exit 0
-
-sleep 1
-
-svstop "$1"
-for _ in $(seq 1 5); do
- svst "$1" || exit 0
- sleep 1
-done
-svst "$1" || exit 0
-
-svstop "$1"
-for _ in $(seq 1 10); do
- svst "$1" || exit 0
- sleep 1
-done
-svst "$1" || exit 0
-
-svkill "$1"
-svst "$1" || exit 0
-
-exit 1
diff --git a/bin/hush/svget b/bin/hush/svget
deleted file mode 100755
index 0eab9bf..0000000
--- a/bin/hush/svget
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-svstat "$HOME/.services/enabled/$1"
diff --git a/bin/hush/svkill b/bin/hush/svkill
deleted file mode 100755
index a84e1a2..0000000
--- a/bin/hush/svkill
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-svc -k "$HOME/.services/enabled/$1"
-svget "$1"
diff --git a/bin/hush/svlog b/bin/hush/svlog
deleted file mode 100755
index 201ce9b..0000000
--- a/bin/hush/svlog
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-tail -F "$HOME/.log/$1/current" | tai64nlocal
diff --git a/bin/hush/svnuke b/bin/hush/svnuke
deleted file mode 100755
index 309a1d5..0000000
--- a/bin/hush/svnuke
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-svdn "$1"
-svdn "$1/log"
-
-rm -f ~/.services/enabled/"$1"
-
-svc -x ~/.services/available/"$1"/log
-svc -x ~/.services/available/"$1"
diff --git a/bin/hush/svstop b/bin/hush/svstop
deleted file mode 100755
index 649ec26..0000000
--- a/bin/hush/svstop
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-svc -d "$HOME/.services/enabled/$1"
-svget "$1"
diff --git a/bin/hush/svup b/bin/hush/svup
deleted file mode 100755
index 3772fdb..0000000
--- a/bin/hush/svup
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-svc -u "$HOME/.services/enabled/$1"
-svget "$1"
diff --git a/bin/hush/update-mail b/bin/hush/update-mail
deleted file mode 100755
index 8149a8d..0000000
--- a/bin/hush/update-mail
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-stat=$(svstat "$HOME/.services/enabled/offlineimap")
-if echo "$stat" | grep -q "offlineimap: down"; then
- echo "no offlineimap process running" >&2
- exit 1
-fi
-pid=$(echo "$stat" | sed 's/.*offlineimap: up (pid \([[:digit:]]\+\)).*/\1/')
-kill -USR1 "$pid"
diff --git a/bin/hush/volume b/bin/hush/volume
deleted file mode 100755
index a0df2d3..0000000
--- a/bin/hush/volume
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-case $1 in
- up)
- pactl set-sink-mute 0 0
- pactl set-sink-volume 0 +5%
- ;;
- down)
- pactl set-sink-mute 0 0
- pactl set-sink-volume 0 -5%
- ;;
- mute)
- pactl set-sink-mute 0 toggle
- ;;
-esac
diff --git a/bin/hush/watch-kbd b/bin/hush/watch-kbd
deleted file mode 100755
index cbb3824..0000000
--- a/bin/hush/watch-kbd
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-inotifywait -mq -e create -e delete --exclude '.*tmp.*' /dev/input/by-id/ | \
- while read -r event; do
- echo "$event"
- if echo "$event" | grep -q USB_Keyboard; then
- setup-inputs
- fi
- done
diff --git a/bin/hush/wifi b/bin/hush/wifi
deleted file mode 100755
index 38c70ee..0000000
--- a/bin/hush/wifi
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-DEV=wlp3s0
-OPEN=open
-
-if [ -z "${1:-}" ]; then
- if sudo netctl status $OPEN > /dev/null 2>&1; then
- sudo netctl restart $OPEN
- else
- sudo systemctl restart netctl-auto@$DEV
- fi
-else
- case "$1" in
- open)
- if [ -n "${2:-}" ]; then
- sudo sed -i "s/^ESSID=.*/ESSID='${2}'/" "/etc/netctl/${OPEN}"
- fi
-
- if sudo netctl status $OPEN > /dev/null 2>&1; then
- sudo netctl restart $OPEN
- else
- sudo systemctl stop netctl-auto@$DEV
- sudo netctl start $OPEN
- fi
- ;;
- wpa)
- if ! sudo systemctl status netctl-auto@$DEV > /dev/null 2>&1; then
- sudo netctl stop $OPEN
- sudo systemctl start netctl-auto@$DEV
- fi
- ;;
- scan)
- sudo iw dev $DEV scan | grep SSID | perl -nle 's/^.*SSID: //; print unless $seen{$_}++'
- ;;
- esac
-fi
diff --git a/bin/local/.gitignore b/bin/local/.gitignore
deleted file mode 100644
index 120f485..0000000
--- a/bin/local/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!/.gitignore
diff --git a/bin/nopaste b/bin/nopaste
deleted file mode 100755
index 573af2e..0000000
--- a/bin/nopaste
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use 5.020;
-
-use Carp;
-use File::Spec;
-use File::Temp;
-use POSIX 'strftime';
-
-if (@ARGV > 1) {
- croak "can only nopaste one file at a time";
-}
-
-my $date = strftime("%Y-%m-%d", localtime);
-my $template = "${date}-XXXXXXXX";
-my $suffix = @ARGV
- ? "-${\(File::Spec->splitdir($ARGV[0]))[-1]}"
- : undef;
-
-my $contents = do { local $/; <> };
-
-my $tmpfile = File::Temp->new(
- TEMPLATE => $template,
- SUFFIX => $suffix,
- UNLINK => 1,
- TMPDIR => 1,
-);
-my $tmpfilename = $tmpfile->filename;
-
-print $tmpfile $contents or croak "Can't write to $tmpfilename: $!";
-close $tmpfile or croak "Can't write to $tmpfilename: $!";
-chmod 0644 => $tmpfilename;
-
-system('scp', '-pq', $tmpfilename, "tozt.net:paste");
-
-say "https://paste.tozt.net/${\(File::Spec->splitdir($tmpfilename))[-1]}";
diff --git a/bin/pacman-dump b/bin/pacman-dump
deleted file mode 100755
index adc21e7..0000000
--- a/bin/pacman-dump
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-set -eu
-set -o pipefail
-
-echo base
-echo base-devel
-comm -23 <(pacman -Qeq | sort) <(pacman -Qgq base base-devel | sort)
diff --git a/bin/pick-music b/bin/pick-music
deleted file mode 100755
index 8c406f7..0000000
--- a/bin/pick-music
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-lastfm-query sync doyster
-lastfm-query recommend "${1:-20}"
diff --git a/bin/pt b/bin/pt
deleted file mode 100755
index c5ca9b9..0000000
--- a/bin/pt
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-if [ -d blib ]; then
- prove -Mlib::require::all=blib/lib,blib/arch -b "$@" t
-else
- prove -Mlib::require::all=lib -l "$@" t
-fi
diff --git a/bin/rand-music b/bin/rand-music
deleted file mode 100755
index 6e9bccc..0000000
--- a/bin/rand-music
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-if [ "${1:-}" = '--old' ]; then
- extra_args="--exclude yearly --include all"
- shift
-else
- extra_args=
-fi
-
-lastfm-query sync doyster
-lastfm-query recommend --random --album $extra_args "${1:-20}"
diff --git a/bin/ringtone b/bin/ringtone
deleted file mode 100755
index 19dddb6..0000000
--- a/bin/ringtone
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-if [ $# -lt 3 ]; then
- echo "usage: ringtone <input> <output> <fake_video_file>"
- echo "note: fake_video_file is unused, but must be valid"
- echo " and at least the length of the output"
- exit 1
-fi
-
-mencoder \
- -ovc frameno \
- -oac mp3lame \
- -lameopts cbr:br=64 \
- -of rawaudio \
- -o "$2" \
- -audiofile "$1" \
- -endpos 256kb \
- "$3"
diff --git a/bin/scratch b/bin/scratch
deleted file mode 100755
index 06bccb0..0000000
--- a/bin/scratch
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-cat > /dev/null
diff --git a/bin/setfont b/bin/setfont
deleted file mode 100755
index d3e9f2a..0000000
--- a/bin/setfont
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-printf '\e]710;%s\007\e]711;%s\007' "$1" "$1"
diff --git a/bin/st-doy2/power-usage b/bin/st-doy2/power-usage
deleted file mode 100755
index 46d61db..0000000
--- a/bin/st-doy2/power-usage
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use 5.010;
-
-my $power_data = `system_profiler SPPowerDataType`;
-my ($volts) = $power_data =~ /Voltage.*: (.*)/;
-my ($amps) = $power_data =~ /Amperage.*: (.*)/;
-
-printf "%0.2f\n", $volts * $amps / 1000000;
diff --git a/bin/t b/bin/t
deleted file mode 100755
index b6c065a..0000000
--- a/bin/t
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-if [ -d blib ]; then
- perl -Mblib "$@"
-else
- perl -Ilib "$@"
-fi
diff --git a/bin/tozt/learn_spam b/bin/tozt/learn_spam
deleted file mode 100755
index 128ca9a..0000000
--- a/bin/tozt/learn_spam
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-MAILDIR=~/Maildir
-OPTS="--no-sync"
-SALEARN=/usr/bin/vendor_perl/sa-learn
-
-if [ "$1" = "-q" ]; then
- OPTS="$OPTS"
- OUTFILE="/dev/null"
-else
- OPTS="$OPTS --showdots"
- OUTFILE="/dev/stdout"
-fi
-
-if [ ! "$1" = "-q" ]; then
- echo "$(date): Learning ham..."
-fi
-nice find $MAILDIR -type f | \
- perl -nl0e'chomp; ($ts) = /(\d{10})/; $now = time; print if m{/(new|cur)/} && !m{/(\.old|\.spam)/} && $ts > $now - 60*60*24*30' | \
- xargs -n1000 -0 $SALEARN "$OPTS" --ham > $OUTFILE
-
-if [ ! "$1" = "-q" ]; then
- echo "$(date): Learning spam..."
-fi
-nice find $MAILDIR -type f | \
- perl -nl0e'chomp; ($ts) = /(\d{10})/; $now = time; print if m{/(new|cur)/} && m{/\.spam/} && $ts > $now - 60*60*24*30' | \
- xargs -n1000 -0 $SALEARN "$OPTS" --spam > $OUTFILE
-
-if [ ! "$1" = "-q" ]; then
- echo "$(date): Syncing..."
-fi
-nice $SALEARN --sync > $OUTFILE
-
-if [ ! "$1" = "-q" ]; then
- echo "$(date): Done!"
-fi
diff --git a/bin/update-addressbook b/bin/update-addressbook
deleted file mode 100755
index 4683e86..0000000
--- a/bin/update-addressbook
+++ /dev/null
@@ -1,276 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use 5.020;
-use feature 'signatures';
-no warnings 'experimental::signatures';
-
-use Config::INI::Reader;
-use Config::INI::Writer;
-use Email::Address;
-use File::Find;
-
-my @exclude_patterns = (
- # quoted-printable (needs special handling, punting for now)
- sub($address) { $address->format =~ /^=\?/ },
- # automated emails
- sub($address) { $address->address =~ /(mailer-daemon|noreply)/i },
-);
-
-# abook uses # for comments instead of ;
-package Abook::Reader {
- use base 'Config::INI::Reader';
-
- sub preprocess_line($self, $line) {
- ${$line} =~ s/\s+#.*$//g;
- }
-
- sub can_ignore($self, $line, $) {
- return $line =~ /\A\s*(?:#|$)/ ? 1 : 0;
- }
-}
-
-# abook is super finicky about its input format
-package Abook::Writer {
- use base 'Config::INI::Writer';
-
- sub write_handle($self, $input, $handle) {
- print $handle "# abook addressbook file\n\n";
- $self->SUPER::write_handle($input, $handle);
- }
-
- sub preprocess_input($self, $data) {
- my $ini_data = [
- format => {
- program => 'abook',
- version => '0.6.1',
- },
- ];
- my $i = 0;
- for my $name (sort { fc($a) cmp fc($b) } keys %$data) {
- my $person_data = $data->{$name}->as_hashref;
- delete $person_data->{name};
- push @$ini_data, (
- $i++ => [
- name => $name,
- %$person_data,
- ],
- );
- }
-
- $self->SUPER::preprocess_input($ini_data);
- }
-
- sub stringify_value_assignment($self, $name, $value) {
- return '' unless defined $value;
- return $name . '=' . $self->stringify_value($value) . "\n";
- }
-}
-
-package Person {
- sub from_hashref($class, $data) {
- return bless $data, $class;
- }
-
- sub from_email($class, $name, $addresses) {
- return $class->from_hashref({
- name => $name,
- email => join(',', map { $_->address } @$addresses),
- });
- }
-
- sub addresses($self) {
- return split(',', $self->{email} // '');
- }
-
- sub as_hashref($self) {
- return { %$self };
- }
-}
-
-sub existing_people($addressbook) {
- my $data = Abook::Reader->read_file($addressbook);
- delete $data->{format};
-
- my %people;
- for my $id (keys %$data) {
- my $person = $data->{$id};
- $people{$person->{name}} = Person->from_hashref($person);
- }
-
- return %people;
-}
-
-sub maildir_addresses($maildir) {
- my %addresses;
-
- find(sub() {
- open my $fh, '<', $_ or die "couldn't open $_: $!";
- while (<$fh>) {
- last if /^$/;
- next unless /^(?:From|Sender): /;
- for my $address (Email::Address->parse($_)) {
- $address = Email::Address->new(
- $address->name,
- $address->address,
- );
-
- my $name = $address->name;
- my $format = $address->format;
-
- next if $addresses{$name} &&
- grep { $format eq $_ } @{ $addresses{$name} };
- next if grep { $_->($address) } @exclude_patterns;
-
- push @{ $addresses{$name} ||= [] }, $address;
- }
- }
- close $fh;
- }, $maildir);
-
- return %addresses;
-}
-
-sub merge_addresses($old, $new) {
- my %reverse_old = map {
- map { $_->address => $_->name } @$_
- } values %$old;
- my @new_addresses = map {
- map { $_->address } @$_
- } values %$new;
-
- my %seen_address;
- my %reverse_ret;
- for my $new_address (@new_addresses) {
- next if $seen_address{$new_address}++;
-
- my @related_addresses = ($new_address);
- my @related_names;
- while (1) {
- my @new_related_names = map {
- my $cur_address = $_;
- (
- (grep {
- grep {
- fc($_->address) eq fc($cur_address)
- } @{ $new->{$_} }
- } keys %$new),
- (grep {
- grep {
- fc($_->address) eq fc($cur_address)
- } @{ $old->{$_} }
- } keys %$old),
- )
- } @related_addresses;
- @new_related_names = keys(
- %{ { map { $_ => 1 } @new_related_names } }
- );
-
- my @new_related_addresses = map {
- $_->address
- } map {
- (
- (exists $new->{$_}
- ? (@{ $new->{$_} })
- : ()),
- (exists $old->{$_}
- ? (@{ $old->{$_} })
- : ()),
- )
- } @new_related_names;
- @new_related_addresses = keys(
- %{ { map { $_ => 1 } @new_related_addresses } }
- );
-
- last if @related_names == @new_related_names
- && @related_addresses == @new_related_addresses;
-
- @related_addresses = @new_related_addresses;
- @related_names = @new_related_names;
- }
-
- my ($name) = grep { exists $old->{$_} } @related_names;
- $name = (sort @related_names)[0] unless defined $name;
-
- for my $related_address (@related_addresses) {
- $seen_address{$related_address}++;
- $reverse_ret{$related_address} = $name;
- }
- }
-
- %reverse_ret = (%reverse_old, %reverse_ret);
-
- my %ret;
- for my $address (keys %reverse_ret) {
- my $name = $reverse_ret{$address};
- push @{ $ret{$name} ||= [] }, Email::Address->new($name, $address);
- }
-
- for my $name (keys %ret) {
- my %seen_name;
- for my $address (@{ $ret{$name} }) {
- if (defined $seen_name{lc($address->address)}) {
- if (defined $reverse_old{$address->address}) {
- $seen_name{lc($address->address)} = $address;
- }
- }
- else {
- $seen_name{lc($address->address)} = $address;
- }
- }
- $ret{$name} = [ values %seen_name ];
- }
-
- return %ret;
-}
-
-sub merge_people($old, $new) {
- for my $name (keys %$new) {
- if (exists $old->{$name}) {
- my $old_person = $old->{$name};
- my @addresses = $old_person->addresses;
- for my $address ($new->{$name}->addresses) {
- push @addresses, $address
- unless grep { $_ eq $address } @addresses;
- }
-
- $old_person->{email} = join(',', @addresses);
- }
- else {
- $old->{$name} = $new->{$name};
- }
- }
-
- return %$old;
-}
-
-sub main($addressbook, $maildir) {
- die "usage: $0 ADDRESSBOOK MAILDIR" unless @_ == 2;
-
- my %existing_people = existing_people($addressbook);
- my %existing_addresses = map {
- my $name = $_;
- $name => [
- map {
- Email::Address->new($name, $_)
- } $existing_people{$name}->addresses
- ]
- } keys %existing_people;
-
- my %maildir = maildir_addresses($maildir);
-
- my %new_addresses = merge_addresses(\%existing_addresses, \%maildir);
- my %new_people = map {
- $_ => Person->from_email($_, $new_addresses{$_})
- } keys %new_addresses;
-
- my %new_abook = merge_people(\%existing_people, \%new_people);
-
- rename $addressbook => "$addressbook.bak"
- or die "couldn't rename $addressbook: $!";
-
- my $writer = Abook::Writer->new;
- $writer->write_file(\%new_abook, $addressbook);
-}
-
-main(@ARGV);
diff --git a/bin/vimmanpager b/bin/vimmanpager
deleted file mode 100755
index d33e4f9..0000000
--- a/bin/vimmanpager
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-sed -e 's/\x1B\[[[:digit:]]\+m//g' | col -b | \
- vim \
- -c 'let no_plugin_maps = 1' \
- -c 'let g:rainbow_active = 0' \
- -c 'let g:airline#extensions#whitespace#checks = []' \
- -c "if exists('\$MAN_PN') | file \$MAN_PN | endif" \
- -c 'setlocal nolist nomod noswf ft=man' \
- -c 'runtime! macros/less.vim' \
- -c 'set ma' \
- -c 'setlocal noma' \
- -
diff --git a/bin/watch-lock b/bin/watch-lock
deleted file mode 100755
index 8545efc..0000000
--- a/bin/watch-lock
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use 5.020;
-
-use POSIX ":sys_wait_h";
-
-$|++;
-
-my $pid = open my $fh, '-|', (
- 'dbus-monitor',
- '--system',
- 'type=signal,interface=org.freedesktop.login1.Session'
-) or die "couldn't spawn dbus-monitor: $!";
-$SIG{CHLD} = sub {
- while ((my $child = waitpid -1, WNOHANG) > 0) {
- if ($child == $pid) {
- undef $pid;
- }
- }
- exit unless $pid;
-};
-
-sub cleanup {
- kill KILL => $pid if $pid;
- undef $pid;
-}
-
-$SIG{TERM} = $SIG{INT} = sub { cleanup; exit; };
-END { cleanup }
-
-while (<$fh>) {
- if (/\bmember=Lock\b/) {
- system("on-lock") && say "on-lock failed";
- say "LOCK";
- }
-}
diff --git a/bin/weechat-config b/bin/weechat-config
deleted file mode 100755
index b040207..0000000
--- a/bin/weechat-config
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-weechat_fifo="${HOME}/.weechat/weechat_fifo"
-weechat_saved_config="${HOME}/.config/weechat/saved"
-weechat_extra_config="${HOME}/.config/weechat/extra"
-
-die() {
- echo "$@" >&2
- exit 1
-}
-
-weechat() {
- [ -p "$weechat_fifo" ] || die "$weechat_fifo is not a fifo"
- echo "*${1}" >> "$weechat_fifo"
-}
-
-case "$1" in
-save)
- # shellcheck disable=SC2016
- weechat '/fset c:${value_changed} && "${file}.${section}" != "irc.server"'
- weechat "/eval /fset -export ${weechat_saved_config}"
- weechat '/buffer close fset'
- ;;
-restore)
- weechat "/exec -oc grep -h '^/' ${weechat_saved_config} ${weechat_extra_config}"
- ;;
-esac
diff --git a/build b/build
new file mode 100755
index 0000000..7b227c4
--- /dev/null
+++ b/build
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -eu
+
+[ -d "$1" ] || (echo "package $1 not found" >&2; exit 1)
+
+[ -f "$1/Makefile" ] && (cd "$1" && make -s build)
+
+true
diff --git a/clean b/clean
new file mode 100755
index 0000000..10f63dd
--- /dev/null
+++ b/clean
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -eu
+
+[ -d "$1" ] || (echo "package $1 not found" >&2; exit 1)
+
+./uninstall "$1"
+[ -f "$1/Makefile" ] && (cd "$1" && make -s clean)
+
+true
diff --git a/config/alacritty/alacritty.yml.hush b/config/alacritty/alacritty.yml.hush
deleted file mode 100644
index 5f7a5b8..0000000
--- a/config/alacritty/alacritty.yml.hush
+++ /dev/null
@@ -1,167 +0,0 @@
----
-env:
- TERM: alacritty-direct
-
-window:
- dimensions:
- columns: 80
- lines: 24
- padding:
- x: 2
- y: 2
- decorations: full
-
-draw_bold_text_with_bright_colors: true
-
-font:
- normal:
- family: Misc Fixed
- bold:
- family: Misc Fixed
- style: Regular
- italic:
- family: Misc Fixed
- size: 6.0
-
-colors:
- primary:
- background: '0x000000'
- foreground: '0xc1c9d2'
- cursor:
- text: '0x000000'
- cursor: '0x00ff00'
- normal:
- black: '0x000000'
- red: '0xed5f74'
- green: '0x1ea672'
- yellow: '0xd97917'
- blue: '0x688ef1'
- magenta: '0xc96ed0'
- cyan: '0x3a97d4'
- white: '0xe3e8ee'
- bright:
- black: '0x697386'
- red: '0xfbb5b2'
- green: '0x85d996'
- yellow: '0xefc078'
- blue: '0x9fcdff'
- magenta: '0xf0b4e4'
- cyan: '0x7fd3ed'
- white: '0xffffff'
-
-mouse_bindings:
- - { mouse: Middle, action: PasteSelection }
-
-mouse:
- double_click: { threshold: 300 }
- triple_click: { threshold: 300 }
- url:
- launcher: None
-
-selection:
- semantic_escape_chars: " "
-
-key_bindings:
- - { key: V, mods: Control|Shift, action: Paste }
- - { key: C, mods: Control|Shift, action: Copy }
- - { key: Q, mods: Command, action: Quit }
- - { key: W, mods: Command, action: Quit }
- - { key: Insert, mods: Shift, action: PasteSelection }
- - { key: Key0, mods: Control, action: ResetFontSize }
- - { key: Equals, mods: Control, action: IncreaseFontSize }
- - { key: Subtract, mods: Control, action: DecreaseFontSize }
- - { key: Home, chars: "\x1bOH", mode: AppCursor }
- - { key: Home, chars: "\x1b[H", mode: ~AppCursor }
- - { key: End, chars: "\x1bOF", mode: AppCursor }
- - { key: End, chars: "\x1b[F", mode: ~AppCursor }
- - { key: PageUp, mods: Shift, chars: "\x1b[5;2~" }
- - { key: PageUp, mods: Control, chars: "\x1b[5;5~" }
- - { key: PageUp, chars: "\x1b[5~" }
- - { key: PageDown, mods: Shift, chars: "\x1b[6;2~" }
- - { key: PageDown, mods: Control, chars: "\x1b[6;5~" }
- - { key: PageDown, chars: "\x1b[6~" }
- - { key: Tab, mods: Shift, chars: "\x1b[Z" }
- - { key: Back, chars: "\x7f" }
- - { key: Back, mods: Alt, chars: "\x1b\x7f" }
- - { key: Insert, chars: "\x1b[2~" }
- - { key: Delete, chars: "\x1b[3~" }
- - { key: Left, mods: Shift, chars: "\x1b[1;2D" }
- - { key: Left, mods: Control, chars: "\x1b[1;5D" }
- - { key: Left, mods: Alt, chars: "\x1b[1;3D" }
- - { key: Left, chars: "\x1b[D", mode: ~AppCursor }
- - { key: Left, chars: "\x1bOD", mode: AppCursor }
- - { key: Right, mods: Shift, chars: "\x1b[1;2C" }
- - { key: Right, mods: Control, chars: "\x1b[1;5C" }
- - { key: Right, mods: Alt, chars: "\x1b[1;3C" }
- - { key: Right, chars: "\x1b[C", mode: ~AppCursor }
- - { key: Right, chars: "\x1bOC", mode: AppCursor }
- - { key: Up, mods: Shift, chars: "\x1b[1;2A" }
- - { key: Up, mods: Control, chars: "\x1b[1;5A" }
- - { key: Up, mods: Alt, chars: "\x1b[1;3A" }
- - { key: Up, chars: "\x1b[A", mode: ~AppCursor }
- - { key: Up, chars: "\x1bOA", mode: AppCursor }
- - { key: Down, mods: Shift, chars: "\x1b[1;2B" }
- - { key: Down, mods: Control, chars: "\x1b[1;5B" }
- - { key: Down, mods: Alt, chars: "\x1b[1;3B" }
- - { key: Down, chars: "\x1b[B", mode: ~AppCursor }
- - { key: Down, chars: "\x1bOB", mode: AppCursor }
- - { key: F1, chars: "\x1bOP" }
- - { key: F2, chars: "\x1bOQ" }
- - { key: F3, chars: "\x1bOR" }
- - { key: F4, chars: "\x1bOS" }
- - { key: F5, chars: "\x1b[15~" }
- - { key: F6, chars: "\x1b[17~" }
- - { key: F7, chars: "\x1b[18~" }
- - { key: F8, chars: "\x1b[19~" }
- - { key: F9, chars: "\x1b[20~" }
- - { key: F10, chars: "\x1b[21~" }
- - { key: F11, chars: "\x1b[23~" }
- - { key: F12, chars: "\x1b[24~" }
- - { key: F1, mods: Shift, chars: "\x1b[1;2P" }
- - { key: F2, mods: Shift, chars: "\x1b[1;2Q" }
- - { key: F3, mods: Shift, chars: "\x1b[1;2R" }
- - { key: F4, mods: Shift, chars: "\x1b[1;2S" }
- - { key: F5, mods: Shift, chars: "\x1b[15;2~" }
- - { key: F6, mods: Shift, chars: "\x1b[17;2~" }
- - { key: F7, mods: Shift, chars: "\x1b[18;2~" }
- - { key: F8, mods: Shift, chars: "\x1b[19;2~" }
- - { key: F9, mods: Shift, chars: "\x1b[20;2~" }
- - { key: F10, mods: Shift, chars: "\x1b[21;2~" }
- - { key: F11, mods: Shift, chars: "\x1b[23;2~" }
- - { key: F12, mods: Shift, chars: "\x1b[24;2~" }
- - { key: F1, mods: Control, chars: "\x1b[1;5P" }
- - { key: F2, mods: Control, chars: "\x1b[1;5Q" }
- - { key: F3, mods: Control, chars: "\x1b[1;5R" }
- - { key: F4, mods: Control, chars: "\x1b[1;5S" }
- - { key: F5, mods: Control, chars: "\x1b[15;5~" }
- - { key: F6, mods: Control, chars: "\x1b[17;5~" }
- - { key: F7, mods: Control, chars: "\x1b[18;5~" }
- - { key: F8, mods: Control, chars: "\x1b[19;5~" }
- - { key: F9, mods: Control, chars: "\x1b[20;5~" }
- - { key: F10, mods: Control, chars: "\x1b[21;5~" }
- - { key: F11, mods: Control, chars: "\x1b[23;5~" }
- - { key: F12, mods: Control, chars: "\x1b[24;5~" }
- - { key: F1, mods: Alt, chars: "\x1b[1;6P" }
- - { key: F2, mods: Alt, chars: "\x1b[1;6Q" }
- - { key: F3, mods: Alt, chars: "\x1b[1;6R" }
- - { key: F4, mods: Alt, chars: "\x1b[1;6S" }
- - { key: F5, mods: Alt, chars: "\x1b[15;6~" }
- - { key: F6, mods: Alt, chars: "\x1b[17;6~" }
- - { key: F7, mods: Alt, chars: "\x1b[18;6~" }
- - { key: F8, mods: Alt, chars: "\x1b[19;6~" }
- - { key: F9, mods: Alt, chars: "\x1b[20;6~" }
- - { key: F10, mods: Alt, chars: "\x1b[21;6~" }
- - { key: F11, mods: Alt, chars: "\x1b[23;6~" }
- - { key: F12, mods: Alt, chars: "\x1b[24;6~" }
- - { key: F1, mods: Super, chars: "\x1b[1;3P" }
- - { key: F2, mods: Super, chars: "\x1b[1;3Q" }
- - { key: F3, mods: Super, chars: "\x1b[1;3R" }
- - { key: F4, mods: Super, chars: "\x1b[1;3S" }
- - { key: F5, mods: Super, chars: "\x1b[15;3~" }
- - { key: F6, mods: Super, chars: "\x1b[17;3~" }
- - { key: F7, mods: Super, chars: "\x1b[18;3~" }
- - { key: F8, mods: Super, chars: "\x1b[19;3~" }
- - { key: F9, mods: Super, chars: "\x1b[20;3~" }
- - { key: F10, mods: Super, chars: "\x1b[21;3~" }
- - { key: F11, mods: Super, chars: "\x1b[23;3~" }
- - { key: F12, mods: Super, chars: "\x1b[24;3~" }
diff --git a/config/alacritty/alacritty.yml.st-doy2 b/config/alacritty/alacritty.yml.st-doy2
deleted file mode 100644
index 3f7fae1..0000000
--- a/config/alacritty/alacritty.yml.st-doy2
+++ /dev/null
@@ -1,172 +0,0 @@
----
-env:
- TERM: alacritty-direct
-
-window:
- dimensions:
- columns: 80
- lines: 24
- padding:
- x: 2
- y: 2
- decorations: full
-
-draw_bold_text_with_bright_colors: true
-
-font:
- normal:
- family: Menlo
- bold:
- family: Menlo
- style: Regular
- italic:
- family: Menlo
- size: 11.0
- use_thin_strokes: true
-
-colors:
- primary:
- background: '0x000000'
- foreground: '0xc1c9d2'
- cursor:
- text: '0x000000'
- cursor: '0x00ff00'
- normal:
- black: '0x000000'
- red: '0xed5f74'
- green: '0x1ea672'
- yellow: '0xd97917'
- blue: '0x688ef1'
- magenta: '0xc96ed0'
- cyan: '0x3a97d4'
- white: '0xe3e8ee'
- bright:
- black: '0x697386'
- red: '0xfbb5b2'
- green: '0x85d996'
- yellow: '0xefc078'
- blue: '0x9fcdff'
- magenta: '0xf0b4e4'
- cyan: '0x7fd3ed'
- white: '0xffffff'
-
-mouse_bindings:
- - { mouse: Middle, action: PasteSelection }
-
-mouse:
- double_click: { threshold: 300 }
- triple_click: { threshold: 300 }
-
-selection:
- semantic_escape_chars: " "
-
-shell:
- program: login
- args:
- - -fp
- - doy
-
-key_bindings:
- - { key: V, mods: Control|Shift, action: Paste }
- - { key: C, mods: Control|Shift, action: Copy }
- - { key: Q, mods: Command, action: Quit }
- - { key: W, mods: Command, action: Quit }
- - { key: Insert, mods: Shift, action: PasteSelection }
- - { key: Key0, mods: Control, action: ResetFontSize }
- - { key: Equals, mods: Control, action: IncreaseFontSize }
- - { key: Subtract, mods: Control, action: DecreaseFontSize }
- - { key: Home, chars: "\x1bOH", mode: AppCursor }
- - { key: Home, chars: "\x1b[H", mode: ~AppCursor }
- - { key: End, chars: "\x1bOF", mode: AppCursor }
- - { key: End, chars: "\x1b[F", mode: ~AppCursor }
- - { key: PageUp, mods: Shift, chars: "\x1b[5;2~" }
- - { key: PageUp, mods: Control, chars: "\x1b[5;5~" }
- - { key: PageUp, chars: "\x1b[5~" }
- - { key: PageDown, mods: Shift, chars: "\x1b[6;2~" }
- - { key: PageDown, mods: Control, chars: "\x1b[6;5~" }
- - { key: PageDown, chars: "\x1b[6~" }
- - { key: Tab, mods: Shift, chars: "\x1b[Z" }
- - { key: Back, chars: "\x7f" }
- - { key: Back, mods: Alt, chars: "\x1b\x7f" }
- - { key: Insert, chars: "\x1b[2~" }
- - { key: Delete, chars: "\x1b[3~" }
- - { key: Left, mods: Shift, chars: "\x1b[1;2D" }
- - { key: Left, mods: Control, chars: "\x1b[1;5D" }
- - { key: Left, mods: Alt, chars: "\x1b[1;3D" }
- - { key: Left, chars: "\x1b[D", mode: ~AppCursor }
- - { key: Left, chars: "\x1bOD", mode: AppCursor }
- - { key: Right, mods: Shift, chars: "\x1b[1;2C" }
- - { key: Right, mods: Control, chars: "\x1b[1;5C" }
- - { key: Right, mods: Alt, chars: "\x1b[1;3C" }
- - { key: Right, chars: "\x1b[C", mode: ~AppCursor }
- - { key: Right, chars: "\x1bOC", mode: AppCursor }
- - { key: Up, mods: Shift, chars: "\x1b[1;2A" }
- - { key: Up, mods: Control, chars: "\x1b[1;5A" }
- - { key: Up, mods: Alt, chars: "\x1b[1;3A" }
- - { key: Up, chars: "\x1b[A", mode: ~AppCursor }
- - { key: Up, chars: "\x1bOA", mode: AppCursor }
- - { key: Down, mods: Shift, chars: "\x1b[1;2B" }
- - { key: Down, mods: Control, chars: "\x1b[1;5B" }
- - { key: Down, mods: Alt, chars: "\x1b[1;3B" }
- - { key: Down, chars: "\x1b[B", mode: ~AppCursor }
- - { key: Down, chars: "\x1bOB", mode: AppCursor }
- - { key: F1, chars: "\x1bOP" }
- - { key: F2, chars: "\x1bOQ" }
- - { key: F3, chars: "\x1bOR" }
- - { key: F4, chars: "\x1bOS" }
- - { key: F5, chars: "\x1b[15~" }
- - { key: F6, chars: "\x1b[17~" }
- - { key: F7, chars: "\x1b[18~" }
- - { key: F8, chars: "\x1b[19~" }
- - { key: F9, chars: "\x1b[20~" }
- - { key: F10, chars: "\x1b[21~" }
- - { key: F11, chars: "\x1b[23~" }
- - { key: F12, chars: "\x1b[24~" }
- - { key: F1, mods: Shift, chars: "\x1b[1;2P" }
- - { key: F2, mods: Shift, chars: "\x1b[1;2Q" }
- - { key: F3, mods: Shift, chars: "\x1b[1;2R" }
- - { key: F4, mods: Shift, chars: "\x1b[1;2S" }
- - { key: F5, mods: Shift, chars: "\x1b[15;2~" }
- - { key: F6, mods: Shift, chars: "\x1b[17;2~" }
- - { key: F7, mods: Shift, chars: "\x1b[18;2~" }
- - { key: F8, mods: Shift, chars: "\x1b[19;2~" }
- - { key: F9, mods: Shift, chars: "\x1b[20;2~" }
- - { key: F10, mods: Shift, chars: "\x1b[21;2~" }
- - { key: F11, mods: Shift, chars: "\x1b[23;2~" }
- - { key: F12, mods: Shift, chars: "\x1b[24;2~" }
- - { key: F1, mods: Control, chars: "\x1b[1;5P" }
- - { key: F2, mods: Control, chars: "\x1b[1;5Q" }
- - { key: F3, mods: Control, chars: "\x1b[1;5R" }
- - { key: F4, mods: Control, chars: "\x1b[1;5S" }
- - { key: F5, mods: Control, chars: "\x1b[15;5~" }
- - { key: F6, mods: Control, chars: "\x1b[17;5~" }
- - { key: F7, mods: Control, chars: "\x1b[18;5~" }
- - { key: F8, mods: Control, chars: "\x1b[19;5~" }
- - { key: F9, mods: Control, chars: "\x1b[20;5~" }
- - { key: F10, mods: Control, chars: "\x1b[21;5~" }
- - { key: F11, mods: Control, chars: "\x1b[23;5~" }
- - { key: F12, mods: Control, chars: "\x1b[24;5~" }
- - { key: F1, mods: Alt, chars: "\x1b[1;6P" }
- - { key: F2, mods: Alt, chars: "\x1b[1;6Q" }
- - { key: F3, mods: Alt, chars: "\x1b[1;6R" }
- - { key: F4, mods: Alt, chars: "\x1b[1;6S" }
- - { key: F5, mods: Alt, chars: "\x1b[15;6~" }
- - { key: F6, mods: Alt, chars: "\x1b[17;6~" }
- - { key: F7, mods: Alt, chars: "\x1b[18;6~" }
- - { key: F8, mods: Alt, chars: "\x1b[19;6~" }
- - { key: F9, mods: Alt, chars: "\x1b[20;6~" }
- - { key: F10, mods: Alt, chars: "\x1b[21;6~" }
- - { key: F11, mods: Alt, chars: "\x1b[23;6~" }
- - { key: F12, mods: Alt, chars: "\x1b[24;6~" }
- - { key: F1, mods: Super, chars: "\x1b[1;3P" }
- - { key: F2, mods: Super, chars: "\x1b[1;3Q" }
- - { key: F3, mods: Super, chars: "\x1b[1;3R" }
- - { key: F4, mods: Super, chars: "\x1b[1;3S" }
- - { key: F5, mods: Super, chars: "\x1b[15;3~" }
- - { key: F6, mods: Super, chars: "\x1b[17;3~" }
- - { key: F7, mods: Super, chars: "\x1b[18;3~" }
- - { key: F8, mods: Super, chars: "\x1b[19;3~" }
- - { key: F9, mods: Super, chars: "\x1b[20;3~" }
- - { key: F10, mods: Super, chars: "\x1b[21;3~" }
- - { key: F11, mods: Super, chars: "\x1b[23;3~" }
- - { key: F12, mods: Super, chars: "\x1b[24;3~" }
diff --git a/config/darksky/location b/config/darksky/location
deleted file mode 100644
index afd13f2..0000000
--- a/config/darksky/location
+++ /dev/null
@@ -1 +0,0 @@
-10012
diff --git a/config/git/ignore b/config/git/ignore
deleted file mode 100644
index 4491917..0000000
--- a/config/git/ignore
+++ /dev/null
@@ -1,9 +0,0 @@
-# ignore vim swap files
-.*.sw?
-# openoffice lock files
-.~lock.*
-# prove state files
-.prove
-# ctags files
-tags
-tags-ja
diff --git a/config/i3/browser-workspace.json b/config/i3/browser-workspace.json
deleted file mode 100644
index a11fba6..0000000
--- a/config/i3/browser-workspace.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "border": "pixel",
- "floating": "auto_off",
- "geometry": {
- "x": 0,
- "y": 0
- },
- "name": "Firefox",
- "percent": 1,
- "swallows": [
- {
- "class": "^firefox$"
- }
- ],
- "type": "con"
-}
diff --git a/config/i3/signal-workspace.json b/config/i3/signal-workspace.json
deleted file mode 100644
index acac998..0000000
--- a/config/i3/signal-workspace.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "border": "pixel",
- "floating": "auto_off",
- "geometry": {
- "x": 0,
- "y": 0
- },
- "name": "Signal",
- "percent": 1,
- "swallows": [
- {
- "class": "^Signal$"
- }
- ],
- "type": "con"
-}
diff --git a/config/i3status/config b/config/i3status/config
deleted file mode 100644
index 4c2bcdd..0000000
--- a/config/i3status/config
+++ /dev/null
@@ -1,44 +0,0 @@
-general {
- output_format = i3bar
- interval = 1
-}
-
-order += "cpu_usage"
-order += "wireless wlp3s0"
-order += "ethernet enp0s25"
-order += "battery 0"
-order += "battery 1"
-order += "time"
-order += "load"
-
-cpu_usage {
- format = "CPU: %usage"
-}
-
-wireless wlp3s0 {
- format_up = "wlp3s0: (%essid: %quality)"
- format_down = "wlp3s0"
-}
-
-ethernet enp0s25 {
- format_up = "enp0s25: (%speed)"
- format_down = "enp0s25"
-}
-
-battery 0 {
- last_full_capacity = true
- format = "%status %percentage (%remaining %consumption)"
-}
-
-battery 1 {
- last_full_capacity = true
- format = "%status %percentage (%remaining %consumption)"
-}
-
-time {
- format = "%a %b %d %H:%M:%S"
-}
-
-load {
- format = "%1min"
-}
diff --git a/config/karabiner/assets/complex_modifications/command-escape.json b/config/karabiner/assets/complex_modifications/command-escape.json
deleted file mode 100644
index f00158c..0000000
--- a/config/karabiner/assets/complex_modifications/command-escape.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "title": "Map Command to Escape when pressed alone",
- "rules": [
- {
- "description": "Map command to escape",
- "manipulators": [
- {
- "type": "basic",
- "from": {
- "key_code": "left_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "left_command",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "right_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "right_command",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/config/karabiner/assets/complex_modifications/number-row.json b/config/karabiner/assets/complex_modifications/number-row.json
deleted file mode 100644
index f56166b..0000000
--- a/config/karabiner/assets/complex_modifications/number-row.json
+++ /dev/null
@@ -1,390 +0,0 @@
-{
- "title": "Exchange numbers and symbols",
- "rules": [
- {
- "description": "Exchange numbers and symbols (1234567890 and !@#$%^&*())",
- "manipulators": [
- {
- "type": "basic",
- "from": {
- "key_code": "1",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "1",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "2",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "2",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "3",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "3",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "4",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "4",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "5",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "5",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "6",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "6",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "7",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "7",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "8",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "8",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "9",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "9",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "0",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "0",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "1",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "1"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "2",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "2"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "3",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "3"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "4",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "4"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "5",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "5"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "6",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "6"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "7",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "7"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "8",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "8"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "9",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "9"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "0",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "0"
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/config/karabiner/assets/complex_modifications/other-remapping.json b/config/karabiner/assets/complex_modifications/other-remapping.json
deleted file mode 100644
index b817219..0000000
--- a/config/karabiner/assets/complex_modifications/other-remapping.json
+++ /dev/null
@@ -1,200 +0,0 @@
-{
- "title": "Other keyboard remappings",
- "rules": [
- {
- "description": "Other keyboard remappings",
- "manipulators": [
- {
- "type": "basic",
- "from": {
- "key_code": "grave_accent_and_tilde",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "grave_accent_and_tilde",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "grave_accent_and_tilde",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "grave_accent_and_tilde"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "hyphen",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "hyphen",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "hyphen",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "hyphen"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "open_bracket",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "open_bracket",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "open_bracket",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "open_bracket"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "close_bracket",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "close_bracket",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "close_bracket",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "close_bracket"
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "backslash",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "backslash",
- "modifiers": [
- "left_shift"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "backslash",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "backslash"
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/config/karabiner/assets/complex_modifications/terminal-overrides.json b/config/karabiner/assets/complex_modifications/terminal-overrides.json
deleted file mode 100644
index 594d9e6..0000000
--- a/config/karabiner/assets/complex_modifications/terminal-overrides.json
+++ /dev/null
@@ -1,140 +0,0 @@
-{
- "title": "Terminal overrides",
- "rules": [
- {
- "description": "Swap command and control in terminal applications",
- "manipulators": [
- {
- "type": "basic",
- "from": {
- "key_code": "left_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "left_control",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ],
- "conditions": [
- {
- "type": "frontmost_application_if",
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "left_control",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "left_command",
- "lazy": true
- }
- ],
- "conditions": [
- {
- "type": "frontmost_application_if",
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "right_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "right_control",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ],
- "conditions": [
- {
- "type": "frontmost_application_if",
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ]
- }
- ]
- },
- {
- "type": "basic",
- "from": {
- "key_code": "right_control",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "right_command",
- "lazy": true
- }
- ],
- "conditions": [
- {
- "type": "frontmost_application_if",
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ]
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/config/karabiner/karabiner.json b/config/karabiner/karabiner.json
deleted file mode 100644
index 9bf0cbb..0000000
--- a/config/karabiner/karabiner.json
+++ /dev/null
@@ -1,1018 +0,0 @@
-{
- "global": {
- "check_for_updates_on_startup": true,
- "show_in_menu_bar": true,
- "show_profile_name_in_menu_bar": false
- },
- "profiles": [
- {
- "complex_modifications": {
- "parameters": {
- "basic.simultaneous_threshold_milliseconds": 50,
- "basic.to_delayed_action_delay_milliseconds": 500,
- "basic.to_if_alone_timeout_milliseconds": 500,
- "basic.to_if_held_down_threshold_milliseconds": 200
- },
- "rules": [
- {
- "description": "Swap command and control in terminal applications",
- "manipulators": [
- {
- "conditions": [
- {
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ],
- "type": "frontmost_application_if"
- }
- ],
- "from": {
- "key_code": "left_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "left_control",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ],
- "type": "basic"
- },
- {
- "conditions": [
- {
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ],
- "type": "frontmost_application_if"
- }
- ],
- "from": {
- "key_code": "left_control",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "left_command",
- "lazy": true
- }
- ],
- "type": "basic"
- },
- {
- "conditions": [
- {
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ],
- "type": "frontmost_application_if"
- }
- ],
- "from": {
- "key_code": "right_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "right_control",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ],
- "type": "basic"
- },
- {
- "conditions": [
- {
- "bundle_identifiers": [
- "^com\\.apple\\.Terminal$",
- "^com\\.googlecode\\.iterm2$",
- "^co\\.zeit\\.hyperterm$",
- "^co\\.zeit\\.hyper$",
- "^io\\.alacritty$",
- "^net\\.kovidgoyal\\.kitty$"
- ],
- "type": "frontmost_application_if"
- }
- ],
- "from": {
- "key_code": "right_control",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "right_command",
- "lazy": true
- }
- ],
- "type": "basic"
- }
- ]
- },
- {
- "description": "Map command to escape",
- "manipulators": [
- {
- "from": {
- "key_code": "left_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "left_command",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "right_command",
- "modifiers": {
- "optional": [
- "any"
- ]
- }
- },
- "to": [
- {
- "key_code": "right_command",
- "lazy": true
- }
- ],
- "to_if_alone": [
- {
- "key_code": "escape"
- }
- ],
- "type": "basic"
- }
- ]
- },
- {
- "description": "Exchange numbers and symbols (1234567890 and !@#$%^&*())",
- "manipulators": [
- {
- "from": {
- "key_code": "1",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "1",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "2",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "2",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "3",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "3",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "4",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "4",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "5",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "5",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "6",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "6",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "7",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "7",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "8",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "8",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "9",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "9",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "0",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "0",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "1",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "1"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "2",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "2"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "3",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "3"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "4",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "4"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "5",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "5"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "6",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "6"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "7",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "7"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "8",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "8"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "9",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "9"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "0",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "0"
- }
- ],
- "type": "basic"
- }
- ]
- },
- {
- "description": "Other keyboard remappings",
- "manipulators": [
- {
- "from": {
- "key_code": "grave_accent_and_tilde",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "grave_accent_and_tilde",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "grave_accent_and_tilde",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "grave_accent_and_tilde"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "hyphen",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "hyphen",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "hyphen",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "hyphen"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "open_bracket",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "open_bracket",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "open_bracket",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "open_bracket"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "close_bracket",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "close_bracket",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "close_bracket",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "close_bracket"
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "backslash",
- "modifiers": {
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "backslash",
- "modifiers": [
- "left_shift"
- ]
- }
- ],
- "type": "basic"
- },
- {
- "from": {
- "key_code": "backslash",
- "modifiers": {
- "mandatory": [
- "shift"
- ],
- "optional": [
- "caps_lock"
- ]
- }
- },
- "to": [
- {
- "key_code": "backslash"
- }
- ],
- "type": "basic"
- }
- ]
- }
- ]
- },
- "devices": [
- {
- "disable_built_in_keyboard_if_exists": false,
- "fn_function_keys": [],
- "identifiers": {
- "is_keyboard": true,
- "is_pointing_device": false,
- "product_id": 361,
- "vendor_id": 1241
- },
- "ignore": false,
- "manipulate_caps_lock_led": false,
- "simple_modifications": [
- {
- "from": {
- "key_code": "left_command"
- },
- "to": {
- "key_code": "left_option"
- }
- },
- {
- "from": {
- "key_code": "left_option"
- },
- "to": {
- "key_code": "left_command"
- }
- },
- {
- "from": {
- "key_code": "right_command"
- },
- "to": {
- "key_code": "right_option"
- }
- },
- {
- "from": {
- "key_code": "right_option"
- },
- "to": {
- "key_code": "right_command"
- }
- }
- ]
- },
- {
- "disable_built_in_keyboard_if_exists": false,
- "fn_function_keys": [],
- "identifiers": {
- "is_keyboard": true,
- "is_pointing_device": false,
- "product_id": 2082,
- "vendor_id": 6134
- },
- "ignore": false,
- "manipulate_caps_lock_led": false,
- "simple_modifications": [
- {
- "from": {
- "key_code": "left_alt"
- },
- "to": {
- "key_code": "left_command"
- }
- },
- {
- "from": {
- "key_code": "left_gui"
- },
- "to": {
- "key_code": "left_option"
- }
- },
- {
- "from": {
- "key_code": "right_alt"
- },
- "to": {
- "key_code": "right_option"
- }
- },
- {
- "from": {
- "key_code": "right_gui"
- },
- "to": {
- "key_code": "right_command"
- }
- }
- ]
- }
- ],
- "fn_function_keys": [
- {
- "from": {
- "key_code": "f1"
- },
- "to": {
- "consumer_key_code": "mute"
- }
- },
- {
- "from": {
- "key_code": "f2"
- },
- "to": {
- "consumer_key_code": "volume_decrement"
- }
- },
- {
- "from": {
- "key_code": "f3"
- },
- "to": {
- "consumer_key_code": "volume_increment"
- }
- },
- {
- "from": {
- "key_code": "f4"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "key_code": "f5"
- },
- "to": {
- "consumer_key_code": "display_brightness_decrement"
- }
- },
- {
- "from": {
- "key_code": "f6"
- },
- "to": {
- "consumer_key_code": "display_brightness_increment"
- }
- },
- {
- "from": {
- "key_code": "f7"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "key_code": "f8"
- },
- "to": {
- "key_code": "f8"
- }
- },
- {
- "from": {
- "key_code": "f9"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "key_code": "f10"
- },
- "to": {
- "key_code": "f18"
- }
- },
- {
- "from": {
- "key_code": "f11"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "key_code": "f12"
- },
- "to": {
- "key_code": "vk_none"
- }
- }
- ],
- "name": "Default profile",
- "selected": true,
- "simple_modifications": [
- {
- "from": {
- "consumer_key_code": "fastforward"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "consumer_key_code": "play_or_pause"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "consumer_key_code": "rewind"
- },
- "to": {
- "key_code": "vk_none"
- }
- },
- {
- "from": {
- "key_code": "caps_lock"
- },
- "to": {
- "key_code": "fn"
- }
- }
- ],
- "virtual_hid_keyboard": {
- "caps_lock_delay_milliseconds": 0,
- "country_code": 0,
- "keyboard_type": "ansi"
- }
- }
- ]
-}
diff --git a/config/mpd/mpd.conf b/config/mpd/mpd.conf
deleted file mode 100644
index e30c2fc..0000000
--- a/config/mpd/mpd.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-db_file "~/.cache/mpd/mpd.db"
-state_file "~/.cache/mpd/mpd.state"
-playlist_directory "~/.config/mpd/playlists"
-music_directory "~/media/audio/copy"
-bind_to_address "localhost"
diff --git a/config/ncmpcpp/bindings b/config/ncmpcpp/bindings
deleted file mode 100644
index 20a0259..0000000
--- a/config/ncmpcpp/bindings
+++ /dev/null
@@ -1,591 +0,0 @@
-##############################################################
-## This is the example bindings file. Copy it to ##
-## ~/.ncmpcpp/bindings or $XDG_CONFIG_HOME/ncmpcpp/bindings ##
-## and set up your preferences ##
-##############################################################
-##
-##### General rules #####
-##
-## 1) Because each action has runtime checks whether it's
-## ok to run it, a few actions can be bound to one key.
-## Actions will be bound in order given in configuration
-## file. When a key is pressed, first action in order
-## will test itself whether it's possible to run it. If
-## test succeeds, action is executed and other actions
-## bound to this key are ignored. If it doesn't, next
-## action in order tests itself etc.
-##
-## 2) It's possible to bind more that one action at once
-## to a key. It can be done using the following syntax:
-##
-## def_key "key"
-## action1
-## action2
-## ...
-##
-## This creates a chain of actions. When such chain is
-## executed, each action in chain is run until the end of
-## chain is reached or one of its actions fails to execute
-## due to its requirements not being met. If multiple actions
-## and/or chains are bound to the same key, they will be
-## consecutively run until one of them gets fully executed.
-##
-## 3) When ncmpcpp starts, bindings configuration file is
-## parsed and then ncmpcpp provides "missing pieces"
-## of default keybindings. If you want to disable some
-## bindings, there is a special action called 'dummy'
-## for that purpose. Eg. if you want to disable ability
-## to crop playlists, you need to put the following
-## into configuration file:
-##
-## def_key "C"
-## dummy
-##
-## After that ncmpcpp will not bind any default action
-## to this key.
-##
-## 4) To let you write simple macros, the following special
-## actions are provided:
-##
-## - push_character "character" - pushes given special
-## character into input queue, so it will be immediately
-## picked by ncmpcpp upon next call to readKey function.
-## Accepted values: mouse, up, down, page_up, page_down,
-## home, end, space, enter, insert, delete, left, right,
-## tab, ctrl-a, ctrl-b, ..., ctrl-z, ctrl-[, ctrl-\\,
-## ctrl-], ctrl-^, ctrl-_, f1, f2, ..., f12, backspace.
-## In addition, most of these names can be prefixed with
-## alt-/ctrl-/shift- to be recognized with the appropriate
-## modifier key(s).
-##
-## - push_characters "string" - pushes given string into
-## input queue.
-##
-## - require_runnable "action" - checks whether given action
-## is runnable and fails if it isn't. This is especially
-## useful when mixed with previous two functions. Consider
-## the following macro definition:
-##
-## def_key "key"
-## push_characters "custom_filter"
-## apply_filter
-##
-## If apply_filter can't be currently run, we end up with
-## sequence of characters in input queue which will be
-## treated just as we typed them. This may lead to unexpected
-## results (in this case 'c' will most likely clear current
-## playlist, 'u' will trigger database update, 's' will stop
-## playback etc.). To prevent such thing from happening, we
-## need to change above definition to this one:
-##
-## def_key "key"
-## require_runnable "apply_filter"
-## push_characters "custom_filter"
-## apply_filter
-##
-## Here, first we test whether apply_filter can be actually run
-## before we stuff characters into input queue, so if condition
-## is not met, whole chain is aborted and we're fine.
-##
-## - require_screen "screen" - checks whether given screen is
-## currently active. accepted values: browser, clock, help,
-## media_library, outputs, playlist, playlist_editor,
-## search_engine, tag_editor, visualizer, last_fm, lyrics,
-## selected_items_adder, server_info, song_info,
-## sort_playlist_dialog, tiny_tag_editor.
-##
-## - run_external_command "command" - runs given command using
-## system() function.
-##
-## 5) In addition to binding to a key, you can also bind actions
-## or chains of actions to a command. If it comes to commands,
-## syntax is very similar to defining keys. Here goes example
-## definition of a command:
-##
-## def_command "quit" [deferred]
-## stop
-## quit
-##
-## If you execute the above command (which can be done by
-## invoking action execute_command, typing 'quit' and pressing
-## enter), ncmpcpp will stop the player and then quit. Note the
-## presence of word 'deferred' enclosed in square brackets. It
-## tells ncmpcpp to wait for confirmation (ie. pressing enter)
-## after you typed quit. Instead of 'deferred', 'immediate'
-## could be used. Then ncmpcpp will not wait for confirmation
-## (enter) and will execute the command the moment it sees it.
-##
-## Note: while command chains are executed, internal environment
-## update (which includes current window refresh and mpd status
-## update) is not performed for performance reasons. However, it
-## may be desirable to do so in some situration. Therefore it's
-## possible to invoke by hand by performing 'update enviroment'
-## action.
-##
-## Note: There is a difference between:
-##
-## def_key "key"
-## action1
-##
-## def_key "key"
-## action2
-##
-## and
-##
-## def_key "key"
-## action1
-## action2
-##
-## First one binds two single actions to the same key whilst
-## second one defines a chain of actions. The behavior of
-## these two is different and is described in (1) and (2).
-##
-## Note: Function def_key accepts non-ascii characters.
-##
-##### List of unbound actions #####
-##
-## The following actions are not bound to any key/command:
-##
-## - set_volume
-##
-
-def_key "j"
- scroll_down
-
-def_key "k"
- scroll_up
-
-def_key "J"
- move_sort_order_down
-
-def_key "K"
- move_sort_order_up
-
-def_key ">"
- next
-
-def_key "<"
- previous
-
-def_key "up"
- volume_up
-
-def_key "down"
- volume_down
-
-def_key "backspace"
- stop
-
-def_key "space"
- pause
-
-def_key "left"
- seek_backward
-
-def_key "right"
- seek_forward
-
-def_key "p"
- previous_found_item
-
-def_key "n"
- next_found_item
-
-def_key "a"
- add_item_to_playlist
-
-def_key "d"
- delete_playlist_items
-
-def_key "g"
- move_home
-
-def_key "G"
- move_end
-
-#def_key "shift-up"
-# select_item
-# scroll_up
-#
-#def_key "down"
-# scroll_down
-#
-#def_key "shift-down"
-# select_item
-# scroll_down
-#
-#def_key "["
-# scroll_up_album
-#
-#def_key "]"
-# scroll_down_album
-#
-#def_key "{"
-# scroll_up_artist
-#
-#def_key "}"
-# scroll_down_artist
-#
-#def_key "page_up"
-# page_up
-#
-#def_key "page_down"
-# page_down
-#
-#def_key "home"
-# move_home
-#
-#def_key "end"
-# move_end
-#
-#def_key "insert"
-# select_item
-#
-#def_key "enter"
-# enter_directory
-#
-#def_key "enter"
-# toggle_output
-#
-#def_key "enter"
-# run_action
-#
-#def_key "enter"
-# play_item
-#
-#def_key "space"
-# add_item_to_playlist
-#
-#def_key "space"
-# toggle_lyrics_update_on_song_change
-#
-#def_key "space"
-# toggle_visualization_type
-#
-#def_key "delete"
-# delete_playlist_items
-#
-#def_key "delete"
-# delete_browser_items
-#
-#def_key "delete"
-# delete_stored_playlist
-#
-#def_key "right"
-# next_column
-#
-#def_key "right"
-# slave_screen
-#
-#def_key "right"
-# volume_up
-#
-#def_key "+"
-# volume_up
-#
-#def_key "left"
-# previous_column
-#
-#def_key "left"
-# master_screen
-#
-#def_key "left"
-# volume_down
-#
-#def_key "-"
-# volume_down
-#
-#def_key ":"
-# execute_command
-#
-#def_key "tab"
-# next_screen
-#
-#def_key "shift-tab"
-# previous_screen
-#
-#def_key "f1"
-# show_help
-#
-#def_key "1"
-# show_playlist
-#
-#def_key "2"
-# show_browser
-#
-#def_key "2"
-# change_browse_mode
-#
-#def_key "3"
-# show_search_engine
-#
-#def_key "3"
-# reset_search_engine
-#
-#def_key "4"
-# show_media_library
-#
-#def_key "4"
-# toggle_media_library_columns_mode
-#
-#def_key "5"
-# show_playlist_editor
-#
-#def_key "6"
-# show_tag_editor
-#
-#def_key "7"
-# show_outputs
-#
-#def_key "8"
-# show_visualizer
-#
-#def_key "="
-# show_clock
-#
-#def_key "@"
-# show_server_info
-#
-#def_key "s"
-# stop
-#
-#def_key "p"
-# pause
-#
-#def_key ">"
-# next
-#
-#def_key "<"
-# previous
-#
-#def_key "ctrl-h"
-# jump_to_parent_directory
-#
-#def_key "ctrl-h"
-# replay_song
-#
-#def_key "backspace"
-# jump_to_parent_directory
-#
-#def_key "backspace"
-# replay_song
-#
-#def_key "f"
-# seek_forward
-#
-#def_key "b"
-# seek_backward
-#
-#def_key "r"
-# toggle_repeat
-#
-#def_key "z"
-# toggle_random
-#
-#def_key "y"
-# save_tag_changes
-#
-#def_key "y"
-# start_searching
-#
-#def_key "y"
-# toggle_single
-#
-#def_key "R"
-# toggle_consume
-#
-#def_key "Y"
-# toggle_replay_gain_mode
-#
-#def_key "T"
-# toggle_add_mode
-#
-#def_key "|"
-# toggle_mouse
-#
-#def_key "#"
-# toggle_bitrate_visibility
-#
-#def_key "Z"
-# shuffle
-#
-#def_key "x"
-# toggle_crossfade
-#
-#def_key "X"
-# set_crossfade
-#
-#def_key "u"
-# update_database
-#
-#def_key "ctrl-s"
-# sort_playlist
-#
-#def_key "ctrl-s"
-# toggle_browser_sort_mode
-#
-#def_key "ctrl-s"
-# toggle_media_library_sort_mode
-#
-#def_key "ctrl-r"
-# reverse_playlist
-#
-#def_key "ctrl-f"
-# apply_filter
-#
-#def_key "ctrl-_"
-# select_found_items
-#
-#def_key "/"
-# find
-#
-#def_key "/"
-# find_item_forward
-#
-#def_key "?"
-# find
-#
-#def_key "?"
-# find_item_backward
-#
-#def_key "."
-# next_found_item
-#
-#def_key ","
-# previous_found_item
-#
-#def_key "w"
-# toggle_find_mode
-#
-#def_key "e"
-# edit_song
-#
-#def_key "e"
-# edit_library_tag
-#
-#def_key "e"
-# edit_library_album
-#
-#def_key "e"
-# edit_directory_name
-#
-#def_key "e"
-# edit_playlist_name
-#
-#def_key "e"
-# edit_lyrics
-#
-#def_key "i"
-# show_song_info
-#
-#def_key "I"
-# show_artist_info
-#
-#def_key "g"
-# jump_to_position_in_song
-#
-#def_key "l"
-# show_lyrics
-#
-#def_key "ctrl-v"
-# select_range
-#
-#def_key "v"
-# reverse_selection
-#
-#def_key "V"
-# remove_selection
-#
-#def_key "B"
-# select_album
-#
-#def_key "a"
-# add_selected_items
-#
-#def_key "c"
-# clear_playlist
-#
-#def_key "c"
-# clear_main_playlist
-#
-#def_key "C"
-# crop_playlist
-#
-#def_key "C"
-# crop_main_playlist
-#
-#def_key "m"
-# move_sort_order_up
-#
-#def_key "m"
-# move_selected_items_up
-#
-#def_key "n"
-# move_sort_order_down
-#
-#def_key "n"
-# move_selected_items_down
-#
-#def_key "M"
-# move_selected_items_to
-#
-#def_key "A"
-# add
-#
-#def_key "S"
-# save_playlist
-#
-#def_key "o"
-# jump_to_playing_song
-#
-#def_key "G"
-# jump_to_browser
-#
-#def_key "G"
-# jump_to_playlist_editor
-#
-#def_key "~"
-# jump_to_media_library
-#
-#def_key "E"
-# jump_to_tag_editor
-#
-#def_key "U"
-# toggle_playing_song_centering
-#
-#def_key "P"
-# toggle_display_mode
-#
-#def_key "\\"
-# toggle_interface
-#
-#def_key "!"
-# toggle_separators_between_albums
-#
-#def_key "L"
-# toggle_lyrics_fetcher
-#
-#def_key "F"
-# fetch_lyrics_in_background
-#
-#def_key "alt-l"
-# toggle_fetching_lyrics_in_background
-#
-#def_key "ctrl-l"
-# toggle_screen_lock
-#
-#def_key "`"
-# toggle_library_tag_type
-#
-#def_key "`"
-# refetch_lyrics
-#
-#def_key "`"
-# add_random_items
-#
-#def_key "ctrl-p"
-# set_selected_items_priority
-#
-#def_key "q"
-# quit
-#
diff --git a/config/offlineimap/config b/config/offlineimap/config
deleted file mode 100644
index a5531a0..0000000
--- a/config/offlineimap/config
+++ /dev/null
@@ -1,34 +0,0 @@
-[general]
-accounts = main
-maxsyncaccounts = 3
-status_backend = sqlite
-pythonfile = ~/.config/offlineimap/pass.py
-ui = basic
-socktimeout = 120
-
-[Account main]
-localrepository = main-local
-remoterepository = main-remote
-autorefresh = 5
-quick = 10
-postsynchook = notmuch new
-
-[Repository main-local]
-type = Maildir
-localfolders = ~/Maildir
-
-[Repository main-remote]
-type = IMAP
-ssl = yes
-sslcacertfile = /etc/ssl/certs/ca-certificates.crt
-remotehost = mail.tozt.net
-remoteuser = doy@tozt.net
-remotepasseval = get_password("websites/mail.tozt.net/doy@tozt.net")
-maxconnections = 5
-keepalive = 60
-holdconnectionopen = yes
-idlefolders = ['INBOX']
-folderfilter = lambda foldername: not re.search('^old(\.|$)', foldername)
-subscribedonly = no
-
-# vim:ft=dosini:
diff --git a/config/offlineimap/pass.py b/config/offlineimap/pass.py
deleted file mode 100644
index 20ca510..0000000
--- a/config/offlineimap/pass.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from subprocess import Popen, PIPE
-
-def get_password(key):
- (out, err) = Popen(["pass", key], stdout=PIPE).communicate()
- return out.strip()
diff --git a/config/perspektiv/config.toml b/config/perspektiv/config.toml
deleted file mode 100644
index 2204dae..0000000
--- a/config/perspektiv/config.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[window]
-width = 200
-height = 200
-padding = 60
-spacing = 20
-margin_horiz = { anchor = "Right", margin = 860 }
-margin_vert = { anchor = "Top", margin = 440 }
-duration = 1200
-opacity = 70
-
-[percentage]
-show_numeric = true
-
-[boolean]
-show_label = true
diff --git a/config/sh/aliases b/config/sh/aliases
deleted file mode 100644
index 1d2c28f..0000000
--- a/config/sh/aliases
+++ /dev/null
@@ -1,41 +0,0 @@
-# improvements to common commands {{{
-alias ls="exa --group-directories-first --time-style=long-iso --git --color-scale"
-alias ll="ls -l"
-alias grep="grep --color=auto"
-alias rm="rm -i"
-alias cp="cp -i"
-alias mv="mv -i"
-alias bc="bc -lq"
-alias ag="ag --pager=less --smart-case"
-type forkprove > /dev/null 2>&1 && alias prove="forkprove"
-type tput > /dev/null 2>&1 && alias reset="tput reset"
-# }}}
-# games {{{
-alias nao="env TERM=rxvt telnet nethack.alt.org"
-alias cao="env TERM=rxvt /usr/bin/ssh -C -i \$HOME/.ssh/cao_key joshua@crawl.akrasiac.org"
-alias cdo="ssh -C -i \$HOME/.ssh/cao_key crawl@crawl.develz.org"
-# }}}
-# termcast {{{
-alias tc="telnet termcast.org"
-# }}}
-# shells {{{
-alias partofme='ssh doy@partofme'
-alias tozt="ssh doy@tozt.net"
-# }}}
-# tmux sessions {{{
-alias main='tmux new -As main'
-alias chat='tmux new -As chat'
-alias work='tmux new -As work'
-alias docs='tmux new -As docs'
-alias misc='tmux new -As misc'
-# }}}
-# other {{{
-alias pm="find lib -type f"
-alias v="vim --cmd 'let g:startify_disable_at_vimenter = 1' -c 'call feedkeys(\"t\")'"
-alias g="vim --cmd 'let g:startify_disable_at_vimenter = 1' -c 'call feedkeys(\"ff\")'"
-alias utc="env TZ=UTC date"
-alias pd="perldoc"
-alias pc="p -c"
-# }}}
-
-# vim:ft=sh:fdm=marker
diff --git a/config/sh/cdhist.sh b/config/sh/cdhist.sh
deleted file mode 100644
index d67d2e9..0000000
--- a/config/sh/cdhist.sh
+++ /dev/null
@@ -1,174 +0,0 @@
-### cdhist.sh
-###
-### Copyright (c) 2001 Yusuke Shinyama <yusuke at cs . nyu . edu>
-###
-### Permission to use, copy, modify, distribute this software and
-### its documentation for any purpose is hereby granted, provided
-### that existing copyright notices are retained in all copies and
-### that this notice is included verbatim in any distributions.
-### This software is provided ``AS IS'' without any express or implied
-### warranty.
-###
-
-### WARNING: THIS SCRIPT IS FOR GNU BASH ONLY!
-
-### What is this?
-###
-### Cdhist adds 'web-browser like history' to your bash shell.
-### Every time you change the current directory it records the directory
-### you can go back by simply typing a short command such as '-' or '+',
-### just like clicking web-browsers's 'back' button.
-### It's more convenient than using directory stacks when
-### you walk around two or three directories.
-###
-
-### Usage
-###
-### Just call this file from your .bashrc script.
-### The following commands are added.
-###
-### cd [pathname]
-### Go to the given directory, or your home directory if
-### pathname is omitted. This overrides the original command.
-### You can use it by typing '\cd'.
-###
-### + [n]
-### 'Forward' button. Go to the n'th posterior directory in the history.
-### Go to the next directory if the number is omitted.
-###
-### - [n]
-### 'Back' button. Go to the n'th prior directory in the history.
-### Go to the previous directory if the number is omitted.
-###
-### = [n]
-### Show histories with directory numbers.
-###
-### A directory number shows the index to the current directory
-### in the history. The current directory always has directory number 0.
-### For prior directories, a negative number is given.
-### For posterior directories, a positive number is given.
-###
-### cdhist_reset
-### Clear the cd history.
-###
-
-### Example
-###
-### /home/yusuke:$ . cdhist.sh
-### /home/yusuke:$ cd /tmp
-### /tmp:$ cd /usr/bin
-### /usr/bin:$ cd /etc
-### /etc:$ -
-### /usr/bin:$ -
-### /tmp:$ +
-### /usr/bin:$ =
-### -2 ~
-### -1 /tmp
-### 0:/usr/bin
-### 1 /etc
-### /usr/bin:$ - 2
-### /home/yusuke:$
-###
-
-
-CDHIST_CDQMAX=10
-declare -a CDHIST_CDQ
-
-function cdhist_reset {
- CDHIST_CDQ=("$PWD")
-}
-
-function cdhist_disp {
- echo "$*" | sed "s $HOME ~ g"
-}
-
-function cdhist_add {
- CDHIST_CDQ=("$1" "${CDHIST_CDQ[@]}")
-}
-
-function cdhist_del {
- [[ -n $ZSH_VERSION ]] && setopt localoptions && setopt ksharrays
- local i=${1-0}
- if [ ${#CDHIST_CDQ[@]} -le 1 ]; then return; fi
- for ((; i<${#CDHIST_CDQ[@]}-1; i++)); do
- CDHIST_CDQ[$i]="${CDHIST_CDQ[$((i+1))]}"
- done
- unset CDHIST_CDQ[$i]
-}
-
-function cdhist_rot {
- [[ -n $ZSH_VERSION ]] && setopt localoptions && setopt ksharrays
- local i q
- declare -a q
- for ((i=0; i<$1; i++)); do
- q[$i]="${CDHIST_CDQ[$(((i+$1+$2)%$1))]}"
- done
- for ((i=0; i<$1; i++)); do
- CDHIST_CDQ[$i]="${q[$i]}"
- done
-}
-
-function cdhist_cd {
- [[ -n $ZSH_VERSION ]] && setopt localoptions && setopt ksharrays
- local i f=0
- builtin cd "$@" || return 1
- for ((i=0; i<${#CDHIST_CDQ[@]}; i++)); do
- if [ "${CDHIST_CDQ[$i]}" = "$PWD" ]; then f=1; break; fi
- done
- if [ $f -eq 1 ]; then
- cdhist_rot $((i+1)) -1
- elif [ ${#CDHIST_CDQ[@]} -lt $CDHIST_CDQMAX ]; then
- cdhist_add "$PWD"
- else
- cdhist_rot ${#CDHIST_CDQ[@]} -1
- CDHIST_CDQ[0]="$PWD"
- fi
-}
-
-function cdhist_history {
- [[ -n $ZSH_VERSION ]] && setopt localoptions && setopt ksharrays
- local i d
- if [ $# -eq 0 ]; then
- for ((i=${#CDHIST_CDQ[@]}-1; 0<=i; i--)); do
- cdhist_disp " $i ${CDHIST_CDQ[$i]}"
- done
- elif [ "$1" -lt ${#CDHIST_CDQ[@]} ]; then
- d=${CDHIST_CDQ[$1]}
- if builtin cd "$d"; then
- cdhist_rot $(($1+1)) -1
- else
- cdhist_del $1
- fi
- cdhist_disp "${CDHIST_CDQ[@]}"
- fi
-}
-
-function cdhist_forward {
- [[ -n $ZSH_VERSION ]] && setopt localoptions && setopt ksharrays
- cdhist_rot ${#CDHIST_CDQ[@]} -${1-1}
- if ! builtin cd "${CDHIST_CDQ[0]}"; then
- cdhist_del 0
- fi
- cdhist_disp "${CDHIST_CDQ[@]}"
-}
-
-function cdhist_back {
- [[ -n $ZSH_VERSION ]] && setopt localoptions && setopt ksharrays
- cdhist_rot ${#CDHIST_CDQ[@]} ${1-1}
- if ! builtin cd "${CDHIST_CDQ[0]}"; then
- cdhist_del 0
- fi
- cdhist_disp "${CDHIST_CDQ[@]}"
-}
-
-
-if [ ${#CDHIST_CDQ[@]} = 0 ]; then cdhist_reset; fi
-
-
-### Aliases
-###
-
-function cd { cdhist_cd "$@"; }
-function + { cdhist_forward "$@"; }
-function - { cdhist_back "$@"; }
-function = { cdhist_history "$@"; }
diff --git a/config/sh/env b/config/sh/env
deleted file mode 100644
index 1b6d7da..0000000
--- a/config/sh/env
+++ /dev/null
@@ -1,26 +0,0 @@
-GPG_TTY=$(tty)
-export GPG_TTY
-export MANPAGER="$HOME/.bin/vimmanpager"
-export PERLDOC_PAGER="$HOME/.bin/vimmanpager"
-EDITOR=$(command -v vim)
-export EDITOR
-ssh="${HOME}/.bin/$(hostname)/ssh"
-if [ -x "$ssh" ]; then
- export GIT_SSH="$ssh"
- export RSYNC_RSH="$ssh"
-fi
-if type sudo-askpass > /dev/null 2>&1; then
- SUDO_ASKPASS=$(command -v sudo-askpass)
- export SUDO_ASKPASS
-fi
-export TEXINPUTS=".:$HOME/.config/tex:"
-export LESS='-QR'
-export PERL_CPANM_OPT="-q --mirror http://mirrors.kernel.org/cpan/ --mirror http://cpan.metacpan.org/ --prompt"
-export FZF_DEFAULT_OPTS="--reverse --inline-info --bind=tab:down,shift-tab:up,change:top"
-export FZF_DEFAULT_COMMAND="ag --hidden -l ."
-export FANCY_PROMPT_COLORS="user_doy=bright_blue,host_st-doy2=bright_white,host_tozt=bright_yellow,host_hush=bright_black,host_partofme=magenta,host_mail=green"
-export PASSWORD_STORE_X_SELECTION=primary
-type brew > /dev/null 2>&1 && export PATH="/usr/local/opt/coreutils/libexec/gnubin:/usr/local/opt/findutils/libexec/gnubin:/usr/local/sbin:$PATH"
-type brew > /dev/null 2>&1 && export MANPATH="/usr/local/opt/coreutils/libexec/gnuman:/usr/local/opt/findutils/libexec/gnuman:$MANPATH"
-
-# vim:ft=sh:
diff --git a/config/sh/functions b/config/sh/functions
deleted file mode 100644
index a662f2d..0000000
--- a/config/sh/functions
+++ /dev/null
@@ -1,20 +0,0 @@
-function perldoc {
- # XXX bash specific
- if type cpandoc > /dev/null 2>&1; then
- cpandoc "$@"
- else
- command perldoc "$@"
- fi
-}
-
-function cdu {
- local root
- root="$(git rev-parse --show-superproject-working-tree 2>/dev/null)"
- if [ -n "$root" ]; then
- cd "$root" || return
- else
- cd "$(git rev-parse --show-toplevel)" || return
- fi
-}
-
-# vim:ft=sh:
diff --git a/config/sh/fzf b/config/sh/fzf
deleted file mode 160000
-Subproject 65773882505b06970c47285b4ace6208ac5e614
diff --git a/config/touchegg/touchegg.conf b/config/touchegg/touchegg.conf
deleted file mode 100644
index 9d58335..0000000
--- a/config/touchegg/touchegg.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-<touchégg>
-
- <settings>
- <property name="composed_gestures_time">0</property>
- </settings>
-
-
- <application name="All">
-
- <gesture type="DRAG" fingers="1" direction="ALL">
- <action type="SCROLL">SPEED=7:INVERTED=true</action>
- </gesture>
-
- </application>
-
-</touchégg>
diff --git a/config/weechat/extra b/config/weechat/extra
deleted file mode 100644
index 9d0cc4a..0000000
--- a/config/weechat/extra
+++ /dev/null
@@ -1,24 +0,0 @@
-/bar del buflist
-/alias add w /buffer
-/filter add irc_smart * irc_smart_filter *
-/key bind ctrl-W /buffer close
-/key bind meta-! /buffer *1
-/key bind meta-@ /buffer *2
-/key bind meta-# /buffer *3
-/key bind meta-$ /buffer *4
-/key bind meta-% /buffer *5
-/key bind meta-^ /buffer *6
-/key bind meta-& /buffer *7
-/key bind meta-* /buffer *8
-/key bind meta-( /buffer *9
-/key bind meta-) /buffer *10
-/key bind meta-q /buffer *11
-/key bind meta-w /buffer *12
-/key bind meta-e /buffer *13
-/key bind meta-r /buffer *14
-/key bind meta-t /buffer *15
-/key bind meta-y /buffer *16
-/key bind meta-u /buffer *17
-/key bind meta-i /buffer *18
-/key bind meta-o /buffer *19
-/key bind meta-p /buffer *20
diff --git a/config/weechat/saved b/config/weechat/saved
deleted file mode 100644
index 7452c56..0000000
--- a/config/weechat/saved
+++ /dev/null
@@ -1,263 +0,0 @@
-# default dictionary (or comma separated list of dictionaries) to use when buffer has no dictionary defined (leave blank to disable aspell on buffers for which you didn't explicitly enabled it)
-/set aspell.check.default_dict "en"
-
-# background color for current buffer
-/set buffers.color.current_bg default
-
-# default foreground color for buffer name
-/set buffers.color.default_fg darkgray
-
-# change foreground color of buffer name if a highlight messaged received
-/set buffers.color.hotlist_highlight_fg lightmagenta
-
-# change foreground color of buffer name if a low message received
-/set buffers.color.hotlist_low_fg cyan
-
-# change foreground color of buffer name if a normal message received
-/set buffers.color.hotlist_message_fg white
-
-# foreground color for none channel buffer (e.g.: core/server/plugin buffer)
-/set buffers.color.none_channel_fg darkgray
-
-# hide merged buffers. The value determines which merged buffers should be hidden, keepserver meaning 'all except server buffers'. Other values correspondent to the buffer type.
-/set buffers.look.hide_merged_buffers server
-
-# contains an optional char(s) that is appended when buffer name is shortened
-/set buffers.look.name_crop_suffix ""
-
-# maximum size of buffer name. 0 means no limitation
-/set buffers.look.name_size_max 3
-
-# display a char behind channel number
-/set buffers.look.number_char ""
-
-# color for nick in input bar
-/set irc.color.input_nick white
-
-# color for channel modes, near channel name
-/set irc.color.item_channel_modes darkgray
-
-# color for text in join messages
-/set irc.color.message_join darkgray
-
-# color for text in part/quit messages
-/set irc.color.message_quit darkgray
-
-# color for text "Notice" in notices
-/set irc.color.notice darkgray
-
-# color for reason in part/quit messages
-/set irc.color.reason_quit darkgray
-
-# color for old channel topic (when topic is changed)
-/set irc.color.topic_old darkgray
-
-# comma separated list of words to highlight in channel buffers (case insensitive, use "(?-i)" at beginning of words to make them case sensitive; special variables $nick, $channel and $server are replaced by their value), these words are added to buffer property "highlight_words" only when buffer is created (it does not affect current buffers), an empty string disables default highlight on nick, examples: "$nick", "(?-i)$nick"
-/set irc.look.highlight_channel "$nick,doy,doyster,@doyster,thedoyster,jesse"
-
-# interval between two checks for lag (in seconds, 0 = never check)
-/set irc.network.lag_check 5
-
-# minimum lag to show (in milliseconds)
-/set irc.network.lag_min_show 4000
-
-# reconnect to server if lag is greater than or equal to this value (in seconds, 0 = never reconnect); this value must be less than or equal to irc.network.lag_max
-/set irc.network.lag_reconnect 10
-
-# nicknames to use on server (separated by comma) (note: content is evaluated, see /help eval; server options are evaluated with ${irc_server.xxx} and ${server} is replaced by the server name)
-/set irc.server_default.nicks "doy,doy1,doy2,doy3,doy4"
-
-# user name to use on server (note: content is evaluated, see /help eval; server options are evaluated with ${irc_server.xxx} and ${server} is replaced by the server name)
-/set irc.server_default.username "doy"
-
-# color for line ending the backlog
-/set logger.color.backlog_end darkgray
-
-# color for backlog lines
-/set logger.color.backlog_line darkgray
-
-# default file name mask for log files (format is "directory/to/file" or "file", without first "/" because "path" option is used to build complete path to file); local buffer variables are permitted (you should use only variables that are defined on all buffers, so for example you should NOT use $server nor $channel); date specifiers are permitted (see man strftime)
-/set logger.file.mask "$server/$channel-%Y-%m.log"
-
-# path for WeeChat log files; "%h" at beginning of string is replaced by WeeChat home ("~/.weechat" by default); date specifiers are permitted (see man strftime) (note: content is evaluated, see /help eval)
-/set logger.file.path "~/irclogs/"
-
-# command for beep on dcc, special value "$bell" is allowed, as well as "$bell;command" (default: "$bell")
-/set plugins.var.perl.beep.beep_command_dcc "$bell"
-
-# command for beep on highlight, special value "$bell" is allowed, as well as "$bell;command" (default: "$bell")
-/set plugins.var.perl.beep.beep_command_highlight "$bell"
-
-# command for beep on private message, special value "$bell" is allowed, as well as "$bell;command" (default: "$bell")
-/set plugins.var.perl.beep.beep_command_pv "$bell"
-
-# timeout for command run (in milliseconds, 0 = never kill (not recommended)) (default: "30000")
-/set plugins.var.perl.beep.beep_command_timeout "30000"
-
-# beep on dcc (default: "on")
-/set plugins.var.perl.beep.beep_dcc "on"
-
-# beep on highlight (default: "on")
-/set plugins.var.perl.beep.beep_highlight "on"
-
-# turn blacklist for highlights on or off (default: "off")
-/set plugins.var.perl.beep.beep_highlight_blacklist "off"
-
-# turn whitelist for highlights on or off (default: "off")
-/set plugins.var.perl.beep.beep_highlight_whitelist "off"
-
-# beep on private message (default: "on")
-/set plugins.var.perl.beep.beep_pv "on"
-
-# turn blacklist for private messages on or off (default: "off")
-/set plugins.var.perl.beep.beep_pv_blacklist "off"
-
-# turn whitelist for private messages on or off (default: "off")
-/set plugins.var.perl.beep.beep_pv_whitelist "off"
-
-# (no description)
-/set plugins.var.perl.chanmon.alignment "schannel"
-
-# (no description)
-/set plugins.var.perl.chanmon.bar_lines "2"
-
-# (no description)
-/set plugins.var.perl.chanmon.color_buf "on"
-
-# (no description)
-/set plugins.var.perl.chanmon.dynamic "off"
-
-# (no description)
-/set plugins.var.perl.chanmon.logging "off"
-
-# (no description)
-/set plugins.var.perl.chanmon.merge_private "on"
-
-# (no description)
-/set plugins.var.perl.chanmon.nick_prefix "<"
-
-# (no description)
-/set plugins.var.perl.chanmon.nick_suffix ">"
-
-# (no description)
-/set plugins.var.perl.chanmon.output "bar"
-
-# (no description)
-/set plugins.var.perl.chanmon.short_names "on"
-
-# (no description)
-/set plugins.var.perl.chanmon.show_aways "off"
-
-# (no description)
-/set plugins.var.perl.chatters.frame_color "red"
-
-# (no description)
-/set plugins.var.perl.chatters.nick_color "yellow"
-
-# (no description)
-/set plugins.var.perl.chatters.nick_timeout "600"
-
-# text color of delimiters in script buffer
-/set script.color.text_delimiters darkgray
-
-# true if bar is hidden, false if it is displayed
-/set weechat.bar.buffers.hidden off
-
-# items of bar, they can be separated by comma (space between items) or "+" (glued items); special syntax "@buffer:item" can be used to force buffer used when displaying the bar item
-/set weechat.bar.buffers.items "buffers"
-
-# items of bar, they can be separated by comma (space between items) or "+" (glued items); special syntax "@buffer:item" can be used to force buffer used when displaying the bar item
-/set weechat.bar.chanmon.items "chanmon"
-
-# items of bar, they can be separated by comma (space between items) or "+" (glued items); special syntax "@buffer:item" can be used to force buffer used when displaying the bar item
-/set weechat.bar.fset.items "fset"
-
-# items of bar, they can be separated by comma (space between items) or "+" (glued items); special syntax "@buffer:item" can be used to force buffer used when displaying the bar item
-/set weechat.bar.nicklist.items "chatters,buffer_nicklist"
-
-# items of bar, they can be separated by comma (space between items) or "+" (glued items); special syntax "@buffer:item" can be used to force buffer used when displaying the bar item
-/set weechat.bar.status.items "[time],[buffer_plugin],buffer_number+:+buffer_name+{buffer_nicklist_count}+buffer_filter,[lag],completion,scroll"
-
-# text color for channel names
-/set weechat.color.chat_channel darkgray
-
-# text color for delimiters
-/set weechat.color.chat_delimiters darkgray
-
-# background color for highlighted prefix
-/set weechat.color.chat_highlight_bg default
-
-# text color for hostnames
-/set weechat.color.chat_host darkgray
-
-# text color for chat when line is inactive (buffer is merged with other buffers and is not selected)
-/set weechat.color.chat_inactive_buffer darkgray
-
-# text color for chat when window is inactive (not current selected window)
-/set weechat.color.chat_inactive_window darkgray
-
-# text color for nicks in chat window: used in some server messages and as fallback when a nick color is not found; most of times nick color comes from option weechat.color.chat_nick_colors
-/set weechat.color.chat_nick darkgray
-
-# text color for nicks (comma separated list of colors, background is allowed with format: "fg:bg", for example: "lightred:blue")
-/set weechat.color.chat_nick_colors "cyan,magenta,green,brown,red,blue"
-
-# text color for offline nick (not in nicklist any more); this color is used only if option weechat.look.color_nick_offline is enabled
-/set weechat.color.chat_nick_offline darkgray
-
-# background color for offline nick with highlight; this color is used only if option weechat.look.color_nick_offline is enabled
-/set weechat.color.chat_nick_offline_highlight_bg darkgray
-
-# color for nick prefix (string displayed before nick in prefix)
-/set weechat.color.chat_nick_prefix black
-
-# color for nick suffix (string displayed after nick in prefix)
-/set weechat.color.chat_nick_suffix black
-
-# text color for inactive buffer name (before prefix, when many buffers are merged with same number and if buffer is not selected)
-/set weechat.color.chat_prefix_buffer_inactive_buffer darkgray
-
-# text color for join prefix
-/set weechat.color.chat_prefix_join darkgray
-
-# text color for network prefix
-/set weechat.color.chat_prefix_network darkgray
-
-# text color for quit prefix
-/set weechat.color.chat_prefix_quit darkgray
-
-# text color for unread data marker
-/set weechat.color.chat_read_marker darkgray
-
-# text color for time delimiters
-/set weechat.color.chat_time_delimiters default
-
-# default notify level for buffers (used to tell WeeChat if buffer must be displayed in hotlist or not, according to importance of message): all=all messages (default), message=messages+highlights, highlight=highlights only, none=never display in hotlist
-/set weechat.look.buffer_notify_default message
-
-# if set, uses real white color, disabled by default for terms with white background (if you never use white background, you should turn on this option to see real white instead of default term foreground color)
-/set weechat.look.color_real_white on
-
-# comma separated list of tags to highlight; case insensitive comparison; wildcard "*" is allowed in each tag; many tags can be separated by "+" to make a logical "and" between tags; examples: "nick_flashcode" for messages from nick "FlashCode", "irc_notice+nick_toto*" for notices from a nick starting with "toto"
-/set weechat.look.highlight_tags "notify_private"
-
-# level for displaying names in hotlist (combination of: 1=join/part, 2=message, 4=private, 8=highlight, for example: 12=private+highlight)
-/set weechat.look.hotlist_names_level 14
-
-# text to display before nick in prefix of message, example: "<"
-/set weechat.look.nick_prefix "<"
-
-# text to display after nick in prefix of message, example: ">"
-/set weechat.look.nick_suffix ">"
-
-# string displayed after prefix
-/set weechat.look.prefix_suffix ""
-
-# string used to draw read marker line (string is repeated until end of line)
-/set weechat.look.read_marker_string "-"
-
-# percent of screen to scroll when scrolling one page up or down (for example 100 means one page, 50 half-page)
-/set weechat.look.scroll_page_percent 50
-
-# comma separated list of plugins to load automatically at startup, "*" means all plugins found, a name beginning with "!" is a negative value to prevent a plugin from being loaded, wildcard "*" is allowed in names (examples: "*" or "*,!lua,!tcl")
-/set weechat.plugin.autoload "*,!buflist"
diff --git a/config/zsh/local-completions/hush/_sv b/config/zsh/local-completions/hush/_sv
deleted file mode 100644
index 8887bd6..0000000
--- a/config/zsh/local-completions/hush/_sv
+++ /dev/null
@@ -1,10 +0,0 @@
-#compdef svdn svget svkill svlog svnuke svre svst svstop svup
-
-local -a service_list
-local services=$(ls ~/.services/enabled/)
-service_list=(${(s:
-:)services})
-
-_describe 'commands' service_list
-
-# vim:ft=zsh
diff --git a/config/zsh/zsh-autosuggestions b/config/zsh/zsh-autosuggestions
deleted file mode 160000
-Subproject 43f3bc4010b2c697d2252fdd8b36a577ea12588
diff --git a/config/zsh/zsh-completions b/config/zsh/zsh-completions
deleted file mode 160000
-Subproject b512d57b6d0d2b85368a8068ec1a13288a93d26
diff --git a/config/zsh/zsh-syntax-highlighting b/config/zsh/zsh-syntax-highlighting
deleted file mode 160000
-Subproject 35c8690c0025ceef9584f64da86ced3a72ee32b
diff --git a/crawl/.config/sh/rc.d/crawl b/crawl/.config/sh/rc.d/crawl
new file mode 100644
index 0000000..704f723
--- /dev/null
+++ b/crawl/.config/sh/rc.d/crawl
@@ -0,0 +1,2 @@
+alias cao="env TERM=screen-256color /usr/bin/ssh -C -i \$HOME/.ssh/cao_key joshua@crawl.akrasiac.org"
+alias cdo="ssh -C -i \$HOME/.ssh/cao_key crawl@crawl.develz.org"
diff --git a/crawlrc b/crawl/.crawlrc
index 3ad3629..3ad3629 100644
--- a/crawlrc
+++ b/crawl/.crawlrc
diff --git a/ssh/cao_key b/crawl/.ssh/cao_key
index 59af0f8..59af0f8 100644
--- a/ssh/cao_key
+++ b/crawl/.ssh/cao_key
diff --git a/crawl/Makefile b/crawl/Makefile
new file mode 100644
index 0000000..d0eb8d6
--- /dev/null
+++ b/crawl/Makefile
@@ -0,0 +1,4 @@
+include ../Makefile.include
+
+build:
+ @chmod 600 .ssh/cao_key
diff --git a/crontab b/crontab
deleted file mode 100644
index e8f0b64..0000000
--- a/crontab
+++ /dev/null
@@ -1 +0,0 @@
-*/15 * * * * /bin/bash -c 'export PATH=~/.bin/hush:~/.bin:/usr/bin:/usr/bin/vendor_perl:$PATH && update-weather'
diff --git a/docker/.config/systemd/user/docker-prune.service b/docker/.config/systemd/user/docker-prune.service
new file mode 100644
index 0000000..f139ee0
--- /dev/null
+++ b/docker/.config/systemd/user/docker-prune.service
@@ -0,0 +1,3 @@
+[Service]
+Type=oneshot
+ExecStart=docker system prune --filter until=168h --force
diff --git a/docker/.config/systemd/user/docker-prune.timer b/docker/.config/systemd/user/docker-prune.timer
new file mode 100644
index 0000000..8a35a75
--- /dev/null
+++ b/docker/.config/systemd/user/docker-prune.timer
@@ -0,0 +1,6 @@
+[Timer]
+OnCalendar=daily
+Persistent=true
+
+[Install]
+WantedBy=timers.target
diff --git a/docker/Makefile b/docker/Makefile
new file mode 100644
index 0000000..87d6b43
--- /dev/null
+++ b/docker/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable docker-prune.timer
+ @systemctl --user start docker-prune.timer
+
+uninstall:
+ @systemctl --user stop docker-prune.timer
+ @systemctl --user disable docker-prune.timer
diff --git a/dzil/config.ini b/dzil/config.ini
deleted file mode 100644
index d60f935..0000000
--- a/dzil/config.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[%User]
-name = Jesse Luehrs
-email = doy@tozt.net
-
-[%Rights]
-license_class = MIT
-copyright_holder = Jesse Luehrs
diff --git a/dzil/profiles/default/Module.pm b/dzil/profiles/default/Module.pm
deleted file mode 100644
index e69de29..0000000
--- a/dzil/profiles/default/Module.pm
+++ /dev/null
diff --git a/dzil/profiles/default/profile.ini b/dzil/profiles/default/profile.ini
deleted file mode 100644
index 47f016a..0000000
--- a/dzil/profiles/default/profile.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[GatherDir::Template]
-root = root
-include_dotfiles = 1
-
-[TemplateModule / :DefaultModuleMaker]
-template = Module.pm
-
-[Git::Init]
diff --git a/dzil/profiles/default/root/.gitignore b/dzil/profiles/default/root/.gitignore
deleted file mode 100644
index 69f82f4..0000000
--- a/dzil/profiles/default/root/.gitignore
+++ /dev/null
@@ -1,18 +0,0 @@
-cover_db
-META.*
-MYMETA.*
-Makefile
-blib
-inc
-pm_to_blib
-MANIFEST
-Makefile.old
-nytprof.out
-nytprof
-MANIFEST.bak
-*.sw[po]
-.DS_Store
-.build
-{{$dist->name}}-*
-*.bs
-*.o
diff --git a/dzil/profiles/default/root/.travis.yml b/dzil/profiles/default/root/.travis.yml
deleted file mode 100644
index 44f4b71..0000000
--- a/dzil/profiles/default/root/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: perl
-perl:
- - "5.22"
- - "5.20"
- - "5.18"
- - "5.16"
- - "5.14"
-install:
- - cpanm -q --notest Dist::Zilla || (cat /home/travis/.cpanm/build.log; false)
- - dzil authordeps --missing | cpanm -q --notest || (cat /home/travis/.cpanm/build.log; false)
- - dzil listdeps --author --missing | cpanm -q --notest || (cat /home/travis/.cpanm/build.log; false)
-script:
- - dzil test --all
diff --git a/dzil/profiles/default/root/Changes b/dzil/profiles/default/root/Changes
deleted file mode 100644
index 0d8af06..0000000
--- a/dzil/profiles/default/root/Changes
+++ /dev/null
@@ -1,4 +0,0 @@
-Revision history for {{ $dist->name }}
-
-{{ '{{$NEXT}}' }}
- - Initial release
diff --git a/dzil/profiles/default/root/dist.ini b/dzil/profiles/default/root/dist.ini
deleted file mode 100644
index 1b2035f..0000000
--- a/dzil/profiles/default/root/dist.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-name = {{ $dist->name }}
-author = Jesse Luehrs <doy@tozt.net>
-license = MIT
-copyright_holder = Jesse Luehrs
-
-[@DOY]
-:version = 0.15
-dist = {{ $dist->name }}
-repository = github
-
-[AutoPrereqs]
diff --git a/eza/.config/sh/rc.d/exa b/eza/.config/sh/rc.d/exa
new file mode 100644
index 0000000..b6c9a9c
--- /dev/null
+++ b/eza/.config/sh/rc.d/exa
@@ -0,0 +1 @@
+alias ls="exa --group-directories-first --time-style=long-iso --git --color-scale"
diff --git a/fortune-mod/.gitignore b/fortune-mod/.gitignore
new file mode 100644
index 0000000..773a6df
--- /dev/null
+++ b/fortune-mod/.gitignore
@@ -0,0 +1 @@
+*.dat
diff --git a/local/share/fortune/buffy b/fortune-mod/.local/share/fortune/buffy
index ff98c9b..ff98c9b 100644
--- a/local/share/fortune/buffy
+++ b/fortune-mod/.local/share/fortune/buffy
diff --git a/local/share/fortune/calvin b/fortune-mod/.local/share/fortune/calvin
index 914631e..914631e 100644
--- a/local/share/fortune/calvin
+++ b/fortune-mod/.local/share/fortune/calvin
diff --git a/local/share/fortune/chapterhouse-dune b/fortune-mod/.local/share/fortune/chapterhouse-dune
index b0d83e7..b0d83e7 100644
--- a/local/share/fortune/chapterhouse-dune
+++ b/fortune-mod/.local/share/fortune/chapterhouse-dune
diff --git a/local/share/fortune/children-of-dune b/fortune-mod/.local/share/fortune/children-of-dune
index a543071..a543071 100644
--- a/local/share/fortune/children-of-dune
+++ b/fortune-mod/.local/share/fortune/children-of-dune
diff --git a/local/share/fortune/dune b/fortune-mod/.local/share/fortune/dune
index d44028b..d44028b 100644
--- a/local/share/fortune/dune
+++ b/fortune-mod/.local/share/fortune/dune
diff --git a/local/share/fortune/dune-messiah b/fortune-mod/.local/share/fortune/dune-messiah
index ce51993..ce51993 100644
--- a/local/share/fortune/dune-messiah
+++ b/fortune-mod/.local/share/fortune/dune-messiah
diff --git a/local/share/fortune/firefly b/fortune-mod/.local/share/fortune/firefly
index 8c5906a..8c5906a 100644
--- a/local/share/fortune/firefly
+++ b/fortune-mod/.local/share/fortune/firefly
diff --git a/local/share/fortune/god-emperor b/fortune-mod/.local/share/fortune/god-emperor
index 6cc7a1e..6cc7a1e 100644
--- a/local/share/fortune/god-emperor
+++ b/fortune-mod/.local/share/fortune/god-emperor
diff --git a/local/share/fortune/heretics-of-dune b/fortune-mod/.local/share/fortune/heretics-of-dune
index f75bcff..f75bcff 100644
--- a/local/share/fortune/heretics-of-dune
+++ b/fortune-mod/.local/share/fortune/heretics-of-dune
diff --git a/local/share/fortune/hitchhiker b/fortune-mod/.local/share/fortune/hitchhiker
index 0ea3338..0ea3338 100644
--- a/local/share/fortune/hitchhiker
+++ b/fortune-mod/.local/share/fortune/hitchhiker
diff --git a/local/share/fortune/house-atreides b/fortune-mod/.local/share/fortune/house-atreides
index 3792818..3792818 100644
--- a/local/share/fortune/house-atreides
+++ b/fortune-mod/.local/share/fortune/house-atreides
diff --git a/local/share/fortune/house-harkonnen b/fortune-mod/.local/share/fortune/house-harkonnen
index 090df36..090df36 100644
--- a/local/share/fortune/house-harkonnen
+++ b/fortune-mod/.local/share/fortune/house-harkonnen
diff --git a/local/share/fortune/ideas b/fortune-mod/.local/share/fortune/ideas
index 4733e08..4733e08 100644
--- a/local/share/fortune/ideas
+++ b/fortune-mod/.local/share/fortune/ideas
diff --git a/local/share/fortune/kernelcookies b/fortune-mod/.local/share/fortune/kernelcookies
index 3dcb616..3dcb616 100644
--- a/local/share/fortune/kernelcookies
+++ b/fortune-mod/.local/share/fortune/kernelcookies
diff --git a/local/share/fortune/perl b/fortune-mod/.local/share/fortune/perl
index e283cb0..e283cb0 100644
--- a/local/share/fortune/perl
+++ b/fortune-mod/.local/share/fortune/perl
diff --git a/local/share/fortune/song-of-ice-and-fire b/fortune-mod/.local/share/fortune/song-of-ice-and-fire
index b892ff4..b892ff4 100644
--- a/local/share/fortune/song-of-ice-and-fire
+++ b/fortune-mod/.local/share/fortune/song-of-ice-and-fire
diff --git a/local/share/fortune/yasd-fortune b/fortune-mod/.local/share/fortune/yasd-fortune
index a19ba71..a19ba71 100644
--- a/local/share/fortune/yasd-fortune
+++ b/fortune-mod/.local/share/fortune/yasd-fortune
diff --git a/fortune-mod/Makefile b/fortune-mod/Makefile
new file mode 100644
index 0000000..9c6a228
--- /dev/null
+++ b/fortune-mod/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+build: $(addsuffix .dat,$(filter-out %.dat,$(wildcard .local/share/fortune/*)))
+
+clean:
+ @rm -f .local/share/fortune/*.dat
+
+%.dat : %
+ @strfile -s $(basename $@)
diff --git a/fzf/.config/sh/rc.d/fzf b/fzf/.config/sh/rc.d/fzf
new file mode 100644
index 0000000..27a1c89
--- /dev/null
+++ b/fzf/.config/sh/rc.d/fzf
@@ -0,0 +1,2 @@
+export FZF_DEFAULT_OPTS="--reverse --inline-info --bind=tab:down,shift-tab:up,change:top,ctrl-space:toggle"
+export FZF_DEFAULT_COMMAND="rg --hidden -l ."
diff --git a/gdbinit b/gdb/.config/gdb/gdbinit
index a9b6f34..a9b6f34 100644
--- a/gdbinit
+++ b/gdb/.config/gdb/gdbinit
diff --git a/git/.bin/git/git-amend b/git/.bin/git/git-amend
new file mode 100755
index 0000000..3b937ec
--- /dev/null
+++ b/git/.bin/git/git-amend
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -eu
+
+if [ -e "$(git root)/.git/branchless" ]; then
+ exec git branchless amend "$@"
+else
+ if [ "${1:-}" = "-i" ]; then
+ git add -p
+ else
+ git add -u
+ fi
+ git commit --amend
+fi
diff --git a/bin/git/git-blame-stats b/git/.bin/git/git-blame-stats
index 320d755..320d755 100755
--- a/bin/git/git-blame-stats
+++ b/git/.bin/git/git-blame-stats
diff --git a/git/.bin/git/git-default-branch b/git/.bin/git/git-default-branch
new file mode 100755
index 0000000..90e225f
--- /dev/null
+++ b/git/.bin/git/git-default-branch
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -eu
+
+git symbolic-ref refs/remotes/origin/HEAD | sed 's/.*\///'
diff --git a/bin/git/git-file-size b/git/.bin/git/git-file-size
index 0e7d00d..0e7d00d 100755
--- a/bin/git/git-file-size
+++ b/git/.bin/git/git-file-size
diff --git a/git/.bin/git/git-pr b/git/.bin/git/git-pr
new file mode 100755
index 0000000..61346bc
--- /dev/null
+++ b/git/.bin/git/git-pr
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+pr_num="$1"
+upstream="${2-origin}"
+git fetch "$upstream" "pull/${pr_num}/head:pull-${pr_num}"
diff --git a/git/.bin/git/git-record b/git/.bin/git/git-record
new file mode 100755
index 0000000..eaa36c9
--- /dev/null
+++ b/git/.bin/git/git-record
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -eu
+
+if [ -e "$(git root)/.git/branchless" ]; then
+ exec git branchless record "$@"
+else
+ if [ "${1:-}" = "-i" ]; then
+ git add -p
+ else
+ git add -u
+ fi
+ git commit
+fi
diff --git a/git/.bin/git/git-root b/git/.bin/git/git-root
new file mode 100755
index 0000000..96fb395
--- /dev/null
+++ b/git/.bin/git/git-root
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -eu
+
+root="$(git rev-parse --show-superproject-working-tree 2>/dev/null)"
+if [ -n "$root" ]; then
+ echo "$root"
+else
+ git rev-parse --show-toplevel
+fi
diff --git a/config/git/config b/git/.config/git/config
index 3a67355..54b054e 100644
--- a/config/git/config
+++ b/git/.config/git/config
@@ -2,50 +2,38 @@
email = doy@tozt.net
name = Jesse Luehrs
[alias]
- a = !git amend
aliases = !git config --get-regexp 'alias.*' | perl -nle'/^alias\\.([^ ]*) (.*)/ && printf \"%-15s = %s\\n\", $1, $2'
alias = "!f() { local name=$1; shift; git config --global alias.$name \"$*\"; }; f"
- amend = !git add -p && git commit --amend
- bd = "!f() { git choose-branch | head -n1 | xargs --no-run-if-empty git branch -D; }; f"
- bda = "!f() { git branch --merged master --format='%(refname:short)' | grep -v '^master$' | xargs -r git branch -d; }; f"
+ amend = !~/.bin/git/git-amend
+ bda = "!f() { git branch --merged $(git default-branch) --format='%(refname:short)' | grep -v \"^$(git default-branch)$\" | xargs -r git branch -d; }; f"
blame-stats = !~/.bin/git/git-blame-stats
br = for-each-ref --sort=committerdate refs/heads/ --format='%(align:30,left)%(HEAD) %(refname:short)%(end) %(color:magenta)(%(committerdate:relative))'
- choose-branch = "!f() { git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short)' | fzf --height 40% --no-sort --preview='git show {} -q --format=medium'; }; f"
- c = "!f() { git choose-branch | head -n1 | xargs --no-run-if-empty git co; }; f"
cc = cherry-pick
co = checkout
- diff-branch = "!f() { local branch=${1:-HEAD}; git diff $(git merge-base master $branch) $branch; }; f"
+ default-branch = !~/.bin/git/git-default-branch
+ diff-branch = "!f() { local branch=${1:-HEAD}; git diff $(git merge-base $(git default-branch) $branch) $branch; }; f"
ff = merge --ff-only
file-size = !~/.bin/git/git-file-size
fixup = "!f() { git record --fixup \"$@\"; }; f"
gc-aggressive = "!f() { git repack -Abd --window=250 --depth=250 --window-memory=1g && git prune --expire \"1 day ago\" && rm -f .git/gc.log && git gc; }; f"
- imerge = !~/.bin/git/git-imerge
- info = remote show -n origin
lg = log --graph --pretty=format:'%Cred%h%Creset%C(yellow)%d%Creset %C(bold blue)%aN%Creset %C(magenta)(%ar)%Creset%n%s%n' --abbrev-commit --date=relative --stat=72
- m = "!f() { git co master && git pull && EDITOR=true git merge --no-ff \"$@\" && git bda; }; f"
- prune-all = !git remote | xargs -n 1 git remote prune
- pushall = "!f() { for repo in origin github; do git push $repo \"$@\"; done; }; f"
- record = !git add -p && git commit --verbose
+ pr = !~/.bin/git/git-pr
+ record = !~/.bin/git/git-record
refix = "!f() { env EDITOR=true git rebase -i \"$@\"; }; f"
re = rebase -i @{u}
- r = !git record
ri = rebase -i
+ root = !~/.bin/git/git-root
rv = checkout -p
- stashed = stash list --pretty=format:'%<(10)%gd: %Cred%h%Creset %Cgreen(%ar)%Creset%n %s'
st = status -sb
- track = "!f() { local name=$(git name-rev --name-only @); git branch --set-upstream-to=origin/$name $name; }; f"
+ start = "!f() { git commit --allow-empty -m 'initial commit' && git add . && git commit -m 'project skeleton'; }; f"
+ track = "!f() { local name=$(git name-rev --name-only --exclude='branchless/*' @); git branch --set-upstream-to=origin/$name $name; }; f"
+ git = !git
[github]
user = doy
-[color]
- ui = auto
[core]
- excludesfile = ~/.config/git/ignore
-[push]
- default = current
-[branch]
- autosetuprebase = always
+ pager = delta
[merge]
- conflictstyle = diff3
+ conflictstyle = zdiff3
[rebase]
autosquash = true
autostash = true
@@ -53,6 +41,7 @@
autocorrect = 5
[diff]
mnemonicprefix = true
+ algorithm = histogram
[advice]
pushUpdateRejected = false
statusHints = false
@@ -61,13 +50,24 @@
detachedHead = false
[rerere]
enabled = true
-[pager]
- log = diff-highlight | less
- show = diff-highlight | less
- diff = diff-highlight | less
[fetch]
prune = true
+[pull]
+ rebase = true
[include]
path = config.private
+[interactive]
+ diffFilter = delta --color-only
+[delta]
+ navigate = true
+[init]
+ defaultBranch = main
+[submodule]
+ recurse = true
+[push]
+ autosetupremote = true
+ recurseSubmodules = check
+[commit]
+ verbose = true
; vim:ft=gitconfig:
diff --git a/git/.config/git/ignore b/git/.config/git/ignore
new file mode 100644
index 0000000..dd33554
--- /dev/null
+++ b/git/.config/git/ignore
@@ -0,0 +1 @@
+.obsidian
diff --git a/git/.config/sh/rc.d/git b/git/.config/sh/rc.d/git
new file mode 100644
index 0000000..52d6b5e
--- /dev/null
+++ b/git/.config/sh/rc.d/git
@@ -0,0 +1 @@
+alias cdu="cd \"\$(git root)\""
diff --git a/gnupg/gpg-agent.conf b/gnupg/gpg-agent.conf
deleted file mode 100644
index 6ca67ee..0000000
--- a/gnupg/gpg-agent.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-grab
-default-cache-ttl 3600
-max-cache-ttl 86400
diff --git a/gnupg/gpg.conf b/gnupg/gpg.conf
deleted file mode 100644
index bc65e11..0000000
--- a/gnupg/gpg.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-no-greeting
-cert-digest-algo SHA512
-default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES 3DES CAST5 BZIP2 ZLIB ZIP Uncompressed
-personal-digest-preferences SHA512 SHA384 SHA256 SHA224
-require-cross-certification
-group pass = 0xF2C2C7E6 0x3741B294
-no-emit-version
-no-random-seed-file
-keyserver-options auto-key-retrieve
-keyserver-options no-honor-keyserver-url
-personal-cipher-preferences AES256 AES192 AES 3DES CAST5
-personal-compress-preferences BZIP2 ZLIB ZIP Uncompressed
-
-default-key 189CE2E2
-keyserver hkp://keys.gnupg.net
diff --git a/hammerspoon/Spoons/ReloadConfiguration.spoon/docs.json b/hammerspoon/Spoons/ReloadConfiguration.spoon/docs.json
deleted file mode 100644
index 50c62f2..0000000
--- a/hammerspoon/Spoons/ReloadConfiguration.spoon/docs.json
+++ /dev/null
@@ -1,90 +0,0 @@
-[
- {
- "Command": [],
- "Constant": [],
- "Constructor": [],
- "Deprecated": [],
- "Field": [],
- "Function": [],
- "Method": [
- {
- "def": "ReloadConfiguration:bindHotkeys(mapping)",
- "desc": "Binds hotkeys for ReloadConfiguration",
- "doc": "Binds hotkeys for ReloadConfiguration\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * reloadConfiguration - This will cause the configuration to be reloaded",
- "name": "bindHotkeys",
- "parameters": [
- " * mapping - A table containing hotkey modifier/key details for the following items:",
- " * reloadConfiguration - This will cause the configuration to be reloaded"
- ],
- "signature": "ReloadConfiguration:bindHotkeys(mapping)",
- "stripped_doc": "",
- "type": "Method"
- },
- {
- "def": "ReloadConfiguration:start()",
- "desc": "Start ReloadConfiguration",
- "doc": "Start ReloadConfiguration\n\nParameters:\n * None",
- "name": "start",
- "parameters": [
- " * None"
- ],
- "signature": "ReloadConfiguration:start()",
- "stripped_doc": "",
- "type": "Method"
- }
- ],
- "Variable": [
- {
- "def": "ReloadConfiguration.watch_paths",
- "desc": "List of directories to watch for changes, defaults to hs.configdir",
- "doc": "List of directories to watch for changes, defaults to hs.configdir",
- "name": "watch_paths",
- "signature": "ReloadConfiguration.watch_paths",
- "stripped_doc": "",
- "type": "Variable"
- }
- ],
- "desc": "Adds a hotkey to reload the hammerspoon configuration, and a pathwatcher to automatically reload on changes.",
- "doc": "Adds a hotkey to reload the hammerspoon configuration, and a pathwatcher to automatically reload on changes.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ReloadConfiguration.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ReloadConfiguration.spoon.zip)",
- "items": [
- {
- "def": "ReloadConfiguration:bindHotkeys(mapping)",
- "desc": "Binds hotkeys for ReloadConfiguration",
- "doc": "Binds hotkeys for ReloadConfiguration\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * reloadConfiguration - This will cause the configuration to be reloaded",
- "name": "bindHotkeys",
- "parameters": [
- " * mapping - A table containing hotkey modifier/key details for the following items:",
- " * reloadConfiguration - This will cause the configuration to be reloaded"
- ],
- "signature": "ReloadConfiguration:bindHotkeys(mapping)",
- "stripped_doc": "",
- "type": "Method"
- },
- {
- "def": "ReloadConfiguration:start()",
- "desc": "Start ReloadConfiguration",
- "doc": "Start ReloadConfiguration\n\nParameters:\n * None",
- "name": "start",
- "parameters": [
- " * None"
- ],
- "signature": "ReloadConfiguration:start()",
- "stripped_doc": "",
- "type": "Method"
- },
- {
- "def": "ReloadConfiguration.watch_paths",
- "desc": "List of directories to watch for changes, defaults to hs.configdir",
- "doc": "List of directories to watch for changes, defaults to hs.configdir",
- "name": "watch_paths",
- "signature": "ReloadConfiguration.watch_paths",
- "stripped_doc": "",
- "type": "Variable"
- }
- ],
- "name": "ReloadConfiguration",
- "stripped_doc": "\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ReloadConfiguration.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ReloadConfiguration.spoon.zip)",
- "submodules": [],
- "type": "Module"
- }
-] \ No newline at end of file
diff --git a/hammerspoon/Spoons/ReloadConfiguration.spoon/init.lua b/hammerspoon/Spoons/ReloadConfiguration.spoon/init.lua
deleted file mode 100644
index bb83f67..0000000
--- a/hammerspoon/Spoons/ReloadConfiguration.spoon/init.lua
+++ /dev/null
@@ -1,49 +0,0 @@
---- === ReloadConfiguration ===
----
---- Adds a hotkey to reload the hammerspoon configuration, and a pathwatcher to automatically reload on changes.
----
---- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ReloadConfiguration.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/ReloadConfiguration.spoon.zip)
-
-local obj = {}
-obj.__index = obj
-
--- Metadata
-obj.name = "ReloadConfiguration"
-obj.version = "1.0"
-obj.author = "Jon Lorusso <jonlorusso@gmail.com>"
-obj.homepage = "https://github.com/Hammerspoon/Spoons"
-obj.license = "MIT - https://opensource.org/licenses/MIT"
-
-
---- ReloadConfiguration.watch_paths
---- Variable
---- List of directories to watch for changes, defaults to hs.configdir
-obj.watch_paths = { hs.configdir }
-
---- ReloadConfiguration:bindHotkeys(mapping)
---- Method
---- Binds hotkeys for ReloadConfiguration
----
---- Parameters:
---- * mapping - A table containing hotkey modifier/key details for the following items:
---- * reloadConfiguration - This will cause the configuration to be reloaded
-function obj:bindHotkeys(mapping)
- local def = { reloadConfiguration = hs.fnutils.partial(hs.reload, self) }
- hs.spoons.bindHotkeysToSpec(def, mapping)
-end
-
---- ReloadConfiguration:start()
---- Method
---- Start ReloadConfiguration
----
---- Parameters:
---- * None
-function obj:start()
- self.watchers = {}
- for _,dir in pairs(self.watch_paths) do
- self.watchers[dir] = hs.pathwatcher.new(dir, hs.reload):start()
- end
- return self
-end
-
-return obj
diff --git a/hammerspoon/Spoons/SpeedMenu.spoon/docs.json b/hammerspoon/Spoons/SpeedMenu.spoon/docs.json
deleted file mode 100644
index f57b965..0000000
--- a/hammerspoon/Spoons/SpeedMenu.spoon/docs.json
+++ /dev/null
@@ -1,39 +0,0 @@
-[
- {
- "Command": [],
- "Constant": [],
- "Constructor": [],
- "Deprecated": [],
- "Field": [],
- "Function": [],
- "Method": [
- {
- "def": "SpeedMenu:rescan()",
- "desc": "Redetect the active interface, darkmode …And redraw everything.",
- "doc": "Redetect the active interface, darkmode …And redraw everything.\n",
- "name": "rescan",
- "signature": "SpeedMenu:rescan()",
- "stripped_doc": "",
- "type": "Method"
- }
- ],
- "Variable": [],
- "desc": "Menubar netspeed meter",
- "doc": "Menubar netspeed meter\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpeedMenu.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpeedMenu.spoon.zip)",
- "items": [
- {
- "def": "SpeedMenu:rescan()",
- "desc": "Redetect the active interface, darkmode …And redraw everything.",
- "doc": "Redetect the active interface, darkmode …And redraw everything.\n",
- "name": "rescan",
- "signature": "SpeedMenu:rescan()",
- "stripped_doc": "",
- "type": "Method"
- }
- ],
- "name": "SpeedMenu",
- "stripped_doc": "\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpeedMenu.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpeedMenu.spoon.zip)",
- "submodules": [],
- "type": "Module"
- }
-] \ No newline at end of file
diff --git a/hammerspoon/Spoons/SpeedMenu.spoon/init.lua b/hammerspoon/Spoons/SpeedMenu.spoon/init.lua
deleted file mode 100644
index d4ecdac..0000000
--- a/hammerspoon/Spoons/SpeedMenu.spoon/init.lua
+++ /dev/null
@@ -1,111 +0,0 @@
---- === SpeedMenu ===
----
---- Menubar netspeed meter
----
---- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpeedMenu.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpeedMenu.spoon.zip)
-
-local obj={}
-obj.__index = obj
-
--- Metadata
-obj.name = "SpeedMenu"
-obj.version = "1.0"
-obj.author = "ashfinal <ashfinal@gmail.com>"
-obj.homepage = "https://github.com/Hammerspoon/Spoons"
-obj.license = "MIT - https://opensource.org/licenses/MIT"
-
-function obj:init()
- self.menubar = hs.menubar.new()
- obj:rescan()
-end
-
-local function data_diff()
- local in_seq = hs.execute(obj.instr)
- local out_seq = hs.execute(obj.outstr)
- local in_diff = in_seq - obj.inseq
- local out_diff = out_seq - obj.outseq
- if in_diff/1024 > 1024 then
- obj.kbin = string.format("%6.2f", in_diff/1024/1024) .. ' mb/s'
- else
- obj.kbin = string.format("%6.2f", in_diff/1024) .. ' kb/s'
- end
- if out_diff/1024 > 1024 then
- obj.kbout = string.format("%6.2f", out_diff/1024/1024) .. ' mb/s'
- else
- obj.kbout = string.format("%6.2f", out_diff/1024) .. ' kb/s'
- end
- local disp_str = '⥄ ' .. obj.kbout .. '\n⥂ ' .. obj.kbin
- if obj.darkmode then
- obj.disp_str = hs.styledtext.new(disp_str, {font={size=9.0, color={hex="#FFFFFF"}}})
- else
- obj.disp_str = hs.styledtext.new(disp_str, {font={size=9.0, color={hex="#000000"}}})
- end
- obj.menubar:setTitle(obj.disp_str)
- obj.inseq = in_seq
- obj.outseq = out_seq
-end
-
---- SpeedMenu:rescan()
---- Method
---- Redetect the active interface, darkmode …And redraw everything.
----
-
-function obj:rescan()
- obj.interface = hs.network.primaryInterfaces()
- obj.darkmode = hs.osascript.applescript('tell application "System Events"\nreturn dark mode of appearance preferences\nend tell')
- local menuitems_table = {}
- if obj.interface then
- -- Inspect active interface and create menuitems
- local interface_detail = hs.network.interfaceDetails(obj.interface)
- if interface_detail.AirPort then
- local ssid = interface_detail.AirPort.SSID
- table.insert(menuitems_table, {
- title = "SSID: " .. ssid,
- tooltip = "Copy SSID to clipboard",
- fn = function() hs.pasteboard.setContents(ssid) end
- })
- end
- if interface_detail.IPv4 then
- local ipv4 = interface_detail.IPv4.Addresses[1]
- table.insert(menuitems_table, {
- title = "IPv4: " .. ipv4,
- tooltip = "Copy IPv4 to clipboard",
- fn = function() hs.pasteboard.setContents(ipv4) end
- })
- end
- if interface_detail.IPv6 then
- local ipv6 = interface_detail.IPv6.Addresses[1]
- table.insert(menuitems_table, {
- title = "IPv6: " .. ipv6,
- tooltip = "Copy IPv6 to clipboard",
- fn = function() hs.pasteboard.setContents(ipv6) end
- })
- end
- local macaddr = hs.execute('ifconfig ' .. obj.interface .. ' | grep ether | awk \'{print $2}\'')
- table.insert(menuitems_table, {
- title = "MAC Addr: " .. macaddr,
- tooltip = "Copy MAC Address to clipboard",
- fn = function() hs.pasteboard.setContents(macaddr) end
- })
- -- Start watching the netspeed delta
- obj.instr = 'netstat -ibn | grep -e ' .. obj.interface .. ' -m 1 | awk \'{print $7}\''
- obj.outstr = 'netstat -ibn | grep -e ' .. obj.interface .. ' -m 1 | awk \'{print $10}\''
-
- obj.inseq = hs.execute(obj.instr)
- obj.outseq = hs.execute(obj.outstr)
-
- if obj.timer then
- obj.timer:stop()
- obj.timer = nil
- end
- obj.timer = hs.timer.doEvery(1, data_diff)
- end
- table.insert(menuitems_table, {
- title = "Rescan Network Interfaces",
- fn = function() obj:rescan() end
- })
- obj.menubar:setTitle("⚠︎")
- obj.menubar:setMenu(menuitems_table)
-end
-
-return obj
diff --git a/hammerspoon/init.lua b/hammerspoon/init.lua
deleted file mode 100644
index d2e000f..0000000
--- a/hammerspoon/init.lua
+++ /dev/null
@@ -1,173 +0,0 @@
-hs.loadSpoon("ReloadConfiguration")
-spoon.ReloadConfiguration:start()
-
-hs.loadSpoon("SpeedMenu")
-
--- apparently hs.eventtap.keyStroke doesn't always work, this is more reliable
--- https://github.com/Hammerspoon/hammerspoon/issues/1984#issuecomment-455317739
-doKeyStroke = function(modifiers, character)
- if type(modifiers) == 'table' then
- local event = hs.eventtap.event
-
- for _, modifier in pairs(modifiers) do
- event.newKeyEvent(modifier, true):post()
- end
-
- event.newKeyEvent(character, true):post()
- event.newKeyEvent(character, false):post()
-
- for i = #modifiers, 1, -1 do
- event.newKeyEvent(modifiers[i], false):post()
- end
- end
-end
-
-hs.hotkey.bind({"alt"}, "h", function()
- hs.window.focusedWindow():focusWindowWest(nil, false, true)
-end)
-hs.hotkey.bind({"alt"}, "j", function()
- hs.window.focusedWindow():focusWindowSouth(nil, false, true)
-end)
-hs.hotkey.bind({"alt"}, "k", function()
- hs.window.focusedWindow():focusWindowNorth(nil, false, true)
-end)
-hs.hotkey.bind({"alt"}, "l", function()
- hs.window.focusedWindow():focusWindowEast(nil, false, true)
-end)
-
-hs.hotkey.bind({"alt"}, "b", function()
- hs.execute("open /Applications/Google\\ Chrome.app --new --args --new-window about:home")
-end)
-
-hs.hotkey.bind({"alt"}, "d", function()
- hs.caffeinate.lockScreen()
-end)
-
-hs.hotkey.bind({"alt"}, "f", function()
- hs.window.focusedWindow():toggleFullScreen()
-end)
-
-hs.hotkey.bind({"alt"}, "o", function()
- hs.execute("open -n /Applications/Alacritty.app/")
-end)
-
-hs.hotkey.bind({"alt"}, "q", function()
- hs.window.focusedWindow():close()
-end)
-
-hs.hotkey.bind({"alt"}, "r", function()
- doKeyStroke({"cmd"}, "space")
-end)
-
-hs.hotkey.bind({"alt"}, "[", function()
- doKeyStroke({"ctrl"}, "left")
-end)
-
-hs.hotkey.bind({"alt"}, "]", function()
- doKeyStroke({"ctrl"}, "right")
-end)
-
-hs.hotkey.bind({"cmd"}, "u", function()
- doKeyStroke({"cmd"}, "delete")
-end)
-
-hs.hotkey.bind({"cmd"}, "a", function()
- doKeyStroke({"cmd"}, "left")
-end)
-
-hs.hotkey.bind({"cmd"}, "e", function()
- doKeyStroke({"cmd"}, "right")
-end)
-
-for i = 1, 6 do
- hs.hotkey.bind({"alt"}, tostring(i), function()
- doKeyStroke({"ctrl"}, tostring(i))
- end)
-end
-
--- bindings for window movement are handled by amethyst, since hammerspoon
--- doesn't support that well
-
-extra_bindings = {
- ["Alacritty"] = hs.hotkey.modal.new(),
- ["Google Chrome"] = hs.hotkey.modal.new(),
-}
-
-slack_cmd_k_watcher = nil
-extra_bindings["Alacritty"]:bind({"ctrl"}, "k", function()
- slack_cmd_k_watcher = hs.application.watcher.new(function(name, event_type, app)
- if event_type == hs.application.watcher.activated then
- if app:name() == "Slack" then
- hs.timer.doAfter(0.001, function()
- doKeyStroke({"cmd"}, "k")
- end)
- slack_cmd_k_watcher:stop()
- slack_cmd_k_watcher = nil
- end
- end
- end)
- slack_cmd_k_watcher:start()
- hs.application.get("Slack"):mainWindow():focus()
-end)
-
-extra_bindings["Google Chrome"]:bind({"cmd"}, "h", function()
- doKeyStroke({"cmd"}, "left")
-end)
-
-extra_bindings["Google Chrome"]:bind({"cmd"}, "l", function()
- doKeyStroke({"cmd"}, "right")
-end)
-
--- doesn't seem to work?
--- extra_bindings["Google Chrome"]:bind({"cmd", "shift"}, "i", function()
--- doKeyStroke({"cmd", "option"}, "i")
--- end)
-
-current_app_name = nil
-
-function enter_bindings(name)
- if extra_bindings[name] then
- extra_bindings[name]:enter()
- current_app_name = name
- end
-end
-
-function exit_bindings(name)
- if extra_bindings[name] then
- extra_bindings[name]:exit()
- current_app_name = nil
- end
-end
-
--- the application watcher receives notifications about new apps being
--- activated before the old apps are deactivated, so we can't rely on
--- deactivated events. this should be fine because there should always be an
--- active app (at the very least, Finder)
-current_application_watcher = hs.application.watcher.new(function(name, event_type, app)
- if event_type == hs.application.watcher.activated then
- if current_app_name ~= app:name() then
- exit_bindings(current_app_name)
- enter_bindings(app:name())
- end
- end
-end)
-enter_bindings(hs.application.frontmostApplication():name())
-current_application_watcher:start()
-
-cpu_usage_bar = hs.menubar.new()
-timer = hs.timer.doEvery(1, function()
- hs.host.cpuUsage(function(cpu)
- local cpuUsage = cpu["overall"]["active"]
- cpu_usage_bar:setTitle(math.floor(cpuUsage + 0.5) .. "%")
- end)
-end)
-
-power_usage_bar = hs.menubar.new()
-timer = hs.timer.doEvery(5, function()
- local watts = hs.execute("/Users/doy/.bin/st-doy2/power-usage")
- power_usage_bar:setTitle(string.gsub(watts, "\n", "") .. "W")
-end)
-
-hs.caffeinate.set("systemIdle", true, true)
-
-hs.alert("Hammerspoon config reloaded")
diff --git a/helix/.config/helix/config.toml b/helix/.config/helix/config.toml
new file mode 100644
index 0000000..d0985ca
--- /dev/null
+++ b/helix/.config/helix/config.toml
@@ -0,0 +1,34 @@
+theme = "vim_dark_high_contrast"
+
+[editor]
+gutters = ["diagnostics", "diff"]
+auto-info = false
+color-modes = true
+true-color = true
+
+[editor.soft-wrap]
+enable = true
+
+[editor.indent-guides]
+render = true
+character = "⸽"
+
+[editor.lsp]
+display-messages = true
+
+[keys.normal]
+tab = ":w"
+"|" = ":q"
+"\\" = "shell_pipe"
+
+"C-d" = ":buffer-close"
+
+"ret" = "goto_definition"
+"backspace" = "jump_backward"
+
+[keys.normal.g]
+j = "goto_last_line"
+k = "goto_file_start"
+
+[keys.normal.space]
+o = ":diffg"
diff --git a/helix/.config/helix/languages.toml b/helix/.config/helix/languages.toml
new file mode 100644
index 0000000..98c9fc2
--- /dev/null
+++ b/helix/.config/helix/languages.toml
@@ -0,0 +1,14 @@
+[language-server.rust-analyzer]
+command = "ra-multiplex"
+config = { checkOnSave = { command = "clippy" }, cargo = { allFeatures = true }, diagnostics = { disabled = ["inactive-code"] } }
+
+[[language]]
+name = "python"
+language-servers = ["pyright"]
+formatter = { command = "black", args = ["--target-version=py311", "--quiet", "-"] }
+auto-format = true
+
+[language-server.pyright]
+command = "pyright-langserver"
+args = ["--stdio"]
+config = {}
diff --git a/helix/.config/sh/rc.d/helix b/helix/.config/sh/rc.d/helix
new file mode 100644
index 0000000..2dad3e5
--- /dev/null
+++ b/helix/.config/sh/rc.d/helix
@@ -0,0 +1,2 @@
+alias hx="helix"
+export EDITOR=$(command -v helix)
diff --git a/bin/hush/i3-switch-workspace b/i3/.bin/i3-switch-workspace
index bcbb8d2..b54afa1 100755
--- a/bin/hush/i3-switch-workspace
+++ b/i3/.bin/i3-switch-workspace
@@ -8,6 +8,8 @@ use JSON::PP;
my $json = JSON::PP->new;
+my $virtual_workspace = 'virtual';
+
my %message_types = (
command => 0,
get_workspaces => 1,
@@ -27,47 +29,59 @@ chomp(my $path = qx(i3 --get-socketpath));
my $sock = IO::Socket::UNIX->new(Peer => $path);
my $workspace_data = $json->decode(i3_msg('get_workspaces'));
+my $tree_data = $json->decode(i3_msg('get_tree'));
+
+my $first = 99999;
+my $last = -99999;
+my $cur;
+my $cur_name;
+my $virtual_output;
+
+for my $i (0..$#$workspace_data) {
+ my $num = $workspace_data->[$i]{num};
+ if ($workspace_data->[$i]{focused}) {
+ $cur = $num;
+ $cur_name = $workspace_data->[$i]{name};
+ if ($cur_name eq $virtual_workspace) {
+ $virtual_output = $workspace_data->[$i]{output};
+ }
+ }
-my $next_workspace = $workspace_data->[-1]{num} + 1;
-my $prev_workspace = $workspace_data->[0]{num} - 1;
+ my $workspace_tree = find_workspace($tree_data, $num);
+ next unless
+ @{ $workspace_tree->{nodes} } ||
+ @{ $workspace_tree->{floating_nodes} };
-if (@$workspace_data == 1) {
- my $current_workspace = $workspace_data->[0]{num};
- my $tree_data = $json->decode(i3_msg('get_tree'));
- my $workspace_tree = find_workspace($tree_data, $current_workspace);
- if ($dir eq 'prev') {
- i3_msg('command', "workspace number $prev_workspace");
- }
- else {
- i3_msg('command', "workspace number $next_workspace");
+ $first = $num if $num < $first;
+ $last = $num if $num > $last;
+}
+
+if ($dir eq 'prev') {
+ if ($cur >= $first) {
+ i3_msg('command', "workspace ${\($cur - 1)}");
}
}
-elsif ($workspace_data->[0]{focused} && $dir eq 'prev') {
- my $current_workspace = $workspace_data->[0]{num};
- my $tree_data = $json->decode(i3_msg('get_tree'));
- my $workspace_tree = find_workspace($tree_data, $current_workspace);
- if (@{ $workspace_tree->{nodes} } || @{ $workspace_tree->{floating_nodes} }) {
- if ($prev_workspace > 0) {
- i3_msg('command', "workspace number $prev_workspace");
- }
+elsif ($dir eq 'next') {
+ if ($cur <= $last) {
+ i3_msg('command', "workspace ${\($cur + 1)}");
}
}
-elsif ($workspace_data->[-1]{focused} && $dir eq 'next') {
- my $current_workspace = $workspace_data->[-1]{num};
- my $tree_data = $json->decode(i3_msg('get_tree'));
- my $workspace_tree = find_workspace($tree_data, $current_workspace);
- if (@{ $workspace_tree->{nodes} } || @{ $workspace_tree->{floating_nodes} }) {
- i3_msg('command', "workspace number $next_workspace");
+elsif ($dir eq $virtual_workspace) {
+ if (!defined $virtual_output || $virtual_output eq 'VIRTUAL1') {
+ i3_msg(
+ 'command',
+ "workspace $virtual_workspace; move workspace to output eDP1",
+ );
+ }
+ else {
+ i3_msg(
+ 'command',
+ "workspace $virtual_workspace; move workspace to output VIRTUAL1",
+ );
}
}
else {
- for my $i (0..$#$workspace_data) {
- if ($workspace_data->[$i]{focused}) {
- my $to = $workspace_data->[$i]{num} + ($dir eq 'prev' ? -1 : 1);
- i3_msg('command', "workspace number $to");
- last;
- }
- }
+ die "unknown subcommand $dir";
}
sub find_workspace {
diff --git a/bin/hush/kill-focused b/i3/.bin/kill-focused
index 37271ac..37271ac 100755
--- a/bin/hush/kill-focused
+++ b/i3/.bin/kill-focused
diff --git a/config/i3/config b/i3/.config/i3/config
index 312df8e..afa6af1 100644
--- a/config/i3/config
+++ b/i3/.config/i3/config
@@ -13,11 +13,13 @@ floating_maximum_size -1 x -1
focus_wrapping no
-for_window [instance="urxvt-kuake"] floating enable
-for_window [instance="urxvt-kuake"] sticky enable
-for_window [instance="urxvt-kuake"] move absolute position 0 px 0 px
+for_window [instance="Alacritty-tdrop"] floating enable
+for_window [instance="Alacritty-tdrop"] sticky enable
for_window [class="Steam"] floating enable
+for_window [class="ArenaTracker"] floating enable
+
+for_window [title="zoom"] floating enable
bindsym $mod+q kill
@@ -31,9 +33,6 @@ bindsym $mod+Shift+j move down
bindsym $mod+Shift+k move up
bindsym $mod+Shift+l move right
-bindsym $mod+Mod1+h split h
-bindsym $mod+Mod1+v split v
-
bindsym $mod+f fullscreen
bindsym $mod+Shift+space floating toggle
@@ -41,6 +40,9 @@ bindsym $mod+space focus mode_toggle
bindsym $mod+bracketleft exec i3-switch-workspace prev
bindsym $mod+bracketright exec i3-switch-workspace next
+bindsym $mod+v exec vscreen goto
+
+bindsym $mod+Shift+o exec "i3-msg 'append_layout .config/i3/terminal-workspace.json; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty'"
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
@@ -69,9 +71,7 @@ bindsym $mod+Shift+q exec "i3-nagbar -t warning -m 'You pressed the exit shortcu
bar {
tray_output primary
status_command status
- font xft:DejaVuSansMono 10
+ font xft:DejaVuSansMono 12
}
-exec --no-startup-id "i3-msg 'workspace 6; append_layout .config/i3/browser-workspace.json; exec firefox'"
-exec --no-startup-id "i3-msg 'workspace 7; append_layout .config/i3/signal-workspace.json; exec signal-desktop'"
-exec --no-startup-id "i3-msg 'workspace 5; append_layout .config/i3/terminal-workspace.json; exec alacritty; exec alacritty; exec alacritty; exec alacritty; exec alacritty'"
+exec "i3-msg 'workspace 5'"
diff --git a/config/i3/terminal-workspace.json b/i3/.config/i3/terminal-workspace.json
index c5d5873..d957bc1 100644
--- a/config/i3/terminal-workspace.json
+++ b/i3/.config/i3/terminal-workspace.json
@@ -1,12 +1,16 @@
+// vim:ts=4:sw=4:et
{
+ // splitv split container with 3 children
"border": "pixel",
"floating": "auto_off",
"layout": "splitv",
- "percent": 0.3,
+ "marks": [],
+ "percent": 0.337251851851852,
"type": "con",
"nodes": [
{
"border": "pixel",
+ "current_border_width": 1,
"floating": "auto_off",
"geometry": {
"height": 340,
@@ -14,7 +18,8 @@
"x": 0,
"y": 0
},
- "name": "main:0:zsh - \"doy@lance:~\"",
+ "marks": [],
+ "name": "main:0:zsh - \"doy@hornet:~/conf\"",
"percent": 0.333333333333333,
"swallows": [
{
@@ -25,6 +30,7 @@
},
{
"border": "pixel",
+ "current_border_width": 1,
"floating": "auto_off",
"geometry": {
"height": 340,
@@ -32,7 +38,8 @@
"x": 0,
"y": 0
},
- "name": "work:0:zsh - \"doy@lance:~/work\"",
+ "marks": [],
+ "name": "work:0:zsh - \"doy@hornet:~\"",
"percent": 0.333333333333333,
"swallows": [
{
@@ -43,6 +50,7 @@
},
{
"border": "pixel",
+ "current_border_width": 1,
"floating": "auto_off",
"geometry": {
"height": 340,
@@ -50,7 +58,8 @@
"x": 0,
"y": 0
},
- "name": "misc:0:zsh - \"doy@lance:~\"",
+ "marks": [],
+ "name": "misc:0:mtr - \"doy@hornet:~\"",
"percent": 0.333333333333333,
"swallows": [
{
@@ -63,14 +72,17 @@
}
{
+ // splitv split container with 2 children
"border": "pixel",
"floating": "auto_off",
"layout": "splitv",
- "percent": 0.7,
+ "marks": [],
+ "percent": 0.662748148148148,
"type": "con",
"nodes": [
{
"border": "pixel",
+ "current_border_width": 1,
"floating": "auto_off",
"geometry": {
"height": 340,
@@ -78,7 +90,8 @@
"x": 0,
"y": 0
},
- "name": "chat:0:WeeChat 0.4.3 - \"WeeChat 0.4.3\"",
+ "marks": [],
+ "name": "chat:0:vim - \"doy@hornet:~\"",
"percent": 0.5,
"swallows": [
{
@@ -89,6 +102,7 @@
},
{
"border": "pixel",
+ "current_border_width": 1,
"floating": "auto_off",
"geometry": {
"height": 340,
@@ -96,7 +110,8 @@
"x": 0,
"y": 0
},
- "name": "docs:0:zsh - \"doy@lance:~\"",
+ "marks": [],
+ "name": "docs:0:zsh - \"doy@hornet:~\"",
"percent": 0.5,
"swallows": [
{
@@ -107,3 +122,4 @@
}
]
}
+
diff --git a/bin/hush/status b/i3status/.bin/status
index d068a17..5674876 100755
--- a/bin/hush/status
+++ b/i3status/.bin/status
@@ -138,6 +138,31 @@ sub handle_i3status {
};
}
+ chomp(my $brightness = `backlight get`);
+ $brightness = sprintf("%3d", $brightness);
+ splice @$line, -1, 0, {
+ name => 'brightness',
+ full_text => "\N{WHITE SUN WITH RAYS} $brightness%",
+ color => '#FFFFFF'
+ };
+
+ chomp(my $volume = `volume get`);
+ if ($volume eq 'mute') {
+ splice @$line, -1, 0, {
+ name => 'volume',
+ full_text => "\N{SPEAKER} ",
+ color => '#FFFFFF'
+ };
+ }
+ else {
+ $volume = sprintf("%3d", $volume);
+ splice @$line, -1, 0, {
+ name => 'volume',
+ full_text => "\N{SPEAKER WITH THREE SOUND WAVES} $volume%",
+ color => '#FFFFFF'
+ };
+ }
+
$current_data = $line;
show_status();
diff --git a/bin/hush/update-weather b/i3status/.bin/update-weather
index 8105223..fb8afca 100755
--- a/bin/hush/update-weather
+++ b/i3status/.bin/update-weather
@@ -2,5 +2,6 @@
set -eu
set -o pipefail
-weather > ~/.cache/weather.new
+echo "updating weather..."
+"$(dirname "$0")"/weather >~/.cache/weather.new
mv ~/.cache/weather.new ~/.cache/weather
diff --git a/bin/hush/weather b/i3status/.bin/weather
index 6d762d7..1cbbffb 100755
--- a/bin/hush/weather
+++ b/i3status/.bin/weather
@@ -11,45 +11,45 @@ use HTTP::Tiny;
use JSON::PP;
use List::Util qw(min max);
-my %weather_pics = (
- 'clear-day' => "\x{2600}",
- 'clear-night' => "\x{2600}",
- 'rain' => "\x{2614}",
- 'snow' => "\x{2744}",
- 'sleet' => "\x{2614}",
- 'wind' => "\x{224B}",
- 'fog' => "\x{2592}",
- 'cloudy' => "\x{2601}",
- 'partly-cloudy-day' => "\x{2601}",
- 'partly-cloudy-night' => "\x{2601}",
-);
-
-my $config_dir = "$ENV{HOME}/.config/darksky";
-
-my $api_key_filename = "$config_dir/api";
-chomp(my $api_key = slurp($api_key_filename));
+my $config_dir = "$ENV{HOME}/.config/weather";
my $location_filename = "$config_dir/location";
chomp(my $location = slurp($location_filename));
if (length($location) == 5) {
$location = zip_location($location);
}
+(my $lat, my $lon) = split ',', $location;
+my $tz = readlink("/etc/localtime");
+$tz =~ s{^/usr/share/zoneinfo/}{};
-my $data = slurp_http("https://api.darksky.net/forecast/$api_key/$location?units=si");
-my $hour = (localtime(int($data->{currently}{time})))[2];
+my $data = slurp_http("https://api.open-meteo.com/v1/forecast?latitude=$lat&longitude=$lon&timezone=$tz&current_weather=true&hourly=temperature_2m,apparent_temperature,precipitation_probability");
+my $time = $data->{current_weather}{time};
+my $hourly = $data->{hourly};
+my @forecast;
+for my $i (0..$#{$hourly->{time}}) {
+ next if $hourly->{time}[$i] lt $time;
+ push @forecast, {
+ temp => $hourly->{temperature_2m}[$i],
+ feels_like => $hourly->{apparent_temperature}[$i],
+ precip_probability => $hourly->{precipitation_probability}[$i],
+ };
+ last if @forecast >= 12;
+}
-my $temp = int($data->{currently}{temperature});
-my $temp_unit = $data->{flags}{units} eq 'us' ? 'F' : 'C';
-my ($temp_limit, $temp_direction) = temp_limit($data->{hourly}{data}, $hour);
-my $feelslike_temp = int($data->{currently}{apparentTemperature});
-my $precip = int($data->{hourly}{data}[0]{precipProbability} * 100);
+my ($hour) = $time =~ /^....-..-..T(..):..$/;
+my $temp = round($data->{current_weather}{temperature});
+my $temp_unit = $data->{hourly_units}{temperature_2m};
+$temp_unit =~ s/\N{DEGREE SIGN}//;
+my ($temp_limit, $temp_direction) = temp_limit(\@forecast, $hour);
+my $feelslike_temp = round($forecast[0]{feels_like});
+my $precip = $forecast[0]{precip_probability};
say join(' ',
"$precip%",
- $weather_pics{$data->{minutely}{icon}} // "?",
+ weather_pic($data->{current_weather}{weathercode}, $data->{current_weather}{is_day}),
"${temp}${temp_unit}",
(($feelslike_temp != $temp)
- ? ("(\x{2245}${feelslike_temp}${temp_unit})")
+ ? ("(\N{APPROXIMATELY EQUAL TO}${feelslike_temp}${temp_unit})")
: ()),
"${temp_direction}${temp_limit}${temp_unit}",
);
@@ -81,16 +81,82 @@ sub zip_location($zip) {
die "couldn't find zip $zip";
}
-sub temp_limit($hourly, $hour) {
- my @temps = map { int($_->{temperature}) } @$hourly[0..12];
+sub temp_limit($forecast, $hour) {
+ my @temps = map { $_->{temp} } @$forecast;
if ($hour < 4 || $hour >= 16) {
- return (min(@temps), "\x{2193}");
+ return (round(min(@temps)), "\N{DOWNWARDS ARROW}");
+ }
+ else {
+ return (round(max(@temps)), "\N{UPWARDS ARROW}");
+ }
+}
+
+sub weather_pic($code, $is_day) {
+ # Clear sky
+ if ($code == 0) {
+ if ($is_day) {
+ "\N{BLACK SUN WITH RAYS}"
+ } else {
+ "\N{LAST QUARTER MOON}"
+ }
+ }
+ # Mainly clear, partly cloudy, and overcast
+ elsif ($code == 1 || $code == 2 || $code == 3) {
+ "\N{CLOUD}"
+ }
+ # Fog and depositing rime fog
+ elsif ($code == 45 || $code == 48) {
+ "\N{MEDIUM SHADE}"
+ }
+ # Drizzle: Light, moderate, and dense intensity
+ elsif ($code == 51 || $code == 53 || $code == 55) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
+ }
+ # Freezing Drizzle: Light and dense intensity
+ elsif ($code == 56 || $code == 57) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
+ }
+ # Rain: Slight, moderate and heavy intensity
+ elsif ($code == 61 || $code == 63 || $code == 65) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
+ }
+ # Freezing Rain: Light and heavy intensity
+ elsif ($code == 66 || $code == 67) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
+ }
+ # Snow fall: Slight, moderate, and heavy intensity
+ elsif ($code == 71 || $code == 73 || $code == 75) {
+ "\N{SNOWFLAKE}"
+ }
+ # Snow grains
+ elsif ($code == 77) {
+ "\N{SNOWFLAKE}"
+ }
+ # Rain showers: Slight, moderate, and violent
+ elsif ($code == 80 || $code == 81 || $code == 82) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
+ }
+ # Snow showers slight and heavy
+ elsif ($code == 85 || $code == 86) {
+ "\N{SNOWFLAKE}"
+ }
+ # Thunderstorm: Slight or moderate
+ elsif ($code == 95) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
+ }
+ # Thunderstorm with slight and heavy hail
+ elsif ($code == 96 || $code == 99) {
+ "\N{UMBRELLA WITH RAIN DROPS}"
}
else {
- return (max(@temps), "\x{2191}");
+ '?'
}
}
+sub round($x) {
+ int($x + 0.5)
+}
+
__DATA__
00601=18.180555,-66.749961
00602=18.361945,-67.175597
diff --git a/i3status/.config/i3status/config b/i3status/.config/i3status/config
new file mode 100644
index 0000000..e7ff076
--- /dev/null
+++ b/i3status/.config/i3status/config
@@ -0,0 +1,32 @@
+general {
+ output_format = i3bar
+ interval = 1
+}
+
+order += "cpu_usage"
+order += "wireless wlan0"
+order += "battery 0"
+order += "time"
+order += "load"
+
+cpu_usage {
+ format = "CPU: %usage"
+}
+
+wireless wlan0 {
+ format_up = "wlan0: (%essid: %quality)"
+ format_down = "wlan0"
+}
+
+battery 0 {
+ last_full_capacity = true
+ format = "%status %percentage (%remaining %consumption)"
+}
+
+time {
+ format = "%a %b %d %H:%M:%S"
+}
+
+load {
+ format = "%1min"
+}
diff --git a/i3status/.config/systemd/user/weather.service b/i3status/.config/systemd/user/weather.service
new file mode 100644
index 0000000..b980952
--- /dev/null
+++ b/i3status/.config/systemd/user/weather.service
@@ -0,0 +1,3 @@
+[Service]
+Type=oneshot
+ExecStart=%h/.bin/update-weather
diff --git a/i3status/.config/systemd/user/weather.timer b/i3status/.config/systemd/user/weather.timer
new file mode 100644
index 0000000..b90e4bf
--- /dev/null
+++ b/i3status/.config/systemd/user/weather.timer
@@ -0,0 +1,6 @@
+[Timer]
+OnStartupSec=0
+OnUnitActiveSec=900
+
+[Install]
+WantedBy=timers.target
diff --git a/i3status/Makefile b/i3status/Makefile
new file mode 100644
index 0000000..6627473
--- /dev/null
+++ b/i3status/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable weather.timer
+ @systemctl --user start weather.timer
+
+uninstall:
+ @systemctl --user stop weather.timer
+ @systemctl --user disable weather.timer
diff --git a/install b/install
new file mode 100755
index 0000000..2216e66
--- /dev/null
+++ b/install
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -eu
+
+[ -d "$1" ] || (echo "package $1 not found" >&2; exit 1)
+
+./build "$1"
+stow "$1"
+[ -f "$1/Makefile" ] && (cd "$1" && make -s install)
+
+true
diff --git a/laptop/.bin/backlight b/laptop/.bin/backlight
new file mode 100755
index 0000000..314e874
--- /dev/null
+++ b/laptop/.bin/backlight
@@ -0,0 +1,47 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.014;
+
+my @levels = (
+ 1,
+ 2,
+ 4,
+ 8,
+ 16,
+ 31,
+ 63,
+ 125,
+ 250,
+ 500,
+ 1000,
+);
+chomp(my $current = `xbacklight -getf`);
+$current = int($current * 10);
+my $idx;
+for my $i (0..$#levels) {
+ my $level = $levels[$i];
+ $idx = $i;
+ last if $level >= $current;
+}
+
+my $inc;
+if ($ARGV[0] eq 'inc') {
+ $inc = 1;
+}
+elsif ($ARGV[0] eq 'dec') {
+ $inc = -1;
+}
+elsif ($ARGV[0] eq 'get') {
+ say $idx * 10;
+ exit;
+}
+else {
+ die "unknown arg '$ARGV[0]'";
+}
+
+my $new_idx = $idx + $inc;
+if ($new_idx >= 0 && $new_idx <= $#levels) {
+ my $new_level = $levels[$new_idx] * 0.1;
+ system("xbacklight -set $new_level");
+}
diff --git a/laptop/.bin/import b/laptop/.bin/import
new file mode 100755
index 0000000..ea4f1f2
--- /dev/null
+++ b/laptop/.bin/import
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+services=""
+trap 'for service in $services; do systemctl --user start $service; done' EXIT
+for service in unclutter picom; do
+ if [ "$(systemctl --user show --property MainPID --value "$service")" != 0 ]; then
+ systemctl --user stop "$service"
+ services="$service $services"
+ fi
+done
+/usr/bin/import "$@"
diff --git a/bin/hush/numkeys b/laptop/.bin/numkeys
index 9d037f5..9b284bb 100755
--- a/bin/hush/numkeys
+++ b/laptop/.bin/numkeys
@@ -47,8 +47,11 @@ toggle() {
}
case "$1" in
- on) on ;;
- off) off ;;
- toggle) toggle ;;
- *) echo invalid 1>&2; exit 1 ;;
+on) on ;;
+off) off ;;
+toggle) toggle ;;
+*)
+ echo invalid 1>&2
+ exit 1
+ ;;
esac
diff --git a/laptop/.bin/sc b/laptop/.bin/sc
new file mode 100755
index 0000000..614a1bc
--- /dev/null
+++ b/laptop/.bin/sc
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+case "$1" in
+on)
+ xset s 300 5
+ xset dpms 600 600 600
+ ;;
+off)
+ xset s off
+ xset dpms 0 0 0
+ ;;
+q)
+ xset q | perl -nlE'print if ((/^(:?Screen Saver|DPMS)/.../^[^\s]/) && /^(:?Screen Saver|DPMS|\s)/)'
+ ;;
+*)
+ echo "$(basename "$0"): unknown argument '$1'" >&2
+ exit 1
+ ;;
+esac
diff --git a/laptop/.bin/setup-inputs b/laptop/.bin/setup-inputs
new file mode 100755
index 0000000..cd1b4cf
--- /dev/null
+++ b/laptop/.bin/setup-inputs
@@ -0,0 +1,18 @@
+#!/bin/sh
+set -eu
+set -o pipefail
+
+# key bindings
+setxkbmap -option ctrl:nocaps
+setxkbmap -option compose:caps
+xmodmap "$HOME"/.Xmodmap
+"$(dirname "$0")"/numkeys on
+
+# trackpad settings
+touchpad="$(xinput list --name-only | grep Touchpad)"
+xinput set-prop "$touchpad" "libinput Accel Speed" 0.4
+xinput set-prop "$touchpad" "libinput Tapping Enabled" 1
+
+# needs to happen after xmodmap stuff
+systemctl --user restart xcape
+systemctl --user restart xbindkeys
diff --git a/laptop/.bin/tv b/laptop/.bin/tv
new file mode 100755
index 0000000..1c99e2e
--- /dev/null
+++ b/laptop/.bin/tv
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+if xrandr -q | grep -q "DP-3 connected ("; then
+ xrandr --auto
+ xrandr --output DP-3 --right-of eDP-1 --mode 1920x1080
+elif xrandr -q | grep -q "DP-4 connected ("; then
+ xrandr --auto
+ xrandr --output DP-4 --right-of eDP-1 --mode 1920x1080
+elif xrandr -q | grep -q "DP-3 connected"; then
+ xrandr --auto
+ xrandr --output DP-4 --off
+elif xrandr -q | grep -q "DP-4 connected"; then
+ xrandr --auto
+ xrandr --output DP-4 --off
+fi
diff --git a/laptop/.bin/volume b/laptop/.bin/volume
new file mode 100755
index 0000000..668c1b1
--- /dev/null
+++ b/laptop/.bin/volume
@@ -0,0 +1,45 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use 5.014;
+
+chomp(my $sink=`pactl get-default-sink`);
+
+sub get {
+ if (`pactl get-sink-mute $sink` =~ /Mute: yes/) {
+ 'mute'
+ }
+ else {
+ (`pactl get-sink-volume $sink` =~ /(\d+)%/)[0]
+ }
+}
+
+if ($ARGV[0] eq 'get') {
+ say get;
+}
+elsif ($ARGV[0] eq 'up') {
+ my $get = get;
+ system("pactl set-sink-mute $sink 0");
+ if ($get eq 'mute') {
+ exit;
+ }
+ elsif ($get <= 90) {
+ system("pactl set-sink-volume $sink +10%");
+ }
+ elsif ($get < 100) {
+ system("pactl set-sink-volume $sink 100%");
+ }
+}
+elsif ($ARGV[0] eq 'down') {
+ my $get = get;
+ if ($get eq 'mute') {
+ exit;
+ }
+ system("pactl set-sink-volume $sink -10%");
+}
+elsif ($ARGV[0] eq 'mute') {
+ system("pactl set-sink-mute $sink toggle")
+}
+else {
+ die "unknown command '$ARGV[0]'";
+}
diff --git a/laptop/.bin/vscreen b/laptop/.bin/vscreen
new file mode 100755
index 0000000..52fc5cc
--- /dev/null
+++ b/laptop/.bin/vscreen
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+case "$1" in
+goto)
+ xrandr --addmode VIRTUAL1 1920x1080
+ xrandr --output VIRTUAL1 --auto --output eDP1 --auto --left-of VIRTUAL1
+ i3-switch-workspace virtual
+ ;;
+off)
+ xrandr --output VIRTUAL1 --off
+ ;;
+*)
+ echo "bad subcommand $1" >&2
+ exit 1
+ ;;
+esac
diff --git a/laptop/.bin/watch-kbd b/laptop/.bin/watch-kbd
new file mode 100755
index 0000000..269213e
--- /dev/null
+++ b/laptop/.bin/watch-kbd
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -eu
+set -o pipefail
+
+trap 'kill $(jobs -p)' EXIT
+
+inotifywait -mq -e create -e delete -e moved_to --exclude '.*tmp.*' /dev/input/by-path/ |
+ while read -r event; do
+ echo "$event"
+ if echo "$event" | grep -q -- '-usb.*-kbd'; then
+ setup-inputs
+ fi
+ done &
+wait
diff --git a/bin/hush/webcam b/laptop/.bin/webcam
index fdac5f8..fdac5f8 100755
--- a/bin/hush/webcam
+++ b/laptop/.bin/webcam
diff --git a/laptop/.config/sh/rc.d/laptop b/laptop/.config/sh/rc.d/laptop
new file mode 100644
index 0000000..6f95731
--- /dev/null
+++ b/laptop/.config/sh/rc.d/laptop
@@ -0,0 +1 @@
+alias wifi="sudo systemctl restart iwd"
diff --git a/laptop/.config/systemd/user/watch-kbd.service b/laptop/.config/systemd/user/watch-kbd.service
new file mode 100644
index 0000000..b1a2add
--- /dev/null
+++ b/laptop/.config/systemd/user/watch-kbd.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=%h/.bin/watch-kbd
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/laptop/Makefile b/laptop/Makefile
new file mode 100644
index 0000000..a16e3bc
--- /dev/null
+++ b/laptop/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable watch-kbd
+ @systemctl --user start watch-kbd
+
+uninstall:
+ @systemctl --user stop watch-kbd
+ @systemctl --user disable watch-kbd
diff --git a/ledgerrc b/ledgerrc
deleted file mode 100644
index 6f379d5..0000000
--- a/ledgerrc
+++ /dev/null
@@ -1 +0,0 @@
---date-format %Y-%m-%d
diff --git a/lesskey b/less/.config/lesskey
index 5b831e1..5b831e1 100644
--- a/lesskey
+++ b/less/.config/lesskey
diff --git a/less/.config/sh/rc.d/less b/less/.config/sh/rc.d/less
new file mode 100644
index 0000000..fd25dbd
--- /dev/null
+++ b/less/.config/sh/rc.d/less
@@ -0,0 +1 @@
+export LESS='-QR'
diff --git a/mbsync/.mbsyncrc b/mbsync/.mbsyncrc
new file mode 100644
index 0000000..6530eb9
--- /dev/null
+++ b/mbsync/.mbsyncrc
@@ -0,0 +1,21 @@
+Expunge None
+Create Both
+
+MaildirStore local
+Path ~/Maildir/
+Inbox ~/Maildir/INBOX
+Trash Trash
+Flatten .
+
+IMAPStore mail
+Host mail.tozt.net
+User doy@tozt.net
+PassCmd "rbw get mail.tozt.net doy@tozt.net"
+SSLType IMAPS
+SSLVersions TLSv1.2 TLSv1.3
+
+Channel all
+Far :mail:
+Near :local:
+Sync Pull Push
+Patterns *
diff --git a/mbsyncloop/.bin/mbsyncloop b/mbsyncloop/.bin/mbsyncloop
new file mode 100755
index 0000000..bb16df1
--- /dev/null
+++ b/mbsyncloop/.bin/mbsyncloop
@@ -0,0 +1,312 @@
+#!/usr/bin/env perl
+use 5.016;
+use strict;
+use warnings;
+
+use File::Path;
+use File::Spec;
+use File::Temp;
+use JSON::PP;
+use POSIX 'mkfifo';
+
+# running a local build until
+# https://gitlab.com/shackra/goimapnotify/-/merge_requests/14 makes it into a
+# release
+my $GOIMAPNOTIFY = "$ENV{HOME}/.bin/local/goimapnotify";
+
+my $RUN_DIR = make_run_dir();
+my ($PW_PID, $GOIMAPNOTIFY_PID);
+
+$SIG{INT} = $SIG{TERM} = sub { cleanup(); exit };
+END { cleanup() }
+
+my $config = "$ENV{HOME}/.config/mbsyncloop/config.json";
+
+main($config);
+
+sub main {
+ my ($config) = @_;
+
+ my $pw_pipe = make_pw_pipe();
+ my $password_command_pipe = "head -n1 '$pw_pipe'";
+
+ my $config_data;
+ if (-f $config) {
+ $config_data = JSON::PP::decode_json(slurp($config));
+ }
+ else {
+ $config_data = {};
+ }
+
+ my $mbsync_config_data = slurp(
+ ($config_data->{mbsync_config} // '~/.mbsyncrc')
+ =~ s{^~/}{$ENV{HOME}/}r
+ );
+ my $password_command = extract_password_command($mbsync_config_data);
+
+ spawn_pw_proc($pw_pipe, $password_command);
+
+ my $goimapnotify_config_data = extract_goimapnotify_config(
+ $config_data,
+ $mbsync_config_data,
+ $password_command_pipe,
+ );
+
+ my $goimapnotify_r = spawn_goimapnotify_proc(
+ $goimapnotify_config_data,
+ );
+
+ my $generated_mbsync_config_file = write_mbsync_config(
+ $mbsync_config_data,
+ $goimapnotify_config_data->{boxes},
+ $password_command_pipe,
+ );
+
+ loop(
+ $config_data,
+ $generated_mbsync_config_file,
+ $goimapnotify_r,
+ );
+}
+
+sub make_pw_pipe {
+ my $file = File::Spec->catfile($RUN_DIR, "mbsyncloop");
+ unlink($file);
+ mkfifo($file, 0700) or die "couldn't create $file: $!";
+ $file
+}
+
+sub extract_goimapnotify_config {
+ my ($config_data, $mbsync_config_data, $password_command) = @_;
+
+ (my $host) = $mbsync_config_data =~ /^Host (.*)$/m;
+ (my $port) = $mbsync_config_data =~ /^Port (.*)$/m;
+ (my $user) = $mbsync_config_data =~ /^User (.*)$/m;
+
+ my $tls;
+ if ($mbsync_config_data =~ /SSLType\s+IMAPS/) {
+ $tls = JSON::PP::true;
+ $port //= 993;
+ }
+ else {
+ $tls = JSON::PP::false;
+ $port //= 143;
+ }
+
+ my $goimapnotify_config = {
+ host => $host,
+ port => $port,
+ tls => $tls,
+ username => $user,
+ passwordCmd => $password_command,
+ };
+
+ my @mailboxes;
+ if ($config_data->{boxes}) {
+ @mailboxes = @{ $config_data->{boxes} };
+ }
+ else {
+ @mailboxes = read_mailboxes($goimapnotify_config);
+ if ($config_data->{box_patterns}) {
+ @mailboxes = grep {
+ my $mailbox = $_;
+ grep {
+ $mailbox =~ /$_/
+ } @{ $config_data->{box_patterns} }
+ } @mailboxes
+ }
+ }
+
+ $goimapnotify_config->{onNewMail} = "echo new";
+ $goimapnotify_config->{boxes} = \@mailboxes;
+
+ $goimapnotify_config
+}
+
+sub read_mailboxes {
+ my ($config) = @_;
+
+ my $tmp = File::Temp->new(DIR => $RUN_DIR);
+ $tmp->print(JSON::PP::encode_json($config));
+ $tmp->flush;
+ open my $fh, '-|', $GOIMAPNOTIFY, '--conf', $tmp->filename, '--list'
+ or die "couldn't run goimapnotify: $!";
+ <$fh>;
+
+ map { chomp; s/^[^ ]* //r } <$fh>
+}
+
+sub extract_password_command {
+ my ($mbsync_config) = @_;
+ (my $password_command) = $mbsync_config =~ /^PassCmd "(.*)"$/m;
+ $password_command
+}
+
+sub spawn_pw_proc {
+ my ($pw_pipe, $password_command) = @_;
+
+ my $pw = fetch_password($password_command);
+
+ $PW_PID = fork;
+ die "fork failed: $!" unless defined $PW_PID;
+ if (!$PW_PID) {
+ $SIG{PIPE} = 'IGNORE';
+ setpgrp(0, 0);
+ while (1) {
+ open my $fh, '>', $pw_pipe or die "couldn't open $pw_pipe";
+ $fh->print("$pw\n");
+ close $fh;
+ }
+ }
+}
+
+sub fetch_password {
+ my ($password_command) = @_;
+ my $pw = `$password_command`;
+ die "failed to fetch password: command returned $?" if $?;
+ $pw
+}
+
+sub spawn_goimapnotify_proc {
+ my ($config) = @_;
+
+ pipe(my $goimapnotify_r, my $goimapnotify_w)
+ or die "failed to create unnamed pipe: $!";
+
+ $GOIMAPNOTIFY_PID = fork;
+ die "fork failed: $!" unless defined $GOIMAPNOTIFY_PID;
+ if (!$GOIMAPNOTIFY_PID) {
+ setpgrp(0, 0);
+ close $goimapnotify_r;
+
+ my $tmp = File::Temp->new(DIR => $RUN_DIR);
+ $tmp->print(JSON::PP::encode_json($config));
+ $tmp->flush;
+
+ while (1) {
+ open my $fh, '-|', $GOIMAPNOTIFY, '--conf', $tmp->filename
+ or die "couldn't run goimapnotify: $!";
+ while (<$fh>) {
+ $goimapnotify_w->print("N\n");
+ $goimapnotify_w->flush;
+ }
+ }
+ }
+ close $goimapnotify_w;
+
+ $goimapnotify_r
+}
+
+sub write_mbsync_config {
+ my ($mbsync_config, $mailboxes, $password_command) = @_;
+
+ $mbsync_config =~ s/^PassCmd .*$/PassCmd "$password_command"/m;
+ my ($far) = $mbsync_config =~ /^IMAPStore (.*)$/m;
+ my ($near) = $mbsync_config =~ /^MaildirStore (.*)$/m;
+
+ my $patterns = join "\n", map { "Pattern $_" } @$mailboxes;
+ my $mbsync_channels = <<EOF;
+Channel mbsyncloop_priority
+Far :$far:
+Near :$near:
+Sync Pull Push
+$patterns
+
+Channel mbsyncloop_all
+Far :$far:
+Near :$near:
+Sync Pull Push
+Patterns *
+EOF
+
+ my $tmp = File::Temp->new(DIR => $RUN_DIR);
+ $tmp->print($mbsync_config);
+ $tmp->print("\n");
+ $tmp->print($mbsync_channels);
+ $tmp->flush;
+
+ $tmp
+}
+
+sub loop {
+ my ($config_data, $mbsync_config, $goimapnotify_r) = @_;
+
+ my $poll_interval = $config_data->{poll_interval} // 15 * 60;
+ my $last_all = 0;
+ $SIG{HUP} = sub { $last_all = 0 };
+ while (1) {
+ my $now = time;
+ if (($now - $last_all) >= $poll_interval) {
+ sync(
+ $mbsync_config,
+ "mbsyncloop_all",
+ $config_data->{on_new_mail},
+ );
+ $last_all = $now;
+ }
+ if (idle($goimapnotify_r, $poll_interval)) {
+ sync(
+ $mbsync_config,
+ "mbsyncloop_priority",
+ $config_data->{on_new_mail},
+ );
+ }
+ }
+}
+
+sub sync {
+ my ($config, $channel, $on_new_mail) = @_;
+ my $config_file = $config->filename;
+ while (1) {
+ my $status = system("mbsync -c '$config_file' $channel");
+ if (!$status) {
+ system($on_new_mail) if defined $on_new_mail;
+ last;
+ }
+ sleep 5;
+ }
+}
+
+sub idle {
+ my ($goimapnotify_r, $max_delay) = @_;
+ my $rin = '';
+ vec($rin, fileno($goimapnotify_r), 1) = 1;
+ my $ready = select(my $rout = $rin, undef, undef, $max_delay);
+ return 0 if $ready == -1 && $! == POSIX::EINTR;
+ die "failed to read goimapnotify output: $!" if $ready == -1;
+ if ($ready) {
+ while (1) {
+ my $ready = select(my $rout = $rin, undef, undef, 0.01);
+ return 0 if $ready == -1 && $! == POSIX::EINTR;
+ die "failed to read goimapnotify output: $!" if $ready == -1;
+ last unless $ready;
+ sysread $goimapnotify_r, my $data, 4096;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+sub slurp {
+ my ($file) = @_;
+ local $/;
+ open my $fh, '<', $file or die "couldn't open $file: $!";
+ <$fh>
+}
+
+sub make_run_dir {
+ my $dir = "/run/user/$>";
+ if (!-d $dir) {
+ $dir = File::Spec->tmpdir();
+ }
+ unlink File::Spec->catfile($dir, "mbsyncloop");
+ mkdir File::Spec->catfile($dir, "mbsyncloop");
+ mkdir File::Spec->catfile($dir, "mbsyncloop", $$);
+ File::Spec->catfile($dir, "mbsyncloop", $$)
+}
+
+sub cleanup {
+ kill KILL => -$PW_PID if $PW_PID;
+ kill KILL => -$GOIMAPNOTIFY_PID if $GOIMAPNOTIFY_PID;
+ File::Path::remove_tree($RUN_DIR) if $RUN_DIR;
+}
diff --git a/mbsyncloop/.config/mbsyncloop/config.json b/mbsyncloop/.config/mbsyncloop/config.json
new file mode 100644
index 0000000..879665f
--- /dev/null
+++ b/mbsyncloop/.config/mbsyncloop/config.json
@@ -0,0 +1,4 @@
+{
+ "box_patterns": ["^(?!old\\.)"],
+ "on_new_mail": "notmuch new | grep -v '^No new mail\\.$'"
+}
diff --git a/mbsyncloop/.config/systemd/user/mbsyncloop.service b/mbsyncloop/.config/systemd/user/mbsyncloop.service
new file mode 100644
index 0000000..c53e989
--- /dev/null
+++ b/mbsyncloop/.config/systemd/user/mbsyncloop.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=%h/.bin/mbsyncloop
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/mbsyncloop/Makefile b/mbsyncloop/Makefile
new file mode 100644
index 0000000..b095cbd
--- /dev/null
+++ b/mbsyncloop/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable mbsyncloop
+ @systemctl --user start mbsyncloop
+
+uninstall:
+ @systemctl --user stop mbsyncloop
+ @systemctl --user disable mbsyncloop
diff --git a/mpdscribble/mpdscribble.conf.tmpl b/mpdscribble/mpdscribble.conf.tmpl
deleted file mode 100644
index c216dfc..0000000
--- a/mpdscribble/mpdscribble.conf.tmpl
+++ /dev/null
@@ -1,7 +0,0 @@
-username = doyster
-password =
-verbose = 5
-log = -
-cache = ~/.cache/mpd/mpdscribble.cache
-musicdir = ~/media/audio/copy
-host = localhost
diff --git a/config/msmtp/config b/msmtp/.config/msmtp/config
index 77be9e9..6ceebb5 100644
--- a/config/msmtp/config
+++ b/msmtp/.config/msmtp/config
@@ -7,5 +7,5 @@ account default
host mail.tozt.net
from doy@tozt.net
user doy@tozt.net
-passwordeval pass "websites/mail.tozt.net/doy@tozt.net"
+passwordeval rbw get mail.tozt.net doy@tozt.net
tls_trust_file /etc/ssl/certs/ca-certificates.crt
diff --git a/msmtp/Makefile b/msmtp/Makefile
new file mode 100644
index 0000000..e0d5b4b
--- /dev/null
+++ b/msmtp/Makefile
@@ -0,0 +1,4 @@
+include ../Makefile.include
+
+build:
+ @chmod 600 .config/msmtp/config
diff --git a/mutt/.config/mutt/choose-muttrc-type b/mutt/.config/mutt/choose-muttrc-type
new file mode 100755
index 0000000..ddadb70
--- /dev/null
+++ b/mutt/.config/mutt/choose-muttrc-type
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+set -o pipefail
+
+case "$(hostname)" in
+hornet)
+ echo 'source ~/.config/mutt/local'
+ ;;
+*)
+ echo 'source ~/.config/mutt/imap'
+ ;;
+esac
diff --git a/mutt/imap b/mutt/.config/mutt/imap
index 13ed472..13ed472 100644
--- a/mutt/imap
+++ b/mutt/.config/mutt/imap
diff --git a/mutt/offlineimap b/mutt/.config/mutt/local
index 883cb67..636bd29 100644
--- a/mutt/offlineimap
+++ b/mutt/.config/mutt/local
@@ -10,8 +10,7 @@ mailboxes `\
echo -n "\"=$basename\" ";\
fi\
done`
-macro index R "<enter-command>unset wait_key<enter><shell-escape>update-mail<enter><enter-command>set wait_key<enter>" "fetch mail with offlineimap"
+macro index R "<enter-command>unset wait_key<enter><shell-escape>kill -HUP $(systemctl --user show --property MainPID --value mbsyncloop)<enter><enter-command>set wait_key<enter>" "fetch mail with mbsync"
set timeout=3
-set mail_check=0
# vim: ft=neomuttrc
diff --git a/mutt/mailcap b/mutt/.config/mutt/mailcap
index a791985..a791985 100644
--- a/mutt/mailcap
+++ b/mutt/.config/mutt/mailcap
diff --git a/mutt/muttrc b/mutt/.config/mutt/muttrc
index 112fc3b..8321ba1 100644
--- a/mutt/muttrc
+++ b/mutt/.config/mutt/muttrc
@@ -1,10 +1,11 @@
-source '~/.mutt/choose-muttrc-type|'
+source '~/.config/mutt/choose-muttrc-type|'
# folders {{{
set record="=Sent"
set postponed="=Drafts"
set header_cache="~/.cache/mutt/headers"
set message_cachedir="~/.cache/mutt/bodies"
-set mailcap_path="~/.mutt/mailcap"
+set mailcap_path="~/.config/mutt/mailcap"
+set nm_default_url="notmuch://$HOME/.cache/notmuch"
# }}}
# identity {{{
# i am "Jesse Luehrs <doy@tozt.net>"
@@ -115,8 +116,8 @@ set quit
bind generic , enter-command
bind generic,pager,index B help
-bind generic,compose i exit
-bind index i noop
+bind pager,compose,attach i exit
+bind generic,index i noop
bind generic,pager,index ? search-reverse
bind generic,pager,index p search-opposite
@@ -140,7 +141,7 @@ macro index,pager I "c=INBOX<enter>"
bind index,pager M compose-to-sender
bind index,pager A group-reply
-macro index S "<enter-command>set resolve=no<enter><clear-flag>N<save-message>=spam<enter><enter-command>set resolve=yes<enter>" "mark message as spam"
+macro index S "<enter-command>set resolve=no<enter><clear-flag>N<save-message>=Junk<enter><enter-command>set resolve=yes<enter>" "mark message as spam"
bind editor <tab> complete-query
# }}}
diff --git a/mutt/Makefile b/mutt/Makefile
new file mode 100644
index 0000000..2caf3fd
--- /dev/null
+++ b/mutt/Makefile
@@ -0,0 +1,5 @@
+include ../Makefile.include
+
+install:
+ @mkdir -p $(HOME)/.cache/mutt/headers
+ @mkdir -p $(HOME)/.cache/mutt/bodies
diff --git a/mutt/choose-muttrc-type b/mutt/choose-muttrc-type
deleted file mode 100755
index 46b2cbe..0000000
--- a/mutt/choose-muttrc-type
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-case "$(hostname)" in
-hush)
- echo 'source ~/.mutt/offlineimap'
- ;;
-*)
- echo 'source ~/.mutt/imap'
- ;;
-esac
diff --git a/nethack/.config/sh/rc.d/nethack b/nethack/.config/sh/rc.d/nethack
new file mode 100644
index 0000000..27583ba
--- /dev/null
+++ b/nethack/.config/sh/rc.d/nethack
@@ -0,0 +1 @@
+alias nao="ssh nethack@alt.org"
diff --git a/nethack/.nethackrc b/nethack/.nethackrc
new file mode 100644
index 0000000..f351c32
--- /dev/null
+++ b/nethack/.nethackrc
@@ -0,0 +1,176 @@
+# improve the consistency of telnet ping/pong
+OPTIONS=!sparkle
+OPTIONS=runmode:teleport
+OPTIONS=!timed_delay
+
+# display
+OPTIONS=showexp
+OPTIONS=showscore
+OPTIONS=time
+OPTIONS=color
+OPTIONS=boulder:0
+OPTIONS=!tombstone
+OPTIONS=!news
+OPTIONS=!legacy
+OPTIONS=suppress_alert:3.4.3
+OPTIONS=hilite_pet
+OPTIONS=hilite_pile
+OPTIONS=hitpointbar
+OPTIONS=lit_corridor
+OPTIONS=msg_window:full
+OPTIONS=pile_limit:0
+
+# functionality
+OPTIONS=autopickup
+OPTIONS=pickup_types:$"?!=/
+OPTIONS=pickup_burden:unburdened
+OPTIONS=paranoid_confirmation:none
+OPTIONS=pettype:none
+OPTIONS=!cmdassist
+OPTIONS=disclose:yi +avgco
+OPTIONS=!number_pad
+
+# miscellaneous
+OPTIONS=!mail
+
+# map changes for code simplicity
+SYMBOLS=S_mimic_def:m
+SYMBOLS=S_ghost:X
+SYMBOLS=S_worm_tail:w
+# "strange monster" = m (mimic)
+# ghost/shade = X now space is solid rock
+# worm tail = w now ~ is water
+
+SYMBOLS=S_web:^
+# spider web = ^ now " is amulet
+
+SYMBOLS=S_sink:{
+SYMBOLS=S_hcdbridge:}
+SYMBOLS=S_vcdbridge:}
+SYMBOLS=S_bars:}
+SYMBOLS=S_tree:}
+SYMBOLS=S_hcdoor:]
+SYMBOLS=S_vcdoor:]
+SYMBOLS=S_grave:\\
+SYMBOLS=S_pool:~
+SYMBOLS=S_water:~
+SYMBOLS=S_lava:~
+# sink => { one less #, walkable
+# drawbridge => } one less #, not walkable
+# iron bars => } one less #, not walkable (color: cyan)
+# trees => } one less #, not walkable (color: green)
+# closed doors => ] now + is spellbook
+# grave => \ now gray | and - are walls, (grey -- thrones)
+# water => ~ it looks cool (blue -- long worm tail)
+
+OPTIONS=statushilites:1
+OPTIONS=hilite_status:carrying-capacity/burdened/yellow
+OPTIONS=hilite_status:carrying-capacity/stressed/red
+OPTIONS=hilite_status:carrying-capacity/strained/orange
+OPTIONS=hilite_status:carrying-capacity/overtaxed/orange
+OPTIONS=hilite_status:carrying-capacity/overloaded/orange
+OPTIONS=hilite_status:hitpoints/<100%/green
+OPTIONS=hilite_status:hitpoints/<50%/yellow
+OPTIONS=hilite_status:hitpoints/<33%/red
+OPTIONS=hilite_status:hitpoints/<25%/orange
+OPTIONS=hilite_status:hitpoints/<15%/black
+OPTIONS=hilite_status:hitpoints/100%/normal
+OPTIONS=hilite_status:hitpoints/<5/black
+OPTIONS=hilite_status:power/<100%/lightcyan
+OPTIONS=hilite_status:power/<50%/lightmagenta
+OPTIONS=hilite_status:power/<33%/magenta
+OPTIONS=hilite_status:power/100%/normal
+OPTIONS=hilite_status:hunger/satiated/green
+OPTIONS=hilite_status:hunger/hungry/yellow
+OPTIONS=hilite_status:hunger/weak/red
+OPTIONS=hilite_status:hunger/fainting/orange
+OPTIONS=hilite_status:hunger/fainted/orange
+OPTIONS=hilite_status:hunger/starved/orange
+OPTIONS=hilite_status:condition/major_troubles/orange
+OPTIONS=hilite_status:condition/minor_troubles/yellow
+OPTIONS=hilite_status:condition/movement/blue
+
+OPTIONS=menucolors
+
+# ascension kit
+MENUCOLOR=" bag .* holding"=magenta
+MENUCOLOR=" luck(stone)?($| )"=magenta
+MENUCOLOR=" wand .* wish(ing)?($| )"=magenta
+MENUCOLOR=" magic marker"=magenta
+MENUCOLOR=" magic lamp|lamp .* magic"=magenta
+MENUCOLOR=" unicorn horn[^[]*$"=magenta
+MENUCOLOR=" ring .* conflict"=magenta
+MENUCOLOR=" ring .* free action($| )"=magenta
+MENUCOLOR=" ring .* tele(port)? control($| )"=magenta
+MENUCOLOR=" ring .* lev(itation)?($| )"=magenta
+MENUCOLOR=" scrolls? .* charging($| )"=magenta
+MENUCOLOR=" amulet .* life saving($| )"=magenta
+MENUCOLOR=" amulet .* ref(lection)?($| )"=magenta
+MENUCOLOR=" c(o|hi)ckatrice (corpse|egg)"=magenta
+MENUCOLOR=" stethoscope"=magenta
+MENUCOLOR=" key($| )"=magenta
+
+# items that need to be fixed
+MENUCOLOR=" cursed.* bag .* holding"=red
+MENUCOLOR=" cursed.* luck(stone)?($| )"=red
+MENUCOLOR=" cursed.* unicorn horn"=red
+MENUCOLOR=" cursed.* (Bell of Opening|silver bell|Candelabrum of Invocation|candelabrum|Book of the Dead|papyrus spellbook)"=red
+MENUCOLOR=" load(stone)?($| )"=red
+
+# magic items
+MENUCOLOR="piece of cloth|opera cloak|ornamental cope|tattered cape"=blue
+MENUCOLOR="plumed helmet|etched helmet|crested helmet|visored helmet"=blue
+MENUCOLOR="(old|padded|riding|fencing) gloves"=blue
+MENUCOLOR="(mud|buckled|riding|snow|hiking|combat|jungle) boots"=blue
+
+# items to keep out of bags of holding
+MENUCOLOR=" bag .* tricks"=red&bold
+MENUCOLOR=" wand .*[^!]canc"=red&bold
+MENUCOLOR=" wand .* vanish"=red&bold
+
+# spell failure
+MENUCOLOR=" 0% "=white
+MENUCOLOR=" [1-9]% "=cyan
+MENUCOLOR=" [12][0-9]% "=cyan
+MENUCOLOR=" [3-6][0-9]% "=yellow
+MENUCOLOR=" 7[0-5]% "=yellow
+MENUCOLOR=" 7[6-9]% "=orange
+MENUCOLOR=" 8[0-9]% "=orange
+MENUCOLOR=" 9[0-9]% "=red
+MENUCOLOR=" 100% "=red
+MENUCOLOR="[a-zA-Z ]+ [0-9]\* [a-z]+ +[0-9]+%"=magenta
+
+# fix mistakenly highlighted menu items
+MENUCOLOR=" is empty. Do what?"=no color
+MENUCOLOR="Put something into .*"=no color
+MENUCOLOR="Take something out of .*"=no color
+MENUCOLOR="unicorn horn.*(Unskilled|Basic|Skilled|Expert)"=no color
+MENUCOLOR="Info on what a given key does."=no color
+MENUCOLOR="Full list of keyboard commands."=no color
+MENUCOLOR="altkeyhandler"=no color
+MENUCOLOR="fruit.*\["=no color
+
+# emergencies
+MSGTYPE=stop "The (couatl.*eel|kraken) swings itself around you!"
+MSGTYPE=stop "The python grabs you!"
+MSGTYPE=stop "You don't feel very well"
+MSGTYPE=stop "You are turning a little green"
+MSGTYPE=stop "Your limbs are getting oozy"
+MSGTYPE=stop "Your skin begins to peel away"
+MSGTYPE=stop "You are turning into a green slime"
+MSGTYPE=stop "You are slowing down"
+MSGTYPE=stop "Your limbs are stiffening"
+MSGTYPE=stop "It constricts your throat!"
+MSGTYPE=stop "You find it hard to breathe"
+MSGTYPE=stop "You're gasping for air"
+MSGTYPE=stop "Your blood is having trouble reaching your brain"
+MSGTYPE=stop "You can no longer breathe"
+MSGTYPE=stop "You're turning blue"
+MSGTYPE=stop "Your consciousness is fading"
+MSGTYPE=stop "You feel deathly sick"
+MSGTYPE=stop "You feel much worse"
+MSGTYPE=stop "You feel even worse"
+
+# vibrating square
+MSGTYPE=stop "You feel a strange vibration beneath "
+MSGTYPE=stop "You feel a strange vibration under your "
diff --git a/nethackrc b/nethackrc
deleted file mode 100644
index 8bdca9d..0000000
--- a/nethackrc
+++ /dev/null
@@ -1,59 +0,0 @@
-# improve the consistency of telnet ping/pong
-OPTIONS=!sparkle
-OPTIONS=runmode:teleport
-OPTIONS=!timed_delay
-
-# display
-OPTIONS=showexp
-OPTIONS=showscore
-OPTIONS=time
-OPTIONS=color
-OPTIONS=boulder:0
-OPTIONS=!tombstone
-OPTIONS=!news
-OPTIONS=!legacy
-OPTIONS=suppress_alert:3.4.3
-OPTIONS=hilite_pet
-
-# functionality
-OPTIONS=autopickup
-OPTIONS=pickup_types:$"?!=/
-OPTIONS=pickup_burden:unburdened
-OPTIONS=!prayconfirm
-OPTIONS=pettype:none
-OPTIONS=!cmdassist
-OPTIONS=disclose:yi +avgc
-OPTIONS=!number_pad
-
-# miscellaneous
-OPTIONS=!mail
-
-# map changes for code simplicity
-SYMBOLS=S_mimic_def:m
-SYMBOLS=S_ghost:X
-SYMBOLS=S_worm_tail:w
-# "strange monster" = m (mimic)
-# ghost/shade = X now space is solid rock
-# worm tail = w now ~ is water
-
-SYMBOLS=S_web:^
-# spider web = ^ now " is amulet
-
-SYMBOLS=S_sink:{
-SYMBOLS=S_hcdbridge:}
-SYMBOLS=S_vcdbridge:}
-SYMBOLS=S_bars:}
-SYMBOLS=S_tree:}
-SYMBOLS=S_hcdoor:]
-SYMBOLS=S_vcdoor:]
-SYMBOLS=S_grave:\\
-SYMBOLS=S_pool:~
-SYMBOLS=S_water:~
-SYMBOLS=S_lava:~
-# sink => { one less #, walkable
-# drawbridge => } one less #, not walkable
-# iron bars => } one less #, not walkable (color: cyan)
-# trees => } one less #, not walkable (color: green)
-# closed doors => ] now + is spellbook
-# grave => \ now gray | and - are walls, (grey -- thrones)
-# water => ~ it looks cool (blue -- long worm tail)
diff --git a/notmuch/hooks/post-new b/notmuch/.cache/notmuch/hooks/post-new
index 8809f91..8809f91 100755
--- a/notmuch/hooks/post-new
+++ b/notmuch/.cache/notmuch/hooks/post-new
diff --git a/notmuch-config b/notmuch/.config/notmuch/default/config
index 9b4117a..35b5547 100644
--- a/notmuch-config
+++ b/notmuch/.config/notmuch/default/config
@@ -1,5 +1,6 @@
[database]
-path=/home/doy/Maildir
+path=/home/doy/.cache/notmuch
+mail_root=/home/doy/Maildir
[user]
name=Jesse Luehrs
@@ -7,7 +8,7 @@ primary_email=doy@tozt.net
other_email=doy@stripe.com;jesse.luehrs@iinteractive.com;doy@cpan.org;
[new]
-ignore=spam
+ignore=spam;.uidvalidity;
[maildir]
synchronize_flags=true
diff --git a/notmuch/Makefile b/notmuch/Makefile
new file mode 100644
index 0000000..d1f30eb
--- /dev/null
+++ b/notmuch/Makefile
@@ -0,0 +1,4 @@
+include ../Makefile.include
+
+install:
+ @mkdir -p $(HOME)/.cache/notmuch
diff --git a/packages.hornet b/packages.hornet
new file mode 100644
index 0000000..c33c4b8
--- /dev/null
+++ b/packages.hornet
@@ -0,0 +1,42 @@
+alacritty
+bash
+bat
+bin
+crawl
+eza
+fortune-mod
+fzf
+gdb
+git
+helix
+i3
+i3status
+laptop
+less
+mbsync
+mbsyncloop
+msmtp
+mutt
+nethack
+notmuch
+picom
+podman
+ra-multiplex
+rbw
+readline
+redshift
+reply
+ripgrep
+sh
+ssh
+starship
+tex
+tig
+tmux
+unclutter
+xbindkeys
+xcape
+xorg
+xss-lock
+zsh
+
diff --git a/packages.mail b/packages.mail
new file mode 100644
index 0000000..bfe1fbf
--- /dev/null
+++ b/packages.mail
@@ -0,0 +1,21 @@
+bash
+bat
+bin
+eza
+fortune-mod
+fzf
+gdb
+git
+helix
+less
+mutt
+readline
+reply
+ripgrep
+sh
+ssh
+starship
+tig
+tmux
+zsh
+
diff --git a/packages.mz-doy1 b/packages.mz-doy1
new file mode 100644
index 0000000..fe7f7a0
--- /dev/null
+++ b/packages.mz-doy1
@@ -0,0 +1,32 @@
+alacritty
+bash
+bat
+bin
+docker
+eza
+fortune-mod
+fzf
+gdb
+git
+helix
+i3
+i3status
+laptop
+less
+picom
+ra-multiplex
+readline
+redshift
+reply
+ripgrep
+sh
+starship
+tig
+tmux
+unclutter
+xbindkeys
+xcape
+xorg
+xss-lock
+zsh
+
diff --git a/packages.partofme b/packages.partofme
new file mode 100644
index 0000000..bfe1fbf
--- /dev/null
+++ b/packages.partofme
@@ -0,0 +1,21 @@
+bash
+bat
+bin
+eza
+fortune-mod
+fzf
+gdb
+git
+helix
+less
+mutt
+readline
+reply
+ripgrep
+sh
+ssh
+starship
+tig
+tmux
+zsh
+
diff --git a/packages.root b/packages.root
new file mode 100644
index 0000000..01bf273
--- /dev/null
+++ b/packages.root
@@ -0,0 +1,20 @@
+bash
+bat
+bin
+eza
+fortune-mod
+fzf
+gdb
+git
+helix
+less
+readline
+reply
+ripgrep
+sh
+ssh
+starship
+tig
+tmux
+zsh
+
diff --git a/packages.tozt b/packages.tozt
new file mode 100644
index 0000000..bfe1fbf
--- /dev/null
+++ b/packages.tozt
@@ -0,0 +1,21 @@
+bash
+bat
+bin
+eza
+fortune-mod
+fzf
+gdb
+git
+helix
+less
+mutt
+readline
+reply
+ripgrep
+sh
+ssh
+starship
+tig
+tmux
+zsh
+
diff --git a/perlcriticrc b/perlcriticrc
deleted file mode 100644
index 6d9110a..0000000
--- a/perlcriticrc
+++ /dev/null
@@ -1 +0,0 @@
-exclude = ProhibitSubroutinePrototypes
diff --git a/picom/.config/systemd/user/picom.service b/picom/.config/systemd/user/picom.service
new file mode 100644
index 0000000..f01df84
--- /dev/null
+++ b/picom/.config/systemd/user/picom.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=picom -m 0.9 -i 0.8 -f -D 5 --inactive-dim 0.3
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/picom/Makefile b/picom/Makefile
new file mode 100644
index 0000000..915d134
--- /dev/null
+++ b/picom/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable picom
+ @systemctl --user start picom
+
+uninstall:
+ @systemctl --user stop picom
+ @systemctl --user disable picom
diff --git a/plists/com.amethyst.Amethyst.plist b/plists/com.amethyst.Amethyst.plist
deleted file mode 100644
index 15e9a6a..0000000
--- a/plists/com.amethyst.Amethyst.plist
+++ /dev/null
Binary files differ
diff --git a/podman/.config/sh/rc.d/podman b/podman/.config/sh/rc.d/podman
new file mode 100644
index 0000000..0669942
--- /dev/null
+++ b/podman/.config/sh/rc.d/podman
@@ -0,0 +1,4 @@
+alias debian="podman run --rm -itv "${HOME}:${HOME}" docker.io/debian:stable bash"
+alias ubuntu="podman run --rm -itv "${HOME}:${HOME}" docker.io/ubuntu:latest bash"
+alias alpine="podman run --rm -itv "${HOME}:${HOME}" docker.io/alpine:latest sh"
+alias arch="podman run --rm -itv "${HOME}:${HOME}" docker.io/archlinux:latest sh"
diff --git a/procmail/mark_as_read b/procmail/mark_as_read
deleted file mode 100644
index bd853f8..0000000
--- a/procmail/mark_as_read
+++ /dev/null
@@ -1,20 +0,0 @@
-:0
-{
- :0c:
- $folder
-
- :0
- * LASTFOLDER ?? /\/[^/]+$
- { tail=$MATCH }
-
- file_read_base="${folder}cur/${tail}"
- file_new=$LASTFOLDER
- # pretty hackish, but what can you do
- file_cur="${file_read_base}*"
- file_read="${file_read_base}:2,S"
- TRAP="mv $file_new $file_read 2>/dev/null || mv $file_cur $file_read 2>/dev/null"
-
- HOST
-}
-
-# vim:ft=procmail:
diff --git a/procmailrc b/procmailrc
deleted file mode 100644
index 658dfd4..0000000
--- a/procmailrc
+++ /dev/null
@@ -1,12 +0,0 @@
-# spam {{{
-:0
-* ^X-Spam-Flag: YES
-{
- folder=$SPAM
- SWITCHRC=$HOME/.procmail/mark_as_read
-}
-# }}}
-# local {{{
-INCLUDERC=$PMDIR/local.rc
-# }}}
-# vim:ft=procmail:fdm=marker
diff --git a/proverc b/proverc
deleted file mode 100644
index e8cd60c..0000000
--- a/proverc
+++ /dev/null
@@ -1 +0,0 @@
--rj5 --timer --state=slow,save
diff --git a/ra-multiplex/.config/systemd/user/ra-multiplex.service b/ra-multiplex/.config/systemd/user/ra-multiplex.service
new file mode 100644
index 0000000..cb62f0b
--- /dev/null
+++ b/ra-multiplex/.config/systemd/user/ra-multiplex.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=%h/.cargo/bin/ra-multiplex-server
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/ra-multiplex/Makefile b/ra-multiplex/Makefile
new file mode 100644
index 0000000..275b415
--- /dev/null
+++ b/ra-multiplex/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable ra-multiplex
+ @systemctl --user start ra-multiplex
+
+uninstall:
+ @systemctl --user stop ra-multiplex
+ @systemctl --user disable ra-multiplex
diff --git a/rbw/.bin/p b/rbw/.bin/p
new file mode 100755
index 0000000..cbf15c4
--- /dev/null
+++ b/rbw/.bin/p
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -eu
+set -o pipefail
+
+rbw ls --fields name,user,folder | perl -plE'/^([^\t]*)\t([^\t]*)\t([^\t]*)$/; $_ = join("/", grep { length } ($3, $1, $2)) . "\0$_"' | sort | fzf --with-nth=1 -d '\x00' | perl -ple'/^([^\0]*)\0([^\t]*)\t([^\t]*)\t([^\t]*)$/; $_ = "$2 $3"; $_ .= " --folder=\"$4\"" if length $4' | xargs -r rbw get
diff --git a/bin/hush/scp b/rbw/.bin/scp
index ffd8d03..ffd8d03 120000
--- a/bin/hush/scp
+++ b/rbw/.bin/scp
diff --git a/bin/hush/sftp b/rbw/.bin/sftp
index ffd8d03..ffd8d03 120000
--- a/bin/hush/sftp
+++ b/rbw/.bin/sftp
diff --git a/bin/hush/ssh b/rbw/.bin/ssh
index 65c2f53..bbacdf9 100755
--- a/bin/hush/ssh
+++ b/rbw/.bin/ssh
@@ -2,5 +2,5 @@
set -eu
set -o pipefail
-ssh-add -l | grep -q "${HOME}/.ssh/id_rsa" || env SSH_ASKPASS="ssh-askpass" ssh-add < /dev/null
+ssh-add -l | grep -q "${HOME}/.ssh/id_rsa" || env SSH_ASKPASS="ssh-askpass" ssh-add </dev/null
exec /usr/bin/"$(basename "$0")" "$@"
diff --git a/bin/hush/svre b/rbw/.bin/ssh-askpass
index 159b017..ace037c 100755
--- a/bin/hush/svre
+++ b/rbw/.bin/ssh-askpass
@@ -2,5 +2,4 @@
set -eu
set -o pipefail
-svdn "$1"
-svup "$1"
+exec rbw get hornet ssh
diff --git a/bin/hush/sudo b/rbw/.bin/sudo
index 1ff8b23..1ff8b23 100755
--- a/bin/hush/sudo
+++ b/rbw/.bin/sudo
diff --git a/bin/hush/svst b/rbw/.bin/sudo-askpass
index 4d0c6ce..2f928ed 100755
--- a/bin/hush/svst
+++ b/rbw/.bin/sudo-askpass
@@ -2,4 +2,4 @@
set -eu
set -o pipefail
-svget "$1" | grep -q ": up ("
+exec rbw get "$(hostname)" doy
diff --git a/rbw/.config/sh/rc.d/rbw b/rbw/.config/sh/rc.d/rbw
new file mode 100644
index 0000000..e40af5c
--- /dev/null
+++ b/rbw/.config/sh/rc.d/rbw
@@ -0,0 +1,5 @@
+alias pc="p | xclip -l 1"
+
+export GIT_SSH="${HOME}/.bin/ssh"
+export RSYNC_RSH="${HOME}/.bin/ssh"
+export SUDO_ASKPASS="${HOME}/.bin/sudo-askpass"
diff --git a/inputrc b/readline/.inputrc
index 87a7701..87a7701 100644
--- a/inputrc
+++ b/readline/.inputrc
diff --git a/redshift/.bin/redshift b/redshift/.bin/redshift
new file mode 100755
index 0000000..c9dcdc9
--- /dev/null
+++ b/redshift/.bin/redshift
@@ -0,0 +1,4 @@
+#!/bin/sh
+set -eu
+
+exec /usr/bin/redshift -l "$(sed 's/,/:/' <~/.config/weather/location)"
diff --git a/redshift/.config/systemd/user/redshift.service b/redshift/.config/systemd/user/redshift.service
new file mode 100644
index 0000000..6920f56
--- /dev/null
+++ b/redshift/.config/systemd/user/redshift.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=%h/.bin/redshift
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/redshift/Makefile b/redshift/Makefile
new file mode 100644
index 0000000..6752779
--- /dev/null
+++ b/redshift/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable redshift
+ @systemctl --user start redshift
+
+uninstall:
+ @systemctl --user stop redshift
+ @systemctl --user disable redshift
diff --git a/replyrc b/reply/.replyrc
index f1e57ae..f1e57ae 100644
--- a/replyrc
+++ b/reply/.replyrc
diff --git a/ripgrep/.bin/rg b/ripgrep/.bin/rg
new file mode 100755
index 0000000..ea88361
--- /dev/null
+++ b/ripgrep/.bin/rg
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ -t 1 ]; then
+ exec /usr/bin/rg --smart-case --no-ignore-messages -p "$@" | less -FR
+else
+ exec /usr/bin/rg --smart-case --no-ignore-messages "$@"
+fi
diff --git a/screenrc b/screenrc
deleted file mode 100644
index 414b4c9..0000000
--- a/screenrc
+++ /dev/null
@@ -1,28 +0,0 @@
-# .screenrc, based on Eidolos' config at http://sartak.org/conf/
-startup_message off
-nethack on
-
-# bells in background windows make bells in the foreground window
-bell_msg "^G"
-
-# i turn visual bell on in terminal settings, don't do it here
-vbell off
-
-# avoid logging in a new user for every term (thanks toft)
-deflogin off
-
-# lines of scrollback!
-defscrollback 4096
-
-# quick esc timeout
-maptimeout 50
-
-# use the alternate screen feature (for full-screen curses apps, etc)
-altscreen on
-
-# some keybindings
-bind ^a windowlist -b
-bind ^g screen //group
-
-# i want utf8 in screen too
-defutf8 on
diff --git a/services/available/compton/log/run b/services/available/compton/log/run
deleted file mode 100755
index 38a5424..0000000
--- a/services/available/compton/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/compton
diff --git a/services/available/compton/run b/services/available/compton/run
deleted file mode 100755
index 21d2ce0..0000000
--- a/services/available/compton/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec compton -m 0.9 -i 0.8 -f -D 7 --inactive-dim 0.3
diff --git a/services/available/duplicati/log/run b/services/available/duplicati/log/run
deleted file mode 100755
index 540c0d7..0000000
--- a/services/available/duplicati/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/duplicati
diff --git a/services/available/duplicati/run b/services/available/duplicati/run
deleted file mode 100755
index 8d2a9ad..0000000
--- a/services/available/duplicati/run
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec /usr/bin/mono /opt/duplicati-latest/Duplicati.Server.exe --webservice-port=8200
diff --git a/services/available/kuake/log/run b/services/available/kuake/log/run
deleted file mode 100755
index c3838ba..0000000
--- a/services/available/kuake/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/kuake
diff --git a/services/available/kuake/run b/services/available/kuake/run
deleted file mode 100755
index 5ea5756..0000000
--- a/services/available/kuake/run
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-cd || exit 1
-exec urxvt -pe "kuake<XF86Tools>" -g 80x24 -name urxvt-kuake -e tmux new -As kuake
diff --git a/services/available/light-locker/log/run b/services/available/light-locker/log/run
deleted file mode 100755
index d92a97c..0000000
--- a/services/available/light-locker/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/light-locker
diff --git a/services/available/light-locker/run b/services/available/light-locker/run
deleted file mode 100755
index 6cf1077..0000000
--- a/services/available/light-locker/run
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec light-locker
diff --git a/services/available/mpd/log/run b/services/available/mpd/log/run
deleted file mode 100755
index b1fdb9c..0000000
--- a/services/available/mpd/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/mpd
diff --git a/services/available/mpd/run b/services/available/mpd/run
deleted file mode 100755
index 186baef..0000000
--- a/services/available/mpd/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec mpd --no-daemon 2>&1
diff --git a/services/available/mpdscribble/log/run b/services/available/mpdscribble/log/run
deleted file mode 100755
index 1a30b0a..0000000
--- a/services/available/mpdscribble/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/mpdscribble
diff --git a/services/available/mpdscribble/run b/services/available/mpdscribble/run
deleted file mode 100755
index 95d4511..0000000
--- a/services/available/mpdscribble/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec mpdscribble --no-daemon 2>&1
diff --git a/services/available/offlineimap/log/run b/services/available/offlineimap/log/run
deleted file mode 100755
index d924c2d..0000000
--- a/services/available/offlineimap/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/offlineimap
diff --git a/services/available/offlineimap/run b/services/available/offlineimap/run
deleted file mode 100755
index 5589a60..0000000
--- a/services/available/offlineimap/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec offlineimap 2>&1
diff --git a/services/available/perspektiv/log/run b/services/available/perspektiv/log/run
deleted file mode 100755
index df97437..0000000
--- a/services/available/perspektiv/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/perspektiv
diff --git a/services/available/perspektiv/run b/services/available/perspektiv/run
deleted file mode 100755
index 11c56ae..0000000
--- a/services/available/perspektiv/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec perspektiv
diff --git a/services/available/redshift/log/run b/services/available/redshift/log/run
deleted file mode 100755
index c80ccab..0000000
--- a/services/available/redshift/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/redshift
diff --git a/services/available/redshift/run b/services/available/redshift/run
deleted file mode 100755
index 6a31b2c..0000000
--- a/services/available/redshift/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec redshift -l 40.728:-73.994
diff --git a/services/available/touchegg/log/run b/services/available/touchegg/log/run
deleted file mode 100755
index d38dc0b..0000000
--- a/services/available/touchegg/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/touchegg
diff --git a/services/available/touchegg/run b/services/available/touchegg/run
deleted file mode 100755
index b1a6780..0000000
--- a/services/available/touchegg/run
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec touchegg 2>/dev/null
diff --git a/services/available/unclutter/log/run b/services/available/unclutter/log/run
deleted file mode 100755
index c36d116..0000000
--- a/services/available/unclutter/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/unclutter
diff --git a/services/available/unclutter/run b/services/available/unclutter/run
deleted file mode 100755
index 2cc69fa..0000000
--- a/services/available/unclutter/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec unclutter --timeout 1 2>&1
diff --git a/services/available/urxvtd/log/run b/services/available/urxvtd/log/run
deleted file mode 100755
index afb8da5..0000000
--- a/services/available/urxvtd/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/urxvtd
diff --git a/services/available/urxvtd/run b/services/available/urxvtd/run
deleted file mode 100755
index 652d2a4..0000000
--- a/services/available/urxvtd/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec urxvtd 2>&1
diff --git a/services/available/watch-kbd/log/run b/services/available/watch-kbd/log/run
deleted file mode 100755
index 41c1a23..0000000
--- a/services/available/watch-kbd/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/watch-kbd
diff --git a/services/available/watch-lock/log/run b/services/available/watch-lock/log/run
deleted file mode 100755
index fd51f06..0000000
--- a/services/available/watch-lock/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/watch-lock
diff --git a/services/available/watch-lock/run b/services/available/watch-lock/run
deleted file mode 100755
index f36a7e7..0000000
--- a/services/available/watch-lock/run
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-set -eu
-set -o pipefail
-
-exec watch-lock
diff --git a/services/available/xbindkeys/run b/services/available/xbindkeys/run
deleted file mode 100755
index 64a1a7a..0000000
--- a/services/available/xbindkeys/run
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-cd $HOME
-exec xbindkeys -p -n
diff --git a/services/available/xcape/log/run b/services/available/xcape/log/run
deleted file mode 100755
index bc152bd..0000000
--- a/services/available/xcape/log/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec multilog t s16777215 $HOME/.log/xcape
diff --git a/services/available/xcape/run b/services/available/xcape/run
deleted file mode 100755
index ead9f5a..0000000
--- a/services/available/xcape/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-exec xcape -d -e 'Control_L=Escape;Control_R=Escape' 2>&1
diff --git a/sh/.config/sh/fzf b/sh/.config/sh/fzf
new file mode 160000
+Subproject 3c877c504b6102daf5dcc1083b1f1a7db88d304
diff --git a/sh/.config/sh/rc.d/00path b/sh/.config/sh/rc.d/00path
new file mode 100644
index 0000000..c9275f4
--- /dev/null
+++ b/sh/.config/sh/rc.d/00path
@@ -0,0 +1 @@
+export PATH="${HOME}/.bin/local:${HOME}/.bin:${HOME}/.cargo/bin:${PATH}"
diff --git a/sh/.config/sh/rc.d/sh b/sh/.config/sh/rc.d/sh
new file mode 100644
index 0000000..319b6d9
--- /dev/null
+++ b/sh/.config/sh/rc.d/sh
@@ -0,0 +1,10 @@
+alias ll="ls -l"
+alias grep="grep --color=auto"
+alias rm="rm -i"
+alias cp="cp -i"
+alias mv="mv -i"
+alias bc="bc -lq"
+type tput >/dev/null 2>&1 && alias reset="tput reset"
+alias utc="env TZ=UTC date"
+
+# vim:ft=sh:fdm=marker
diff --git a/profile b/sh/.profile
index 76e64da..76e64da 100644
--- a/profile
+++ b/sh/.profile
diff --git a/ssh/.ssh/authorized_keys b/ssh/.ssh/authorized_keys
new file mode 100644
index 0000000..8399421
--- /dev/null
+++ b/ssh/.ssh/authorized_keys
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCTbG1c3aDGADsII4rTxKuSudxpy6gXSMJ3ZQk8kQBgtWhp+eC3VgoslWqwpSatvtXGEp/wLsskdvWeoq7LAEx3vBqOxuvtqvf98EMSkdrp3zqVMh0ZxE+9lnrZnGTb+Ck7etgOIYfxYD77MWKUvwJdL/Y2+7joux5edmNzPtf/hNNCjxqVZsQGYpcausEpR/+KOJlswaERUsvSBOm0C7kq+3bZbqoHBw2sP0cQA3ZzMriMomuSRNIAqCfV5VUPUr5mbGamSYU/rBMesUy9Sz0B494F5m21KiUqjzG2K2KoGZiXHBAigAh7PZCa1WZjPSvh9sFvHfsciAT1ITLW3A/HEq+370Zy7fz+LYEuc25coIxqiPtfwGBRRNfiZHJkKubQ6VRPOsxhj66mJ0rrteHi2YwtsNpgJfSooCG74tqoZCQ3f7vESu1uRUFqyI/6UjMOSm23lQPrw+Q0eULtw8eJpcciVyHIZP+HoP5RXZBn2cO+rQFjSCVAwfNvtGh+08= doy@hornet
diff --git a/ssh/authorized_keys b/ssh/authorized_keys
deleted file mode 100644
index 8916b53..0000000
--- a/ssh/authorized_keys
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCiNr2wXBIDl8osRgrXcVsJnxNT6D6VFK5KMkWHRamwa9FhYzBOtLYJxuOVJmleECqdff/d/Mp0gHNY7znsX39/e7AzWVbcopli6WYPQDe/qgDuTl4Xb/SyrdjBMAHEsz8pOcSnON3EhMbrqlLzB0//vSu9Cb97c/9p2JzHGiUB+nTIwFyvvhf93EB5s5YCP12iA/UcU6yGCRFluZ8Sz0IzLumVmeKiWgVmSjqHAazPFxHdSNz2+XTtdfAaSlkasab7feHV+Eiu7mA/j0v72xEyUAA8s/h/hZdhjA4MZUckEGb7o7C6zWMkZ/PufUGRQsav/BMzoEOgWO6XJppNmXC9 doy@hush
diff --git a/starship/.config/starship.toml.PL b/starship/.config/starship.toml.PL
new file mode 100644
index 0000000..8a5dc5b
--- /dev/null
+++ b/starship/.config/starship.toml.PL
@@ -0,0 +1,159 @@
+#!/usr/bin/env perl
+use 5.014;
+use warnings;
+
+chomp(my $hostname = `hostname`);
+
+my $char = $ENV{USER} eq 'root' ? '#' : '\\\\$';
+my $user = $ENV{USER} eq 'root' ? 'bright-red' : 'bright-blue';
+my $host = {
+ 'mz-doy1' => 'bright-white',
+ 'tozt' => 'bright-yellow',
+ 'partofme' => 'purple',
+ 'mail' => 'green',
+ 'hornet' => 'red',
+}->{$hostname} // 'yellow';
+
+while (<DATA>) {
+ s/\@\@CHAR\@\@/$char/;
+ s/\@\@USER\@\@/$user/;
+ s/\@\@HOST\@\@/$host/;
+ print;
+}
+
+__DATA__
+format = """
+ [\\(](host)$directory([|](host)$git_branch$git_commit$git_status([|](host)$git_state))[\\)](host)( $python) $fill ($cmd_duration )($battery )$username[@](bg)$hostname [\\[](host)$time[\\]](host) $line_break\
+$status [@@CHAR@@](user)
+"""
+right_format = '$character'
+add_newline = false
+palette = 'local'
+
+[directory]
+format = '[$path]($style)[$read_only]($read_only_style)'
+style = 'bg'
+repo_root_format = '[$before_root_path]($before_repo_root_style)[$repo_root]($repo_root_style)[$path]($style)[$read_only]($read_only_style)'
+repo_root_style = 'git'
+fish_style_pwd_dir_length = 1
+
+[git_state]
+format = '[$state(:$progress_current/$progress_total)]($style)'
+style = 'git'
+rebase = 'r'
+merge = 'm'
+revert = 'v'
+cherry_pick = 'c'
+bisect = 'b'
+am = 'a'
+am_or_rebase = 'r'
+
+[git_branch]
+format = '[$branch(:$remote_branch)]($style)'
+style = 'git'
+ignore_branches = ['main', 'master', 'HEAD']
+
+[git_commit]
+format = '[$hash$tag]($style)'
+style = 'git'
+
+[git_status]
+format = '[$all_status$ahead_behind]($style)'
+style = 'bold git'
+modified = '*'
+stashed = ''
+diverged = '+$ahead_count-$behind_count'
+ahead = '+$count'
+behind = '-$count'
+
+[kubernetes]
+disabled = false
+format = '[$symbol$context]($style)'
+symbol = '☸ '
+style = 'bg'
+
+[pulumi]
+format = '[$symbol$stack]($style)'
+symbol = ' '
+style = 'bg'
+
+[python]
+format = '([🐍$virtualenv]($style))'
+style = 'bg'
+
+[fill]
+symbol = '─'
+style = 'bg'
+
+[cmd_duration]
+format = '[\($duration\)]($style)'
+style = 'bg'
+
+[battery]
+format = '[$symbol]($style)'
+unknown_symbol = ''
+
+[[battery.display]]
+threshold = 5
+charging_symbol = '⚡️ '
+discharging_symbol = ' '
+style = 'bright-red'
+
+[[battery.display]]
+threshold = 15
+charging_symbol = '⚡️ '
+discharging_symbol = ' '
+style = 'red'
+
+[[battery.display]]
+threshold = 40
+charging_symbol = '⚡️ '
+discharging_symbol = ' '
+style = 'yellow'
+
+[[battery.display]]
+threshold = 80
+charging_symbol = '⚡️ '
+discharging_symbol = ' '
+style = 'bright-black'
+
+[[battery.display]]
+threshold = 100
+charging_symbol = '⚡️ '
+discharging_symbol = ' '
+style = 'green'
+
+[username]
+disabled = false
+format = '[$user]($style)'
+style_user = 'user'
+show_always = true
+
+[hostname]
+disabled = false
+format = '[$hostname]($style)'
+style = 'host'
+ssh_only = false
+
+[time]
+disabled = false
+format = '[$time]($style)'
+style = 'bg'
+
+[line_break]
+
+[status]
+disabled = false
+format = '[$status]($style)'
+
+[character]
+format = '$symbol'
+success_symbol = ''
+error_symbol = ''
+vimcmd_symbol = '[\[NOR\]](bright-yellow)'
+
+[palettes.local]
+bg = 'bright-black'
+git = 'green'
+user = '@@USER@@'
+host = '@@HOST@@'
diff --git a/starship/.gitignore b/starship/.gitignore
new file mode 100644
index 0000000..9e5ee9a
--- /dev/null
+++ b/starship/.gitignore
@@ -0,0 +1 @@
+.config/starship.toml
diff --git a/starship/Makefile b/starship/Makefile
new file mode 100644
index 0000000..bec31d4
--- /dev/null
+++ b/starship/Makefile
@@ -0,0 +1,6 @@
+include ../Makefile.include
+
+build: .config/starship.toml
+
+clean:
+ @rm -f .config/starship.toml
diff --git a/tex/.config/sh/rc.d/tex b/tex/.config/sh/rc.d/tex
new file mode 100644
index 0000000..7a0fba8
--- /dev/null
+++ b/tex/.config/sh/rc.d/tex
@@ -0,0 +1 @@
+export TEXINPUTS=".:$HOME/.config/tex:"
diff --git a/config/tex/jesse.sty b/tex/.config/tex/jesse.sty
index 189938e..189938e 100644
--- a/config/tex/jesse.sty
+++ b/tex/.config/tex/jesse.sty
diff --git a/config/tex/jesse_essay.sty b/tex/.config/tex/jesse_essay.sty
index 3fb34f2..3fb34f2 100644
--- a/config/tex/jesse_essay.sty
+++ b/tex/.config/tex/jesse_essay.sty
diff --git a/config/tex/jesse_letter.sty b/tex/.config/tex/jesse_letter.sty
index 734021f..734021f 100644
--- a/config/tex/jesse_letter.sty
+++ b/tex/.config/tex/jesse_letter.sty
diff --git a/config/tex/jesse_macros.sty b/tex/.config/tex/jesse_macros.sty
index e27fa25..e27fa25 100644
--- a/config/tex/jesse_macros.sty
+++ b/tex/.config/tex/jesse_macros.sty
diff --git a/config/tex/jesse_resume.sty b/tex/.config/tex/jesse_resume.sty
index 05580d9..05580d9 100644
--- a/config/tex/jesse_resume.sty
+++ b/tex/.config/tex/jesse_resume.sty
diff --git a/config/tex/sarah_resume.sty b/tex/.config/tex/sarah_resume.sty
index 8ed2a20..2dadb30 100644
--- a/config/tex/sarah_resume.sty
+++ b/tex/.config/tex/sarah_resume.sty
@@ -47,6 +47,14 @@
% <<< \resitem
\newcommand{\resitem}[1]{\item {\small #1}}
% >>>
+% <<< \resdesc
+\newcommand{\resdesc}[1]{
+ \begin{minipage}
+ {\textwidth-0.5in}
+ \vspace{4pt}{\small #1}
+ \end{minipage}
+}
+% >>>
% <<< \resheading
\newcommand{\resheading}[1]{
{\large \colorbox{mygrey}{
@@ -67,6 +75,19 @@
\vspace{-0.8pt}
}
% >>>
+% \ressubsubheading <<<
+\newcommand{\ressubsubheading}[3]{
+ \begin{tabular*}{\textwidth-0.8in}{l@{\extracolsep{\fill}}r}
+ \textbf{#2} &
+ \begin{tabular*}{\textwidth-4in}{l@{\extracolsep{\fill}}r}
+ & #1 \\
+ & \textit{#3} \\
+ \end{tabular*}
+ \end{tabular*}
+ \\
+ \vspace{-0.8pt}
+}
+% >>>
% \resshortsubheading <<<
\newcommand{\resshortsubheading}[2]{
\begin{tabular*}{\textwidth-0.5in}{l@{\extracolsep{\fill}}r}
diff --git a/config/tig/config b/tig/.config/tig/config
index 8eb4aa5..8eb4aa5 100644
--- a/config/tig/config
+++ b/tig/.config/tig/config
diff --git a/bin/tmux-clipboard b/tmux/.bin/tmux-clipboard
index dae796b..dae796b 100755
--- a/bin/tmux-clipboard
+++ b/tmux/.bin/tmux-clipboard
diff --git a/tmux/.config/sh/rc.d/tmux b/tmux/.config/sh/rc.d/tmux
new file mode 100644
index 0000000..520e98c
--- /dev/null
+++ b/tmux/.config/sh/rc.d/tmux
@@ -0,0 +1,5 @@
+alias main='tmux new -As main'
+alias chat='tmux new -As chat'
+alias work='tmux new -As work'
+alias docs='tmux new -As docs'
+alias misc='tmux new -As misc'
diff --git a/tmux.conf b/tmux/.config/tmux/tmux.conf
index 67e7dd6..a1ea5ec 100644
--- a/tmux.conf
+++ b/tmux/.config/tmux/tmux.conf
@@ -33,7 +33,7 @@ bind ^F run 'tmux choose-tree -Nwf"##{==:##{session_name},#{session_name}}"'
bind ^N new-window
bind ^D detach-client
bind ^[ copy-mode
-bind { copy-mode
+bind \{ copy-mode
bind Enter run 'tmux capture-pane -pJ | open-link'
bind -T copy-mode-vi v send-keys -X begin-selection
diff --git a/unclutter/.config/systemd/user/unclutter.service b/unclutter/.config/systemd/user/unclutter.service
new file mode 100644
index 0000000..c792aef
--- /dev/null
+++ b/unclutter/.config/systemd/user/unclutter.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=unclutter --timeout 1
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/unclutter/Makefile b/unclutter/Makefile
new file mode 100644
index 0000000..04bc432
--- /dev/null
+++ b/unclutter/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable unclutter
+ @systemctl --user start unclutter
+
+uninstall:
+ @systemctl --user stop unclutter
+ @systemctl --user disable unclutter
diff --git a/uninstall b/uninstall
new file mode 100755
index 0000000..456e656
--- /dev/null
+++ b/uninstall
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -eu
+
+[ -d "$1" ] || (echo "package $1 not found" >&2; exit 1)
+
+[ -f "$1/Makefile" ] && (cd "$1" && make -s uninstall)
+stow -D "$1"
+
+true
diff --git a/vim/after/ftplugin/rust.vim b/vim/after/ftplugin/rust.vim
deleted file mode 100644
index f30a884..0000000
--- a/vim/after/ftplugin/rust.vim
+++ /dev/null
@@ -1 +0,0 @@
-set tw=78
diff --git a/vim/colors/local.vim b/vim/colors/local.vim
deleted file mode 100644
index 7e22c18..0000000
--- a/vim/colors/local.vim
+++ /dev/null
@@ -1,126 +0,0 @@
-highlight clear
-syntax reset
-set background=dark
-let g:colors_name = expand('<sfile>:t:r')
-
-let s:g = {
- \"black": "#000000",
- \"red": "#ed5f74",
- \"green": "#1ea672",
- \"yellow": "#d97917",
- \"blue": "#688ef1",
- \"magenta": "#c96ed0",
- \"cyan": "#3a97d4",
- \"white": "#e3e8ee",
- \"brightblack": "#697386",
- \"brightred": "#fbb5b2",
- \"brightgreen": "#85d996",
- \"brightyellow": "#efc078",
- \"brightblue": "#9fcdff",
- \"brightmagenta": "#f0b4e4",
- \"brightcyan": "#7fd3ed",
- \"brightwhite": "#ffffff",
- \"darkblack": "#000000",
- \"darkred": "#742833",
- \"darkgreen": "#00643c",
- \"darkyellow": "#6e3500",
- \"darkblue": "#2c4074",
- \"darkmagenta": "#602864",
- \"darkcyan": "#144c71",
- \"darkwhite": "#3e4043",
- \"darkerwhite": "#090e14",
-\}
-
-let s:c = {
- \"black": "0",
- \"red": "1",
- \"green": "2",
- \"yellow": "3",
- \"blue": "4",
- \"magenta": "5",
- \"cyan": "6",
- \"white": "7",
- \"brightblack": "8",
- \"brightred": "9",
- \"brightgreen": "10",
- \"brightyellow": "11",
- \"brightblue": "12",
- \"brightmagenta": "13",
- \"brightcyan": "14",
- \"brightwhite": "15",
-\}
-
-function s:hi(name, fg, bg)
- if a:fg == ""
- let ctermfg = ""
- let guifg = ""
- elseif a:fg =~ "^#"
- let ctermfg = ""
- let guifg = "guifg=" . a:fg
- else
- let ctermfg = "ctermfg=" . s:c[a:fg]
- let guifg = "guifg=" . s:g[a:fg]
- endif
-
- if a:bg == ""
- let ctermbg = ""
- let guibg = ""
- elseif a:bg =~ "^#"
- let ctermbg = ""
- let guibg = "guibg=" . a:bg
- else
- let ctermbg = "ctermbg=" . s:c[a:bg]
- let guibg = "guibg=" . s:g[a:bg]
- endif
-
- silent exe "highlight clear " . a:name
- if a:fg != "" || a:bg != ""
- silent exe "highlight " . a:name . " " . ctermfg . " " . ctermbg . " " . guifg . " " . guibg
- endif
-endfunction
-
-" text
-call <sid>hi("Comment", "brightblack", "")
-call <sid>hi("Constant", "red", "")
-call <sid>hi("Delimiter", "blue", "")
-call <sid>hi("Error", "black", "brightmagenta")
-call <sid>hi("Function", "brightcyan", "")
-call <sid>hi("Identifier", "", "")
-call <sid>hi("Include", "blue", "")
-call <sid>hi("Operator", "", "")
-call <sid>hi("PreProc", "magenta", "")
-call <sid>hi("Special", "magenta", "")
-call <sid>hi("SpecialKey", "magenta", "")
-call <sid>hi("Statement", "yellow", "")
-call <sid>hi("Title", "magenta", "")
-call <sid>hi("Todo", "black", "brightyellow")
-call <sid>hi("Type", "green", "")
-
-autocmd FileType go call <sid>hi("goBuiltins", "yellow", "")
-autocmd FileType go call <sid>hi("goFunctionCall", "brightcyan", "")
-autocmd FileType markdown call <sid>hi("mkdListItem", "yellow", "")
-autocmd FileType perl call <sid>hi("Identifier", "brightcyan", "")
-autocmd FileType puppet call <sid>hi("puppetStringDelimiter", "red", "")
-autocmd FileType ruby call <sid>hi("rubyInterpolationDelimiter", "magenta", "")
-autocmd FileType ruby call <sid>hi("rubyPercentStringDelimiter", "yellow", "")
-autocmd FileType ruby call <sid>hi("rubyStringDelimiter", "red", "")
-autocmd FileType ruby call <sid>hi("rubyRegexDelimiter", "red", "")
-autocmd FileType sh call <sid>hi("shQuote", "red", "")
-autocmd FileType vim call <sid>hi("vimBracket", "magenta", "")
-autocmd FileType vim call <sid>hi("vimMapMod", "magenta", "")
-
-" ui
-call <sid>hi("DiffAdd", "", s:g["darkgreen"])
-call <sid>hi("DiffChange", "", s:g["darkblue"])
-call <sid>hi("DiffDelete", "", s:g["darkred"])
-call <sid>hi("DiffText", "", s:g["darkmagenta"])
-call <sid>hi("Folded", "brightgreen", s:g["darkgreen"])
-call <sid>hi("MatchParen", "brightcyan", s:g["darkcyan"])
-call <sid>hi("MoreMsg", "green", s:g["darkgreen"])
-call <sid>hi("NonText", "brightblue", s:g["darkerwhite"])
-call <sid>hi("Search", "", s:g["darkmagenta"])
-call <sid>hi("SpellBad", "", s:g["darkred"])
-call <sid>hi("SpellCap", "", s:g["darkblue"])
-call <sid>hi("SpellRare", "", s:g["darkgreen"])
-call <sid>hi("SpellLocal", "", s:g["darkmagenta"])
-call <sid>hi("Visual", "", s:g["darkwhite"])
diff --git a/vim/ftdetect/c.vim b/vim/ftdetect/c.vim
deleted file mode 100644
index 8dac68b..0000000
--- a/vim/ftdetect/c.vim
+++ /dev/null
@@ -1 +0,0 @@
-let c_syntax_for_h = 1
diff --git a/vim/ftdetect/levdes.vim b/vim/ftdetect/levdes.vim
deleted file mode 100644
index c016fd8..0000000
--- a/vim/ftdetect/levdes.vim
+++ /dev/null
@@ -1 +0,0 @@
-au! BufRead,BufNewFile *crawl*/*.des set filetype=levdes
diff --git a/vim/ftdetect/nhdes.vim b/vim/ftdetect/nhdes.vim
deleted file mode 100644
index 5886d51..0000000
--- a/vim/ftdetect/nhdes.vim
+++ /dev/null
@@ -1 +0,0 @@
-au! BufRead,BufNewFile *nethack*/*.des set filetype=nhdes
diff --git a/vim/ftplugin/c.vim b/vim/ftplugin/c.vim
deleted file mode 100644
index 13c7d4a..0000000
--- a/vim/ftplugin/c.vim
+++ /dev/null
@@ -1 +0,0 @@
-setlocal cinoptions+=:0,l1,g0,(0,W1s
diff --git a/vim/ftplugin/cpp.vim b/vim/ftplugin/cpp.vim
deleted file mode 100644
index 83d7802..0000000
--- a/vim/ftplugin/cpp.vim
+++ /dev/null
@@ -1,2 +0,0 @@
-let b:load_doxygen_syntax = 1
-setlocal cinoptions+=:0,l1,g0,(0,W1s
diff --git a/vim/ftplugin/gitcommit.vim b/vim/ftplugin/gitcommit.vim
deleted file mode 100644
index b1c1450..0000000
--- a/vim/ftplugin/gitcommit.vim
+++ /dev/null
@@ -1,9 +0,0 @@
-setlocal viminfo=
-augroup local_gitcommit
- autocmd!
- autocmd BufWinEnter <buffer>
- \ if getline(1) == '' |
- \ exe "normal! ggO" |
- \ startinsert |
- \ endif
-augroup END
diff --git a/vim/ftplugin/go.vim b/vim/ftplugin/go.vim
deleted file mode 100644
index eb9c22a..0000000
--- a/vim/ftplugin/go.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-setlocal ts=4
-let b:ale_fixers = {"go": ["gofmt"]}
-let b:ale_fix_on_save = 1
diff --git a/vim/ftplugin/help.vim b/vim/ftplugin/help.vim
deleted file mode 100644
index 475e0a7..0000000
--- a/vim/ftplugin/help.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-setlocal keywordprg=:help
-nnoremap <buffer> K K
-vnoremap <buffer> K K
diff --git a/vim/ftplugin/javascript.vim b/vim/ftplugin/javascript.vim
deleted file mode 100644
index 414b519..0000000
--- a/vim/ftplugin/javascript.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-let b:ale_fixers = {"javascript": ["eslint"]}
-let b:ale_fix_on_save = 1
-let b:ale_javascript_eslint_executable = "node_modules/.bin/eslint"
diff --git a/vim/ftplugin/perl.vim b/vim/ftplugin/perl.vim
deleted file mode 100644
index a7705a7..0000000
--- a/vim/ftplugin/perl.vim
+++ /dev/null
@@ -1,25 +0,0 @@
-let b:ale_linters = { 'perl': ['perlcritic'] }
-" rainbow parens break syntax-based indent
-autocmd vimrc BufEnter <buffer> let b:indent_use_syntax = 0
-
-" look up words in perldoc rather than man for K
-function! s:perldoc(word)
- exe 'silent read! perldoc -o PlainText -f "' . a:word . '" 2>/dev/null || perldoc -o PlainText "' . a:word . '"'
- setlocal ft=man
-endfunction
-nnoremap <buffer> <silent>K :call Help(0, [':'], '<SID>perldoc')<CR>
-vnoremap <buffer> <silent>K :call Help(1, [':'], '<SID>perldoc')<CR>
-
-function! s:set_excludes()
- if filereadable("dist.ini")
- for line in readfile("dist.ini", '', 10)
- let name = matchstr(line, '\s*name\s*=\s*\zs.*')
- if name != ""
- exe 'setlocal wildignore+=' . name . '-*/*'
- break
- endif
- endfor
- endif
-endfunction
-autocmd BufReadPost * call <SID>set_excludes()
-call <SID>set_excludes()
diff --git a/vim/ftplugin/puppet.vim b/vim/ftplugin/puppet.vim
deleted file mode 100644
index d1652a3..0000000
--- a/vim/ftplugin/puppet.vim
+++ /dev/null
@@ -1 +0,0 @@
-let g:puppet_align_hashes = 0
diff --git a/vim/ftplugin/python.vim b/vim/ftplugin/python.vim
deleted file mode 100644
index b317797..0000000
--- a/vim/ftplugin/python.vim
+++ /dev/null
@@ -1,13 +0,0 @@
-" look up words in pydoc rather than man for K
-function! s:pydoc(word)
- let l:pydoc_manpager = $MANPAGER
- let l:pydoc_pager = $PAGER
- let $MANPAGER = 'cat'
- let $PAGER = 'cat'
- exe 'silent read! pydoc "' . a:word . '" 2>/dev/null'
- let $MANPAGER = l:pydoc_manpager
- let $PAGER = l:pydoc_pager
- setlocal ft=man
-endfunction
-nnoremap <buffer> <silent>K :call Help(0, ['.'], '<SID>pydoc')<CR>
-vnoremap <buffer> <silent>K :call Help(1, ['.'], '<SID>pydoc')<CR>
diff --git a/vim/ftplugin/ruby.vim b/vim/ftplugin/ruby.vim
deleted file mode 100644
index 035f432..0000000
--- a/vim/ftplugin/ruby.vim
+++ /dev/null
@@ -1,25 +0,0 @@
-function! s:rubocop_in_bundler()
- let l:gemfiles = glob("*.gemspec", 1, 1)
- if filereadable("Gemfile")
- let l:gemfiles += ["Gemfile"]
- endif
- for l:file in l:gemfiles
- for l:line in readfile(l:file)
- if l:line =~ 'gem.*rubocop'
- return 1
- endif
- endfor
- endfor
- return 0
-endfunction
-if s:rubocop_in_bundler()
- let b:ale_ruby_rubocop_executable = 'bundle'
-endif
-
-" look up words in ri rather than man for K
-function! s:ri(word)
- exe 'silent read! ri -T -f rdoc "' . a:word . '" 2>/dev/null'
- setlocal ft=
-endfunction
-nnoremap <buffer> <silent>K :call Help(0, [':', '.'], '<SID>ri')<CR>
-vnoremap <buffer> <silent>K :call Help(1, [':', '.'], '<SID>ri')<CR>
diff --git a/vim/ftplugin/rust.vim b/vim/ftplugin/rust.vim
deleted file mode 100644
index 2e527e8..0000000
--- a/vim/ftplugin/rust.vim
+++ /dev/null
@@ -1,12 +0,0 @@
-let b:ale_linters = { 'rust': ['rls'] }
-let b:ale_rust_rls_toolchain = 'stable'
-let b:ale_rust_rls_config = { 'rust': { 'clippy_preference': 'on' } }
-let b:ale_fixers = { 'rust': ['rustfmt'] }
-let b:ale_fix_on_save = 1
-
-if filereadable("Cargo.toml")
- compiler cargo
- setlocal makeprg=cargo\ build
-else
- setlocal makeprg=rustc\ %
-endif
diff --git a/vim/ftplugin/sh.vim b/vim/ftplugin/sh.vim
deleted file mode 100644
index fd3281e..0000000
--- a/vim/ftplugin/sh.vim
+++ /dev/null
@@ -1 +0,0 @@
-let b:is_bash = 1
diff --git a/vim/ftplugin/terraform.vim b/vim/ftplugin/terraform.vim
deleted file mode 100644
index 5764f2e..0000000
--- a/vim/ftplugin/terraform.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-setlocal commentstring=#\ %s
-let b:ale_fixers = { 'terraform': ['terraform'] }
-let b:ale_fix_on_save = 1
diff --git a/vim/ftplugin/tex.vim b/vim/ftplugin/tex.vim
deleted file mode 100644
index 3a62790..0000000
--- a/vim/ftplugin/tex.vim
+++ /dev/null
@@ -1,96 +0,0 @@
-let b:tex_flavor="latex"
-
-" :make converts to pdf
-setlocal makeprg=(cd\ /tmp\ &&\ pdflatex\ --synctex=1\ --halt-on-error\ %:p)
-
-function! s:zathura()
- if s:is_running('^zathura')
- " zathura automatically reloads
- return
- endif
- call remote_startserver("vim-zathura")
- call system('zathura --fork -x "vim --servername vim-zathura --remote +%{line} %{input}" ' . s:current_pdf())
-endfunction
-
-function! s:current_pdf()
- let base = expand('<afile>:t:r')
- if base == ''
- let base = expand('%:t:r')
- endif
- return '/tmp/' . base . '.pdf'
-endfunction
-
-function! s:is_running(re)
- let processes = split(system('ps xo args'), '\n')
- for process in processes
- if process =~ a:re
- return 1
- endif
- endfor
- return 0
-endfunction
-
-function! s:synctex()
- if s:is_running('^zathura')
- exe "silent !zathura --synctex-forward " . line('.') . ":" . col('.') . ":" . expand('%:p') . " " . s:current_pdf()
- redraw
- endif
-endfunction
-
-let g:_tex_last_line_seen = -1
-function! s:cursor_moved()
- let line = line('.')
- if line != g:_tex_last_line_seen
- call s:synctex()
- endif
- let g:_tex_last_line_seen = line
-endfunction
-
-" don't load the pdf if the make failed
-function! s:make_errors()
- let qf = getqflist()
- for line in qf
- if line['type'] == 'E'
- return 1
- endif
- endfor
- return 0
-endfunction
-
-augroup _tex
- autocmd!
- if executable('zathura') && strlen(expand('$DISPLAY'))
- autocmd QuickFixCmdPost make if !s:make_errors() | call s:zathura() | endif
- endif
- autocmd CursorMoved <buffer> call s:cursor_moved()
-augroup END
-
-" see :help errorformat-LaTeX
-setlocal errorformat=
- \%E!\ LaTeX\ %trror:\ %m,
- \%E!\ %m,
- \%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#,
- \%+W%.%#\ at\ lines\ %l--%*\\d,
- \%WLaTeX\ %.%#Warning:\ %m,
- \%Cl.%l\ %m,
- \%+C\ \ %m.,
- \%+C%.%#-%.%#,
- \%+C%.%#[]%.%#,
- \%+C[]%.%#,
- \%+C%.%#%[{}\\]%.%#,
- \%+C<%.%#>%.%#,
- \%C\ \ %m,
- \%-GSee\ the\ LaTeX%m,
- \%-GType\ \ H\ <return>%m,
- \%-G\ ...%.%#,
- \%-G%.%#\ (C)\ %.%#,
- \%-G(see\ the\ transcript%.%#),
- \%-G\\s%#,
- \%+O(%f)%r,
- \%+P(%f%r,
- \%+P\ %\\=(%f%r,
- \%+P%*[^()](%f%r,
- \%+P[%\\d%[^()]%#(%f%r,
- \%+Q)%r,
- \%+Q%*[^()])%r,
- \%+Q[%\\d%*[^()])%r
diff --git a/vim/ftplugin/vim.vim b/vim/ftplugin/vim.vim
deleted file mode 100644
index 475e0a7..0000000
--- a/vim/ftplugin/vim.vim
+++ /dev/null
@@ -1,3 +0,0 @@
-setlocal keywordprg=:help
-nnoremap <buffer> K K
-vnoremap <buffer> K K
diff --git a/vim/ftplugin/xs.vim b/vim/ftplugin/xs.vim
deleted file mode 100644
index 8dc989f..0000000
--- a/vim/ftplugin/xs.vim
+++ /dev/null
@@ -1,10 +0,0 @@
-setlocal cindent
-setlocal cinoptions+=:0,l1,g0,(0,W1s
-
-" look up words in perldoc rather than man for K if they exist
-function! s:perldoc_or_man(word)
- exe 'silent read! perldoc -o PlainText -a "' . a:word . '" 2>/dev/null || man -Pcat ' . a:word
- setlocal ft=man
-endfunction
-nnoremap <buffer> <silent>K :call Help(0, [], '<SID>perldoc_or_man')<CR>
-vnoremap <buffer> <silent>K :call Help(1, [], '<SID>perldoc_or_man')<CR>
diff --git a/vim/pack/filetype/start/ledger b/vim/pack/filetype/start/ledger
deleted file mode 160000
-Subproject 3d76cee270b1a9583d535737ac2e63166335d45
diff --git a/vim/pack/filetype/start/polyglot b/vim/pack/filetype/start/polyglot
deleted file mode 160000
-Subproject 3ddca5da461ebfaa82104f82e3cbf19d1c326ad
diff --git a/vim/pack/plugins/start/airline b/vim/pack/plugins/start/airline
deleted file mode 160000
-Subproject c213f2ac44292a6c5548872e63acb0648cc07a9
diff --git a/vim/pack/plugins/start/ale b/vim/pack/plugins/start/ale
deleted file mode 160000
-Subproject dd1e1025b8a9b13cb7966bf2baa3e6b42a86285
diff --git a/vim/pack/plugins/start/autobrace b/vim/pack/plugins/start/autobrace
deleted file mode 160000
-Subproject e51de9e6265ade6195c8983edf58c462695acfe
diff --git a/vim/pack/plugins/start/commentary b/vim/pack/plugins/start/commentary
deleted file mode 160000
-Subproject 141d9d32a9fb58fe474fcc89cd7221eb2dd57b3
diff --git a/vim/pack/plugins/start/diff-changes b/vim/pack/plugins/start/diff-changes
deleted file mode 160000
-Subproject 97cf3bc8b51f27452b4174e4f770758d42162d0
diff --git a/vim/pack/plugins/start/editorconfig b/vim/pack/plugins/start/editorconfig
deleted file mode 160000
-Subproject c718cefc51ccdaf7bd27c4c1ae2de5510343424
diff --git a/vim/pack/plugins/start/fzf b/vim/pack/plugins/start/fzf
deleted file mode 160000
-Subproject 65773882505b06970c47285b4ace6208ac5e614
diff --git a/vim/pack/plugins/start/fzf.vim b/vim/pack/plugins/start/fzf.vim
deleted file mode 160000
-Subproject 359a80e3a34aacbd5257713b6a88aa085337166
diff --git a/vim/pack/plugins/start/gundo b/vim/pack/plugins/start/gundo
deleted file mode 160000
-Subproject 46c443ee9d5854320eb965a1fdee781ba83a070
diff --git a/vim/pack/plugins/start/history-sync b/vim/pack/plugins/start/history-sync
deleted file mode 160000
-Subproject 279aa756157ab818df67e854e953f6e05809b4a
diff --git a/vim/pack/plugins/start/neosnippet b/vim/pack/plugins/start/neosnippet
deleted file mode 160000
-Subproject ed80ae8cee732d52eb841d509a95aca9c27ece7
diff --git a/vim/pack/plugins/start/startify b/vim/pack/plugins/start/startify
deleted file mode 160000
-Subproject 9abd2c76845de00eab207576b69332cf0e16d35
diff --git a/vim/pack/plugins/start/textobj b/vim/pack/plugins/start/textobj
deleted file mode 160000
-Subproject fd84055046d38c7e850fdbf13f92ab2898f8114
diff --git a/vim/plugin/dircreate.vim b/vim/plugin/dircreate.vim
deleted file mode 100644
index 11da7f9..0000000
--- a/vim/plugin/dircreate.vim
+++ /dev/null
@@ -1,31 +0,0 @@
-function! s:ensure_dir_exists()
- let l:required_dir = expand("%:h")
- if !isdirectory(l:required_dir)
- if <SID>ask_quit("Directory '" . l:required_dir . "' doesn't exist.", "&Create it?")
- return
- endif
-
- try
- call mkdir(l:required_dir, 'p')
- catch
- call <SID>ask_quit("Can't create '" . l:required_dir . "'", "&Continue anyway?")
- endtry
- endif
-endfunction
-
-function! s:ask_quit(msg, proposed_action)
- if confirm(a:msg, "&Quit?\n" . a:proposed_action) == 1
- if len(getbufinfo()) > 1
- silent bd
- return 1
- else
- exit
- end
- endif
- return 0
-endfunction
-
-augroup dircreate
- autocmd!
- autocmd BufNewFile * call <SID>ensure_dir_exists()
-augroup END
diff --git a/vim/plugin/eolws.vim b/vim/plugin/eolws.vim
deleted file mode 100644
index 1f1a003..0000000
--- a/vim/plugin/eolws.vim
+++ /dev/null
@@ -1,6 +0,0 @@
-augroup eolws
- autocmd!
- autocmd InsertEnter * syn clear EOLWS | syn match EOLWS excludenl /\s\+\%#\@!$/
- autocmd InsertLeave * syn clear EOLWS | syn match EOLWS excludenl /\s\+$/
-augroup END
-highlight EOLWS ctermbg=red guibg=red
diff --git a/vim/plugin/keywordprg.vim b/vim/plugin/keywordprg.vim
deleted file mode 100644
index dfedd80..0000000
--- a/vim/plugin/keywordprg.vim
+++ /dev/null
@@ -1,33 +0,0 @@
-function! Help(visual, iskeyword, command)
- let l:iskeyword = &iskeyword
- for l:kw in a:iskeyword
- exe 'set iskeyword+=' . l:kw
- endfor
- if a:visual
- let l:oldreg = @a
- normal! gv"aygv
- let l:word = @a
- let @a = l:oldreg
- else
- let l:word = expand('<cword>')
- endif
- let &iskeyword = l:iskeyword
-
- exe 'noswapfile ' . &helpheight . 'new ' . l:word
- setlocal buftype=nofile
- setlocal bufhidden=wipe
- setlocal nobuflisted
-
- setlocal modifiable
- exe 'call ' . a:command . '("' . l:word . '")'
- normal! ggdd
- setlocal nomodifiable
-endfunction
-
-function! s:man(word)
- exe 'silent read! man -Pcat ' . a:word
- setlocal filetype=man
-endfunction
-
-nnoremap <silent>K :call Help(0, [], '<SID>man')<CR>
-xnoremap <silent>K :call Help(1, [], '<SID>man')<CR>
diff --git a/vim/plugin/nopaste.vim b/vim/plugin/nopaste.vim
deleted file mode 100644
index cb904f7..0000000
--- a/vim/plugin/nopaste.vim
+++ /dev/null
@@ -1,19 +0,0 @@
-function! s:nopaste(visual)
- if a:visual
- silent normal! gv:!nopaste<CR>
- else
- let l:pos = getpos('.')
- silent normal! :%!nopaste<CR>
- endif
- silent normal! "+yy
- let @* = @+
- silent undo
- " can't restore visual selection because that will overwrite "*
- if !a:visual
- call setpos('.', l:pos)
- endif
- echo @+
-endfunction
-
-nnoremap <silent><Leader>p :call <SID>nopaste(0)<CR>
-xnoremap <silent><Leader>p :<C-U>call <SID>nopaste(1)<CR>
diff --git a/vim/plugin/opinionated-defaults.vim b/vim/plugin/opinionated-defaults.vim
deleted file mode 100644
index 87eaf57..0000000
--- a/vim/plugin/opinionated-defaults.vim
+++ /dev/null
@@ -1,157 +0,0 @@
-""" GENERAL """
-set nocompatible
-syntax on
-filetype indent plugin on
-augroup opinionated_defaults
- autocmd!
-augroup END
-
-
-""" PERSISTENCE """
-
-" remember as many history items as possible (command, search, etc)
-set history=10000
-" enable persistent undo (undo even after closing and reopening vim)
-if has('persistent_undo')
- let s:undocachedir = $HOME . '/.cache/vim/undo'
- if !isdirectory(s:undocachedir)
- call mkdir(s:undocachedir, 'p')
- endif
- exe "set undodir=" . s:undocachedir
- set undofile
-endif
-" use a separate swapfile directory
-let s:swapfiledir = $HOME . '/.cache/vim/swap'
-if !isdirectory(s:swapfiledir)
- call mkdir(s:swapfiledir, 'p')
-endif
-exe "set directory=" . s:swapfiledir
-" use a separate view directory
-let s:viewdir = $HOME . '/.cache/vim/view'
-if !isdirectory(s:viewdir)
- call mkdir(s:viewdir, 'p')
-endif
-exe "set viewdir=" . s:viewdir
-
-
-""" BUFFERS """
-
-" automatically write the buffer before :make, shell commands, etc
-set autowrite
-" ask to save modified buffers when quitting, instead of throwing an error
-set confirm
-" allow switching to other buffers when the current one is modified
-set hidden
-" these two restore the last known cursor position when a buffer is loaded
-set nostartofline
-autocmd opinionated_defaults BufReadPost *
- \ if line("'\"") <= line('$') |
- \ exe 'normal! g`"' |
- \ endif
-
-
-""" DISPLAY """
-
-" show as much of a line as possible if it doesn't all fit on the screen
-set display+=truncate
-" more useful display of nonprinting characters (<07> instead of ^G)
-set display+=uhex
-" don't redraw in the middle of noninteractive commands (maps, macros, etc)
-set lazyredraw
-" always give a message for the number of lines delete/changed
-set report=0
-" keep some additional context visible when scrolling
-set scrolloff=5
-if has('cmdline_info')
- " display the current partial command and size of the visual selection
- set showcmd
-endif
-if has('conceal')
- " enable syntax-specific hiding of text
- set conceallevel=2
-endif
-if has('linebreak')
- " display a marker when a line was wrapped
- set showbreak=>
-endif
-
-
-""" EDITING """
-
-" automatically use an indent that matches the previous line
-set autoindent
-" allow backspacing over everything
-set backspace=indent,eol,start
-" remove leading comment characters intelligently when joining lines
-set formatoptions+=j
-" always join with a single space, even between sentences
-set nojoinspaces
-" try to always keep indentation lined up on shiftwidth boundaries
-set shiftround
-" keep softtabstop and shiftwidth in sync
-set softtabstop=-1
-
-
-""" COMMAND MODE """
-
-" make command mode completion work more like the shell:
-" first, complete the longest common sequence,
-" then show a list,
-" then cycle through completing the full names in the list in order
-set wildmode=longest,list,full
-if exists('+wildignorecase')
- " make command mode completion case insensitive
- set wildignorecase
-endif
-
-
-""" SEARCH """
-
-" make searches case-insensitive
-set ignorecase
-" unless they include a capital letter
-set smartcase
-if has('extra_search')
- " highlight all matches when searching
- set hlsearch
-endif
-
-
-""" TERMINAL STUFF """
-
-" wait a much shorter amount of time for escape sequences
-" (this makes <Esc> much more responsive)
-set ttimeoutlen=50
-" send text to the terminal in such a way that line wrapping is done at the
-" terminal level, so copying and pasting wrapped lines works correctly
-" (assuming you temporarily unset showbreak)
-set ttyfast
-" entirely disable error bells:
-" make all bells visual bells
-set visualbell
-" and then disable visual bells
-set t_vb=
-
-
-""" COLORS """
-
-" force vim to use 256 colors
-" (it typically can't detect this while in screen/tmux since TERM=screen
-" doesn't advertise it, even though ~everything does support it these days)
-set t_Co=256
-" globally highlight diff conflict markers
-match ErrorMsg '^\(<\||\|=\|>\)\{7\}\([^=].\+\)\?$'
-
-
-""" MAPPINGS """
-
-" keep the current selection when indenting
-xnoremap < <gv
-xnoremap > >gv
-" make Y behave analogously to D instead of dd
-nnoremap Y y$
-" make arrow keys move visually (since j/k already move linewise)
-noremap <up> gk
-noremap <down> gj
-inoremap <up> <C-o>gk
-inoremap <down> <C-o>gj
diff --git a/vim/plugin/rainbow_paren.vim b/vim/plugin/rainbow_paren.vim
deleted file mode 100644
index 9c26134..0000000
--- a/vim/plugin/rainbow_paren.vim
+++ /dev/null
@@ -1,96 +0,0 @@
-" this script by Shawn M Moore aka Sartak <sartak at gmail.com>
-" also by Michael R Geddes aka frogonwheels <vimmer at frog.wheelycreek.net>
-" originally by anonymous
-
-" this in the public domain
-" last updated 25 Mar 07
-
-" this does nothing unless you,
-" let g:rainbow = 1
-
-" and set which kinds of character pairs you want to rainbow
-" let g:rainbow_paren = 1 " ()
-" let g:rainbow_brace = 1 " {}
-" let g:rainbow_bracket = 1 " []
-" let g:rainbow_angle = 1 " <>
-
-" if you want the different types to nest, such that the braces in ({}) are
-" colored the same as the internal parens of (()), then
-" let g:rainbow_nested = 1
-
-function! Rainbow()
- let s:basename = 'level'
- exe 'hi '.s:basename.'1c ctermfg=6 guifg=#1673b0'
- exe 'hi '.s:basename.'2c ctermfg=2 guifg=#008551'
- exe 'hi '.s:basename.'3c ctermfg=3 guifg=#b25200'
- exe 'hi '.s:basename.'4c ctermfg=4 guifg=#4369cc'
- exe 'hi '.s:basename.'5c ctermfg=5 guifg=#a045a7'
- " this color is never nested, it only appears on the outermost layer
- exe 'hi '.s:basename.'6c ctermfg=1 guifg=#c7394e'
-
- " helper function
- func s:DoSyn(cur, top, left, right, uniq)
- let uniq = a:uniq
- if exists("g:rainbow_nested") && g:rainbow_nested != 0
- let uniq = ""
- endif
-
- let cmd = 'syn region '.s:basename.uniq.a:cur.' transparent fold matchgroup='.s:basename.a:cur.'c start=/'.a:left.'/ end=/'.a:right.'/ contains=TOP'
-
- let i = a:cur
-
- if i == 1
- let i = a:top
- endif
-
- while i <= a:top
- let cmd = cmd . ',' . s:basename . uniq . i
- let i = i + 1
- endwhile
- exe cmd
- endfunc
-
- func s:DoSyntaxes(count)
- let i = 1
-
- while i <= a:count
- " if you define new pairs, make sure to take into account that the
- " delimiter is currently / and that it uses regex, so you need to escape
- " regex metachars (like what is done for brackets)
-
- if exists("g:rainbow_paren") && g:rainbow_paren != 0
- " ocaml uses (* *) for comments; these shouldn't be highlighted
- if &filetype == "ocaml"
- call s:DoSyn(i, a:count, "(\\*\\@!", "\\*\\@<!)", "a")
- else
- call s:DoSyn(i, a:count, "(", ")", "a")
- endif
- endif
-
- if exists("g:rainbow_brace") && g:rainbow_brace != 0
- call s:DoSyn(i, a:count, "{", "}", "b")
- endif
-
- if exists("g:rainbow_bracket") && g:rainbow_bracket != 0
- call s:DoSyn(i, a:count, "\\[", "\\]", "c")
- endif
-
- if exists("g:rainbow_angle") && g:rainbow_angle != 0
- call s:DoSyn(i, a:count, "<", ">", "d")
- endif
-
- let i = i + 1
- endwhile
- endfun
-
- call s:DoSyntaxes(6) " 6 is the number of colors we have
-
- delfun s:DoSyn
- delfun s:DoSyntaxes
-endfunction
-
-if exists("g:rainbow") && g:rainbow
- augroup rainbow
- autocmd BufWinEnter,FileType * call Rainbow()
- augroup END
-endif
diff --git a/vim/snippets/_.snippets b/vim/snippets/_.snippets
deleted file mode 100644
index 982a614..0000000
--- a/vim/snippets/_.snippets
+++ /dev/null
@@ -1,4 +0,0 @@
-snippet now
- `strftime("%Y-%m-%d %H:%M")`
-snippet nows
- "`strftime("%Y-%m-%d %H:%M")`"
diff --git a/vim/snippets/c.snippets b/vim/snippets/c.snippets
deleted file mode 100644
index eece346..0000000
--- a/vim/snippets/c.snippets
+++ /dev/null
@@ -1,12 +0,0 @@
-snippet guard
- #ifndef ${1:`'_' . toupper(substitute(matchstr(expand("%"), '^.*/\zs.*\.h'), '[.-]', '_', 'g'))`}
- #define $1
-
- ${0}
-
- #endif
-snippet main
- int main(int argc, char *argv[])
- {
- ${0}
- }
diff --git a/vim/snippets/perl.snippets b/vim/snippets/perl.snippets
deleted file mode 100644
index d522f63..0000000
--- a/vim/snippets/perl.snippets
+++ /dev/null
@@ -1,123 +0,0 @@
-snippet tbl
- local $Test::Builder::Level = $Test::Builder::Level + 1;
-snippet ccl
- local $Carp::CarpLevel = $Carp::CarpLevel + 1;
-snippet linc
- local $${1:a} = $$1 + ${2:1};
- ${0}
-snippet script
- #!/usr/bin/env perl
- use strict;
- use warnings;
-
- ${0}
-snippet test
- #!/usr/bin/env perl
- use strict;
- use warnings;
- use Test::More;
-
- ${0}
-
- done_testing;
-snippet sub
- sub ${1:foo} {
- ${0}
- }
-snippet wd
- use Data::Dump; ddx(${1});
- ${0}
-snippet wdd
- use Data::Dump; push @Data::Dump::FILTERS, sub { return {dump => "$_[1]"} if $_[0]->depth > ${1:1} }; ddx(${2});
- ${0}
-snippet package
- package ${1:`substitute(matchstr(expand("%"), '^lib/\zs.*\ze\.pm'), '/', '::', 'g')`};
- use strict;
- use warnings;
-
- ${0}
-
- 1;
-snippet test_psgi
- test_psgi
- app => ${1:MyApp}->new->to_app,
- client => sub {
- my $cb = shift;
-
- {
- ${0}
- }
- };
-#
-# Moose
-#
-snippet class
- package ${1:`substitute(matchstr(expand("%"), '^lib/\zs.*\ze\.pm'), '/', '::', 'g')`};
- use Moose;
-
- ${0}
-
- __PACKAGE__->meta->make_immutable;
- no Moose;
-
- 1;
-# XXX: ideally, this would be merged with the one above, but we need posthooks
-# for that to happen. also, some way to get the extends line to update with
-# the package line would be nice, maybe?
-snippet subclass
- package ${1:`substitute(matchstr(expand("%"), '^lib/\zs.*\ze\.pm'), '/', '::', 'g')`};
- use Moose;
- extends '${2:`matchstr(substitute(matchstr(expand("%"), '^lib/\zs.*\ze\.pm'), '/', '::', 'g'), '.*\ze::.*')`}';
-
- ${0}
-
- __PACKAGE__->meta->make_immutable;
- no Moose;
-
- 1;
-snippet role
- package ${1:`substitute(matchstr(expand("%"), '^lib/\zs.*\ze\.pm'), '/', '::', 'g')`};
- use Moose::Role;
-
- ${0}
-
- no Moose::Role;
-
- 1;
-snippet has
- has ${1:attr} => (
- is => '${2:ro}',
- isa => '${3:Str}',${0}
- );
-snippet hasl
- has ${1:attr} => (
- is => '${2:ro}',
- isa => '${3:Str}',
- lazy_build => 1,${4}
- );
-
- sub _build_$1 {
- my $self = shift;
- ${0}
- }
-snippet m
- sub ${1:foo} {
- my $self = shift;
- ${0}
- }
-snippet around
- around ${1:foo} => sub {
- my $orig = shift;
- my $self = shift;
- ${0}
- };
-snippet after
- after ${1:foo} => sub {
- my $self = shift;
- ${0}
- };
-snippet before
- before ${1:foo} => sub {
- my $self = shift;
- ${0}
- };
diff --git a/vim/snippets/python.snippets b/vim/snippets/python.snippets
deleted file mode 100644
index fc0dd70..0000000
--- a/vim/snippets/python.snippets
+++ /dev/null
@@ -1,8 +0,0 @@
-snippet test
- import unittest
-
- ${1}
-
- class ${2:`join(map(split(matchstr(expand("%"), '^t\(ests\?\)\?/\zs.*\ze\.py'), '_'), 'toupper(v:val[0]) . v:val[1:]'), '')`}(unittest.TestCase):
- def test_${3}(self):
- ${0}
diff --git a/vim/snippets/ruby.snippets b/vim/snippets/ruby.snippets
deleted file mode 100644
index 3bf5f28..0000000
--- a/vim/snippets/ruby.snippets
+++ /dev/null
@@ -1,22 +0,0 @@
-snippet script
- #!/usr/bin/env ruby
-
- def main
- ${0}
- end
-
- if \$0 == __FILE__
- main(*ARGV)
- end
-snippet def
- def ${1:foo}
- ${0}
- end
-snippet class
- class ${1:Foo}
- ${0}
- end
-snippet module
- module ${1:Foo}
- ${0}
- end
diff --git a/vim/snippets/rust.snippets b/vim/snippets/rust.snippets
deleted file mode 100644
index f9e885d..0000000
--- a/vim/snippets/rust.snippets
+++ /dev/null
@@ -1,16 +0,0 @@
-snippet main
- fn main () {
- ${0}
- }
-snippet pr
- println!(${0});
-snippet struct
- #[deriving(PartialEq, Eq, Show)]
- struct ${1} {
- ${0}
- }
-snippet test
- #[test]
- fn ${1} () {
- ${0}
- }
diff --git a/vim/snippets/sh.snippets b/vim/snippets/sh.snippets
deleted file mode 100644
index 2a8e4b0..0000000
--- a/vim/snippets/sh.snippets
+++ /dev/null
@@ -1,6 +0,0 @@
-snippet script
- #!/usr/bin/env bash
- set -eux
- set -o pipefail
-
- ${0}
diff --git a/vim/snippets/tex.snippets b/vim/snippets/tex.snippets
deleted file mode 100644
index 3a79579..0000000
--- a/vim/snippets/tex.snippets
+++ /dev/null
@@ -1,13 +0,0 @@
-snippet article
- \documentclass[11pt]{article}
- \usepackage{jesse}
-
- \headers{${1}}
- {\huge \textbf{${2}}}
- {${3}}
-
- \begin{document}
-
- ${0}
-
- \end{document}
diff --git a/vim/snippets/xs.snippets b/vim/snippets/xs.snippets
deleted file mode 100644
index eada925..0000000
--- a/vim/snippets/xs.snippets
+++ /dev/null
@@ -1,16 +0,0 @@
-snippet xs
- #include "EXTERN.h"
- #include "perl.h"
- #include "XSUB.h"
-
- MODULE = ${1:`matchstr(expand("%"), '^.*\ze\.xs')`} PACKAGE = ${2:$1}
-
- PROTOTYPES: DISABLE
-
-
- ${0}
-snippet xsub
- ${3:void}
- ${1:name}(${2})
- CODE:
- ${0}
diff --git a/vim/spell/en.utf-8.add b/vim/spell/en.utf-8.add
deleted file mode 100644
index 14fe17c..0000000
--- a/vim/spell/en.utf-8.add
+++ /dev/null
@@ -1,111 +0,0 @@
-schedulable
-mutex
-hippocampus
-anterograde
-playtesters
-gameplay
-SQL
-API
-endianness
-timestamp
-Luehrs
-doy
-tozt
-UIUC
-Hydrogeology
-Geochemists
-Tcl
-Tk
-PDF
-SVG
-PostScript
-http
-TrueType
-OpenMP
-perl
-org
-MooseX
-NonMoose
-interoperate
-github
-IRC
-multiplayer
-plugin
-TAEB
-taeb
-sartak
-NetHack
-nethack
-Pty
-sourceforge
-OCaml
-LablGTK
-LuaIRC
-luaforge
-luairc
-Lua
-CTCP
-DCC
-CPAN
-JavaScript
-CSS
-sed
-Debian
-Gentoo
-XP
-Cygwin
-Darcs
-Inline
-webmaster
-rollerblading
-Illini
-templating
-programmatically
-JS
-Xslate
-misparsed
-CSV
-ParseXLSX
-XLSX
-ParseExcel
-WriteExcel
-tmux
-unshifted
-xbindkeys
-Firefox
-remappings
-Pentadactyl
-Zsh
-readline
-vim
-vimrc
-zshrc
-inputrc
-structs
-inlined
-println
-printf
-builtin
-parsable
-Mozilla
-inlinable
-LLVM
-backend
-sandboxed
-Acid2
-fn
-mut
-utf8
-interoperating
-Mozilla's
-stringification
-enum
-enums
-destructuring
-NES
-blog
-https
-doyster
-pdf
-termcast
-Avaaz
diff --git a/vim/syntax/levdes.vim b/vim/syntax/levdes.vim
deleted file mode 100644
index a4f1982..0000000
--- a/vim/syntax/levdes.vim
+++ /dev/null
@@ -1,304 +0,0 @@
-" Vim syntax file
-" Language: Dungeon Crawl level design (.des) files.
-" Maintainer: Darshan Shaligram <scintilla@gmail.com>
-" Last Change: 2007 Jun 28
-" Remark: Basic Vim syntax highlighting for Dungeon Crawl Stone Soup
-" level design (.des) files.
-"
-" How to use this:
-" * Put levdes.vim (this file) under ~/.vim/syntax (or similar directory for
-" your system - usually C:\Program Files\Vim\vimfiles\syntax on Windows).
-" * In your .vimrc, or in a new file ~/.vim/ftdetect/levdes.vim, add this line:
-" au BufRead,BufNewFile *.des set syntax=levdes
-" Thereafter, any .des files you edit in (g)vim will use syntax highlighting.
-
-if version < 600
- syntax clear
-elseif exists("b:current_syntax")
- finish
-endif
-
-if !exists("main_syntax")
- let main_syntax = 'des'
-endif
-
-syn include @desLua syntax/lua.vim
-
-syn case match
-
-syn match desLuaBlock /\(lua\)\?\s\+{{/ contained
-syn match desOtherLuaBlock /^\(prelude\|lua\|validate\|epilogue\|veto\)\?\s*{{/ contained
-syn match desLuaBlockEnd /}}/ contained
-"syn match desColonLine /^\s*:/ contained
-
-syn cluster desLuaGroup contains=desLuaBlock,desOtherLuaBlock,desLuaBlockEnd
-
-syn region desLua start=/^\s*\(lua\)\?\s*{{/ end=/}}\s*$/ contains=@desLuaGroup,@desLua keepend
-syn region desLuaCol start=/^\s*:/ end=/$/ contains=@desLuaGroup,@desLua keepend
-syn region desVal start=/^\s*validate\?\s*{{/ end=/}}\s*$/ contains=@desLuaGroup,@desLua keepend
-syn region desPre start=/^\s*prelude\?\s*{{/ end=/}}\s*$/ contains=@desLuaGroup,@desLua keepend
-syn region desEpi start=/^\s*epilogue\?\s*{{/ end=/}}\s*$/ contains=@desLuagroup,@deslua keepend
-syn region desVet start=/^\s*veto\?\s*{{/ end=/}}\s*$/ contains=@desLuagroup,@deslua keepend
-
-setlocal iskeyword+=:
-setlocal iskeyword+=-
-
-" These have extra matching going on, so not in desDeclarator (global)
-syn keyword desDec NAME: COLOUR: SUBST: NSUBST: SHUFFLE: CLEAR: LROCKCOL: LFLOORCOL: contained
-
-syn region desSubst start=/^SUBST:\s*/ end=/$/ contains=desDec,desSubstArg,desSubstSep,@desMapElements keepend
-syn region desNsubst start=/^NSUBST:\s*/ end=/$/ contains=desDec,desSubstArg,desSubstSep,@desMapElements keepend
-syn region desShuffle start=/^SHUFFLE:\s*/ end=/$/ contains=desDec,desMapFrag keepend
-syn region desClear start=/^CLEAR:\s*/ end=/$/ contains=desDec,desSubstArg keepend
-syn region desColourline start=/^\(COLOUR\|L[A-Z]*COL\):/ end=/$/ contains=desDec,desColour keepend
-
-" Absolutely always highlight the vault name as just that
-syn region desNameline start=/^NAME:/ end=/$/ contains=desDec,desVaultname keepend
-syn match desVaultname /\w*/ contained
-
-syn match desGod contained /ashenzari\|beogh\|cheibriados\|dithmenos\|elyvilon/
-syn match desGod contained /fedhas\|gozag\|jiyva\|kikubaaqudgha\|lugonu/
-syn match desGod contained /makhleb\|nemelex_xobeh\|okawaru\|qazlal\|ru/
-syn match desGod contained /sif_muna\|trog\|vehumet\|xom\|yredelemnul\|zin/
-syn match desGod contained /the_shining_one/
-
-syn keyword desDeclarator ORIENT: DEPTH: PLACE: MONS: FLAGS: default-depth: TAGS: CHANCE: WEIGHT:
-syn keyword desDeclarator ITEM: KFEAT: KMONS: KITEM: KMASK: KPROP: MARKER: WELCOME:
-syn keyword desDeclarator LFLOORTILE: LROCKTILE: FTILE: RTILE: TILE: SUBVAULT: FHEIGHT: DESC: ORDER:
-
-" keywords
-" ORIENT
-syn keyword desOrientation north south east west northwest northeast southwest southeast encompass float centre
-
-" DEPTH | PLACE
-syn keyword desOrientation Depths Temple Orc Elf Lair Swamp Shoals Snake Spider Slime Vaults Blade Crypt Tomb
-"Note: `Zot` totally highlights in e.g. the items `rune of Zot` and `Orb of Zot`. Not worth fixing.
-syn keyword desOrientation Hell Dis Geh Coc Tar Zot Forest Abyss Pan Zig Lab Bazaar Trove Sewer Ossuary
-syn keyword desOrientation Bailey IceCv Volcano WizLab
-
-"Note: This is the list above, but lower-cased
-syn match desBranch contained /d\|temple\|orc\|elf\|lair\|swamp\|shoals\|snake\|spider\|slime\|vaults\|blade\|crypt\|tomb/
-syn match desBranch contained /hell\|dis\|geh\|coc\|tar\|zot\|forest\|abyss\|pan\|zig\|lab\|bazaar\|trove\|sewer\|ossuary/
-syn match desBranch contained /bailey\|icecv\|volcano\|wizlab/
-
-syn match desBranchname contained /dungeon\|depths\|temple\|orcish_mines\|elven_halls\|lair\|swamp\|shoals/
-syn match desBranchname contained /snake_pit\|spider_nest\|slime_pits\|vaults\|hall_of_blades\|crypt\|tomb/
-syn match desBranchname contained /hell\|dis\|gehenna\|cocytus\|tartarus\|zot\|forest\|abyss\|pandemonium/
-syn match desBranchname contained /ziggurat\|labyrinth\|bazaar\|trove\|sewer\|ossuary/
-syn match desBranchname contained /bailey\|ice_cave\|volcano\|wizlab/
-
-" TAGS
-" in abyss.cc
-syn keyword desOrientation abyss_exit
-" in decks.cc and dgn-labyrinth.cc (without `minotaur` because monster)
-syn keyword desOrientation lab generate_loot
-" from dlua.ziggurat
-syn keyword desOrientation ziggurat_pillar centered
-" map building in dungeon.cc (`transparent` is handled later)
-"Note: `dummy` mis-catches `training dummy` about half as often as actually used as tag
-syn keyword desOrientation dummy arrival no_exits extra ruin layout pan decor
-syn keyword desOrientation allow_dup uniq luniq
-syn keyword desOrientation no_hmirror no_vmirror no_rotate
-syn keyword desOrientation no_dump
-" vault placement in maps.cc
-syn keyword desOrientation unrand place_unique special_room tutorial
-syn keyword desOrientation water_ok overwrite_floor_cell replace_portal
-" V vault building (mostly dlua/v_layouts and v_rooms)
-syn keyword desOrientation vaults_room vaults_empty vaults_hard no_windows preserve_wall
-
-" ITEM | KITEM (in mapdef.cc, without `random`)
-syn keyword desOrientation randbook any good_item star_item superb_item gold nothing
-syn keyword desOrientation acquire mundane damaged cursed randart not_cursed useful unobtainable
-syn keyword desOrientation mimic no_mimic no_pickup no_uniq allow_uniq
-"Note: `rotting` removed here which often caught `rotting devil` but was unused as item tag
-syn keyword desOrientation corpse chunk skeleton never_decay
-
-" MONS | KMONS (in mapdef.cc)
-syn keyword desOrientation fix_slot priest_spells actual_spells god_gift
-syn keyword desOrientation generate_awake patrolling band
-syn keyword desOrientation hostile friendly good_neutral fellow_slime strict_neutral neutral
-"Note: `spectre` removed: mis-catches `silent spectre` but was unused as modifier (`spectral` exists)
-syn keyword desOrientation zombie skeleton simulacrum spectral
-syn keyword desOrientation seen always_corpse never_corpse
-syn keyword desOrientation base nonbase
-syn keyword desOrientation n_suf n_adj n_rpl n_the
-syn keyword desOrientation name_suffix name_adjective name_replace name_definite
-syn keyword desOrientation n_des n_spe n_zom n_noc
-syn keyword desOrientation name_descriptor name_species name_zombie name_nocorpse
-
-" COLOUR
-" Base
-syn keyword desColour contained blue green cyan red magenta brown darkgrey
-syn keyword desColour contained lightblue lightgreen lightcyan lightred lightmagenta yellow lightgrey white
-" Elemental
-syn keyword desColour contained fire ice earth electricity air poison water magic mutagenic warp enchant
-syn keyword desColour contained heal holy dark death unholy vehumet beogh crystal blood smoke slime jewel
-syn keyword desColour contained elven dwarven orcish flash kraken floor rock mist shimmer_blue decay
-syn keyword desColour contained silver gold iron bone elven_brick waves tree mangrove tornado liquefied
-syn keyword desColour contained orb_glow disjunction random
-
-" TILE
-syn keyword desOrientation no_random
-
-" KFEAT
-syn keyword desOrientation known mimic
-
-" abyss TAGS in mapdef.cc
-syn keyword desOrientation abyss abyss_rune
-syn keyword desOrientation overwritable
-" KMASK (in mapdef.cc)
-syn keyword desOrientation vault no_item_gen no_monster_gen no_pool_fixup no_wall_fixup opaque no_trap_gen
-
-" KPROP
-syn keyword desOrientation bloody highlight mold no_cloud_gen no_tele_into no_submerge no_tide no_jiyva
-
-syn match desComment "^\s*#.*$&"
-
-"Note: `;` and `|` are necessary due to monster/randbook `spells:`,
-" `.` can be an empty spell slot and `'` is contained in certain spell names,
-" `$` and `-` are used in depth definitions (but `,` should not match there).
-syn match desProperty /\w*:[[:alnum:]_\.';|\$-]\+/ contains=desAttribute
-" Without `oneline` this wraps around and matches e.g. some SUBST: on the next line
-syn region desAttribute start=/\</ end=/:/ contained oneline
-
-syn match desEntry "\<\w*_entry\>" contains=desBranch
-syn match desEntry "\<serial_\w*\>"
-syn match desEntry "\<no_species_\w\w\>"
-syn match desEntry "\<\(no\)\=layout_\w*\>"
-syn match desEntry "\<l\=uniq_\w*\>"
-syn match desEntry "\<chance_\w*\>"
-syn match desEntry "\<fallback_\w*\>"
-syn match desEntry "\<vaults_entry_\w*\>" contains=desBranch
-syn match desEntry "\<vaults_orient_\w\>"
-syn match desEntry "\<altar_\w*\>" contains=desGod
-syn match desEntry "\<uniq_altar_\w*\>" contains=desGod
-syn match desEntry "\<temple_overflow_\w*\>" contains=desGod
-syn match desEntry "\<overflow_altar_\w*\>" contains=desGod
-syn match desEntry "\<enter_\w*\>" contains=desBranchname
-syn match desEntry "\<exit_\w*\>" contains=desBranchname
-syn match desEntry "\<ruin_\w*\>" contains=desBranchname
-
-" 'transparent' is a Vim syntax keyword
-syn match desTransparent "\<transparent\>"
-syn match desRange "\d*-\d*"
-syn match desNumber "\s\d*"
-syn match desWeight "w\(eight\)\=:\d*"
-syn match desWeight "q:\d*\(-\d*\)\="
-syn match desSlash "/"
-
-syn keyword desMapBookend MAP ENDMAP contained
-syn match desMapWall /x/ contained
-syn match desMapPermaWall /X/ contained
-syn match desMapStoneWall /c/ contained
-syn match desMapGlassWall /[mno]/ contained
-syn match desMapMetalWall /v/ contained
-syn match desMapCrystalWall /b/ contained
-syn match desMapTree /t/ contained
-
-syn match desMapFloor /\./ contained
-syn match desMapDoor /[+=]/ contained
-
-syn match desMapShallow /W/ contained
-syn match desMapWater /w/ contained
-syn match desMapLava /l/ contained
-
-syn match desMapEntry /@/ contained
-syn match desMapStairs /[}{)(\]\[]/ contained
-syn match desMapTrap /[\^~]/ contained
-
-syn match desMapGold /\$/ contained
-syn match desMapValuable /[%*|]/ contained
-
-syn match desMapMonst /[0-9]/ contained
-
-syn cluster desMapElements contains=desMapBookend
-syn cluster desMapElements add=desMapWall,desMapPermaWall,desMapStoneWall,desMapGlassWall,desMapCrystalWall,desMapMetalWall,desMapTree
-syn cluster desMapElements add=desMapFloor,desMapDoor
-syn cluster desMapElements add=desMapShallow,desMapWater,desMapLava
-syn cluster desMapElements add=desMapEntry,desMapStairs,desMapTrap
-syn cluster desMapElements add=desMapGold,desMapValuable
-syn cluster desMapElements add=desMapMons
-
-syn match desSubstArg /\S/ contained nextgroup=desSubstSep skipwhite
-syn match desSubstSep /[:=]/ contained nextgroup=desMapFrag skipwhite
-syn match desColourSep /[:=]/ contained nextgroup=desColour skipwhite
-syn region desMapFrag start=/./ end=/$/ contains=@desMapElements contained
-
-syn region desMap start=/^\s*\<MAP\>\s*$/ end=/^\s*\<ENDMAP\>\s*$/ contains=@desMapElements keepend
-
-hi link desDec Statement
-hi link desDeclarator Statement
-hi link desVaultname Identifier
-hi link desMapBookend Statement
-hi link desLuaBlock Statement
-hi link desOtherLuaBlock Statement
-hi link desLuaBlockEnd Statement
-"hi link desColonLine Statement
-hi link desComment Comment
-hi link desMap String
-hi link desSubstArg String
-hi link desRange String
-hi link desEntry Type
-hi link desNumber String
-hi link desWeight String
-hi link desSlash Comment
-
-hi link desSubstSep Type
-hi link desOrientation Type
-hi link desAttribute Type
-hi link desProperty Special
-hi link desGod Special
-hi link desBranch Special
-hi link desBranchname Special
-hi link desColour Type
-hi link desTransparent Type
-
-" It would be really nice if this worked for people who switch bg
-" post-loading, like "normal" highlights do. Does someone know how?
-if &bg == "dark"
- hi desMapWall guifg=darkgray term=bold gui=bold ctermfg=white
- hi desMapPermaWall guifg=#a0a000 gui=bold ctermfg=yellow
- hi desMapStoneWall guifg=black gui=bold ctermfg=gray
- hi desMapGlassWall guifg=lightcyan ctermfg=lightcyan
- hi desMapMetalWall guifg=#004090 term=bold gui=bold ctermfg=lightblue
- hi desMapCrystalWall guifg=#009040 term=bold gui=bold ctermfg=green
- hi desMapTree guifg=#00aa00 ctermfg=darkgreen
- hi desMapFloor guifg=#008000 ctermfg=darkgray
- hi desMapDoor guifg=brown gui=bold ctermfg=white
- hi desMapShallow guifg=lightcyan ctermfg=darkcyan
- hi desMapWater guifg=lightblue ctermfg=darkblue
- hi desMapLava guifg=red gui=bold ctermfg=darkred
-
- hi desMapEntry guifg=black guibg=white gui=bold ctermfg=white ctermbg=black
- hi desMapStairs guifg=orange gui=bold ctermfg=magenta
- hi desMapTrap guifg=red gui=bold ctermfg=darkred
-
- hi desMapGold guifg=#c09000 ctermfg=yellow
- hi desMapValuable guifg=darkgreen gui=bold ctermfg=yellow
- hi desMapMonst guifg=red ctermfg=red
-else
- hi desMapWall guifg=darkgray term=bold gui=bold ctermfg=brown
- hi desMapPermaWall guifg=#a0a000 gui=bold ctermfg=yellow
- hi desMapStoneWall guifg=black gui=bold ctermfg=darkgray
- hi desMapGlassWall guifg=lightcyan ctermfg=lightcyan
- hi desMapMetalWall guifg=#004090 term=bold gui=bold ctermfg=blue
- hi desMapCrystalWall guifg=#009040 term=bold gui=bold ctermfg=green
- hi desMapTree guifg=#00aa00 ctermfg=darkgreen
- hi desMapFloor guifg=#008000 ctermfg=lightgray
- hi desMapDoor guifg=brown gui=bold ctermfg=black ctermbg=brown
- hi desMapShallow guifg=lightcyan ctermfg=darkcyan
- hi desMapWater guifg=lightblue ctermfg=darkblue
- hi desMapLava guifg=red gui=bold ctermfg=red
-
- hi desMapEntry guifg=black guibg=white gui=bold ctermfg=white ctermbg=black
- hi desMapStairs guifg=orange gui=bold ctermfg=white
- hi desMapTrap guifg=red gui=bold ctermfg=red
-
- hi desMapGold guifg=#c09000 ctermfg=yellow
- hi desMapValuable guifg=darkgreen gui=bold ctermfg=lightgreen
- hi desMapMonst guifg=red ctermfg=darkred
-endif
-
-syn sync minlines=45
-
-let b:current_syntax="levdes"
diff --git a/vim/syntax/nhdes.vim b/vim/syntax/nhdes.vim
deleted file mode 100644
index dcafdf3..0000000
--- a/vim/syntax/nhdes.vim
+++ /dev/null
@@ -1,99 +0,0 @@
-" Vim syntax file
-" Language: NetHack DES file
-" Author: Pasi Kallinen <paxed@alt.org>
-" Version: 20061119
-" Copyright: Copyright (c) 2006 Pasi Kallinen
-" Licence: You may redistribute this under the same terms as NetHack itself
-
-if exists("b:current_syntax")
- finish
-endif
-
-syn sync minlines=30
-
-" we're case sensitive
-syn case match
-
-" some keywords use '-'
-setlocal iskeyword+=-
-
-syn region nhDesComment start=/^[ \t]*#/ end=/$/
-
-syn keyword nhDesCommandNoArgs
- \ NOMAP RANDOM_CORRIDORS WALLIFY
-
-syn keyword nhDesCommandWithArgs
- \ ALTAR BRANCH CHANCE CONTAINER CORRIDOR DOOR DRAWBRIDGE ENGRAVING
- \ FLAGS FOUNTAIN GEOMETRY GOLD INIT_MAP LADDER LEVEL MAZE MAZEWALK
- \ MESSAGE MONSTER NAME NON_DIGGABLE NON_PASSWALL OBJECT POOL PORTAL
- \ RANDOM_MONSTERS RANDOM_OBJECTS RANDOM_PLACES REGION ROOM SINK STAIR
- \ SUBROOM TELEPORT_REGION TRAP
-
-syn keyword nhDesRegister
- \ align monster object place
-
-syn keyword nhDesConstant
- \ altar arboreal asleep awake blessed bottom broken burn center chaos
- \ closed coaligned \contained cursed down dust east engrave false filled
- \ half-left half-right hardfloor hostile law left levregion lit locked
- \ mark m_feature m_monster m_object neutral noalign nodoor nommap
- \ noncoaligned none north noteleport open peaceful random right sanctum
- \ shortsighted shrine south top true uncursed unfilled unlit up west
-
-syn region nhDesString start=/"/ end=/"/
-syn match nhDesChar /'.'/
-
-syn match nhDesCoord /(\s*\d\+\s*,\s*\d\+\s*)/
-syn match nhDesRegion /(\s*\d\+\s*,\s*\d\+\s*,\s*\d\+\s*,\s*\d\+\s*)/
-
-syn match nhDesMapCharDoor /[+S]/ contained
-syn match nhDesMapCharFloor /[\.B]/ contained
-syn match nhDesMapCharCorridor /[#H]/ contained
-syn match nhDesMapCharWall /[\-\| ]/ contained
-syn match nhDesMapCharWater /[WP}{]/ contained
-syn match nhDesMapCharThrone /\\/ contained
-syn match nhDesMapCharAir /A/ contained
-syn match nhDesMapCharCloud /C/ contained
-syn match nhDesMapCharLava /L/ contained
-syn match nhDesMapCharSink /K/ contained
-syn match nhDesMapCharIce /I/ contained
-syn match nhDesMapCharTree /T/ contained
-syn match nhDesMapCharIronbars /F/ contained
-syn match nhDesMapCharLinenum /[0123456789]/ contained
-" TODO: Any better way to do this?
-syn match nhDesMapCharError /[^+S\.B#H\-\| WP}{\\ACLKITF0-9]/ contained
-
-syn region nhDesMap matchgroup=nhDesCommandNoArgs start=/^MAP$/ end=/^ENDMAP$/
- \ contains=nhDesMapCharError,nhDesMapCharDoor,nhDesMapCharFloor,
- \ nhDesMapCharCorridor,nhDesMapCharWall,nhDesMapCharWater,
- \ nhDesMapCharThrone,nhDesMapCharAir,nhDesMapCharCloud,nhDesMapCharLava,
- \ nhDesMapCharSink,nhDesMapCharIce,nhDesMapCharTree,nhDesMapCharIronbars,
- \ nhDesMapCharLinenum
-
-hi def link nhDesComment Comment
-hi def link nhDesCommandNoArgs KeyWord
-hi def link nhDesCommandWithArgs KeyWord
-hi def link nhDesRegister Constant
-hi def link nhDesConstant Constant
-hi def link nhDesString String
-hi def link nhDesChar String
-hi def link nhDesCoord Number
-hi def link nhDesRegion Number
-
-highlight nhDesMapCharDoor ctermbg=black ctermfg=brown guibg=black guifg=brown
-highlight nhDesMapCharFloor ctermbg=black ctermfg=grey guibg=black guifg=grey
-highlight nhDesMapCharCorridor ctermbg=black ctermfg=grey guibg=black guifg=grey
-highlight nhDesMapCharWall ctermbg=black ctermfg=grey guibg=black guifg=grey
-highlight nhDesMapCharWater ctermbg=black ctermfg=darkblue guibg=black guifg=darkblue
-highlight nhDesMapCharThrone ctermbg=black ctermfg=yellow guibg=black guifg=yellow
-highlight nhDesMapCharAir ctermbg=black ctermfg=lightblue guibg=black guifg=lightblue
-highlight nhDesMapCharCloud ctermbg=black ctermfg=grey guibg=black guifg=grey
-highlight nhDesMapCharLava ctermbg=black ctermfg=red guibg=black guifg=red
-highlight nhDesMapCharSink ctermbg=black ctermfg=grey guibg=black guifg=grey
-highlight nhDesMapCharIce ctermbg=black ctermfg=lightblue guibg=black guifg=lightblue
-highlight nhDesMapCharTree ctermbg=black ctermfg=green guibg=black guifg=green
-highlight nhDesMapCharIronbars ctermbg=black ctermfg=cyan guibg=black guifg=cyan
-highlight nhDesMapCharLinenum ctermbg=black ctermfg=darkgrey guibg=black guifg=darkgrey
-highlight nhDesMapCharError ctermbg=red ctermfg=yellow guibg=red guifg=yellow
-
-let b:current_syntax = "nhdes"
diff --git a/vim/syntax/perl.vim b/vim/syntax/perl.vim
deleted file mode 100644
index c70fa27..0000000
--- a/vim/syntax/perl.vim
+++ /dev/null
@@ -1 +0,0 @@
-let perl_sub_signatures = 1
diff --git a/vimrc b/vimrc
deleted file mode 100644
index 58fe375..0000000
--- a/vimrc
+++ /dev/null
@@ -1,194 +0,0 @@
-" options {{{
-set shiftwidth=4
-set expandtab
-set termguicolors
-let &t_8f="\e[38;2;%lu;%lu;%lum"
-let &t_8b="\e[48;2;%lu;%lu;%lum"
-colorscheme local
-" }}}
-" hooks {{{
-augroup vimrc
- autocmd!
-augroup END
-" }}}
-" bindings {{{
-" general {{{
-let g:mapleader = ';'
-let g:maplocalleader = ';'
-" }}}
-" M to :make {{{
-noremap <silent>M :<C-u>make<CR><CR><C-W>k
-" }}}
-" F11 for spell checking {{{
-noremap <silent><expr><F11> &spell ? ":\<C-u>setlocal nospell\<CR>" : ":\<C-u>setlocal spell\<CR>"
-inoremap <silent><expr><F11> &spell ? "\<C-o>:setlocal nospell\<CR>" : "\<C-o>:setlocal spell\<CR>"
-" }}}
-" editing binary files {{{
-nnoremap <C-B> :%!xxd<CR>
-nnoremap <C-R> :%!xxd -r<CR>
-" }}}
-" easier tag traversal {{{
-nnoremap <CR> <C-]>
-nnoremap <BS> <C-T>
-autocmd vimrc CmdWinEnter * nnoremap <buffer><CR> <CR>
-" }}}
-" buffer switching {{{
-nnoremap <silent>H :bp<CR>
-nnoremap <silent>L :bn<CR>
-" }}}
-" use tab for completion {{{
-inoremap <expr> <Tab>
- \ strpart(getline('.'), 0, col('.') - 1) =~ '\(^\\|\s\+\)$'
- \ ? "\<Tab>"
- \ : "\<C-n>"
-inoremap <S-Tab> <C-p>
-" }}}
-" fixups for my keyboard remappings {{{
-nmap <silent>) 0
-nmap <silent>g) g0
-nmap <Bar> \
-" }}}
-" miscellaneous {{{
-nnoremap e c
-nnoremap E C
-nnoremap r <C-r>
-nnoremap , :
-xnoremap , :
-nnoremap ! :!
-xnoremap ! :!
-autocmd vimrc BufEnter * exe "nnoremap T :e " . expand('%')
-nnoremap <silent><Leader>/ :nohl<CR>
-nnoremap <silent><Tab> :w<CR>
-nnoremap <silent>\ :q<CR>
-nnoremap <silent><C-D> :bd<CR>
-" }}}
-" }}}
-" plugin configuration {{{
-" ale {{{
-let g:ale_lint_on_text_changed = 'normal'
-let g:ale_lint_on_insert_leave = 1
-let g:ale_history_enabled = 0
-let g:ale_history_log_output = 0
-" }}}
-" airline
-" autobrace
-" commentary {{{
-map <silent><Leader>x :Commentary<CR>
-" }}}
-" diff-changes {{{
-nnoremap <silent>ds :DiffAgainstFilesystem<CR>
-nnoremap <silent>dc :DiffAgainstVCS<CR>
-nnoremap <silent>de :DiffStop<CR>
-" }}}
-" fzf {{{
-let g:fzf_layout = { 'up': '~40%' }
-if &columns >= 160
- let s:horiz_preview_layout = 'right:50%'
-else
- let s:horiz_preview_layout = 'right:50%:hidden'
-endif
-let s:ag_opts = {"options": ["-d:", "-n4.."]}
-function! s:fzf_files()
- silent let out = system("git rev-parse --show-toplevel 2>/dev/null")
- if strlen(out)
- exe "GFiles -co --exclude-standard"
- else
- exe "Files"
- endif
-endfunction
-command! -bang -nargs=* Ag
- \ call fzf#vim#ag(<q-args>,
- \ "--hidden",
- \ <bang>0 ? fzf#vim#with_preview(s:ag_opts, 'up:60%')
- \ : fzf#vim#with_preview(s:ag_opts, s:horiz_preview_layout, '?'),
- \ <bang>0)
-nnoremap <silent> t :call <SID>fzf_files()<CR>
-nnoremap <silent> ff :Ag<CR>
-nnoremap <silent> fh :Helptags<CR>
-nnoremap <silent> ft :Filetypes<CR>
-" }}}
-" gundo {{{
-if has("python")
- nnoremap <silent>U :silent GundoToggle<CR>
- let g:gundo_help = 0
- let g:gundo_preview_bottom = 1
-else
- let g:gundo_disable = 1
-endif
-" }}}
-" history-sync
-" matchit {{{
-packadd! matchit
-" }}}
-" multiple-cursors
-" neosnippet {{{
-let g:neosnippet#snippets_directory = '~/.vim/snippets'
-let g:neosnippet#disable_runtime_snippets = { '_' : 1 }
-
-function! s:configure_neosnippet_tab_mappings()
- let g:neosnippet_tab_override_i_tab = maparg("<Tab>", "i", 0, 1)
- let g:neosnippet_tab_override_i_stab = maparg("<S-Tab>", "i", 0, 1)
- let g:neosnippet_tab_override_s_tab = maparg("<Tab>", "s", 0, 1)
- imap <expr> <Tab>
- \ neosnippet#expandable_or_jumpable() ?
- \ "\<Plug>(neosnippet_expand_or_jump)" :
- \ g:neosnippet_tab_override_i_tab["expr"]
- \ ? eval(g:neosnippet_tab_override_i_tab["rhs"])
- \ : g:neosnippet_tab_override_i_tab["rhs"]
- imap <expr> <S-Tab>
- \ neosnippet#expandable_or_jumpable() ?
- \ "\<Plug>(neosnippet_expand_or_jump)" :
- \ g:neosnippet_tab_override_i_stab["expr"]
- \ ? eval(g:neosnippet_tab_override_i_stab["rhs"])
- \ : g:neosnippet_tab_override_i_stab["rhs"]
- smap <expr> <Tab>
- \ neosnippet#expandable_or_jumpable() ?
- \ "\<Plug>(neosnippet_expand_or_jump)" :
- \ g:neosnippet_tab_override_s_tab["expr"]
- \ ? eval(g:neosnippet_tab_override_s_tab["rhs"])
- \ : g:neosnippet_tab_override_s_tab["rhs"]
-endfunction
-autocmd vimrc VimEnter * call <SID>configure_neosnippet_tab_mappings()
-" }}}
-" netrw {{{
-let g:netrw_home = $HOME . '/.cache/vim/netrw'
-if !isdirectory(g:netrw_home)
- call mkdir(g:netrw_home, 'p')
-endif
-" }}}
-" polyglot {{{
-" this is for things that can't be set in ftplugin files for whatever reason
-let g:go_highlight_functions = 1
-let g:go_highlight_function_calls = 1
-let g:go_highlight_types = 1
-" }}}
-" rainbow {{{
-let g:rainbow = 1
-let g:rainbow_paren = 1
-let g:rainbow_bracket = 1
-let g:rainbow_brace = 1
-" }}}
-" startify {{{
-let g:startify_list_order = ['dir', 'bookmarks', 'commands']
-let g:startify_files_number = 7
-let g:startify_commands = [
- \ {'t': ['Open file', 'Files']},
- \ {'ff': ['Grep', 'Ag']},
- \ {'fh': ['Help', 'Helptags']},
- \ ]
-let g:startify_change_to_vcs_root = 1
-let g:startify_custom_indices = [
- \'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'
-\]
-let g:startify_custom_header = []
-let s:fortune = system('fortune -n200 -s ~/.local/share/fortune | grep -v -E "^$"')
-let g:startify_custom_footer = [''] + map(split(s:fortune, '\n'), '" ".v:val')
-" }}}
-" textobj {{{
-let g:textobj_defs = {
-\ '/': ['paired'],
-\ '\|': ['paired'],
-\}
-" }}}
-" }}}
-" vim: fdm=marker
diff --git a/weechat/perl/autoload/beep.pl b/weechat/perl/autoload/beep.pl
deleted file mode 100644
index 69096c2..0000000
--- a/weechat/perl/autoload/beep.pl
+++ /dev/null
@@ -1,257 +0,0 @@
-#
-# Copyright (C) 2006-2012 Sebastien Helleu <flashcode@flashtux.org>
-# Copyright (C) 2011 Nils Görs <weechatter@arcor.de>
-# Copyright (C) 2011 ArZa <arza@arza.us>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# Beep (terminal bell) and/or run command on highlight/private message or new DCC.
-#
-# History:
-# 2012-06-05, ldvx<ldvx@freenode>:
-# version 1.1: Added wildcard support for whitelist_nicks.
-# 2012-05-09, ldvx <ldvx@freenode>:
-# version 1.0: Added beep_pv_blacklist, beep_highlight_blacklist, blacklist_nicks,
-# and wildcard support for blacklist_nicks.
-# 2012-05-02, ldvx <ldvx@freenode>:
-# version 0.9: fix regex for nick in tags, add options "whitelist_channels"
-# and "bell_always"
-# 2012-04-19, ldvx <ldvx@freenode>:
-# version 0.8: add whitelist, trigger, use hook_process for commands,
-# rename option "beep_command" to "beep_command_pv", add help for options
-# 2011-04-16, ArZa <arza@arza.us>:
-# version 0.7: fix default beep command
-# 2011-03-11, nils_2 <weechatter@arcor.de>:
-# version 0.6: add additional command options for dcc and highlight
-# 2011-03-09, nils_2 <weechatter@arcor.de>:
-# version 0.5: add option for beep command and dcc
-# 2009-05-02, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.4: sync with last API changes
-# 2008-11-05, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.3: conversion to WeeChat 0.3.0+
-# 2007-08-10, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.2: upgraded licence to GPL 3
-# 2006-09-02, Sebastien Helleu <flashcode@flashtux.org>:
-# version 0.1: initial release
-
-use strict;
-my $SCRIPT_NAME = "beep";
-my $VERSION = "1.1";
-
-# default values in setup file (~/.weechat/plugins.conf)
-my %options_default = ('beep_pv' => ['on', 'beep on private message'],
- 'beep_pv_whitelist' => ['off', 'turn whitelist for private messages on or off'],
- 'beep_pv_blacklist' => ['off', 'turn blacklist for private messages on or off'],
- 'beep_highlight' => ['on', 'beep on highlight'],
- 'beep_highlight_whitelist' => ['off', 'turn whitelist for highlights on or off'],
- 'beep_highlight_blacklist' => ['off', 'turn blacklist for highlights on or off'],
- 'beep_dcc' => ['on', 'beep on dcc'],
- 'beep_trigger_pv' => ['', 'word that will trigger execution of beep_command_pv (it empty, anything will trigger)'],
- 'beep_trigger_highlight' => ['', 'word that will trigger execution of beep_command_highlight (if empty, anything will trigger)'],
- 'beep_command_pv' => ['$bell', 'command for beep on private message, special value "$bell" is allowed, as well as "$bell;command"'],
- 'beep_command_highlight' => ['$bell', 'command for beep on highlight, special value "$bell" is allowed, as well as "$bell;command"'],
- 'beep_command_dcc' => ['$bell', 'command for beep on dcc, special value "$bell" is allowed, as well as "$bell;command"'],
- 'beep_command_timeout' => ['30000', 'timeout for command run (in milliseconds, 0 = never kill (not recommended))'],
- 'whitelist_nicks' => ['', 'comma-separated list of "server.nick": if not empty, only these nicks will trigger execution of commands (example: "freenode.nick1,freenode.nick2")'],
- 'blacklist_nicks' => ['', 'comma-separated list of "server.nick": if not empty, these nicks will not be able to trigger execution of commands. Cannot be used in conjuction with whitelist (example: "freenode.nick1,freenode.nick2")'],
- 'whitelist_channels' => ['', 'comma-separated list of "server.#channel": if not empty, only these channels will trigger execution of commands (example: "freenode.#weechat,freenode.#channel2")'],
- 'bell_always' => ['', 'use $bell on private messages and/or highlights regardless of trigger and whitelist settings (example: "pv,highlight")'],
-);
-my %options = ();
-
-weechat::register($SCRIPT_NAME, "FlashCode <flashcode\@flashtux.org>", $VERSION,
- "GPL3", "Beep (terminal bell) and/or run command on highlight/private message or new DCC", "", "");
-init_config();
-
-weechat::hook_config("plugins.var.perl.$SCRIPT_NAME.*", "toggle_config_by_set", "");
-weechat::hook_print("", "", "", 1, "pv_and_highlight", "");
-weechat::hook_signal("irc_dcc", "dcc", "");
-
-sub pv_and_highlight
-{
- my ($data, $buffer, $date, $tags, $displayed, $highlight, $prefix, $message) = @_;
-
- # return if message is filtered
- return weechat::WEECHAT_RC_OK if ($displayed != 1);
-
- # return if nick in message is own nick
- my $nick = "";
- $nick = $2 if ($tags =~ m/(^|,)nick_([^,]*)(,|$)/);
- return weechat::WEECHAT_RC_OK if (weechat::buffer_get_string($buffer, "localvar_nick") eq $nick);
-
- # highlight
- if ($highlight)
- {
- # Always print visual bel, regardless of whitelist and trigger settings
- # beep_command_highlight does not need to contain $bell
- if ($options{bell_always} =~ m/(^|,)highlight(,|$)/)
- {
- print STDERR "\a";
- }
- # Channels whitelist for highlights
- if ($options{beep_highlight} eq "on")
- {
- if ($options{whitelist_channels} ne "")
- {
- my $serverandchannel = weechat::buffer_get_string($buffer, "localvar_server"). "." .
- weechat::buffer_get_string($buffer, "localvar_channel");
- if ($options{beep_trigger_highlight} eq "" or $message =~ m/\b$options{beep_trigger_highlight}\b/)
- {
- if ($options{whitelist_channels} =~ /(^|,)$serverandchannel(,|$)/)
- {
- beep_exec_command($options{beep_command_highlight});
- }
- # What if we are highlighted and we're in a PM? For now, do nothing.
- }
- }
- else
- {
- # Execute $bell and/or command with trigger and whitelist/blacklist settings
- beep_trigger_whitelist_blacklist($buffer, $message, $nick, $options{beep_trigger_highlight},
- $options{beep_highlight_whitelist}, $options{beep_highlight_blacklist},
- $options{beep_command_highlight});
- }
- }
- }
- # private message
- elsif (weechat::buffer_get_string($buffer, "localvar_type") eq "private" and $tags =~ m/(^|,)notify_private(,|$)/)
- {
- # Always print visual bel, regardless of whitelist and trigger settings
- # beep_command_pv does not need to contain $bell
- if ($options{bell_always} =~ m/(^|,)pv(,|$)/)
- {
- print STDERR "\a";
- }
- # Execute $bell and/or command with trigger and whitelist/blacklist settings
- if ($options{beep_pv} eq "on")
- {
- beep_trigger_whitelist_blacklist($buffer, $message, $nick, $options{beep_trigger_pv},
- $options{beep_pv_whitelist}, $options{beep_pv_blacklist},
- $options{beep_command_pv});
- }
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-sub dcc
-{
- beep_exec_command($options{beep_command_dcc}) if ($options{beep_dcc} eq "on");
- return weechat::WEECHAT_RC_OK;
-}
-
-sub beep_trigger_whitelist_blacklist
-{
- my ($buffer, $message, $nick, $trigger, $whitelist, $blacklist, $command) = @_;
-
- if ($trigger eq "" or $message =~ m/\b$trigger\b/)
- {
- my $serverandnick = weechat::buffer_get_string($buffer, "localvar_server").".".$nick;
- if ($whitelist eq "on" and $options{whitelist_nicks} ne "")
- {
- # What to do if there's a wildcard in the whitelit
- if ($options{whitelist_nicks} =~ m/\*/ and
- match_in_wild_card($serverandnick, $options{whitelist_nicks}))
- {
- beep_exec_command($command);
- }
- # What to do if there's no wildcard in the whitelist
- elsif ($options{whitelist_nicks} =~ /(^|,)$serverandnick(,|$)/)
- {
- beep_exec_command($command);
- }
- }
- elsif ($blacklist eq "on" and $options{blacklist_nicks} ne "")
- {
- # What to do if there's a wildcard in the blacklist
- if ($options{blacklist_nicks} =~ m/\*/ and
- !match_in_wild_card($serverandnick, $options{blacklist_nicks}))
- {
- beep_exec_command($command);
- }
- # What to do if there's no wildcard in the blacklist
- elsif ($options{blacklist_nicks} !~ /(^|,)$serverandnick(,|$)/)
- {
- beep_exec_command($command);
- }
- }
- # What to do if we are not using whitelist of blacklist feature
- elsif ($whitelist eq "off" and $blacklist eq "off")
- {
- beep_exec_command($command);
- }
- }
-}
-
-sub beep_exec_command
-{
- my $command = $_[0];
- if ($command =~ /^\$bell/)
- {
- print STDERR "\a";
- ($command) = $command =~ /^\$bell;(.+)$/;
- }
- weechat::hook_process($command, $options{beep_command_timeout}, "my_process", "") if ($command);
-}
-
-sub match_in_wild_card
-{
- my ($serverandnick, $white_or_black) = @_;
- my $nick_iter;
- my @array_of_nicks = split(",", $white_or_black);
-
- foreach $nick_iter (@array_of_nicks)
- {
- $nick_iter =~ s/\*/[^,]*/g;
- if ($serverandnick =~ /$nick_iter/)
- {
- return 1;
- }
- }
- return 0;
-}
-
-sub my_process
-{
- return weechat::WEECHAT_RC_OK;
-}
-
-sub toggle_config_by_set
-{
- my ($pointer, $name, $value) = @_;
- $name = substr($name, length("plugins.var.perl.".$SCRIPT_NAME."."), length($name));
- $options{$name} = $value;
- return weechat::WEECHAT_RC_OK;
-}
-
-sub init_config
-{
- my $version = weechat::info_get("version_number", "") || 0;
- foreach my $option (keys %options_default)
- {
- if (!weechat::config_is_set_plugin($option))
- {
- weechat::config_set_plugin($option, $options_default{$option}[0]);
- $options{$option} = $options_default{$option}[0];
- }
- else
- {
- $options{$option} = weechat::config_get_plugin($option);
- }
- if ($version >= 0x00030500)
- {
- weechat::config_set_desc_plugin($option, $options_default{$option}[1]." (default: \"".$options_default{$option}[0]."\")");
- }
- }
-}
diff --git a/weechat/perl/autoload/buffers.pl b/weechat/perl/autoload/buffers.pl
deleted file mode 100644
index 6323dc7..0000000
--- a/weechat/perl/autoload/buffers.pl
+++ /dev/null
@@ -1,1292 +0,0 @@
-#
-# Copyright (C) 2008-2013 Sebastien Helleu <flashcode@flashtux.org>
-# Copyright (C) 2011-2013 Nils G <weechatter@arcor.de>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# Display sidebar with list of buffers.
-#
-# History:
-# 2013-10-20, nils_2@freenode.#weechat:
-# v4.0: add options "detach_displayed_buffers", "detach_display_window_number"
-# 2013-09-27, nils_2@freenode.#weechat:
-# v3.9: add option "toggle_bar" and option "show_prefix_query" (idea by IvarB)
-# : fix problem with linefeed at end of list of buffers (reported by grawity)
-# 2012-10-18, nils_2@freenode.#weechat:
-# v3.8: add option "mark_inactive", to mark buffers you are not in (idea by xrdodrx)
-# : add wildcard "*" for immune_detach_buffers (idea by StarWeaver)
-# : add new options "detach_query" and "detach_free_content" (idea by StarWeaver)
-# 2012-10-06, Nei <anti.teamidiot.de>:
-# v3.7: call menu on right mouse if menu script is loaded.
-# 2012-10-06, nils_2 <weechatter@arcor.de>:
-# v3.6: add new option "hotlist_counter" (idea by torque).
-# 2012-06-02, nils_2 <weechatter@arcor.de>:
-# v3.5: add values "server|channel|private|all|keepserver|none" to option "hide_merged_buffers" (suggested by dominikh).
-# 2012-05-25, nils_2 <weechatter@arcor.de>:
-# v3.4: add new option "show_lag".
-# 2012-04-07, Sebastien Helleu <flashcode@flashtux.org>:
-# v3.3: fix truncation of wide chars in buffer name (option name_size_max) (bug #36034)
-# 2012-03-15, nils_2 <weechatter@arcor.de>:
-# v3.2: add new option "detach"(weechat >= 0.3.8)
-# add new option "immune_detach_buffers" (requested by Mkaysi)
-# add new function buffers_whitelist add|del|reset (suggested by FiXato)
-# add new function buffers_detach add|del|reset
-# 2012-03-09, Sebastien Helleu <flashcode@flashtux.org>:
-# v3.1: fix reload of config file
-# 2012-01-29, nils_2 <weechatter@arcor.de>:
-# v3.0: fix: buffers did not update directly during window_switch (reported by FiXato)
-# 2012-01-29, nils_2 <weechatter@arcor.de>:
-# v2.9: add options "name_size_max" and "name_crop_suffix"
-# 2012-01-08, nils_2 <weechatter@arcor.de>:
-# v2.8: fix indenting for option "show_number off"
-# fix unset of buffer activity in hotlist when buffer was moved with mouse
-# add buffer with free content and core buffer sorted first (suggested by nyuszika7h)
-# add options queries_default_fg/bg and queries_message_fg/bg (suggested by FiXato)
-# add clicking with left button on current buffer will do a jump_previously_visited_buffer (suggested by FiXato)
-# add clicking with right button on current buffer will do a jump_next_visited_buffer
-# add additional informations in help texts
-# add default_fg and default_bg for whitelist channels
-# internal changes (script is now 3Kb smaller)
-# 2012-01-04, Sebastien Helleu <flashcode@flashtux.org>:
-# v2.7: fix regex lookup in whitelist buffers list
-# 2011-12-04, nils_2 <weechatter@arcor.de>:
-# v2.6: add own config file (buffers.conf)
-# add new behavior for indenting (under_name)
-# add new option to set different color for server buffers and buffers with free content
-# 2011-10-30, nils_2 <weechatter@arcor.de>:
-# v2.5: add new options "show_number_char" and "color_number_char",
-# add help-description for options
-# 2011-08-24, Sebastien Helleu <flashcode@flashtux.org>:
-# v2.4: add mouse support
-# 2011-06-06, nils_2 <weechatter@arcor.de>:
-# v2.3: added: missed option "color_whitelist_default"
-# 2011-03-23, Sebastien Helleu <flashcode@flashtux.org>:
-# v2.2: fix color of nick prefix with WeeChat >= 0.3.5
-# 2011-02-13, nils_2 <weechatter@arcor.de>:
-# v2.1: add options "color_whitelist_*"
-# 2010-10-05, Sebastien Helleu <flashcode@flashtux.org>:
-# v2.0: add options "sort" and "show_number"
-# 2010-04-12, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.9: replace call to log() by length() to align buffer numbers
-# 2010-04-02, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.8: fix bug with background color and option indenting_number
-# 2010-04-02, Helios <helios@efemes.de>:
-# v1.7: add indenting_number option
-# 2010-02-25, m4v <lambdae2@gmail.com>:
-# v1.6: add option to hide empty prefixes
-# 2010-02-12, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.5: add optional nick prefix for buffers like IRC channels
-# 2009-09-30, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.4: remove spaces for indenting when bar position is top/bottom
-# 2009-06-14, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.3: add option "hide_merged_buffers"
-# 2009-06-14, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.2: improve display with merged buffers
-# 2009-05-02, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.1: sync with last API changes
-# 2009-02-21, Sebastien Helleu <flashcode@flashtux.org>:
-# v1.0: remove timer used to update bar item first time (not needed any more)
-# 2009-02-17, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.9: fix bug with indenting of private buffers
-# 2009-01-04, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.8: update syntax for command /set (comments)
-# 2008-10-20, Jiri Golembiovsky <golemj@gmail.com>:
-# v0.7: add indenting option
-# 2008-10-01, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.6: add default color for buffers, and color for current active buffer
-# 2008-09-18, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.5: fix color for "low" level entry in hotlist
-# 2008-09-18, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.4: rename option "show_category" to "short_names",
-# remove option "color_slash"
-# 2008-09-15, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.3: fix bug with priority in hotlist (var not defined)
-# 2008-09-02, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.2: add color for buffers with activity and config options for
-# colors, add config option to display/hide categories
-# 2008-03-15, Sebastien Helleu <flashcode@flashtux.org>:
-# v0.1: script creation
-#
-# Help about settings:
-# display all settings for script (or use iset.pl script to change settings):
-# /set buffers*
-# show help text for option buffers.look.whitelist_buffers:
-# /help buffers.look.whitelist_buffers
-#
-# Mouse-support (standard key bindings):
-# left mouse-button:
-# - click on a buffer to switch to selected buffer
-# - click on current buffer will do action jump_previously_visited_buffer
-# - drag a buffer and drop it on another position will move the buffer to position
-# right mouse-button:
-# - click on current buffer will do action jump_next_visited_buffer
-# - moving buffer to the left/right will close buffer.
-#
-
-use strict;
-use Encode qw( decode encode );
-# -------------------------------[ internal ]-------------------------------------
-my $SCRIPT_NAME = "buffers";
-my $version = "4.0";
-
-my $BUFFERS_CONFIG_FILE_NAME = "buffers";
-my $buffers_config_file;
-my $cmd_buffers_whitelist= "buffers_whitelist";
-my $cmd_buffers_detach = "buffers_detach";
-
-my %mouse_keys = ("\@item(buffers):button1*" => "hsignal:buffers_mouse", # catch all left mouse button gestures
- "\@item(buffers):button2*" => "hsignal:buffers_mouse"); # catch all right mouse button gestures
-my %options;
-my %hotlist_level = (0 => "low", 1 => "message", 2 => "private", 3 => "highlight");
-my @whitelist_buffers = ();
-my @immune_detach_buffers= ();
-my @buffers_focus = ();
-my %buffers_timer = ();
-my %Hooks = ();
-
-# --------------------------------[ init ]--------------------------------------
-weechat::register($SCRIPT_NAME, "Sebastien Helleu <flashcode\@flashtux.org>", $version,
- "GPL3", "Sidebar with list of buffers", "shutdown_cb", "");
-my $weechat_version = weechat::info_get("version_number", "") || 0;
-
-buffers_config_init();
-buffers_config_read();
-
-weechat::bar_item_new($SCRIPT_NAME, "build_buffers", "");
-weechat::bar_new($SCRIPT_NAME, "0", "0", "root", "", "left", "horizontal",
- "vertical", "0", "0", "default", "default", "default", "1",
- $SCRIPT_NAME);
-
-if ( check_bar_item() == 0 )
-{
- weechat::command("","/bar show " . $SCRIPT_NAME) if ( weechat::config_boolean($options{"toggle_bar"}) eq 1 );
-}
-
-weechat::hook_signal("buffer_*", "buffers_signal_buffer", "");
-weechat::hook_signal("window_switch", "buffers_signal_buffer", "");
-weechat::hook_signal("hotlist_*", "buffers_signal_hotlist", "");
-#weechat::hook_command_run("/input switch_active_*", "buffers_signal_buffer", "");
-weechat::bar_item_update($SCRIPT_NAME);
-
-
-if ($weechat_version >= 0x00030600)
-{
- weechat::hook_focus($SCRIPT_NAME, "buffers_focus_buffers", "");
- weechat::hook_hsignal("buffers_mouse", "buffers_hsignal_mouse", "");
- weechat::key_bind("mouse", \%mouse_keys);
-}
-
-weechat::hook_command( $cmd_buffers_whitelist,
- "add/del current buffer to/from buffers whitelist",
- "[add] || [del] || [reset]",
-
- " add: add current buffer in configuration file\n".
- " del: delete current buffer from configuration file\n".
- "reset: reset all buffers from configuration file (no confirmation!)\n\n".
- "Examples:\n".
- "/$cmd_buffers_whitelist add\n",
- "add %-||".
- "del %-||".
- "reset %-",
- "buffers_cmd_whitelist", "");
-weechat::hook_command( $cmd_buffers_detach,
- "add/del current buffer to/from buffers detach",
- "[add] || [del] || [reset]",
-
- " add: add current buffer in configuration file\n".
- " del: delete current buffer from configuration file\n".
- "reset: reset all buffers from configuration file (no confirmation!)\n\n".
- "Examples:\n".
- "/$cmd_buffers_detach add\n",
- "add %-||".
- "del %-||".
- "reset %-",
- "buffers_cmd_detach", "");
-
-if ($weechat_version >= 0x00030800)
-{
- weechat::hook_config("buffers.look.detach", "hook_timer_detach", "");
- $Hooks{timer_detach} = weechat::hook_timer( weechat::config_integer( $options{"detach"}) * 1000, 60, 0, "buffers_signal_buffer", "") if ( weechat::config_integer( $options{"detach"}) > 0 );
-}
-
- weechat::hook_config("buffers.look.show_lag", "hook_timer_lag", "");
-
- $Hooks{timer_lag} = weechat::hook_timer( weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000, 0, 0, "buffers_signal_hotlist", "") if ( weechat::config_boolean($options{"show_lag"}) );
-
-# -------------------------------- [ command ] --------------------------------
-sub buffers_cmd_whitelist
-{
-my ( $data, $buffer, $args ) = @_;
- $args = lc($args);
- my $buffers_whitelist = weechat::config_string( weechat::config_get("buffers.look.whitelist_buffers") );
- return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" and $args eq "del" or $buffers_whitelist eq "" and $args eq "reset" );
- my @buffers_list = split( /,/, $buffers_whitelist );
- # get buffers name
- my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), "");
- weechat::infolist_next($infolist);
- my $buffers_name = weechat::infolist_string($infolist, "name");
- weechat::infolist_free($infolist);
- return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" ); # should never happen
-
- if ( $args eq "add" )
- {
- return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list ); # check if buffer already in list
- push @buffers_list,( $buffers_name );
- my $buffers_list = &create_whitelist(\@buffers_list);
- weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list,1 );
- weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to buffers whitelist");
- }
- elsif ( $args eq "del" )
- {
- return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list ); # check if buffer is in list
- @buffers_list = grep {$_ ne $buffers_name} @buffers_list; # delete entry
- my $buffers_list = &create_whitelist(\@buffers_list);
- weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), $buffers_list,1 );
- weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from buffers whitelist");
- }
- elsif ( $args eq "reset" )
- {
- return weechat::WEECHAT_RC_OK if ( $buffers_whitelist eq "" );
- weechat::config_option_set( weechat::config_get("buffers.look.whitelist_buffers"), "",1 );
- weechat::print(weechat::current_buffer(), "buffers whitelist is empty, now...");
- }
- return weechat::WEECHAT_RC_OK;
-}
-sub buffers_cmd_detach
-{
-my ( $data, $buffer, $args ) = @_;
- $args = lc($args);
- my $immune_detach_buffers = weechat::config_string( weechat::config_get("buffers.look.immune_detach_buffers") );
- return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" and $args eq "del" or $immune_detach_buffers eq "" and $args eq "reset" );
- my @buffers_list = split( /,/, $immune_detach_buffers );
- # get buffers name
- my $infolist = weechat::infolist_get("buffer", weechat::current_buffer(), "");
- weechat::infolist_next($infolist);
- my $buffers_name = weechat::infolist_string($infolist, "name");
- weechat::infolist_free($infolist);
- return weechat::WEECHAT_RC_OK if ( $buffers_name eq "" ); # should never happen
-
- if ( $args eq "add" )
- {
- return weechat::WEECHAT_RC_OK if ( grep /^$buffers_name$/, @buffers_list ); # check if buffer already in list
- push @buffers_list,( $buffers_name );
- my $buffers_list = &create_whitelist(\@buffers_list);
- weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list,1 );
- weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" added to immune detach buffers");
- }
- elsif ( $args eq "del" )
- {
- return weechat::WEECHAT_RC_OK unless ( grep /^$buffers_name$/, @buffers_list ); # check if buffer is in list
- @buffers_list = grep {$_ ne $buffers_name} @buffers_list; # delete entry
- my $buffers_list = &create_whitelist(\@buffers_list);
- weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), $buffers_list,1 );
- weechat::print(weechat::current_buffer(), "buffer \"$buffers_name\" deleted from immune detach buffers");
- }
- elsif ( $args eq "reset" )
- {
- return weechat::WEECHAT_RC_OK if ( $immune_detach_buffers eq "" );
- weechat::config_option_set( weechat::config_get("buffers.look.immune_detach_buffers"), "",1 );
- weechat::print(weechat::current_buffer(), "immune detach buffers is empty, now...");
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-sub create_whitelist
-{
- my @buffers_list = @{$_[0]};
- my $buffers_list = "";
- foreach (@buffers_list)
- {
- $buffers_list .= $_ .",";
- }
- chop $buffers_list; # remove last ","
- return $buffers_list;
-}
-
-# -------------------------------- [ config ] --------------------------------
-sub hook_timer_detach
-{
- my $detach = $_[2];
- if ( $detach eq 0 )
- {
- weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach};
- $Hooks{timer_detach} = "";
- }
- else
- {
- weechat::unhook($Hooks{timer_detach}) if $Hooks{timer_detach};
- $Hooks{timer_detach} = weechat::hook_timer( weechat::config_integer( $options{"detach"}) * 1000, 60, 0, "buffers_signal_buffer", "");
- }
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-
-sub hook_timer_lag
-{
- my $lag = $_[2];
- if ( $lag eq 0 )
- {
- weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag};
- $Hooks{timer_lag} = "";
- }
- else
- {
- weechat::unhook($Hooks{timer_lag}) if $Hooks{timer_lag};
- $Hooks{timer_lag} = weechat::hook_timer( weechat::config_integer(weechat::config_get("irc.network.lag_refresh_interval")) * 1000, 0, 0, "buffers_signal_hotlist", "");
- }
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-
-sub buffers_config_read
-{
- return weechat::config_read($buffers_config_file) if ($buffers_config_file ne "");
-}
-sub buffers_config_write
-{
- return weechat::config_write($buffers_config_file) if ($buffers_config_file ne "");
-}
-sub buffers_config_reload_cb
-{
- my ($data,$config_file) = ($_[0], $_[1]);
- return weechat::config_reload($config_file)
-}
-sub buffers_config_init
-{
- $buffers_config_file = weechat::config_new($BUFFERS_CONFIG_FILE_NAME,"buffers_config_reload_cb","");
- return if ($buffers_config_file eq "");
-
-my %default_options_color =
-("color_current_fg" => ["current_fg", "color", "foreground color for current buffer", "", 0, 0,"lightcyan", "lightcyan", 0, "", "","buffers_signal_config", "", "", ""],
- "color_current_bg" => ["current_bg", "color", "background color for current buffer", "", 0, 0,"red", "red", 0, "", "","buffers_signal_config", "", "", ""],
- "color_default_fg" => ["default_fg", "color", "default foreground color for buffer name", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_default_bg" => ["default_bg", "color", "default background color for buffer name", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_highlight_fg" => ["hotlist_highlight_fg", "color", "change foreground color of buffer name if a highlight messaged received","", 0, 0,"magenta", "magenta", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_highlight_bg" => ["hotlist_highlight_bg", "color", "change background color of buffer name if a highlight messaged received", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_low_fg" => ["hotlist_low_fg", "color", "change foreground color of buffer name if a low message received", "", 0, 0,"white", "white", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_low_bg" => ["hotlist_low_bg", "color", "change background color of buffer name if a low message received", "", 0, 0,
- "default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_message_fg" => ["hotlist_message_fg", "color", "change foreground color of buffer name if a normal message received", "", 0, 0,"yellow", "yellow", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_message_bg" => ["hotlist_message_bg", "color", "change background color of buffer name if a normal message received", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_private_fg" => ["hotlist_private_fg", "color", "change foreground color of buffer name if a private message received", "", 0, 0,"lightgreen", "lightgreen", 0, "", "","buffers_signal_config", "", "", ""],
- "color_hotlist_private_bg" => ["hotlist_private_bg", "color", "change background color of buffer name if a private message received", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_number" => ["number", "color", "color for buffer number", "", 0, 0,"lightgreen", "lightgreen", 0, "", "","buffers_signal_config", "", "", ""],
- "color_number_char" => ["number_char", "color", "color for buffer number char", "", 0, 0,"lightgreen", "lightgreen", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_default_fg" => ["whitelist_default_fg", "color", "default foreground color for whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_default_bg" => ["whitelist_default_bg", "color", "default background color for whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_low_fg" => ["whitelist_low_fg", "color", "low color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_low_bg" => ["whitelist_low_bg", "color", "low color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_message_fg" => ["whitelist_message_fg", "color", "message color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_message_bg" => ["whitelist_message_bg", "color", "message color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_private_fg" => ["whitelist_private_fg", "color", "private color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_private_bg" => ["whitelist_private_bg", "color", "private color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_highlight_fg" => ["whitelist_highlight_fg", "color", "highlight color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_whitelist_highlight_bg" => ["whitelist_highlight_bg", "color", "highlight color of whitelist buffer name", "", 0, 0,"", "", 0, "", "","buffers_signal_config", "", "", ""],
- "color_none_channel_fg" => ["none_channel_fg", "color", "foreground color for none channel buffer (e.g.: core/server/plugin buffer)", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "color_none_channel_bg" => ["none_channel_bg", "color", "background color for none channel buffer (e.g.: core/server/plugin buffer)", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "queries_default_fg" => ["queries_default_fg", "color", "foreground color for query buffer without message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "queries_default_bg" => ["queries_default_bg", "color", "background color for query buffer without message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "queries_message_fg" => ["queries_message_fg", "color", "foreground color for query buffer with unread message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "queries_message_bg" => ["queries_message_bg", "color", "background color for query buffer with unread message", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "queries_highlight_fg" => ["queries_highlight_fg", "color", "foreground color for query buffer with unread highlight", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
- "queries_highlight_bg" => ["queries_highlight_bg", "color", "background color for query buffer with unread highlight", "", 0, 0,"default", "default", 0, "", "","buffers_signal_config", "", "", ""],
-);
-
-my %default_options_look =
-(
- "hotlist_counter" => ["hotlist_counter","boolean","show number of message for the buffer (this option needs WeeChat >= 0.3.5). The relevant option for notification is \"weechat.look.buffer_notify_default\"","",0,0,"off","off",0,"","","buffers_signal_config","","",""],
- "show_lag" => ["show_lag","boolean","show lag behind servername. This option is using \"irc.color.item_lag_finished\", \"irc.network.lag_min_show\" and \"irc.network.lag_refresh_interval\"","",0,0,"off","off",0,"","","buffers_signal_config","","",""],
- "look_whitelist_buffers" => ["whitelist_buffers", "string", "comma separated list of buffers for using a differnt color scheme (for example: freenode.#weechat,freenode.#weechat-fr)", "", 0, 0,"", "", 0, "", "", "buffers_signal_config_whitelist", "", "", ""],
- "hide_merged_buffers" => ["hide_merged_buffers", "integer", "hide merged buffers. The value determines which merged buffers should be hidden, keepserver meaning 'all except server buffers'. Other values correspondent to the buffer type.", "server|channel|private|keepserver|all|none", 0, 0,"none", "none", 0, "", "", "buffers_signal_config", "", "", ""],
- "indenting" => ["indenting", "integer", "use indenting for channel and query buffers. This option only takes effect if bar is left/right positioned", "off|on|under_name", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "indenting_number" => ["indenting_number", "boolean", "use indenting for numbers. This option only takes effect if bar is left/right positioned", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""],
- "short_names" => ["short_names", "boolean", "display short names (remove text before first \".\" in buffer name)", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""],
- "show_number" => ["show_number", "boolean", "display channel number in front of buffername", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""],
- "show_number_char" => ["number_char", "string", "display a char behind channel number", "", 0, 0,".", ".", 0, "", "", "buffers_signal_config", "", "", ""],
- "show_prefix" => ["prefix", "boolean", "displays your prefix for channel in front of buffername", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "show_prefix_empty" => ["prefix_empty", "boolean", "use a placeholder for channels without prefix", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""],
-"show_prefix_query" => ["prefix_for_query", "string", "prefix displayed in front of query buffer", "", 0, 0,"", "", 0, "", "", "buffers_signal_config", "", "", ""],
- "sort" => ["sort", "integer", "sort buffer-list by \"number\" or \"name\"", "number|name", 0, 0,"number", "number", 0, "", "", "buffers_signal_config", "", "", ""],
- "core_to_front" => ["core_to_front", "boolean", "core buffer and buffers with free content will be listed first. Take only effect if buffer sort is by name", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "jump_prev_next_visited_buffer" => ["jump_prev_next_visited_buffer", "boolean", "jump to previously or next visited buffer if you click with left/right mouse button on currently visiting buffer", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "name_size_max" => ["name_size_max","integer","maximum size of buffer name. 0 means no limitation","",0,256,0,0,0, "", "", "buffers_signal_config", "", "", ""],
- "name_crop_suffix" => ["name_crop_suffix","string","contains an optional char(s) that is appended when buffer name is shortened","",0,0,"+","+",0,"","","buffers_signal_config", "", "", ""],
- "detach" => ["detach", "integer","detach channel from buffers list after a specific period of time (in seconds) without action (weechat ≥ 0.3.8 required) (0 means \"off\")", "", 0, 31536000,0, "number", 0, "", "", "buffers_signal_config", "", "", ""],
- "immune_detach_buffers"=> ["immune_detach_buffers", "string", "Comma seperated list of buffers to NOT automatically detatch. Allows \"*\" wildcard. Ex: \"BitlBee,freenode.*\"", "", 0, 0,"", "", 0, "", "", "buffers_signal_config_immune_detach_buffers", "", "", ""],
- "detach_query" => ["detach_query", "boolean", "query buffer will be detachted", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "detach_free_content" => ["detach_free_content", "boolean", "buffers with free content will be detached (Ex: iset, chanmon)", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "detach_displayed_buffers" => ["detach_displayed_buffers", "boolean", "buffers displayed in a (split) window will be detached", "", 0, 0,"on", "on", 0, "", "", "buffers_signal_config", "", "", ""],
- "detach_display_window_number" => ["detach_display_window_number", "boolean", "window number will be add, behind buffer name (this option takes only effect with \"detach_displayed_buffers\" option)", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "mark_inactive" => ["mark_inactive", "boolean", "if option is \"on\", inactive buffers (those you are not in) will have parentesis around them. An inactive buffer will not be detached.", "", 0, 0,"off", "off", 0, "", "", "buffers_signal_config", "", "", ""],
- "toggle_bar" => ["toogle_bar", "boolean", "if option is \"on\", buffers bar will hide/show when script is (un)loaded.", "", 0, 0,"on","on", 0, "", "", "buffers_signal_config", "", "", ""],
-);
- # section "color"
- my $section_color = weechat::config_new_section($buffers_config_file,"color", 0, 0, "", "", "", "", "", "", "", "", "", "");
- if ($section_color eq "")
- {
- weechat::config_free($buffers_config_file);
- return;
- }
- foreach my $option (keys %default_options_color)
- {
- $options{$option} = weechat::config_new_option($buffers_config_file, $section_color,
- $default_options_color{$option}[0],$default_options_color{$option}[1],$default_options_color{$option}[2],
- $default_options_color{$option}[3],$default_options_color{$option}[4],$default_options_color{$option}[5],
- $default_options_color{$option}[6],$default_options_color{$option}[7],$default_options_color{$option}[8],
- $default_options_color{$option}[9],$default_options_color{$option}[10],$default_options_color{$option}[11],
- $default_options_color{$option}[12],$default_options_color{$option}[13],$default_options_color{$option}[14]);
- }
-
- # section "look"
- my $section_look = weechat::config_new_section($buffers_config_file,"look", 0, 0, "", "", "", "", "", "", "", "", "", "");
- if ($section_look eq "")
- {
- weechat::config_free($buffers_config_file);
- return;
- }
- foreach my $option (keys %default_options_look)
- {
- $options{$option} = weechat::config_new_option($buffers_config_file, $section_look,
- $default_options_look{$option}[0],$default_options_look{$option}[1],$default_options_look{$option}[2],
- $default_options_look{$option}[3],$default_options_look{$option}[4],$default_options_look{$option}[5],
- $default_options_look{$option}[6],$default_options_look{$option}[7],$default_options_look{$option}[8],
- $default_options_look{$option}[9],$default_options_look{$option}[10],$default_options_look{$option}[11],
- $default_options_look{$option}[12],$default_options_look{$option}[13],$default_options_look{$option}[14],
- $default_options_look{$option}[15]);
- }
-}
-
-sub build_buffers
-{
- my $str = "";
-
- # get bar position (left/right/top/bottom)
- my $position = "left";
- my $option_position = weechat::config_get("weechat.bar.buffers.position");
- if ($option_position ne "")
- {
- $position = weechat::config_string($option_position);
- }
-
- # read hotlist
- my %hotlist;
- my $infolist = weechat::infolist_get("hotlist", "", "");
- while (weechat::infolist_next($infolist))
- {
- $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")} =
- weechat::infolist_integer($infolist, "priority");
- if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 1 and $weechat_version >= 0x00030500)
- {
- $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_00"} =
- weechat::infolist_integer($infolist, "count_00"); # low message
- $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_01"} =
- weechat::infolist_integer($infolist, "count_01"); # channel message
- $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_02"} =
- weechat::infolist_integer($infolist, "count_02"); # private message
- $hotlist{weechat::infolist_pointer($infolist, "buffer_pointer")."_count_03"} =
- weechat::infolist_integer($infolist, "count_03"); # highlight message
- }
- }
- weechat::infolist_free($infolist);
-
- # read buffers list
- @buffers_focus = ();
- my @buffers;
- my @current1 = ();
- my @current2 = ();
- my $old_number = -1;
- my $max_number = 0;
- my $max_number_digits = 0;
- my $active_seen = 0;
- $infolist = weechat::infolist_get("buffer", "", "");
- while (weechat::infolist_next($infolist))
- {
- my $buffer;
- my $number = weechat::infolist_integer($infolist, "number");
- if ($number ne $old_number)
- {
- @buffers = (@buffers, @current2, @current1);
- @current1 = ();
- @current2 = ();
- $active_seen = 0;
- }
- if ($number > $max_number)
- {
- $max_number = $number;
- }
- $old_number = $number;
- my $active = weechat::infolist_integer($infolist, "active");
- if ($active)
- {
- $active_seen = 1;
- }
- $buffer->{"pointer"} = weechat::infolist_pointer($infolist, "pointer");
- $buffer->{"number"} = $number;
- $buffer->{"active"} = $active;
- $buffer->{"current_buffer"} = weechat::infolist_integer($infolist, "current_buffer");
- $buffer->{"num_displayed"} = weechat::infolist_integer($infolist, "num_displayed");
- $buffer->{"plugin_name"} = weechat::infolist_string($infolist, "plugin_name");
- $buffer->{"name"} = weechat::infolist_string($infolist, "name");
- $buffer->{"short_name"} = weechat::infolist_string($infolist, "short_name");
- $buffer->{"full_name"} = $buffer->{"plugin_name"}.".".$buffer->{"name"};
- $buffer->{"type"} = weechat::buffer_get_string($buffer->{"pointer"},"localvar_type");
-# weechat::print("",$buffer->{"type"});
-
- # check if buffer is active (or maybe a /part, /kick channel)
- if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1)
- {
- my $server = weechat::buffer_get_string($buffer->{"pointer"},"localvar_server");
- my $channel = weechat::buffer_get_string($buffer->{"pointer"},"localvar_channel");
- my $infolist_channel = weechat::infolist_get("irc_channel","",$server.",".$channel);
- if ($infolist_channel)
- {
- weechat::infolist_next($infolist_channel);
- $buffer->{"nicks_count"} = weechat::infolist_integer($infolist_channel,"nicks_count");
- }else
- {
- $buffer->{"nicks_count"} = 0;
- }
- weechat::infolist_free($infolist_channel);
- }
-
- my $result = check_immune_detached_buffers($buffer->{"name"}); # checking for wildcard
- unless ($result)
- {
- my $detach_time = weechat::config_integer( $options{"detach"});
- my $current_time = time();
- # set timer for buffers with no hotlist action
- $buffers_timer{$buffer->{"pointer"}} = $current_time
- if ( not exists $hotlist{$buffer->{"pointer"}}
- and $buffer->{"type"} eq "channel"
- and not exists $buffers_timer{$buffer->{"pointer"}}
- and $detach_time > 0);
-
- $buffers_timer{$buffer->{"pointer"}} = $current_time
- if (weechat::config_boolean($options{"detach_query"}) eq 1
- and not exists $hotlist{$buffer->{"pointer"}}
- and $buffer->{"type"} eq "private"
- and not exists $buffers_timer{$buffer->{"pointer"}}
- and $detach_time > 0);
-
- $detach_time = 0
- if (weechat::config_boolean($options{"detach_query"}) eq 0
- and $buffer->{"type"} eq "private");
-
- # free content buffer
- $buffers_timer{$buffer->{"pointer"}} = $current_time
- if (weechat::config_boolean($options{"detach_free_content"}) eq 1
- and not exists $hotlist{$buffer->{"pointer"}}
- and $buffer->{"type"} eq ""
- and not exists $buffers_timer{$buffer->{"pointer"}}
- and $detach_time > 0);
- $detach_time = 0
- if (weechat::config_boolean($options{"detach_free_content"}) eq 0
- and $buffer->{"type"} eq "");
-
- $detach_time = 0 if (weechat::config_boolean($options{"mark_inactive"}) eq 1 and defined $buffer->{"nicks_count"} and $buffer->{"nicks_count"} == 0);
-
- # check for detach
- unless ( $buffer->{"current_buffer"} eq 0
- and not exists $hotlist{$buffer->{"pointer"}}
-# and $buffer->{"type"} eq "channel"
- and exists $buffers_timer{$buffer->{"pointer"}}
- and $detach_time > 0
- and $weechat_version >= 0x00030800
- and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
- {
- if ($active_seen)
- {
- push(@current2, $buffer);
- }
- else
- {
- push(@current1, $buffer);
- }
- }
- elsif ( $buffer->{"current_buffer"} eq 0
- and not exists $hotlist{$buffer->{"pointer"}}
-# and $buffer->{"type"} eq "channel"
- and exists $buffers_timer{$buffer->{"pointer"}}
- and $detach_time > 0
- and $weechat_version >= 0x00030800
- and $current_time - $buffers_timer{$buffer->{"pointer"}} >= $detach_time)
- { # check for option detach_displayed_buffers and if buffer is displayed in a split window
- if ( $buffer->{"num_displayed"} eq 1
- and weechat::config_boolean($options{"detach_displayed_buffers"}) eq 0 )
- {
- my $infolist_window = weechat::infolist_get("window","","");
- while (weechat::infolist_next($infolist_window))
- {
- my $buffer_ptr = weechat::infolist_pointer($infolist_window, "buffer");
- if ($buffer_ptr eq $buffer->{"pointer"})
- {
- $buffer->{"window"} = weechat::infolist_integer($infolist_window, "number");
- }
- }
- weechat::infolist_free($infolist_window);
-
- push(@current2, $buffer);
- }
- }
- }
- else # buffer in "immune_detach_buffers"
- {
- if ($active_seen)
- {
- push(@current2, $buffer);
- }
- else
- {
- push(@current1, $buffer);
- }
- }
- } # while end
-
-
- if ($max_number >= 1)
- {
- $max_number_digits = length(int($max_number));
- }
- @buffers = (@buffers, @current2, @current1);
- weechat::infolist_free($infolist);
-
- # sort buffers by number, name or shortname
- my %sorted_buffers;
- if (1)
- {
- my $number = 0;
- for my $buffer (@buffers)
- {
- my $key;
- if (weechat::config_integer( $options{"sort"} ) eq 1) # number = 0; name = 1
- {
- my $name = $buffer->{"name"};
- $name = $buffer->{"short_name"} if (weechat::config_boolean( $options{"short_names"} ) eq 1);
- if (weechat::config_integer($options{"name_size_max"}) >= 1){
- $name = encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"})));
- }
- if ( weechat::config_boolean($options{"core_to_front"}) eq 1)
- {
- if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") )
- {
- my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
- if ( $type eq "" and $name ne "weechat")
- {
- $name = " " . $name
- }else
- {
- $name = " " . $name;
- }
- }
- }
- $key = sprintf("%s%08d", lc($name), $buffer->{"number"});
- }
- else
- {
- $key = sprintf("%08d", $number);
- }
- $sorted_buffers{$key} = $buffer;
- $number++;
- }
- }
-
- # build string with buffers
- $old_number = -1;
- foreach my $key (sort keys %sorted_buffers)
- {
- my $buffer = $sorted_buffers{$key};
-
- if ( weechat::config_string($options{"hide_merged_buffers"}) eq "server" )
- {
- # buffer type "server" or merged with core?
- if ( ($buffer->{"type"} eq "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
- {
- next;
- }
- }
- if ( weechat::config_string($options{"hide_merged_buffers"}) eq "channel" )
- {
- # buffer type "channel" or merged with core?
- if ( ($buffer->{"type"} eq "channel" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
- {
- next;
- }
- }
- if ( weechat::config_string($options{"hide_merged_buffers"}) eq "private" )
- {
- # buffer type "private" or merged with core?
- if ( ($buffer->{"type"} eq "private" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
- {
- next;
- }
- }
- if ( weechat::config_string($options{"hide_merged_buffers"}) eq "keepserver" )
- {
- if ( ($buffer->{"type"} ne "server" or $buffer->{"plugin_name"} eq "core") && (! $buffer->{"active"}) )
- {
- next;
- }
- }
- if ( weechat::config_string($options{"hide_merged_buffers"}) eq "all" )
- {
- if ( ! $buffer->{"active"} )
- {
- next;
- }
- }
-
- push(@buffers_focus, $buffer); # buffer > buffers_focus, for mouse support
- my $color = "";
- my $bg = "";
-
- $color = weechat::config_color( $options{"color_default_fg"} );
- $bg = weechat::config_color( $options{"color_default_bg"} );
-
- if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" )
- {
- if ( (weechat::config_color($options{"queries_default_bg"})) ne "default" || (weechat::config_color($options{"queries_default_fg"})) ne "default" )
- {
- $bg = weechat::config_color( $options{"queries_default_bg"} );
- $color = weechat::config_color( $options{"queries_default_fg"} );
- }
- }
- # check for core and buffer with free content
- if ( (weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "channel" ) and ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") ne "private") )
- {
- $color = weechat::config_color( $options{"color_none_channel_fg"} );
- $bg = weechat::config_color( $options{"color_none_channel_bg"} );
- }
- # default whitelist buffer?
- if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers)
- {
- $color = weechat::config_color( $options{"color_whitelist_default_fg"} );
- $bg = weechat::config_color( $options{"color_whitelist_default_bg"} );
- }
-
- $color = "default" if ($color eq "");
-
- # color for channel and query buffer
- if (exists $hotlist{$buffer->{"pointer"}})
- {
- delete $buffers_timer{$buffer->{"pointer"}};
- # check if buffer is in whitelist buffer
- if (grep {$_ eq $buffer->{"name"}} @whitelist_buffers)
- {
- $bg = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
- $color = weechat::config_color( $options{"color_whitelist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} );
- }
- elsif ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "private" )
- {
- # queries_default_fg/bg and buffers.color.queries_message_fg/bg
- if ( (weechat::config_color($options{"queries_highlight_fg"})) ne "default" ||
- (weechat::config_color($options{"queries_highlight_bg"})) ne "default" ||
- (weechat::config_color($options{"queries_message_fg"})) ne "default" ||
- (weechat::config_color($options{"queries_message_bg"})) ne "default" )
- {
- if ( ($hotlist{$buffer->{"pointer"}}) == 2 )
- {
- $bg = weechat::config_color( $options{"queries_message_bg"} );
- $color = weechat::config_color( $options{"queries_message_fg"} );
- }
-
- elsif ( ($hotlist{$buffer->{"pointer"}}) == 3 )
- {
- $bg = weechat::config_color( $options{"queries_highlight_bg"} );
- $color = weechat::config_color( $options{"queries_highlight_fg"} );
- }
- }else
- {
- $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
- $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} );
- }
- }else
- {
- $bg = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_bg"} );
- $color = weechat::config_color( $options{"color_hotlist_".$hotlist_level{$hotlist{$buffer->{"pointer"}}}."_fg"} );
- }
- }
-
- if ($buffer->{"current_buffer"})
- {
- $color = weechat::config_color( $options{"color_current_fg"} );
- $bg = weechat::config_color( $options{"color_current_bg"} );
- }
- my $color_bg = "";
- $color_bg = weechat::color(",".$bg) if ($bg ne "");
-
- # create channel number for output
- if ( weechat::config_boolean( $options{"show_number"} ) eq 1 ) # on
- {
- if (( weechat::config_boolean( $options{"indenting_number"} ) eq 1)
- && (($position eq "left") || ($position eq "right")))
- {
- $str .= weechat::color("default").$color_bg
- .(" " x ($max_number_digits - length(int($buffer->{"number"}))));
- }
- if ($old_number ne $buffer->{"number"})
- {
- $str .= weechat::color( weechat::config_color( $options{"color_number"} ) )
- .$color_bg
- .$buffer->{"number"}
- .weechat::color("default")
- .$color_bg
- .weechat::color( weechat::config_color( $options{"color_number_char"} ) )
- .weechat::config_string( $options{"show_number_char"} )
- .$color_bg;
- }
- else
- {
- my $indent = "";
- $indent = ((" " x length($buffer->{"number"}))." ") if (($position eq "left") || ($position eq "right"));
- $str .= weechat::color("default")
- .$color_bg
- .$indent;
- }
- }
-
- if (( weechat::config_integer( $options{"indenting"} ) ne 0 ) # indenting NOT off
- && (($position eq "left") || ($position eq "right")))
- {
- my $type = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type");
- if (($type eq "channel") || ($type eq "private"))
- {
- if ( weechat::config_integer( $options{"indenting"} ) eq 1 )
- {
- $str .= " ";
- }
- elsif ( (weechat::config_integer($options{"indenting"}) eq 2) and (weechat::config_integer($options{"indenting_number"}) eq 0) ) #under_name
- {
- if ( weechat::config_boolean( $options{"show_number"} ) eq 0 )
- {
- $str .= " ";
- }else
- {
- $str .= ( (" " x ( $max_number_digits - length($buffer->{"number"}) ))." " );
- }
- }
- }
- }
-
- $str .= weechat::config_string( $options{"show_prefix_query"}) if (weechat::config_string( $options{"show_prefix_query"} ) ne "" and $buffer->{"type"} eq "private");
-
- if (weechat::config_boolean( $options{"show_prefix"} ) eq 1)
- {
- my $nickname = weechat::buffer_get_string($buffer->{"pointer"}, "localvar_nick");
- if ($nickname ne "")
- {
- # with version >= 0.3.2, this infolist will return only nick
- # with older versions, whole nicklist is returned for buffer, and this can be very slow
- my $infolist_nick = weechat::infolist_get("nicklist", $buffer->{"pointer"}, "nick_".$nickname);
- if ($infolist_nick ne "")
- {
- my $version = weechat::info_get("version_number", "");
- $version = 0 if ($version eq "");
- while (weechat::infolist_next($infolist_nick))
- {
- if ((weechat::infolist_string($infolist_nick, "type") eq "nick")
- && (weechat::infolist_string($infolist_nick, "name") eq $nickname))
- {
- my $prefix = weechat::infolist_string($infolist_nick, "prefix");
- if (($prefix ne " ") or (weechat::config_boolean( $options{"show_prefix_empty"} ) eq 1))
- {
- # with version >= 0.3.5, it is now a color name (for older versions: option name with color)
- if (int($version) >= 0x00030500)
- {
- $str .= weechat::color(weechat::infolist_string($infolist_nick, "prefix_color"));
- }
- else
- {
- $str .= weechat::color(weechat::config_color(
- weechat::config_get(
- weechat::infolist_string($infolist_nick, "prefix_color"))));
- }
- $str .= $prefix;
- }
- last;
- }
- }
- weechat::infolist_free($infolist_nick);
- }
- }
- }
- if ($buffer->{"type"} eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buffer->{"nicks_count"} == 0)
- {
- $str .= "(";
- }
-
- $str .= weechat::color($color) . weechat::color(",".$bg);
-
- if (weechat::config_boolean( $options{"short_names"} ) eq 1)
- {
- my $name = $buffer->{"short_name"};
- $name = '?' . $name if $buffer->{"type"} eq 'private';
-
- if (weechat::config_integer($options{"name_size_max"}) >= 1) # check max_size of buffer name
- {
- $str .= encode("UTF-8", substr(decode("UTF-8", $name), 0, weechat::config_integer($options{"name_size_max"})));
- $str .= weechat::color(weechat::config_color( $options{"color_number_char"})).weechat::config_string($options{"name_crop_suffix"}) if (length($name) > weechat::config_integer($options{"name_size_max"}));
- $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
- $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
- }
- else
- {
- $str .= $name;
- $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
- $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
- }
- }
- else
- {
- my $name = $buffer->{"name"};
- $name = '?' . $name if $buffer->{"type"} eq 'private';
-
- if (weechat::config_integer($options{"name_size_max"}) >= 1) # check max_size of buffer name
- {
- $str .= encode("UTF-8", substr(decode("UTF-8", $name,), 0, weechat::config_integer($options{"name_size_max"})));
- $str .= weechat::color(weechat::config_color( $options{"color_number_char"})).weechat::config_string($options{"name_crop_suffix"}) if (length($name) > weechat::config_integer($options{"name_size_max"}));
- $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
- $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
- }
- else
- {
- $str .= $name;
- $str .= add_inactive_parentless($buffer->{"type"},$buffer->{"nicks_count"});
- $str .= add_hotlist_count($buffer->{"pointer"},%hotlist);
- }
- }
- if ( weechat::buffer_get_string($buffer->{"pointer"}, "localvar_type") eq "server" and weechat::config_boolean($options{"show_lag"}) eq 1)
- {
- my $color_lag = weechat::config_color(weechat::config_get("irc.color.item_lag_finished"));
- my $min_lag = weechat::config_integer(weechat::config_get("irc.network.lag_min_show"));
- my $infolist_server = weechat::infolist_get("irc_server","",$buffer->{"short_name"});
- weechat::infolist_next($infolist_server);
- my $lag = (weechat::infolist_integer($infolist_server, "lag"));
- weechat::infolist_free($infolist_server);
- if ( int($lag) > int($min_lag) )
- {
- $lag = $lag / 1000;
- $str .= weechat::color("default") . " (" . weechat::color($color_lag) . $lag . weechat::color("default") . ")";
- }
- }
- if (weechat::config_boolean($options{"detach_displayed_buffers"}) eq 0
- and weechat::config_boolean($options{"detach_display_window_number"}) eq 1)
- {
- if ($buffer->{"window"})
- {
- $str .= weechat::color("default") . " (" . weechat::color(weechat::config_color( $options{"color_number"})) . $buffer->{"window"} . weechat::color("default") . ")";
- }
- }
- $str .= "\n";
- $old_number = $buffer->{"number"};
- }
-
- # remove spaces and/or linefeed at the end
- $str =~ s/\s+$//;
- chomp($str);
- return $str;
-}
-
-sub add_inactive_parentless
-{
-my ($buf_type, $buf_nicks_count) = @_;
-my $str = "";
- if ($buf_type eq "channel" and weechat::config_boolean( $options{"mark_inactive"} ) eq 1 and $buf_nicks_count == 0)
- {
- $str .= weechat::color(weechat::config_color( $options{"color_number_char"}));
- $str .= ")";
- }
-return $str;
-}
-
-sub add_hotlist_count
-{
-my ($bufpointer,%hotlist) = @_;
-
-return "" if ( weechat::config_boolean( $options{"hotlist_counter"} ) eq 0 or ($weechat_version < 0x00030500)); # off
-my $col_number_char = weechat::color(weechat::config_color( $options{"color_number_char"}) );
-my $str = " ".$col_number_char."(";
-
-# 0 = low level
-if (defined $hotlist{$bufpointer."_count_00"})
-{
- my $bg = weechat::config_color( $options{"color_hotlist_low_bg"} );
- my $color = weechat::config_color( $options{"color_hotlist_low_fg"} );
- $str .= weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_00"} if ($hotlist{$bufpointer."_count_00"} ne "0");
-}
-
-# 1 = message
-if (defined $hotlist{$bufpointer."_count_01"})
-{
- my $bg = weechat::config_color( $options{"color_hotlist_message_bg"} );
- my $color = weechat::config_color( $options{"color_hotlist_message_fg"} );
- if ($str =~ /[0-9]$/)
- {
- $str .= ",".
- weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
- }else
- {
- $str .= weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_01"} if ($hotlist{$bufpointer."_count_01"} ne "0");
- }
-}
-# 2 = private
-if (defined $hotlist{$bufpointer."_count_02"})
-{
- my $bg = weechat::config_color( $options{"color_hotlist_private_bg"} );
- my $color = weechat::config_color( $options{"color_hotlist_private_fg"} );
- if ($str =~ /[0-9]$/)
- {
- $str .= ",".
- weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
- }else
- {
- $str .= weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_02"} if ($hotlist{$bufpointer."_count_02"} ne "0");
- }
-}
-# 3 = highlight
-if (defined $hotlist{$bufpointer."_count_03"})
-{
- my $bg = weechat::config_color( $options{"color_hotlist_highlight_bg"} );
- my $color = weechat::config_color( $options{"color_hotlist_highlight_fg"} );
- if ($str =~ /[0-9]$/)
- {
- $str .= ",".
- weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
- }else
- {
- $str .= weechat::color($bg).
- weechat::color($color).
- $hotlist{$bufpointer."_count_03"} if ($hotlist{$bufpointer."_count_03"} ne "0");
- }
-}
-$str .= $col_number_char. ")";
-
-$str = "" if (weechat::string_remove_color($str, "") eq " ()"); # remove color and check for buffer with no messages
-return $str;
-}
-
-sub buffers_signal_buffer
-{
-my ($data, $signal, $signal_data) = @_;
- # check for buffer_switch and set or remove detach time
- if ($weechat_version >= 0x00030800)
- {
- if ($signal eq "buffer_switch")
- {
- my $pointer = weechat::hdata_get_list (weechat::hdata_get("buffer"), "gui_buffer_last_displayed"); # get switched buffer
- my $current_time = time();
- if ( weechat::buffer_get_string($pointer, "localvar_type") eq "channel")
- {
- $buffers_timer{$pointer} = $current_time;
- }
- else
- {
- delete $buffers_timer{$pointer};
- }
- }
- if ($signal eq "buffer_opened")
- {
- my $current_time = time();
- $buffers_timer{$signal_data} = $current_time;
- }
- if ($signal eq "buffer_closing")
- {
- delete $buffers_timer{$signal_data};
- }
- }
-
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-
-sub buffers_signal_hotlist
-{
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-
-
-sub buffers_signal_config_whitelist
-{
- @whitelist_buffers = ();
- @whitelist_buffers = split( /,/, weechat::config_string( $options{"look_whitelist_buffers"} ) );
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-sub buffers_signal_config_immune_detach_buffers
-{
- @immune_detach_buffers = ();
- @immune_detach_buffers = split( /,/, weechat::config_string( $options{"immune_detach_buffers"} ) );
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-
-sub buffers_signal_config
-{
- weechat::bar_item_update($SCRIPT_NAME);
- return weechat::WEECHAT_RC_OK;
-}
-
-# called when mouse click occured in buffers item: this callback returns buffer
-# hash according to line of item where click occured
-sub buffers_focus_buffers
-{
- my %info = %{$_[1]};
- my $item_line = int($info{"_bar_item_line"});
- undef my $hash;
- if (($info{"_bar_item_name"} eq $SCRIPT_NAME) && ($item_line >= 0) && ($item_line <= $#buffers_focus))
- {
- $hash = $buffers_focus[$item_line];
- }
- else
- {
- $hash = {};
- my $hash_focus = $buffers_focus[0];
- foreach my $key (keys %$hash_focus)
- {
- $hash->{$key} = "?";
- }
- }
- return $hash;
-}
-
-# called when a mouse action is done on buffers item, to execute action
-# possible actions: jump to a buffer or move buffer in list (drag & drop of buffer)
-sub buffers_hsignal_mouse
-{
- my ($data, $signal, %hash) = ($_[0], $_[1], %{$_[2]});
- my $current_buffer = weechat::buffer_get_integer(weechat::current_buffer(), "number"); # get current buffer number
-
- if ( $hash{"_key"} eq "button1" ) # left mouse button
- {
- if ($hash{"number"} eq $hash{"number2"})
- {
- if ( weechat::config_integer($options{"jump_prev_next_visited_buffer"}) eq 1 )
- {
- if ( $current_buffer eq $hash{"number"} )
- {
- weechat::command("","/input jump_previously_visited_buffer");
- }
- else
- {
- weechat::command("", "/buffer ".$hash{"full_name"});
- }
- }
- else
- {
- weechat::command("", "/buffer ".$hash{"full_name"});
- }
- }
- else
- {
- move_buffer(%hash);
- }
- }
- elsif ( ($hash{"_key"} eq "button2") && (weechat::config_integer($options{"jump_prev_next_visited_buffer"}) eq 1) )# right mouse button
- {
- if ( $current_buffer eq $hash{"number2"} )
- {
- weechat::command("","/input jump_next_visited_buffer");
- }
- }
- else
- {
- my $infolist = weechat::infolist_get("hook", "", "command,menu");
- my $has_menu_command = weechat::infolist_next($infolist);
- weechat::infolist_free($infolist);
-
- if ( $has_menu_command && $hash{"_key"} =~ /button2/ )
- {
- if ($hash{"number"} eq $hash{"number2"})
- {
- weechat::command($hash{"pointer"}, "/menu buffer1 $hash{short_name} $hash{number}");
- }
- else
- {
- weechat::command($hash{"pointer"}, "/menu buffer2 $hash{short_name}/$hash{short_name2} $hash{number} $hash{number2}")
- }
- }
- else
- {
- move_buffer(%hash);
- }
- }
-}
-
-sub move_buffer
-{
- my %hash = @_;
- my $number2 = $hash{"number2"};
- if ($number2 eq "?")
- {
- # if number 2 is not known (end of gesture outside buffers list), then set it
- # according to mouse gesture
- $number2 = "999999";
- $number2 = "1" if (($hash{"_key"} =~ /gesture-left/) || ($hash{"_key"} =~ /gesture-up/));
- }
- my $ptrbuf = weechat::current_buffer();
- weechat::command($hash{"pointer"}, "/buffer move ".$number2);
-}
-
-sub check_immune_detached_buffers
-{
- my ($buffername) = @_;
- foreach ( @immune_detach_buffers ){
- my $immune_buffer = weechat::string_mask_to_regex($_);
- if ($buffername =~ /^$immune_buffer$/i)
- {
- return 1;
- }
- }
- return 0;
-}
-
-sub shutdown_cb
-{
- weechat::command("","/bar hide " . $SCRIPT_NAME) if ( weechat::config_boolean($options{"toggle_bar"}) eq 1 );
- return weechat::WEECHAT_RC_OK
-}
-
-sub check_bar_item
-{
- my $item = 0;
- my $infolist = weechat::infolist_get("bar", "", "");
- while (weechat::infolist_next($infolist))
- {
- my $bar_items = weechat::infolist_string($infolist, "items");
- if (index($bar_items,$SCRIPT_NAME) != -1)
- {
- my $name = weechat::infolist_string($infolist, "name");
- if ($name ne $SCRIPT_NAME)
- {
- $item = 1;
- last;
- }
- }
- }
- weechat::infolist_free($infolist);
- return $item;
-}
diff --git a/weechat/perl/autoload/chanmon.pl b/weechat/perl/autoload/chanmon.pl
deleted file mode 100644
index 14c0b1e..0000000
--- a/weechat/perl/autoload/chanmon.pl
+++ /dev/null
@@ -1,1154 +0,0 @@
-#
-# chanmon.pl - Channel Monitoring for weechat 0.3.0
-# Version 2.4
-#
-# Add 'Channel Monitor' buffer/bar that you can position to show IRC channel
-# messages in a single location without constantly switching buffers
-# i.e. In a seperate window beneath the main channel buffer
-#
-# Usage:
-# /chanmon [help] | [monitor [channel [server]]] | [dynmon] | [clean default|orphan|all]
-# Command wrapper for chanmon commands
-#
-# /chmonitor [channel] [server] is used to toggle a channel monitoring on and off, this
-# can be used in the channel buffer for the channel you wish to toggle, or be given
-# with arguments e.g. /monitor #weechat freenode
-#
-# /dynmon is used to toggle 'Dynamic Channel Monitoring' on and off, this
-# will automagically stop monitoring the current active buffer, without
-# affecting regular settings (Default is off)
-#
-# /chanclean default|orphan|all will clean the config section of default 'on' entries,
-# channels you are no longer joined, or both
-#
-# /set plugins.var.perl.chanmon.alignment
-# The config setting "alignment" can be changed to;
-# "channel", "schannel", "nchannel", "channel,nick", "schannel,nick", "nchannel,nick"
-# to change how the monitor appears
-# The 'channel' value will show: "#weechat"
-# The 'schannel' value will show: "6"
-# The 'nchannel' value will show: "6:#weechat"
-#
-# /set plugins.var.perl.chanmon.short_names
-# Setting this to 'on' will trim the network name from chanmon, ala buffers.pl
-#
-# /set plugins.var.perl.chanmon.merge_private
-# Setting this to 'on' will merge private messages to chanmon's display
-#
-# /set plugins.var.perl.chanmon.color_buf
-# This turns colored buffer names on or off, you can also set a single fixed color by using a weechat color name.
-# This *must* be a valid color name, or weechat will likely do unexpected things :)
-#
-# /set plugins.var.perl.chanmon.show_aways
-# Toggles showing the Weechat away messages
-#
-# /set plugins.var.perl.chanmon.logging
-# Toggles logging status for chanmon buffer (default: off)
-#
-# /set plugins.var.perl.chanmon.output
-# Changes where output method of chanmon; takes either "bar" or "buffer" (default; buffer)
-# /set plugins.var.perl.chanmon.bar_lines
-# Changes the amount of lines the output bar will hold.
-# (Only appears once output has been set to bar, defaults to 10)
-#
-# /set plugins.var.perl.chanmon.nick_prefix
-# /set plugins.var.perl.chanmon.nick_suffix
-# Sets the prefix and suffix chars in the chanmon buffer
-# (Defaults to <> if nothing set, and blank if there is)
-#
-# servername.#channel
-# servername is the internal name for the server (set when you use /server add)
-# #channel is the channel name, (where # is whatever channel type that channel happens to be)
-#
-# Example set up:
-# Split the layout 70/30 (or there abouts) horizontally and load
-# Optionally, make the status and input lines only show on active windows
-#
-# /window splith 70 --> open the chanmon buffer
-# /set weechat.bar.status.conditions "active"
-# /set weechat.bar.input.conditions "active"
-#
-
-# Bugs and feature requests at: https://github.com/KenjiE20/chanmon
-
-# History:
-# 2013-12-04, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.4: -add: Support for eval style colour codes in time format used for bar output
-# 2013-10-10, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.3.3.1: -fix: Typo in closed buffer warning
-# 2013-10-07, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.3.3: -add: Warning and fixer for accidental buffer closes
-# 2013-01-15, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.3.2: -fix: Let bar output use the string set in weechat's config option
-# -add: github info
-# -change: Ideal set up -> Example set up
-# 2012-04-15, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.3.1: -fix: Colour tags in bar timestamp string, bar error fixes from highmon
-# 2012-02-28, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.3: -feature: Added merge_private option to display private messages (default: off)
-# 2010-12-22, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.2: -change: Use API instead of config to find channel colours, ready for 0.3.4 and 256 colours
-# 2010-12-05, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.1.3: -change: /monitor is now /chmonitor to avoid command conflicts (thanks m4v)
-# (/chanmon monitor remains the same)
-# -fix: Add command list to inbuilt help
-# 2010-09-30, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.1.2: -fix: logging config was not correctly toggling back on (thanks to sleo for noticing)
-# 2010-09-20, m4v <lambdae2@gmail.com>:
-# v2.1.1: -fix: chanmon wasn't detecting buffers displayed on more than one window
-# 2010-08-27, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.1: -feature: Add 'nchannel' option to alignment to display buffer and name
-# 2010-04-25, KenjiE20 <longbow@longbowslair.co.uk>:
-# v2.0: Release as version 2.0
-# 2010-04-24, KenjiE20 <longbow@longbowslair.co.uk>:
-# -fix: No longer using hard-coded detection for ACTION and
-# TOPIC messages. Use config settings for ACTION printing
-# 2010-04-15, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.9: Rewrite for v2.0
-# -feature: /monitor takes arguments
-# -feature: Added /chanclean for config cleanup
-# -feature: Buffer logging option (default: off)
-# -feature: Selectable output (Bar/Buffer (default))
-# -feature: /chanmon is now a command wrapper for all commands
-# /help chanmon gives command help
-# /chanmon help gives config help
-# -code change: Made more subs to shrink the code down in places
-# -fix: Stop chanmon attempting to double load/hook
-# 2010-02-10, m4v <lambdae2@gmail.com>:
-# v1.7.1: -fix: chanmon was leaking infolists, changed how chanmon
-# detects if the buffer is displayed or not.
-# 2010-01-25, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.7: -fixture: Let chanmon be aware of nick_prefix/suffix
-# and allow custom prefix/suffix for chanmon buffer
-# (Defaults to <> if nothing set, and blank if there is)
-# -fix: Make dynamic monitoring aware of multiple windows
-# rather than just the active buffer
-# (Thanks to m4v for these)
-# 2009-09-07, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.6: -feature: colored buffer names
-# -change: chanmon version sync
-# 2009-09-05, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.5: -fix: disable buffer highlight
-# 2009-09-02, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.4.1 -change: Stop unsightly text block on '/help'
-# 2009-08-10, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.4: -feature: In-client help added
-# -fix: Added missing help entries
-# Fix remaining ugly vars
-# 2009-07-09, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.3.3 -fix: highlight on the channel monitor when someone /me highlights
-# 2009-07-04, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.3.2 -fix: use new away_info tag instead of ugly regexp for away detection
-# -code: cleanup old raw callback arguement variables to nice neat named ones
-# 2009-07-04, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.3.1 -feature(tte): Hide /away messages by default, change 'show_aways' to get them back
-# 2009-07-01, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.3 -feature(tte): Mimic buffers.pl 'short_names'
-# 2009-06-29, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.2.1 -fix: let the /monitor message respect the alignment setting
-# 2009-06-19, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.2 -feature(tte): Customisable alignment
-# Thanks to 'FreakGaurd' for the idea
-# 2009-06-14, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.1.2 -fix: don't assume chanmon buffer needs creating
-# fixes crashing with /upgrade
-# 2009-06-13, KenjiE20 <longbow@longbowslair.co.uk>:
-# v.1.1.1 -code: change from True/False to on/off for weechat consistency
-# Settings WILL NEED to be changed manually from previous versions
-# 2009-06-13, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.1: -feature: Dynamic Channel Monitoring,
-# don't display messages from active channel buffer
-# defaults to Disabled
-# Thanks to 'sjohnson' for the idea
-# -fix: don't set config entries for non-channels
-# -fix: don't assume all channels are #
-# 2009-06-12, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.0.1: -fix: glitch with tabs in IRC messages
-# 2009-06-10, KenjiE20 <longbow@longbowslair.co.uk>:
-# v1.0: Initial Public Release
-
-# Copyright (c) 2009 by KenjiE20 <longbow@longbowslair.co.uk>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-@bar_lines = ();
-@bar_lines_time = ();
-# Replicate info earlier for in-client help
-$chanmonhelp = weechat::color("bold")."/chanmon [help] | [monitor [channel [server]]] | [dynmon] | [clean default|orphan|all]".weechat::color("-bold")."
-Command wrapper for chanmon commands
-
-".weechat::color("bold")."/chmonitor [channel] [server]".weechat::color("-bold")." is used to toggle a channel monitoring on and off, this
- can be used in the channel buffer for the channel you wish to toggle, or be given with arguments e.g. /monitor #weechat freenode
-
-".weechat::color("bold")."/dynmon".weechat::color("-bold")." is used to toggle 'Dynamic Channel Monitoring' on and off, this will automagically stop monitoring the current active buffer, without affecting regular settings (Default is off)
-
-".weechat::color("bold")."/chanclean".weechat::color("-bold")." default|orphan|all will clean the config section of default 'on' entries, channels you are no longer joined, or both
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.alignment".weechat::color("-bold")."
- The config setting \"alignment\" can be changed to;
- \"channel\", \"schannel\", \"nchannel\", \"channel,nick\", \"schannel,nick\", \"nchannel,nick\"
- to change how the monitor appears
- The 'channel' value will show: \"#weechat\"
- The 'schannel' value will show: \"6\"
- The 'nchannel' value will show: \"6:#weechat\"
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.short_names".weechat::color("-bold")."
- Setting this to 'on' will trim the network name from chanmon, ala buffers.pl
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.merge_private".weechat::color("-bold")."
- Setting this to 'on' will merge private messages to chanmon's display
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.color_buf".weechat::color("-bold")."
- This turns colored buffer names on or off, you can also set a single fixed color by using a weechat color name.
- This ".weechat::color("bold")."must".weechat::color("-bold")." be a valid color name, or weechat will likely do unexpected things :)
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.show_aways".weechat::color("-bold")."
- Toggles showing the Weechat away messages
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.logging".weechat::color("-bold")."
- Toggles logging status for chanmon buffer (default: off)
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.output".weechat::color("-bold")."
- Changes where output method of chanmon; takes either \"bar\" or \"buffer\" (default; buffer)
-".weechat::color("bold")."/set plugins.var.perl.chanmon.bar_lines".weechat::color("-bold")."
- Changes the amount of lines the output bar will hold.
- (Only appears once output has been set to bar, defaults to 10)
-
-".weechat::color("bold")."/set plugins.var.perl.chanmon.nick_prefix".weechat::color("-bold")."
-".weechat::color("bold")."/set plugins.var.perl.chanmon.nick_suffix".weechat::color("-bold")."
- Sets the prefix and suffix chars in the chanmon buffer
- (Defaults to <> if nothing set, and blank if there is)
-
-".weechat::color("bold")."servername.#channel".weechat::color("-bold")."
- servername is the internal name for the server (set when you use /server add)
- #channel is the channel name, (where # is whatever channel type that channel happens to be)
-
-".weechat::color("bold")."Example set up:".weechat::color("-bold")."
-Split the layout 70/30 (or there abouts) horizontally and load
-Optionally, make the status and input lines only show on active windows
-
-".weechat::color("bold")."/window splith 70 --> open the chanmon buffer".weechat::color("-bold")."
-".weechat::color("bold")."/set weechat.bar.status.conditions \"active\"".weechat::color("-bold")."
-".weechat::color("bold")."/set weechat.bar.input.conditions \"active\"".weechat::color("-bold");
-# Print verbose help
-sub print_help
-{
- weechat::print("", "\t".weechat::color("bold")."Chanmon Help".weechat::color("-bold")."\n\n");
- weechat::print("", "\t".$chanmonhelp);
- return weechat::WEECHAT_RC_OK;
-}
-
-# Bar item build
-sub chanmon_bar_build
-{
- # Get max lines
- $max_lines = weechat::config_get_plugin("bar_lines");
- $max_lines = $max_lines ? $max_lines : 10;
- $str = '';
- $align_num = 0;
- $count = 0;
- # Keep lines within max
- while ($#bar_lines > $max_lines)
- {
- shift(@bar_lines);
- shift(@bar_lines_time);
- }
- # So long as we have some lines, build a string
- if (@bar_lines)
- {
- # Build loop
- $sep = " ".weechat::config_string(weechat::config_get("weechat.look.prefix_suffix"))." ";
- foreach(@bar_lines)
- {
- # Find max align needed
- $prefix_num = (index(weechat::string_remove_color($_, ""), $sep));
- $align_num = $prefix_num if ($prefix_num > $align_num);
- }
- foreach(@bar_lines)
- {
- # Get align for this line
- $prefix_num = (index(weechat::string_remove_color($_, ""), $sep));
-
- # Make string
- $str = $str.$bar_lines_time[$count]." ".(" " x ($align_num - $prefix_num)).$_."\n";
- # Increment count for sync with time list
- $count++;
- }
- }
- return $str;
-}
-
-# Make a new bar
-sub chanmon_bar_open
-{
- # Make the bar item
- weechat::bar_item_new("chanmon", "chanmon_bar_build", "");
-
- $chanmon_bar = weechat::bar_new ("chanmon", "off", 100, "root", "", "bottom", "vertical", "vertical", 0, 0, "default", "cyan", "default", "on", "chanmon");
-
- return weechat::WEECHAT_RC_OK;
-}
-# Close bar
-sub chanmon_bar_close
-{
- # Find if bar exists
- $chanmon_bar = weechat::bar_search("chanmon");
- # If is does, close it
- if ($chanmon_bar ne "")
- {
- weechat::bar_remove($chanmon_bar);
- }
-
- # Find if bar item exists
- $chanmon_bar_item = weechat::bar_item_search("chanmon_bar");
- # If is does, close it
- if ($chanmon_bar_item ne "")
- {
- weechat::bar_remove($chanmon_bar_item);
- }
-
- @bar_lines = ();
- return weechat::WEECHAT_RC_OK;
-}
-
-# Make a new buffer
-sub chanmon_buffer_open
-{
- # Search for pre-existing buffer
- $chanmon_buffer = weechat::buffer_search("perl", "chanmon");
-
- # Make a new buffer
- if ($chanmon_buffer eq "")
- {
- $chanmon_buffer = weechat::buffer_new("chanmon", "chanmon_buffer_input", "", "chanmon_buffer_close", "");
- }
-
- # Turn off notify, highlights
- if ($chanmon_buffer ne "")
- {
- weechat::buffer_set($chanmon_buffer, "notify", "0");
- weechat::buffer_set($chanmon_buffer, "highlight_words", "-");
- weechat::buffer_set($chanmon_buffer, "title", "Channel Monitor");
- # Set no_log
- if (weechat::config_get_plugin("logging") eq "off")
- {
- weechat::buffer_set($chanmon_buffer, "localvar_set_no_log", "1");
- }
- }
- return weechat::WEECHAT_RC_OK;
-}
-# Buffer input has no action
-sub chanmon_buffer_input
-{
- return weechat::WEECHAT_RC_OK;
-}
-# Close up
-sub chanmon_buffer_close
-{
- $chanmon_buffer = "";
- # If user hasn't changed output style warn user
- if (weechat::config_get_plugin("output") eq "buffer")
- {
- weechat::print("", "\tChanmon buffer has been closed but output is still set to buffer, unusual results may occur. To recreate the buffer use ".weechat::color("bold")."/chanmon fix".weechat::color("-bold"));
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-# Chanmon command wrapper
-sub chanmon_command_cb
-{
- $data = $_[0];
- $buffer = $_[1];
- $args = $_[2];
- my $cmd = '';
- my $arg = '';
-
- if ($args ne "")
- {
- # Split argument up
- @arg_array = split(/ /,$args);
- # Take first as command
- $cmd = shift(@arg_array);
- # Rebuild string to pass to subs
- if (@arg_array)
- {
- $arg = join(" ", @arg_array);
- }
- }
-
- # Help command
- if ($cmd eq "" || $cmd eq "help")
- {
- print_help();
- }
- # /monitor command
- elsif ($cmd eq "monitor")
- {
- chanmon_toggle($data, $buffer, $arg);
- }
- # /dynmon command
- elsif ($cmd eq "dynmon")
- {
- chanmon_dyn_toggle();
- }
- # /chanclean command
- elsif ($cmd eq "clean")
- {
- chanmon_config_clean($data, $buffer, $arg);
- }
- # Fix closed buffer
- elsif ($cmd eq "fix")
- {
- if (weechat::config_get_plugin("output") eq "buffer" && $chanmon_buffer eq "")
- {
- chanmon_buffer_open();
- }
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-# Clean up config entries
-sub chanmon_config_clean
-{
- $data = $_[0];
- $buffer = $_[1];
- $args = $_[2];
-
- # Don't do anything if bad option given
- if ($args ne "default" && $args ne "orphan" && $args ne "all")
- {
- weechat::print("", "\tchanmon.pl: Unknown option");
- return weechat::WEECHAT_RC_OK;
- }
-
- @chans = ();
- # Load an infolist of chanmon options
- $infolist = weechat::infolist_get("option", "", "*chanmon*");
- while (weechat::infolist_next($infolist))
- {
- $name = weechat::infolist_string($infolist, "option_name");
- $name =~ s/perl\.chanmon\.(\w*)\.([#&\+!])(.*)/$1.$2$3/;
- if ($name =~ /^(.*)\.([#&\+!])(.*)$/)
- {
- $action = 0;
- # Clean up all 'on's
- if ($args eq "default" || $args eq "all")
- {
- # If value in config is "on"
- if (weechat::config_get_plugin($name) eq "on")
- {
- # Unset and if successful flag as changed
- $rc = weechat::config_unset_plugin($name);
- if ($rc eq weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED)
- {
- $action = 1;
- }
- }
- }
- # Clean non joined
- if ($args eq "orphan" || $args eq "all")
- {
- # If we can't find the buffer for this entry
- if (weechat::buffer_search("irc", $name) eq "")
- {
- # Unset and if successful flag as changed
- $rc = weechat::config_unset_plugin($name);
- if ($rc eq weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED)
- {
- $action = 1;
- }
- }
- }
- # Add changed entry names to list
- push (@chans, $name) if ($action);
- }
- }
- weechat::infolist_free($infolist);
- # If channels were cleaned from config
- if (@chans)
- {
- # If only one entry
- if (@chans == 1)
- {
- $str = "\tchanmon.pl: Cleaned ".@chans." entry from the config:";
- }
- else
- {
- $str = "\tchanmon.pl: Cleaned ".@chans." entries from the config:";
- }
- # Build a list of channels
- foreach(@chans)
- {
- $str = $str." ".$_;
- }
- # Print what happened
- weechat::print("",$str);
- }
- # Config seemed to be clean
- else
- {
- weechat::print("", "\tchanmon.pl: No entries removed");
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-# Check config elements
-sub chanmon_config_init
-{
- # Alignment default
- if (!(weechat::config_is_set_plugin ("alignment")))
- {
- weechat::config_set_plugin("alignment", "channel");
- }
- if (weechat::config_get_plugin("alignment") eq "")
- {
- weechat::config_set_plugin("alignment", "none");
- }
-
- # Dynmon default
- if (!(weechat::config_is_set_plugin ("dynamic")))
- {
- weechat::config_set_plugin("dynamic", "off");
- }
-
- # Short name default
- if (!(weechat::config_is_set_plugin ("short_names")))
- {
- weechat::config_set_plugin("short_names", "off");
- }
-
- # Coloured names default
- if (!(weechat::config_is_set_plugin ("color_buf")))
- {
- weechat::config_set_plugin("color_buf", "on");
- }
-
- # Away message default
- if (!(weechat::config_is_set_plugin ("show_aways")))
- {
- weechat::config_set_plugin("show_aways", "off");
- }
-
- # chanmon log default
- if (!(weechat::config_is_set_plugin ("logging")))
- {
- weechat::config_set_plugin("logging", "off");
- }
-
- # Output default
- if (!(weechat::config_is_set_plugin ("output")))
- {
- weechat::config_set_plugin("output", "buffer");
- }
-
- # Private message merging
- if (!(weechat::config_is_set_plugin ("merge_private")))
- {
- weechat::config_set_plugin("merge_private", "off");
- }
-
- # Check for exisiting prefix/suffix chars, and setup accordingly
- $prefix = weechat::config_get("irc.look.nick_prefix");
- $prefix = weechat::config_string($prefix);
- $suffix = weechat::config_get("irc.look.nick_suffix");
- $suffix = weechat::config_string($suffix);
-
- if (!(weechat::config_is_set_plugin("nick_prefix")))
- {
- if ($prefix eq "" && $suffix eq "")
- {
- weechat::config_set_plugin("nick_prefix", "<");
- }
- else
- {
- weechat::config_set_plugin("nick_prefix", "");
- }
- }
-
- if (!(weechat::config_is_set_plugin("nick_suffix")))
- {
- if ($prefix eq "" && $suffix eq "")
- {
- weechat::config_set_plugin("nick_suffix", ">");
- }
- else
- {
- weechat::config_set_plugin("nick_suffix", "");
- }
- }
-}
-
-# Get config updates
-sub chanmon_config_cb
-{
- $point = $_[0];
- $name = $_[1];
- $value = $_[2];
-
- $name =~ s/^plugins\.var\.perl\.chanmon\.//;
-
- # Set logging on buffer
- if ($name eq "logging")
- {
- # Search for pre-existing buffer
- $chanmon_buffer = weechat::buffer_search("perl", "chanmon");
- if ($value eq "off")
- {
- weechat::buffer_set($chanmon_buffer, "localvar_set_no_log", "1");
- }
- else
- {
- weechat::buffer_set($chanmon_buffer, "localvar_del_no_log", "");
- }
- }
- # Output changer
- elsif ($name eq "output")
- {
- if ($value eq "bar")
- {
- # Search for pre-existing buffer
- $chanmon_buffer = weechat::buffer_search("perl", "chanmon");
- # Close if it exists
- if ($chanmon_buffer ne "")
- {
- weechat::buffer_close($chanmon_buffer)
- }
-
- # Output bar lines default
- if (!(weechat::config_is_set_plugin ("bar_lines")))
- {
- weechat::config_set_plugin("bar_lines", "10");
- }
- # Make a bar if doesn't exist
- chanmon_bar_open();
- }
- elsif ($value eq "buffer")
- {
- # If a bar exists, close it
- chanmon_bar_close();
- # Open buffer
- chanmon_buffer_open();
- }
-
- }
- elsif ($name eq "weechat.look.prefix_suffix")
- {
- if (weechat::config_get_plugin("output") eq "bar")
- {
- @bar_lines = ();
- weechat::print("", "\tchanmon: weechat.look.prefix_suffix changed, clearing chanmon bar");
- weechat::bar_item_update("chanmon");
- }
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-# Toggle dynamic monitoring on/off
-sub chanmon_dyn_toggle
-{
- if (weechat::config_get_plugin("dynamic") eq "off")
- {
- weechat::config_set_plugin("dynamic", "on");
- chanmon_print("Dynamic Channel Monitoring Enabled");
- return weechat::WEECHAT_RC_OK;
- }
- elsif (weechat::config_get_plugin("dynamic") eq "on")
- {
- weechat::config_set_plugin("dynamic", "off");
- chanmon_print("Dynamic Channel Monitoring Disabled");
- return weechat::WEECHAT_RC_OK;
- }
-}
-
-# Set up weechat hooks / commands
-sub chanmon_hook
-{
- weechat::hook_print("", "", "", 0, "chanmon_new_message", "");
- weechat::hook_command("chmonitor", "Toggles monitoring for a channel", "[channel [server]]", " channel: What channel to toggle monitoring for\n server: Internal server name, if channel is on more than one server", "%(irc_channels) %(irc_servers)", "chanmon_toggle", "");
- weechat::hook_command("dynmon", "Toggles 'dynamic' monitoring (auto-disable monitoring for current channel)", "", "", "", "chanmon_dyn_toggle", "");
- weechat::hook_command("chanclean", "Chanmon config clean up", "default|orphan|all", " default: Cleans all config entries with the default \"on\" value\n orphan: Cleans all config entries for channels you aren't currently joined\n all: Does both defaults and orphan", "default|orphan|all", "chanmon_config_clean", "");
-
- weechat::hook_command("chanmon", "Chanmon help", "[help] | [monitor [channel [server]]] | [dynmon] | [clean default|orphan|all]", " help: Print help for chanmon\n monitor: Toggles monitoring for a channel (/chmonitor)\n dynmon: Toggles 'dynamic' monitoring (auto-disable monitoring for current channel) (/dynmon)\n clean: Chanmon config clean up (/chanclean)", "help || monitor %(irc_channels) %(irc_servers) || dynmon || clean default|orphan|all", "chanmon_command_cb", "");
-
- weechat::hook_config("plugins.var.perl.chanmon.*", "chanmon_config_cb", "");
- weechat::hook_config("weechat.look.prefix_suffix", "chanmon_config_cb", "");
-}
-
-# Main body, Callback for hook_print
-sub chanmon_new_message
-{
- my $net = "";
- my $chan = "";
- my $nick = "";
- my $outstr = "";
- my $window_displayed = "";
- my $dyncheck = "0";
-
-# DEBUG point
-# $string = "\t"."0: ".$_[0]." 1: ".$_[1]." 2: ".$_[2]." 3: ".$_[3]." 4: ".$_[4]." 5: ".$_[5]." 6: ".$_[6]." 7: ".$_[7];
-# weechat::print("", "\t".$string);
-
- $cb_datap = $_[0];
- $cb_bufferp = $_[1];
- $cb_date = $_[2];
- $cb_tags = $_[3];
- $cb_disp = $_[4];
- $cb_high = $_[5];
- $cb_prefix = $_[6];
- $cb_msg = $_[7];
-
- # Only work on messages and topic notices
- if ($cb_tags =~ /irc_privmsg/ || $cb_tags =~ /irc_topic/)
- {
- # Check buffer name is an IRC channel or private message when enabled
- $bufname = weechat::buffer_get_string($cb_bufferp, 'name');
- if ($bufname =~ /(.*)\.([#&\+!])(.*)/ || (weechat::config_get_plugin("merge_private") eq "on" && $cb_tags =~ /notify_private/))
- {
- # Are we running on this channel
- if (weechat::config_get_plugin($bufname) ne "off" && $cb_disp eq "1")
- {
- # Are we running dynamically
- if (weechat::config_get_plugin("dynamic") eq "on")
- {
- # Check if this buffer is shown in a window somewhere
- $window_displayed = weechat::buffer_get_integer($cb_bufferp, "num_displayed");
- if ($window_displayed ne 0)
- {
- # Stop running
- return weechat::WEECHAT_RC_OK;
- }
- }
-
- # Format nick
- # Line isn't action or topic notify
- if (!($cb_tags =~ /irc_action/) && !($cb_tags =~ /irc_topic/))
- {
- # Highlight
- if ($cb_high eq "1")
- {
- # Strip nick colour
- $uncolnick = weechat::string_remove_color($cb_prefix, "");
- # Format nick
- $nick = " ".weechat::config_get_plugin("nick_prefix").weechat::color("chat_highlight").$uncolnick.weechat::color("reset").weechat::config_get_plugin("nick_suffix");
- }
- # Normal line
- else
- {
- # Format nick
- $nick = " ".weechat::config_get_plugin("nick_prefix").$cb_prefix.weechat::color("reset").weechat::config_get_plugin("nick_suffix");
- }
- }
- # Topic line
- elsif ($cb_tags =~ /irc_topic/)
- {
-
- $nick = " ".$cb_prefix.weechat::color("reset");
- }
- # Action line
- else
- {
- # Highlight
- if ($cb_high eq "1")
- {
- $uncolnick = weechat::string_remove_color($cb_prefix, "");
- $nick = weechat::color("chat_highlight").$uncolnick.weechat::color("reset");
- }
- # Normal line
- else
- {
- $nick = $cb_prefix.weechat::color("reset");
- }
- }
- # Send to output
- chanmon_print ($cb_msg, $cb_bufferp, $nick);
- }
- }
- }
- # Special outgoing ACTION & away_info catcher
- elsif ($cb_tags eq "" || $cb_tags =~ /away_info/ && weechat::config_get_plugin("show_aways") eq "on" )
- {
- # Check buffer name is an IRC channel or private message when enabled
- $bufname = weechat::buffer_get_string($cb_bufferp, 'name');
- if ($bufname =~ /(.*)\.([#&\+!])(.*)/ || (weechat::config_get_plugin("merge_private") eq "on" && $cb_tags =~ /notify_private/))
- {
- # Are we running dynamically
- if (weechat::config_get_plugin("dynamic") eq "on")
- {
- # Check if this buffer is shown in a window somewhere
- $window_displayed = weechat::buffer_get_integer($cb_bufferp, "num_displayed");
- if ($window_displayed eq 1)
- {
- # Stop running
- return weechat::WEECHAT_RC_OK;
- }
- }
-
- $net = $1;
- $mynick = weechat::info_get("irc_nick", $net);
- if ($cb_msg =~ $mynick)
- {
- $action_colour = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_prefix_action")));
- $action_prefix = weechat::config_string(weechat::config_get("weechat.look.prefix_action"));
- $nick_self_colour = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_nick_self")));
- $nick = $action_colour.$action_prefix.$nick_self_colour.$nick.weechat::color("reset");
- # Send to output
- chanmon_print ($cb_msg, $cb_bufferp, $nick);
- }
- }
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-# Output formatter and printer takes (msg bufpointer nick)
-sub chanmon_print
-{
- $cb_msg = $_[0];
- my $cb_bufferp = $_[1] if ($_[1]);
- my $nick = $_[2] if ($_[2]);
-
- #Normal channel message
- if ($cb_bufferp && $nick)
- {
- # Format buffer name
- $bufname = format_buffer_name($cb_bufferp);
-
- # If alignment is #channel | nick msg
- if (weechat::config_get_plugin("alignment") eq "channel")
- {
- $nick =~ s/\s(.*)/$1/;
- # Build string
- $outstr = $bufname."\t".$nick." ".$cb_msg;
- }
- # or if it is channel number | nick msg
- elsif (weechat::config_get_plugin("alignment") eq "schannel")
- {
- $nick =~ s/\s(.*)/$1/;
- # Use channel number instead
- $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').weechat::color("reset");
- # Build string
- $outstr = $bufname."\t".$nick." ".$cb_msg;
- }
- # or if it is number:#channel | nick msg
- elsif (weechat::config_get_plugin("alignment") eq "nchannel")
- {
- $nick =~ s/\s(.*)/$1/;
- # Place channel number in front of formatted name
- $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').":".weechat::color("reset").$bufname;
- # Build string
- $outstr = $bufname."\t".$nick." ".$cb_msg;
- }
- # or if it is #channel nick | msg
- elsif (weechat::config_get_plugin("alignment") eq "channel,nick")
- {
- # Build string
- $outstr = $bufname.":".$nick."\t".$cb_msg;
- }
- # or if it is channel number nick | msg
- elsif (weechat::config_get_plugin("alignment") eq "schannel,nick")
- {
- # Use channel number instead
- $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').weechat::color("reset");
- # Build string
- $outstr = $bufname.":".$nick."\t".$cb_msg;
- }
- # or if it is number:#channel nick | msg
- elsif (weechat::config_get_plugin("alignment") eq "nchannel,nick")
- {
- # Place channel number in front of formatted name
- $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').":".weechat::color("reset").$bufname;
- # Build string
- $outstr = $bufname.":".$nick."\t".$cb_msg;
- }
- # or finally | #channel nick msg
- else
- {
- # Build string
- $outstr = "\t".$bufname.":".$nick." ".$cb_msg;
- }
- }
- # chanmon channel toggle message
- elsif ($cb_bufferp && !$nick)
- {
- # Format buffer name
- $bufname = format_buffer_name($cb_bufferp);
-
- # If alignment is #channel * | *
- if (weechat::config_get_plugin("alignment") =~ /channel/)
- {
- # If it's actually channel number * | *
- if (weechat::config_get_plugin("alignment") =~ /schannel/)
- {
- # Use channel number instead
- $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').weechat::color("reset");
- }
- # Or if it's actually number:#channel * | *
- if (weechat::config_get_plugin("alignment") =~ /nchannel/)
- {
- # Place channel number in front of formatted name
- $bufname = weechat::color("chat_prefix_buffer").weechat::buffer_get_integer($cb_bufferp, 'number').":".weechat::color("reset").$bufname;
- }
- $outstr = $bufname."\t".$cb_msg;
- }
- # or if alignment is | *
- else
- {
- $outstr = $bufname.": ".$cb_msg;
- }
- }
- # chanmon dynmon
- elsif (!$cb_bufferp && !$nick)
- {
- $outstr = "\t".$cb_msg;
- }
-
- # Send string to buffer
- if (weechat::config_get_plugin("output") eq "buffer")
- {
- # Search for and confirm buffer
- $chanmon_buffer = weechat::buffer_search("perl", "chanmon");
- # Print
- weechat::print($chanmon_buffer, $outstr);
- }
- elsif (weechat::config_get_plugin("output") eq "bar")
- {
- # Add time string
- use POSIX qw(strftime);
- $time = strftime(weechat::config_string(weechat::config_get("weechat.look.buffer_time_format")), localtime);
- # Colourise
- if ($time =~ /\$\{(?:color:)?[\w,]+\}/) # Coloured string
- {
- while ($time =~ /\$\{(?:color:)?([\w,]+)\}/)
- {
- $color = weechat::color($1);
- $time =~ s/\$\{(?:color:)?[\w,]+\}/$color/;
- }
- $time .= weechat::color("reset");
- }
- else # Default string
- {
- $colour = weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_time_delimiters")));
- $reset = weechat::color("reset");
- $time =~ s/(\d*)(.)(\d*)/$1$colour$2$reset$3/g;
- }
- # Push updates to bar lists
- push (@bar_lines_time, $time);
-
- # Change tab char
- $delim = " ".weechat::color(weechat::config_string(weechat::config_get("weechat.color.chat_delimiters"))).weechat::config_string(weechat::config_get("weechat.look.prefix_suffix")).weechat::color("reset")." ";
- $outstr =~ s/\t/$delim/;
-
- push (@bar_lines, $outstr);
- # Trigger update
- weechat::bar_item_update("chanmon");
- }
-}
-
-# Start the output display
-sub chanmon_start
-{
- if (weechat::config_get_plugin("output") eq "buffer")
- {
- chanmon_buffer_open();
- }
- elsif (weechat::config_get_plugin("output") eq "bar")
- {
- chanmon_bar_open();
- }
-}
-
-# Takes two optional args (channel server), toggles monitoring on/off
-sub chanmon_toggle
-{
- $data = $_[0];
- $buffer = $_[1];
- $args = $_[2];
-
- # Check if we've been told what channel to act on
- if ($args ne "")
- {
- # Split argument up
- @arg_array = split(/ /,$args);
- # Check if a server was given
- if ($arg_array[1])
- {
- # Find matching
- $bufp = weechat::buffer_search("irc", $arg_array[1].".".$arg_array[0]);
- }
- else
- {
- $found_chans = 0;
- # Loop through defined servers
- $infolist = weechat::infolist_get("buffer", "", "");
- while (weechat::infolist_next($infolist))
- {
- # Only interesting in IRC buffers
- if (weechat::infolist_string($infolist, "plugin_name") eq "irc")
- {
- # Find buffers that maych
- $sname = weechat::infolist_string($infolist, "short_name");
- if ($sname eq $arg_array[0])
- {
- $found_chans++;
- $bufp = weechat::infolist_pointer($infolist, "pointer");
- }
- }
- }
- weechat::infolist_free($infolist);
- # If the infolist found more than one channel, halt as we need to know which one
- if ($found_chans > 1)
- {
- weechat::print("", "Channel name is not unique, please define server");
- return weechat::WEECHAT_RC_OK;
- }
- }
- # Something didn't return right
- if ($bufp eq "")
- {
- weechat::print("", "Could not find buffer");
- return weechat::WEECHAT_RC_OK;
- }
- }
- else
- {
- # Get pointer from where we are
- $bufp = weechat::current_buffer();
- }
- # Get buffer name
- $bufname = weechat::buffer_get_string($bufp, 'name');
- # Test if buffer is an IRC channel
- if ($bufname =~ /(.*)\.([#&\+!])(.*)/)
- {
- if (weechat::config_get_plugin($bufname) eq "off")
- {
- # If currently off, set on
- weechat::config_set_plugin($bufname, "on");
-
- # Send to output formatter
- chanmon_print("Channel Monitoring Enabled", $bufp);
- return weechat::WEECHAT_RC_OK;
- }
- elsif (weechat::config_get_plugin($bufname) eq "on" || weechat::config_get_plugin($bufname) eq "")
- {
- # If currently on, set off
- weechat::config_set_plugin($bufname, "off");
-
- # Send to output formatter
- chanmon_print("Channel Monitoring Disabled", $bufp);
- return weechat::WEECHAT_RC_OK;
- }
- }
-}
-
-# Takes a buffer pointer and returns a formatted name
-sub format_buffer_name
-{
- $cb_bufferp = $_[0];
- $bufname = weechat::buffer_get_string($cb_bufferp, 'name');
-
- # Set colour from buffer name
- if (weechat::config_get_plugin("color_buf") eq "on")
- {
- # Determine what colour to use
- $color = weechat::info_get("irc_nick_color", $bufname);
- if (!$color)
- {
- $color = 0;
- @char_array = split(//,$bufname);
- foreach $char (@char_array)
- {
- $color += ord($char);
- }
- $color %= 10;
- $color = sprintf "weechat.color.chat_nick_color%02d", $color+1;
- $color = weechat::config_get($color);
- $color = weechat::config_string($color);
- $color = weechat::color($color);
- }
-
- # Private message just show network
- if (weechat::config_get_plugin("merge_private") eq "on" && weechat::buffer_get_string($cb_bufferp, "localvar_type") eq "private")
- {
- $bufname = weechat::buffer_get_string($cb_bufferp, "localvar_server");
- }
- # Format name to short or 'nicename'
- elsif (weechat::config_get_plugin("short_names") eq "on")
- {
- $bufname = weechat::buffer_get_string($cb_bufferp, 'short_name');
- }
- else
- {
- $bufname =~ s/(.*)\.([#&\+!])(.*)/$1$2$3/;
- }
-
- # Build a coloured string
- $bufname = $color.$bufname.weechat::color("reset");
- }
- # User set colour name
- elsif (weechat::config_get_plugin("color_buf") ne "off")
- {
- # Private message just show network
- if (weechat::config_get_plugin("merge_private") eq "on" && weechat::buffer_get_string($cb_bufferp, "localvar_type") eq "private")
- {
- $bufname = weechat::buffer_get_string($cb_bufferp, "localvar_server");
- }
- # Format name to short or 'nicename'
- elsif (weechat::config_get_plugin("short_names") eq "on")
- {
- $bufname = weechat::buffer_get_string($cb_bufferp, 'short_name');
- }
- else
- {
- $bufname =~ s/(.*)\.([#&\+!])(.*)/$1$2$3/;
- }
-
- $color = weechat::config_get_plugin("color_buf");
- $bufname = weechat::color($color).$bufname.weechat::color("reset");
- }
- # Stick with default colour
- else
- {
- # Private message just show network
- if (weechat::config_get_plugin("merge_private") eq "on" && weechat::buffer_get_string($cb_bufferp, "localvar_type") eq "private")
- {
- $bufname = weechat::buffer_get_string($cb_bufferp, "localvar_server");
- }
- # Format name to short or 'nicename'
- elsif (weechat::config_get_plugin("short_names") eq "on")
- {
- $bufname = weechat::buffer_get_string($cb_bufferp, 'short_name');
- }
- else
- {
- $bufname =~ s/(.*)\.([#&\+!])(.*)/$1$2$3/;
- }
- }
-
- return $bufname;
-}
-
-# Check result of register, and attempt to behave in a sane manner
-if (!weechat::register("chanmon", "KenjiE20", "2.4", "GPL3", "Channel Monitor", "", ""))
-{
- # Double load
- weechat::print ("", "\tChanmon is already loaded");
- return weechat::WEECHAT_RC_OK;
-}
-else
-{
- # Start everything
- chanmon_hook();
- chanmon_config_init();
- chanmon_start();
-}
diff --git a/weechat/perl/autoload/chatters.pl b/weechat/perl/autoload/chatters.pl
deleted file mode 100644
index 993ccad..0000000
--- a/weechat/perl/autoload/chatters.pl
+++ /dev/null
@@ -1,287 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2012 Arvydas Sidorenko <asido4@gmail.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# Usage:
-# To show the bar item:
-# /set weechat.bar.nicklist.items "chatters,buffer_nicklist"
-# Config options:
-# /set plugins.var.perl.chatters.frame_color "red"
-# /set plugins.var.perl.chatters.nick_color "yellow"
-# /set plugins.var.perl.chatters.nick_timeout "600"
-#
-#
-# History:
-#
-# 2012-05-01, Arvydas Sidorenko <asido4@gmail.com>
-# Version 0.1: initial release
-# 2012-05-11, Arvydas Sidorenko <asido4@gmail.com>
-# Version 0.2: rewritten script using bar_item to store the chatters
-# instead of nicklist_group
-# 2012-05-16, Arvydas Sidorenko <asido4@gmail.com>
-# Version 0.2.1: Bug fix: same channels under different servers share a
-# common chatter list.
-# 2012-05-18, Nils G <weechatter@arcor.de>
-# Version 0.3: missing return value for callbacks fixed
-# version check added
-# improved option handling
-# 2013-02-07, Ailin Nemui <anti.teamidiot.de>
-# Version 0.4: add focus info
-#
-
-use strict;
-use warnings;
-
-my $version = "0.4";
-my $script_name = "chatters";
-my $weechat_version = "";
-
-# A hash with groups where the chatters are going to be added
-#
-# Structure:
-# "#channel1" -- "nick1" -- last msg timestamp
-# `- "nick2" -- last msg timestamp
-# `- "nick3" -- last msg timestamp
-# "#channel2" -- "nick1" -- last msg timestamp
-# `- ...
-my %chatter_groups = ();
-my $chatters_bar_item_name = "chatters";
-
-weechat::register($script_name, "Arvydas Sidorenko <asido4\@gmail.com>", $version, "GPL3", "Groups people into chatters and idlers", "", "");
-$weechat_version = weechat::info_get("version_number", "");
-if (($weechat_version eq "") or ($weechat_version < 0x00030600)) # minimum v0.3.6
-{
- weechat::print("",weechat::prefix("error")."$script_name: needs at least WeeChat v0.3.6");
- weechat::command("","/wait 1ms /perl unload $script_name");
-}
-
-# Check configs
-my %default_settings = (frame_color => "red",
- nick_color => "yellow",
- nick_timeout => 600);
-for (keys %default_settings)
-{
- weechat::config_set_plugin($_ => $default_settings{$_}) unless weechat::config_is_set_plugin($_);
-}
-
-
-# Close a channel
-weechat::hook_signal("buffer_closing", "buffer_close_cb", "");
-# Callback whenever someone leaves the channel
-weechat::hook_signal("nicklist_nick_removed", "on_leave_cb", "");
-# Callback whenever someone writes something in the channel
-weechat::hook_signal("*,irc_in_PRIVMSG", "msg_cb", "");
-# Chatter observer callback
-weechat::hook_timer(60000, 0, 0, "cleanup_chatters", 0);
-# On config change
-weechat::hook_config("plugins.var.perl.${script_name}.*", "config_change_cb", "");
-
-
-weechat::bar_item_new($chatters_bar_item_name, "chatters_bar_cb", "");
-
-# For mouse support
-weechat::hook_focus($chatters_bar_item_name, "chatters_focus_cb", "") if $weechat_version >= 0x00030600;
-
-###############################################################################
-# Buffer update callback
-sub chatters_bar_cb
-{
- # $_[0] - data
- # $_[1] - bar item
- # $_[2] - window
- my $str = "";
- my $buffer = weechat::window_get_pointer($_[2], "buffer");
- my $channel = buf_to_channel_key($buffer);
- my $frame_color = weechat::color(weechat::config_get_plugin("frame_color"));
- my $nick_color = weechat::color(weechat::config_get_plugin("nick_color"));
-
- $str = $frame_color . "-- Chatters -----\n";
-
- if ($channel and $chatter_groups{$channel})
- {
- foreach my $nick (sort {uc($a) cmp uc($b)} keys %{ $chatter_groups{$channel} })
- {
- $str .= $nick_color . $nick . "\n";
- }
- }
-
- $str .= $frame_color . "-----------------\n";
-
- return $str;
-}
-
-###############################################################################
-# Buffer close callback
-sub buffer_close_cb
-{
- # $_[0] - callback data (3rd hook arg)
- # $_[1] - signal (buffer_closing)
- # $_[2] - buffer pointer
- my $channel = buf_to_channel_key($_[2]);
-
- if ($chatter_groups{$channel})
- {
- delete $chatter_groups{$channel};
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-###############################################################################
-# Gets called when someones writes in a channel
-sub msg_cb
-{
- # $_[0] - callback data (3rd hook arg)
- # $_[1] - event name
- # $_[2] - the message:
- # :Asido!~asido@2b600000.rev.myisp.com PRIVMSG #linux :yoo
- my $msg = weechat::info_get_hashtable("irc_message_parse" => + { "message" => $_[2] });
- my $channel = "";
- my ($server) = split ",", $_[1];
- my $key = "";
-
- # Ignore private messages
- unless ($msg->{channel} =~ /^#/)
- {
- return weechat::WEECHAT_RC_OK;
- }
-
- $key = format_key($server, $msg->{channel});
-
- $chatter_groups{$key}{$msg->{nick}} = time();
- weechat::bar_item_update($chatters_bar_item_name);
-
- return weechat::WEECHAT_RC_OK;
-}
-
-###############################################################################
-# Gets called when someones leaves a channel
-sub on_leave_cb
-{
- # $_[0] - data
- # $_[1] - event name (nicklist_nick_removed)
- # $_[2] - 0x1ffda70,spoty (<buffer_pointer>,<nick>)
- my ($buf, $nick) = split ",", $_[2];
- my $channel = buf_to_channel_key($buf);
-
- if ($chatter_groups{$channel} and $chatter_groups{$channel}{$nick})
- {
- delete $chatter_groups{$channel}{$nick};
- weechat::bar_item_update($chatters_bar_item_name);
- }
-
- return weechat::WEECHAT_RC_OK;
-}
-
-###############################################################################
-# Script config edit callback
-sub config_change_cb
-{
- # $_[0] - data
- # $_[1] - option name
- # $_[2] - new value
-# my $opt = $_[1];
- my ( $pointer, $name, $value ) = @_;
- $name = substr($name,length("plugins.var.perl.".$script_name."."),length($name)); # don't forget the "."
-# $default_settings{$name} = $value; # store new value, if needed!
-
-# if ($opt =~ /frame_color$/ or $opt =~ /nick_color$/)
- if ($name eq "frame_color" or $name eq "nick_color")
- {
- weechat::bar_item_update($chatters_bar_item_name);
- }
-# elsif ($opt =~ /nick_timeout$/)
- elsif ($name eq "nick_timeout")
- {
- cleanup_chatters();
- }
- return weechat::WEECHAT_RC_OK;
-}
-
-###############################################################################
-# Adds nick info to focus hashtable
-sub chatters_focus_cb
-{
- my $channel = buf_to_channel_key($_[1]{_buffer});
- if ($channel and $chatter_groups{$channel} and
- $_[1]{_bar_item_line} > 0 and $_[1]{_bar_item_line} <= keys %{ $chatter_groups{$channel} })
- {
- +{ nick => (sort {uc($a) cmp uc($b)} keys %{ $chatter_groups{$channel} })[$_[1]{_bar_item_line}-1] }
- }
- else {
- $_[1]
- }
-}
-
-###############################################################################
-# Removes nicks from chatter list who idle for too long
-sub cleanup_chatters
-{
- my $changed = 0;
- my $nick_timeout = weechat::config_get_plugin("nick_timeout");
-
- foreach my $channel (keys %chatter_groups)
- {
- foreach my $nick (keys %{ $chatter_groups{$channel} })
- {
- if (time() - $chatter_groups{$channel}{$nick} >= $nick_timeout)
- {
- delete $chatter_groups{$channel}{$nick};
- $changed = 1;
- }
- }
- }
-
- if ($changed)
- {
- weechat::bar_item_update($chatters_bar_item_name);
- }
-}
-
-###############################################################################
-# Returns a key for use in chatter_groups
-sub buf_to_channel_key
-{
- my $buf = shift;
- my $server = weechat::buffer_get_string($buf, "localvar_server");
- my $channel = weechat::buffer_get_string($buf, "localvar_channel");
-
- return format_key($server, $channel);
-}
-
-###############################################################################
-# Formats a key out of server and channel to use in chatter_groups
-sub format_key
-{
- my $server = shift;
- my $channel = shift;
-
- # For unknown reason to me some channels have prepended #, some prepended ##
- # so the best to get rid of them to keep consistency
- $channel =~ /#*(.*)/;
- $channel = $1;
-
- return $server . "|" . $channel;
-}
-
-###############################################################################
-#
-sub _log
-{
- my $msg = shift;
-
- weechat::print("", "${script_name}: ${msg}\n");
-}
diff --git a/xbindkeys/.config/systemd/user/xbindkeys.service b/xbindkeys/.config/systemd/user/xbindkeys.service
new file mode 100644
index 0000000..d1f83e5
--- /dev/null
+++ b/xbindkeys/.config/systemd/user/xbindkeys.service
@@ -0,0 +1,9 @@
+[Service]
+ExecStart=/bin/sh -c '. ${HOME}/.config/sh/rc.d/00path && xbindkeys -p -n'
+Restart=always
+# otherwise any applications launched via a keybinding will be killed when
+# the service is restarted
+KillMode=process
+
+[Install]
+WantedBy=default.target
diff --git a/xbindkeysrc b/xbindkeys/.xbindkeysrc
index b9dbffb..caaac4b 100644
--- a/xbindkeysrc
+++ b/xbindkeys/.xbindkeysrc
@@ -1,4 +1,4 @@
-"alacritty"
+"env WINIT_X11_SCALE_FACTOR=1 alacritty"
Mod4 + o
"firefox"
@@ -10,7 +10,7 @@
"dmenu_run -fn 'Misc Fixed:pixelsize=14'"
Mod4 + r
-"light-locker-command -l"
+"xset s activate"
Mod4 + d
"numkeys toggle"
@@ -19,30 +19,33 @@
"numkeys toggle"
Shift + Shift_L
-"volume mute"
+"volume mute && pkill -USR1 i3status"
XF86AudioMute
-"volume down"
+"volume down && pkill -USR1 i3status"
XF86AudioLowerVolume
-"volume up"
+"volume up && pkill -USR1 i3status"
XF86AudioRaiseVolume
-"pactl set-source-mute 1 toggle"
+"pactl set-source-mute 5 toggle"
XF86AudioMicMute
-"xbacklight -dec 10"
+"backlight dec && pkill -USR1 i3status"
XF86MonBrightnessDown
-"xbacklight -inc 10"
+"backlight inc && pkill -USR1 i3status"
XF86MonBrightnessUp
-"xrandr --auto"
+"tv"
XF86Display
"[ $(rfkill --output type,soft | grep wlan | awk '{print $2}') = 'unblocked' ] && sudo rfkill block wlan || sudo rfkill unblock wlan"
XF86WLAN
+"env WINIT_X11_SCALE_FACTOR=1 tdrop -w 724 -h 436 alacritty --class Alacritty-tdrop -e tmux"
+ XF86Tools
+
"xset dpms force off"
XF86Search
diff --git a/xbindkeys/Makefile b/xbindkeys/Makefile
new file mode 100644
index 0000000..b89c717
--- /dev/null
+++ b/xbindkeys/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable xbindkeys
+ @systemctl --user start xbindkeys
+
+uninstall:
+ @systemctl --user stop xbindkeys
+ @systemctl --user disable xbindkeys
diff --git a/xcape/.config/systemd/user/xcape.service b/xcape/.config/systemd/user/xcape.service
new file mode 100644
index 0000000..7b5a384
--- /dev/null
+++ b/xcape/.config/systemd/user/xcape.service
@@ -0,0 +1,7 @@
+[Service]
+ExecStart=xcape -d -e 'Control_L=Escape;Control_R=Escape'
+StandardOutput=null
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/xcape/Makefile b/xcape/Makefile
new file mode 100644
index 0000000..7d03634
--- /dev/null
+++ b/xcape/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable xcape
+ @systemctl --user start xcape
+
+uninstall:
+ @systemctl --user stop xcape
+ @systemctl --user disable xcape
diff --git a/Xdefaults b/xorg/.Xdefaults
index 71e1a51..71e1a51 100644
--- a/Xdefaults
+++ b/xorg/.Xdefaults
diff --git a/xorg/.Xmodmap b/xorg/.Xmodmap
new file mode 100644
index 0000000..8225271
--- /dev/null
+++ b/xorg/.Xmodmap
@@ -0,0 +1,38 @@
+! reset state
+clear control
+clear mod1
+clear mod4
+
+! swap alt and control
+keycode 37 = Alt_L Meta_L
+keycode 64 = Control_L
+keycode 105 = Alt_R Meta_R
+keycode 108 = Control_R
+
+! map prtsc to super, because the thinkpad layout puts it in that location
+keycode 107 = Super_R
+
+! set the values for control, mod1 (meta), and mod4 (super) now that they have
+! been assigned to keycodes
+add control = Control_L Control_R
+add mod1 = Alt_L Alt_R Meta_L Meta_R
+add mod4 = Super_L Super_R
+
+! map home and end to insert, because the thinkpad layout puts them where
+! insert should be
+keycode 110 = Insert
+keycode 115 = Insert
+
+! use media keys instead of function keys
+keycode 67 = XF86AudioMute
+keycode 68 = XF86AudioLowerVolume
+keycode 69 = XF86AudioRaiseVolume
+keycode 70 = XF86AudioMicMute
+keycode 71 = XF86MonBrightnessDown
+keycode 72 = XF86MonBrightnessUp
+keycode 73 = XF86Display
+keycode 74 = XF86WLAN
+keycode 75 = XF86Tools
+keycode 76 = XF86Search
+keycode 95 = XF86LaunchA
+keycode 96 = XF86Explorer
diff --git a/xinitrc b/xorg/.xinitrc
index 8d6d364..088ac3d 100644
--- a/xinitrc
+++ b/xorg/.xinitrc
@@ -1,6 +1,6 @@
#!/bin/sh
-# shellcheck source=xprofile
+# shellcheck source=xorg/.xprofile
[ -f ~/.xprofile ] && . ~/.xprofile
exec i3
diff --git a/xorg/.xprofile b/xorg/.xprofile
new file mode 100644
index 0000000..8f968f8
--- /dev/null
+++ b/xorg/.xprofile
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# shellcheck disable=SC1091
+. "${HOME}/.config/sh/rc.d/00path"
+
+eval "$(ssh-agent)"
+
+setup-inputs
+
+xset s 300 5
diff --git a/xprofile b/xprofile
deleted file mode 100644
index 4213a9c..0000000
--- a/xprofile
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-start-pulseaudio-x11
-
-eval "$(ssh-agent)"
-
-pidof svscan || (svscan "$HOME"/.services/enabled 2>&1 | readproctitle "$USER" ........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................) &
-
-setup-inputs
diff --git a/bin/on-lock b/xss-lock/.bin/on-lock
index b9fa1fe..3de3724 100755
--- a/bin/on-lock
+++ b/xss-lock/.bin/on-lock
@@ -3,3 +3,4 @@
sudo -K
ssh-add -D
echo RELOADAGENT | gpg-connect-agent
+type rbw >/dev/null 2>&1 && rbw lock
diff --git a/xss-lock/.config/systemd/user/xss-lock.service b/xss-lock/.config/systemd/user/xss-lock.service
new file mode 100644
index 0000000..8885dfc
--- /dev/null
+++ b/xss-lock/.config/systemd/user/xss-lock.service
@@ -0,0 +1,6 @@
+[Service]
+ExecStart=xss-lock -n /usr/lib/xsecurelock/dimmer -l -- sh -c 'on-lock; env XSECURELOCK_BLANK_TIMEOUT=1 XSECURELOCK_SHOW_DATETIME=1 xsecurelock'
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/xss-lock/Makefile b/xss-lock/Makefile
new file mode 100644
index 0000000..ae8dbc8
--- /dev/null
+++ b/xss-lock/Makefile
@@ -0,0 +1,9 @@
+include ../Makefile.include
+
+install:
+ @systemctl --user enable xss-lock
+ @systemctl --user start xss-lock
+
+uninstall:
+ @systemctl --user stop xss-lock
+ @systemctl --user disable xss-lock
diff --git a/zsh/.config/zsh/zsh-autosuggestions b/zsh/.config/zsh/zsh-autosuggestions
new file mode 160000
+Subproject c3d4e576c9c86eac62884bd47c01f6faed043fc
diff --git a/zsh/.config/zsh/zsh-completions b/zsh/.config/zsh/zsh-completions
new file mode 160000
+Subproject 83cbd8108261e3285b0744f4d412f68525dd18e
diff --git a/zsh/.config/zsh/zsh-syntax-highlighting b/zsh/.config/zsh/zsh-syntax-highlighting
new file mode 160000
+Subproject e0165eaa730dd0fa321a6a6de74f092fe87630b
diff --git a/zshcomplete b/zsh/.zshcomplete
index 0198f58..fa206b4 100644
--- a/zshcomplete
+++ b/zsh/.zshcomplete
@@ -19,3 +19,8 @@ bashcompinit
# End of lines added by compinstall
source ~/.config/sh/fzf/shell/completion.zsh
+type kubectl >/dev/null 2>&1 && source <(kubectl completion zsh)
+if type steampipe >/dev/null 2>&1; then
+ source <(steampipe completion zsh)
+ compdef _steampipe steampipe
+fi
diff --git a/zshinput b/zsh/.zshinput
index 3ab9ac4..ada9a5e 100644
--- a/zshinput
+++ b/zsh/.zshinput
@@ -12,31 +12,21 @@ bindkey "^[OB" history-beginning-search-forward-end
bindkey -M viins '^R' fzf-history-widget
bindkey -M vicmd '^R' fzf-history-widget
-bindkey -M vicmd '/' history-incremental-search-backward
-bindkey -M vicmd '?' history-incremental-search-forward
-bindkey -rM viins '^[/'
bindkey -M vicmd ')' vi-digit-or-beginning-of-line
bindkey -M vicmd 'e' vi-change
bindkey -M vicmd 'E' vi-change-eol
-bindkey -M vicmd ',' execute-named-cmd
-bindkey -M vicmd '!' vi-insert
bindkey -M vicmd '_' vi-first-non-blank
bindkey -M vicmd '|' send-break
-bindkey -M vicmd '\' send-break
bindkey "^?" backward-delete-char
bindkey "^H" backward-delete-char
-bindkey "^U" backward-kill-line
-
-bindkey "^[[3~" delete-char
+bindkey -M viins "^[[3~" delete-char
+bindkey -M vicmd "^[[3~" delete-char
page-up-within-tmux() {
if [[ $TMUX == '' ]]; then
- # no-op; default behavior isn't useful, and anyway you don't want to do
- # something TOO cool here since you won't be able to do it inside tmux.
- # TODO if there's any way to command the /emu/ to scroll up one page, i
- # would love to hear about it
+ :
else
tmux copy-mode -u
fi
diff --git a/zsh/.zshrc b/zsh/.zshrc
new file mode 100644
index 0000000..5bd948b
--- /dev/null
+++ b/zsh/.zshrc
@@ -0,0 +1,77 @@
+for file in ~/.config/sh/rc.d/*; do
+ # shellcheck disable=SC1090
+ source "$file"
+done
+# completion {{{
+# shellcheck disable=SC2206
+fpath=( \
+ "${HOME}/.config/zsh/local-completions/$(hostname)" \
+ "${HOME}/.config/zsh/local-completions" \
+ "${HOME}/.config/zsh/zsh-completions/src" \
+ $fpath \
+)
+# shellcheck source=zsh/.zshcomplete
+source ~/.zshcomplete
+# }}}
+# zsh configuration {{{
+# shellcheck source=zsh/.zshinput
+source ~/.zshinput
+autoload -U colors
+colors
+setopt incappendhistory
+setopt extendedhistory
+setopt histignoredups
+setopt noclobber
+setopt nobeep
+setopt completeinword
+setopt correct
+export HISTFILE=$HOME/.zsh_history
+export HISTSIZE=1000000000
+export SAVEHIST=1000000000
+# shellcheck disable=SC2154
+export SPROMPT="Correct ${fg[red]}%R$reset_color to ${fg[green]}%r$reset_color? [ynae] "
+export KEYTIMEOUT=5
+# plugins {{{
+# zsh-syntax-highlighting {{{
+# shellcheck disable=SC2154,SC2034
+{
+ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets)
+# shellcheck source=zsh/.config/zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
+# shellcheck disable=SC1094
+source ~/.config/zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
+ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=green'
+ZSH_HIGHLIGHT_STYLES[alias]='fg=green'
+ZSH_HIGHLIGHT_STYLES[builtin]='fg=green'
+ZSH_HIGHLIGHT_STYLES[function]='fg=green'
+ZSH_HIGHLIGHT_STYLES[command]='fg=green'
+ZSH_HIGHLIGHT_STYLES[precommand]='fg=yellow'
+ZSH_HIGHLIGHT_STYLES[hashed-command]='fg=green'
+ZSH_HIGHLIGHT_STYLES[path]='fg=blue,bold'
+ZSH_HIGHLIGHT_STYLES[path_prefix]='fg=blue,underline'
+ZSH_HIGHLIGHT_STYLES[path_approx]='underline'
+ZSH_HIGHLIGHT_STYLES[globbing]='fg=magenta'
+ZSH_HIGHLIGHT_STYLES[history-expansion]='none'
+ZSH_HIGHLIGHT_STYLES[back-quoted-argument]='fg=green'
+ZSH_HIGHLIGHT_STYLES[assign]='fg=cyan'
+}
+# }}}
+# zsh-autosuggestions {{{
+# shellcheck source=zsh/.config/zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
+# shellcheck disable=SC1094
+source ~/.config/zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
+# shellcheck disable=SC2034
+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=black,bold'
+# see https://github.com/zsh-users/zsh-autosuggestions/issues/619
+unset ZSH_AUTOSUGGEST_USE_ASYNC
+# }}}
+# }}}
+# prompt {{{
+if type starship > /dev/null 2>&1; then
+ eval "$(starship init zsh)"
+fi
+# }}}
+# }}}
+# fortune {{{
+fortune -n600 -s ~/.local/share/fortune | grep -v -E "^$"
+# }}}
+# vim: fdm=marker
diff --git a/zshrc b/zshrc
deleted file mode 100644
index 26d8996..0000000
--- a/zshrc
+++ /dev/null
@@ -1,103 +0,0 @@
-# language environments {{{
-test -f $HOME/perl5/perlbrew/etc/bashrc && source $HOME/perl5/perlbrew/etc/bashrc
-test -f $HOME/python/bin/activate && source $HOME/python/bin/activate
-type rbenv > /dev/null 2>&1 && eval "$(rbenv init -)"
-test -d $HOME/.cargo/bin && export PATH="$HOME/.cargo/bin:$PATH"
-# }}}
-# environment {{{
-# not using .zshenv, because it runs before /etc/profile, and /etc/profile
-# tends to hard-set $PATH and such
-[ -d /usr/share/git/diff-highlight ] && export PATH="/usr/share/git/diff-highlight:${PATH}"
-[ -d /usr/local/share/git-core/contrib/diff-highlight ] && export PATH="/usr/local/share/git-core/contrib/diff-highlight:${PATH}"
-export PATH="${HOME}/.bin/local:${HOME}/.bin/$(hostname):${HOME}/.bin:/usr/lib/ccache/bin:$PATH"
-[ -f "$HOME/.config/sh/env" ] && source $HOME/.config/sh/env
-# }}}
-# Change the window title of X terminals {{{
-function term_title_precmd () {
- echo -ne "\033]0;${USER}@${HOST}:${PWD/$HOME/~}\007"
-}
-case ${TERM} in
- xterm*|rxvt*|Eterm|aterm|kterm|gnome|screen*)
- precmd_functions+=(term_title_precmd)
- ;;
-esac # }}}
-# aliases {{{
-[ -f "$HOME/.config/sh/aliases" ] && source $HOME/.config/sh/aliases
-[ -f "$HOME/.config/sh/functions" ] && source $HOME/.config/sh/functions
-# }}}
-# completion {{{
-fpath=(~/.config/zsh/local-completions/$(hostname) ~/.config/zsh/local-completions ~/.config/zsh/zsh-completions/src $fpath)
-source ~/.zshcomplete
-# }}}
-# zsh configuration {{{
-source ~/.zshinput
-autoload -U colors
-colors
-setopt incappendhistory
-setopt extendedhistory
-setopt histignoredups
-setopt noclobber
-setopt nobeep
-setopt completeinword
-setopt correct
-export REPORTTIME=120
-export HISTFILE=$HOME/.zsh_history
-export HISTSIZE=1000000000
-export SAVEHIST=1000000000
-export SPROMPT="Correct $fg[red]%R$reset_color to $fg[green]%r$reset_color? [ynae] "
-export KEYTIMEOUT=5
-# plugins {{{
-# cdhist {{{
-source ~/.config/sh/cdhist.sh
-# }}}
-# zsh-syntax-highlighting {{{
-ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets)
-source ~/.config/zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
-ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=green'
-ZSH_HIGHLIGHT_STYLES[alias]='fg=green'
-ZSH_HIGHLIGHT_STYLES[builtin]='fg=green'
-ZSH_HIGHLIGHT_STYLES[function]='fg=green'
-ZSH_HIGHLIGHT_STYLES[command]='fg=green'
-ZSH_HIGHLIGHT_STYLES[precommand]='fg=yellow'
-ZSH_HIGHLIGHT_STYLES[hashed-command]='fg=green'
-ZSH_HIGHLIGHT_STYLES[path]='fg=blue,bold'
-ZSH_HIGHLIGHT_STYLES[path_prefix]='fg=blue,underline'
-ZSH_HIGHLIGHT_STYLES[path_approx]='underline'
-ZSH_HIGHLIGHT_STYLES[globbing]='fg=magenta'
-ZSH_HIGHLIGHT_STYLES[history-expansion]='none'
-ZSH_HIGHLIGHT_STYLES[back-quoted-argument]='fg=green'
-ZSH_HIGHLIGHT_STYLES[assign]='fg=cyan'
-# }}}
-# zsh-autosuggestions {{{
-source ~/.config/zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
-ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=black,bold'
-# }}}
-# vim-history-sync {{{
-source ~/.vim/pack/plugins/start/history-sync/sh/history-sync.zsh
-# }}}
-# }}}
-# prompt {{{
-if type fancy-prompt > /dev/null 2>&1; then
- function shell_prompt_precmd () {
- PROMPT=`fancy-prompt --prompt-escape zsh $?`
- RPS1=''
- }
- precmd_functions+=(shell_prompt_precmd)
-fi
-function zle-keymap-select () {
- setopt localoptions no_ksharrays
- { [[ "${@[2]-main}" == opp ]] } && return
- if [[ "x$KEYMAP" == 'xmain' ]]; then
- RPS1=''
- else
- RPS1="%{$fg_bold[yellow]%}[${KEYMAP/vicmd/NORMAL}]%{$reset_color%}"
- fi
- zle reset-prompt
-}
-zle -N zle-keymap-select
-# }}}
-# }}}
-# fortune {{{
-fortune -n600 -s ~/.local/share/fortune | grep -v -E "^$"
-# }}}
-# vim: fdm=marker