nix

configuration files that power my machines
Log | Files | Refs | README | LICENSE

commit 2e6903d1b4bd26d5caeb329c8a8bb7f9451acd1d
Author: mtmn <miro@haravara.org>
Date:   Mon,  6 Apr 2026 19:38:27 +0200

init: move out of internal repo

Diffstat:
A.git-crypt/.gitattributes | 4++++
A.git-crypt/keys/default/0/AA1EDFF6365A4B0B1D7EE17365461E10605531F2.gpg | 0
A.gitattributes | 13+++++++++++++
A.gitignore | 3+++
A.pre-commit-config.yaml | 40++++++++++++++++++++++++++++++++++++++++
AREADME.md | 32++++++++++++++++++++++++++++++++
Aflake.lock | 262+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aflake.nix | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahack/disk-config.nix | 42++++++++++++++++++++++++++++++++++++++++++
Ahack/install_anywhere | 46++++++++++++++++++++++++++++++++++++++++++++++
Ahack/run_nix_du | 2++
Ahome.nix | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts.nix | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/nixaran/configuration.nix | 0
Ahosts/nixaran/disk-config.nix | 0
Ahosts/nixaran/flake.lock | 0
Ahosts/nixaran/flake.nix | 0
Ahosts/nixaran/hardware-configuration.nix | 0
Ahosts/proton/default.nix | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/proton/overlays/bin/.gitkeep | 0
Ahosts/proton/overlays/config/ghostty/config | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/proton/overlays/default.nix | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/proton/overlays/home/.gitkeep | 0
Ahosts/proton/overlays/local/.gitkeep | 0
Ahosts/void/default.nix | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/void/overlays/bin/.gitkeep | 0
Ahosts/void/overlays/bin/rinit | 3+++
Ahosts/void/overlays/config/.gitkeep | 0
Ahosts/void/overlays/config/battery-notify/config.toml | 6++++++
Ahosts/void/overlays/config/shell/void | 0
Ahosts/void/overlays/default.nix | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/void/overlays/home/.gitkeep | 0
Ahosts/void/overlays/local/.gitkeep | 0
Ahosts/wsl/default.nix | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/wsl/overlays/bin/.gitkeep | 0
Ahosts/wsl/overlays/config/.gitkeep | 0
Ahosts/wsl/overlays/config/ghostty/config | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/wsl/overlays/default.nix | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahosts/wsl/overlays/home/.gitkeep | 0
Ahosts/wsl/overlays/local/.gitkeep | 0
Ajustfile | 36++++++++++++++++++++++++++++++++++++
Amodules/mixins/default.nix | 5+++++
Amodules/mixins/dotfiles/bin/amen-or-not | 22++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/blissify | 4++++
Amodules/mixins/dotfiles/bin/btmenu | 38++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/clipmenu | 7+++++++
Amodules/mixins/dotfiles/bin/dedupli | 19+++++++++++++++++++
Amodules/mixins/dotfiles/bin/dnsleak | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/ff2mpv | 14++++++++++++++
Amodules/mixins/dotfiles/bin/ffpurge | 222+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/git-diff-upstream | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/git-id | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/git-list | 202+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/git-number | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/gotcover | 21+++++++++++++++++++++
Amodules/mixins/dotfiles/bin/habitual | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/hakuna | 2++
Amodules/mixins/dotfiles/bin/harper_dict_update | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/huemenu | 37+++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/langmenu | 26++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/meq | 3+++
Amodules/mixins/dotfiles/bin/moshrc | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/mpc | 3+++
Amodules/mixins/dotfiles/bin/napkins | 11+++++++++++
Amodules/mixins/dotfiles/bin/ncm | 3+++
Amodules/mixins/dotfiles/bin/nota | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/nsxiv-rifle | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/passmenu | 26++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/pinentry-bemenu | 2++
Amodules/mixins/dotfiles/bin/plsmenu | 34++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/ptn | 2++
Amodules/mixins/dotfiles/bin/qw | 9+++++++++
Amodules/mixins/dotfiles/bin/reaktor | 9+++++++++
Amodules/mixins/dotfiles/bin/reaper | 8++++++++
Amodules/mixins/dotfiles/bin/record | 4++++
Amodules/mixins/dotfiles/bin/recup | 10++++++++++
Amodules/mixins/dotfiles/bin/remind | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/screenshot | 41+++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/scup | 9+++++++++
Amodules/mixins/dotfiles/bin/seek | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/sft | 2++
Amodules/mixins/dotfiles/bin/speedread | 283+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/sshrc | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/tempmenu | 24++++++++++++++++++++++++
Amodules/mixins/dotfiles/bin/todo-notify | 14++++++++++++++
Amodules/mixins/dotfiles/bin/todomenu | 6++++++
Amodules/mixins/dotfiles/bin/tw | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/aerc/aerc.conf | 33+++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/aerc/binds.conf | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/aerc/stylesets/mine | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/bash/.keep | 0
Amodules/mixins/dotfiles/config/bash/rc/.keep | 0
Amodules/mixins/dotfiles/config/bash/rc/completion | 7+++++++
Amodules/mixins/dotfiles/config/bash/rc/history | 9+++++++++
Amodules/mixins/dotfiles/config/bash/rc/options | 5+++++
Amodules/mixins/dotfiles/config/bat/config | 2++
Amodules/mixins/dotfiles/config/bat/themes/magnolia.tmTheme | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/battery-notify/config.toml | 6++++++
Amodules/mixins/dotfiles/config/bcrc | 1+
Amodules/mixins/dotfiles/config/dunst/dunstrc | 47+++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/eza | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/foot/foot.ini | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/gtk-3.0/settings.ini | 17+++++++++++++++++
Amodules/mixins/dotfiles/config/gtk-4.0/settings.ini | 17+++++++++++++++++
Amodules/mixins/dotfiles/config/helix/config.toml | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/helix/languages.toml | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/helix/themes/mine.toml | 2++
Amodules/mixins/dotfiles/config/iamb/config.toml | 3+++
Amodules/mixins/dotfiles/config/jj/config.toml | 48++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/kanshi/config | 18++++++++++++++++++
Amodules/mixins/dotfiles/config/khal/config.nix | 18++++++++++++++++++
Amodules/mixins/dotfiles/config/magdalena/config.json.nix | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/mpv/input.conf | 16++++++++++++++++
Amodules/mixins/dotfiles/config/mpv/mpv.conf | 36++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/ncmpcpp/bindings | 22++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nota | 3+++
Amodules/mixins/dotfiles/config/nvim/README.md | 22++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/aliases.fnl | 21+++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/config/blink.fnl | 21+++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/config/lsp.fnl | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/config/treesitter.fnl | 24++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/flsproject.fnl | 17+++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/functions.fnl | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/init.fnl | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/fnl/keymaps.fnl | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/init_.vim | 3+++
Amodules/mixins/dotfiles/config/nvim/lua/std/_base.lua | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/debug.lua | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/functional/_base.lua | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/functional/init.lua | 883+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/functional/operator.lua | 239+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/functional/tuple.lua | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/init.lua | 389+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/io.lua | 322+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/math.lua | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/normalize/init.lua | 1342+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/package.lua | 263+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/string.lua | 504+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/nvim/lua/std/table.lua | 439+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/offpunk/offpunkrc | 4++++
Amodules/mixins/dotfiles/config/pipewire/client.conf.d/resample.conf | 3+++
Amodules/mixins/dotfiles/config/plants/devices.toml | 17+++++++++++++++++
Amodules/mixins/dotfiles/config/psi-notify | 6++++++
Amodules/mixins/dotfiles/config/rclone/rclone.conf | 4++++
Amodules/mixins/dotfiles/config/river/init | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/.keep | 0
Amodules/mixins/dotfiles/config/shell/early-funcs | 18++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/profile/.keep | 0
Amodules/mixins/dotfiles/config/shell/profile/environment | 26++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/profile/fzf | 10++++++++++
Amodules/mixins/dotfiles/config/shell/profile/less | 19+++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/profile/nix | 4++++
Amodules/mixins/dotfiles/config/shell/profile/woodpecker | 6++++++
Amodules/mixins/dotfiles/config/shell/rc/.keep | 0
Amodules/mixins/dotfiles/config/shell/rc/aliased-short-names | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/rc/command_overrides | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/rc/functions | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/rc/git | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/rc/jujutsu | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/rc/prompt-functions | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/shell/rc/stty | 3+++
Amodules/mixins/dotfiles/config/shell/rc/todo | 21+++++++++++++++++++++
Amodules/mixins/dotfiles/config/twitch/channels | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/vifm/colors/ef_tritanopia_dark | 47+++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/vifm/vifmrc | 2++
Amodules/mixins/dotfiles/config/xdg-desktop-portal/portals.conf | 3+++
Amodules/mixins/dotfiles/config/yt-dlp/config.nix | 3+++
Amodules/mixins/dotfiles/config/zed/settings-nix.json | 37+++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zed/themes/doris-dark.json | 402+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/.keep | 0
Amodules/mixins/dotfiles/config/zsh/completion/_bazel | 341+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/twitch | 25+++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zoxide | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.editorconfig | 10++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.travis.yml | 35+++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.zunit.yml | 8++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/LICENSE | 22++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/README.md | 249+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/autopair.plugin.zsh | 4++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/autopair.zsh | 227+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/_support/bootstrap | 15+++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/balanced-p.zunit | 16++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-delete-p.zunit | 24++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-pair-p.zunit | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-skip-p.zunit | 25+++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/get-pair.zunit | 26++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/zsh-autopair.plugin.zsh | 4++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/LICENSE | 21+++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/README.org | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/db_migrations/0to2.sql | 30++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-interactive.zsh | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-merge | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-migrate | 27+++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/sqlite-history.zsh | 503+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/zsh-histdb.plugin.zsh | 1+
Amodules/mixins/dotfiles/config/zsh/rc/.keep | 0
Amodules/mixins/dotfiles/config/zsh/rc/completion | 29+++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/functions | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/global_aliases | 11+++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/history | 8++++++++
Amodules/mixins/dotfiles/config/zsh/rc/keybindings | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/magdalena | 17+++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/options | 19+++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/plugins | 36++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/config/zsh/rc/prompt | 4++++
Amodules/mixins/dotfiles/default.nix | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/G | 35+++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/NextSlide | 3+++
Amodules/mixins/dotfiles/home/ad/bin/PrevSlide | 3+++
Amodules/mixins/dotfiles/home/ad/bin/Slide | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/cs | 42++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/fmt | 22++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/indent | 7+++++++
Amodules/mixins/dotfiles/home/ad/bin/lint | 27+++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/mount-ad | 6++++++
Amodules/mixins/dotfiles/home/ad/bin/rust-check | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/toggle-comment | 45+++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/bin/unindent | 7+++++++
Amodules/mixins/dotfiles/home/ad/bin/wd | 15+++++++++++++++
Amodules/mixins/dotfiles/home/ad/colorschemes/default_dark.toml | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/colorschemes/default_light.toml | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/colorschemes/doric_dark.toml | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/config.toml | 210+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/lib/ad.sh | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/lib/ftype-comment-chars.txt | 15+++++++++++++++
Amodules/mixins/dotfiles/home/ad/plumbing.rules | 45+++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/ad/syntax/ad.toml | 2++
Amodules/mixins/dotfiles/home/ad/syntax/plumbing-rules.toml | 3+++
Amodules/mixins/dotfiles/home/ad/syntax/txtar.toml | 1+
Amodules/mixins/dotfiles/home/atoprc | 1+
Amodules/mixins/dotfiles/home/bash_profile | 11+++++++++++
Amodules/mixins/dotfiles/home/bashrc | 13+++++++++++++
Amodules/mixins/dotfiles/home/cargo/config.toml | 13+++++++++++++
Amodules/mixins/dotfiles/home/curlrc | 8++++++++
Amodules/mixins/dotfiles/home/gitconfig | 46++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/gnupg/gpg-agent.conf | 3+++
Amodules/mixins/dotfiles/home/gtkrc-2.0 | 15+++++++++++++++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursor.theme | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/00008160000006810000408080010102 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/028006030e0e7ebffc7f7070c0600140 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/03b6e0fcb3499374a867c041f52298f0 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/08e8e1c95fe2fc01f976f1e063a24ccd | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/1081e37283d90000800003c07f3ef6bf | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/14fef782d02440884392942c11205230 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/2870a09082c103050810ffdffffe0204 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/3085a0e285430894940527032f8b26df | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/3ecb610c1bf2410f44200f48c40d3599 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/4498f0e0c1937ffe01fd06f973665830 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/6407b0e94181790501fd1e167b474872 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/640fb0e74195791501fd1ed57b41487f | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/9081237383d90e509aa00f00170e968f | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/9d800788f1b08800ae810202380a0822 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/X_cursor | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/arrow | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bd_double_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_left_corner | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_right_corner | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_side | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_tee | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/c7088f0f3e6c8088236ef8e1e3e70000 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/circle | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/color-picker | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/copy | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/cross | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/cross_reverse | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/crossed_circle | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/crosshair | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/d9ce0ab605698f320427677b458ad60b | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/diamond_cross | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-ask | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-copy | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-link | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-move | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-none | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dot_box_mask | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dotbox | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/double_arrow | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draft_large | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draft_small | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draped_box | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/e29285e634086352946a0e7090d73106 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fcf1c3c7cd4491d801f1e1c78f100000 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fd_double_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fleur | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/grabbing | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/h_double_arrow | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand1 | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand2 | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/help | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/icon | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr_help | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr_watch | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_side | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_tee | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/link | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ll_angle | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/lr_angle | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/move | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/pencil | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/pirate | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/plus | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/question_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_ptr | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_side | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_tee | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_down_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_h_double_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_left_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_right_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_up_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_v_double_arrow | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/target | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/tcross | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_left_arrow | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_left_corner | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_right_corner | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_side | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_tee | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ul_angle | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ur_angle | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/v_double_arrow | 2++
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/watch | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/xterm | 0
Amodules/mixins/dotfiles/home/icons/OSX-ElCap/index.theme | 3+++
Amodules/mixins/dotfiles/home/inputrc | 36++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/lftprc | 1+
Amodules/mixins/dotfiles/home/local/share/applications/nsxiv.desktop | 8++++++++
Amodules/mixins/dotfiles/home/ne/dot_keys | 17+++++++++++++++++
Amodules/mixins/dotfiles/home/ne/end-of-line | 1+
Amodules/mixins/dotfiles/home/ne/insert-done | 1+
Amodules/mixins/dotfiles/home/ne/insert-todo | 1+
Amodules/mixins/dotfiles/home/ne/replace-todo-with-done | 4++++
Amodules/mixins/dotfiles/home/python-version | 1+
Amodules/mixins/dotfiles/home/pythonrc | 31+++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/sshrc | 33+++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/sshrc.d/tmuxconf.nix | 3+++
Amodules/mixins/dotfiles/home/sshrc.d/vimrc.nix | 3+++
Amodules/mixins/dotfiles/home/tmux.conf | 47+++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/README.md | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_autumn.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_classic.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_dawn.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_day.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_dusk.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_fugit.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_future.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_night.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_past.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_rift.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_spring.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_summer.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_tempest.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_totus.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_warp.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vim/colors/tempus_winter.vim | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/vimrc | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/mixins/dotfiles/home/xinitrc | 7+++++++
Amodules/mixins/dotfiles/home/zprofile | 13+++++++++++++
Amodules/mixins/dotfiles/home/zshrc | 13+++++++++++++
Amodules/mixins/secrets.nix | 0
Amodules/nixos/base.nix | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/bandeno.nix | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/bazel-cache.nix | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/caddy.nix | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/cinny.nix | 32++++++++++++++++++++++++++++++++
Amodules/services/couchdb.nix | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/dex.nix | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/filestash.nix | 0
Amodules/services/forgejo.nix | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/headscale.nix | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/heisenbridge.nix | 24++++++++++++++++++++++++
Amodules/services/matrix.nix | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/monitord-exporter.lock | 2218+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/monitord.lock | 1664+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/monitoring.nix | 430+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/mtmn.nix | 0
Amodules/services/oauth2-proxy.nix | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/redlib.nix | 36++++++++++++++++++++++++++++++++++++
Amodules/services/searxng.nix | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/seaweedfs.nix | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/shirt-linkener.nix | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/services/storage-box.nix | 0
Asecrets.nix | 15+++++++++++++++
Asecrets/couchdb-admin-pass.age | 0
Asecrets/dex-client-secret.age | 0
Asecrets/grafana-secret-key.age | 0
Asecrets/headscale-api-key.age | 0
Asecrets/oauth2-proxy-client-secret.age | 0
Asecrets/oauth2-proxy-cookie-secret.age | 0
Asecrets/searx-secret-key.age | 0
Asecrets/storage-box-pass.age | 0
394 files changed, 25712 insertions(+), 0 deletions(-)

diff --git a/.git-crypt/.gitattributes b/.git-crypt/.gitattributes @@ -0,0 +1,4 @@ +# Do not edit this file. To specify the files to encrypt, create your own +# .gitattributes file in the directory where your files are. +* !filter !diff +*.gpg binary diff --git a/.git-crypt/keys/default/0/AA1EDFF6365A4B0B1D7EE17365461E10605531F2.gpg b/.git-crypt/keys/default/0/AA1EDFF6365A4B0B1D7EE17365461E10605531F2.gpg Binary files differ. diff --git a/.gitattributes b/.gitattributes @@ -0,0 +1,13 @@ +# modules +modules/services/filestash.nix filter=git-crypt diff=git-crypt +modules/mixins/secrets.nix filter=git-crypt diff=git-crypt +modules/services/mtmn.nix filter=git-crypt diff=git-crypt + +# hosts +hosts/void/overlays/config/shell/void filter=git-crypt diff=git-crypt +hosts/nixaran/* filter=git-crypt diff=git-crypt +hosts/work/* filter=git-crypt diff=git-crypt + +# misc +modules/mixins/dotfiles/bin/shirt filter=git-crypt diff=git-crypt +secrets/* filter=git-crypt diff=git-crypt diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +.crush +result +*.png diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml @@ -0,0 +1,40 @@ +--- +exclude: 'hardware-configuration\.nix$|^modules/mixins/dotfiles/config/(?:zsh/plugins|waybar/scripts)/' +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: double-quote-string-fixer + + - repo: https://github.com/biomejs/pre-commit + rev: v2.3.10 + hooks: + - id: biome-format + + - repo: https://github.com/gitleaks/gitleaks + rev: v8.30.0 + hooks: + - id: gitleaks + + - repo: https://github.com/astro/deadnix + rev: v1.3.0 + hooks: + - id: deadnix + + - repo: local + hooks: + - id: alejandra + name: alejandra + language: system + entry: alejandra + files: \.nix$ + + - repo: local + hooks: + - id: shellcheck + name: shellcheck + entry: shellcheck + language: system + types: [shell] diff --git a/README.md b/README.md @@ -0,0 +1,32 @@ +# nix + +NixOS and home-manager configurations for multiple systems. + +## Structure + +- **`hosts/`** - Machine-specific configurations (nixaran, void, proton, work, wsl) +- **`modules/`** - Reusable modules: + - **`services/`** - Service definitions (Forgejo, Matrix, Caddy, etc.) + - **`mixins/`** - Shared dotfiles and user configurations + +## Usage + +Commands are typically run via [just](https://github.com/casey/just), which wraps: + +```bash +# Validate flake +nix flake check + +# Apply home-manager configuration +nh home switch "<repo-path>" + +# Deploy to remote host +nix run github:serokell/deploy-rs .#<host> + +# Update flake.lock +nix flake update + +# Nix store and collection cleanup +nix-store --gc +nix-collect-garbage -d +``` diff --git a/flake.lock b/flake.lock @@ -0,0 +1,262 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1770165109, + "narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=", + "owner": "ryantm", + "repo": "agenix", + "rev": "b027ee29d959fda4b60b57566d64c98a202e0feb", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1744478979, + "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "43975d782b418ebf4969e9ccba82466728c2851b", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nixpkgs" + ], + "utils": "utils" + }, + "locked": { + "lastModified": 1770019181, + "narHash": "sha256-hwsYgDnby50JNVpTRYlF3UR/Rrpt01OrxVuryF40CFY=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "77c906c0ba56aabdbc72041bf9111b565cdd6171", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773889306, + "narHash": "sha256-PAqwnsBSI9SVC2QugvQ3xeYCB0otOwCacB1ueQj2tgw=", + "owner": "nix-community", + "repo": "disko", + "rev": "5ad85c82cc52264f4beddc934ba57f3789f28347", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1775143651, + "narHash": "sha256-S0RqAyDPMTcv9vASMaE8eY1QexFysAOdnxUxFHIPOyE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "d166a078541982a76f14d3e06e9665fa5c9ed85e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nix-index-database": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1774762074, + "narHash": "sha256-89Mh4Eb/5stVJX6kGagVMijcU2FmfeD8Qv7UXc5d92o=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "bc13aeaed568be76eab84df88ff39261bb52ff70", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1775095191, + "narHash": "sha256-CsqRiYbgQyv01LS0NlC7shwzhDhjNDQSrhBX8VuD3nM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "106eb93cbb9d4e4726bf6bc367a3114f7ed6b32f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "deploy-rs": "deploy-rs", + "disko": "disko", + "home-manager": "home-manager_2", + "nix-index-database": "nix-index-database", + "nixpkgs": "nixpkgs", + "tools": "tools" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "tools": { + "flake": false, + "locked": { + "lastModified": 1775211609, + "narHash": "sha256-30bmeRPr1dFwjcgtLZaHl36dtjRn3lIer1piSC1ySPk=", + "ref": "refs/heads/master", + "rev": "eb162916e0520824983022d79d4ca5483f499a8a", + "revCount": 839, + "type": "git", + "url": "ssh://forgejo@haravara.org/miro/tools.git" + }, + "original": { + "ref": "refs/heads/master", + "type": "git", + "url": "ssh://forgejo@haravara.org/miro/tools.git" + } + }, + "utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix @@ -0,0 +1,145 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + nix-index-database = { + url = "github:nix-community/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + deploy-rs = { + url = "github:serokell/deploy-rs"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + agenix = { + url = "github:ryantm/agenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + tools = { + url = "git+ssh://forgejo@haravara.org/miro/tools.git?ref=refs/heads/master"; + flake = false; + }; + }; + + outputs = { + self, + nixpkgs, + home-manager, + deploy-rs, + disko, + ... + } @ inputs: let + inherit (nixpkgs) lib; + configData = import ./hosts.nix; + + specialArgs = { + inherit inputs self configData; + }; + + nixosConfigurations = lib.mapAttrs (hostName: host: let + hostDir = ./hosts/${hostName}; + username = host.username or "miro"; + in + lib.nixosSystem { + inherit (host) system; + specialArgs = specialArgs // {inherit username;}; + modules = + [ + inputs.agenix.nixosModules.default + (hostDir + "/configuration.nix") + ] + ++ (lib.attrValues self.nixosModules) + ++ lib.optionals (host.disko or false) ( + [disko.nixosModules.disko] + ++ lib.optional (builtins.pathExists (hostDir + "/disk-config.nix")) (hostDir + "/disk-config.nix") + ); + }) + (lib.filterAttrs (_: host: host.nixos or false) configData.hosts); + + homeConfigurations = lib.concatMapAttrs (userName: user: + lib.mapAttrs' (hostName: config: let + host = configData.hosts.${hostName}; + username = host.username or userName; + homeDirectory = + if lib.hasInfix "darwin" host.system + then "/Users/${username}" + else "/home/${username}"; + in + lib.nameValuePair "${username}@${hostName}" ( + home-manager.lib.homeManagerConfiguration { + pkgs = nixpkgs.legacyPackages.${host.system}; + extraSpecialArgs = specialArgs // {inherit username homeDirectory;}; + modules = [./home.nix] ++ (config.pkgSets or []); + } + )) + user.configs) + configData.users; + + deployNodes = + lib.mapAttrs (hostName: host: let + username = host.username or "miro"; + in { + hostname = host.hostname or hostName; + sshUser = host.sshUser or username; + sshOpts = host.sshOpts or []; + profiles = + (lib.optionalAttrs (host.nixos or false) { + system = { + user = "root"; + path = deploy-rs.lib.${host.system}.activate.nixos nixosConfigurations.${hostName}; + }; + }) + // (let + homeName = "${username}@${hostName}"; + in + lib.optionalAttrs (homeConfigurations ? ${homeName}) { + "${username}" = { + user = username; + path = deploy-rs.lib.${host.system}.activate.home-manager homeConfigurations.${homeName}; + }; + }); + }) + configData.hosts; + in { + inherit nixosConfigurations homeConfigurations configData; + + nixosModules = { + base = import ./modules/nixos/base.nix; + cinny = import ./modules/services/cinny.nix; + monitoring = import ./modules/services/monitoring.nix; + caddy = import ./modules/services/caddy.nix; + mtmn = import ./modules/services/mtmn.nix; + forgejo = import ./modules/services/forgejo.nix; + matrix = import ./modules/services/matrix.nix; + dex = import ./modules/services/dex.nix; + redlib = import ./modules/services/redlib.nix; + seaweedfs = import ./modules/services/seaweedfs.nix; + filestash = import ./modules/services/filestash.nix; + heisenbridge = import ./modules/services/heisenbridge.nix; + couchdb = import ./modules/services/couchdb.nix; + oauth2-proxy = import ./modules/services/oauth2-proxy.nix; + storage-box = import ./modules/services/storage-box.nix; + bazel-cache = import ./modules/services/bazel-cache.nix; + shirt-linkener = import ./modules/services/shirt-linkener.nix; + bandeno = import ./modules/services/bandeno.nix; + headscale = import ./modules/services/headscale.nix; + searxng = import ./modules/services/searxng.nix; + }; + + deploy = { + nodes = deployNodes; + }; + }; +} diff --git a/hack/disk-config.nix b/hack/disk-config.nix @@ -0,0 +1,42 @@ +_: { + disko.devices = { + disk = { + main = { + device = "/dev/sda"; + type = "disk"; + content = { + type = "gpt"; + partitions = { + boot = { + name = "boot"; + size = "100M"; + type = "EF02"; + }; + root = { + name = "root"; + size = "100%"; + content = { + type = "btrfs"; + extraArgs = ["-f"]; + subvolumes = { + "@root" = { + mountOptions = ["compress=zstd" "noatime"]; + mountpoint = "/"; + }; + "@home" = { + mountOptions = ["compress=zstd" "noatime"]; + mountpoint = "/home"; + }; + "@nix" = { + mountOptions = ["compress=zstd" "noatime"]; + mountpoint = "/nix"; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hack/install_anywhere b/hack/install_anywhere @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +HOST_TARGET="${1:-}" + +if [[ -z "$HOST_TARGET" ]]; then + echo "Usage: $0 <hostname>" + exit 1 +fi + +HOST_DIR="hosts/$HOST_TARGET" +mkdir -p "$HOST_DIR" + +IS_DISKO=$(nix eval .#configData.hosts."$HOST_TARGET".disko --json 2>/dev/null || echo "false") + +if [[ "$IS_DISKO" == "true" && ! -f "$HOST_DIR/disk-config.nix" ]]; then + echo "Copying default disk-config.nix for $HOST_TARGET..." + cp ./disk-config.nix "$HOST_DIR/disk-config.nix" + git add "$HOST_DIR/disk-config.nix" +fi + +if [[ ! -f "$HOST_DIR/configuration.nix" ]]; then + echo "Creating bootstrap configuration.nix for $HOST_TARGET..." + cat >"$HOST_DIR/configuration.nix" <<EOF +{ ... }: { + imports = [ ./hardware-configuration.nix ]; + networking.hostName = "$HOST_TARGET"; + boot.loader.grub.enable = true; + boot.loader.grub.device = "nodev"; + system.stateVersion = "26.05"; +} +EOF + git add "$HOST_DIR/configuration.nix" +fi + +echo "Resolving IP for $HOST_TARGET..." +IP=$(nix eval .#deploy.nodes."$HOST_TARGET".hostname --raw) + +if ! ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 "root@$IP" "echo OK" >/dev/null 2>&1; then + exit 1 +fi + +nix run github:nix-community/nixos-anywhere -- \ + --flake ".#$HOST_TARGET" \ + --generate-hardware-config nixos-generate-config "$HOST_DIR/hardware-configuration.nix" \ + "root@$IP" diff --git a/hack/run_nix_du b/hack/run_nix_du @@ -0,0 +1,2 @@ +#!/bin/bash +nix-du -s 500M | dot -Tpng >"$(date +%Y-%m-%dT%H:%M:%S%Z)".png diff --git a/home.nix b/home.nix @@ -0,0 +1,52 @@ +{ + inputs, + lib, + pkgs, + username, + homeDirectory, + ... +}: { + imports = [ + inputs.nix-index-database.homeModules.default + ]; + + home = { + inherit username homeDirectory; + stateVersion = "26.05"; + }; + + news = { + display = "silent"; + json = lib.mkForce {}; + entries = lib.mkForce []; + }; + + manual = { + html.enable = false; + manpages.enable = false; + json.enable = false; + }; + + programs.home-manager.enable = true; + + nix = { + package = pkgs.nix; + distributedBuilds = true; + settings = { + auto-optimise-store = true; + warn-dirty = false; + experimental-features = ["nix-command" "flakes"]; + substituters = ["https://cache.nixos.org" "https://nix-community.cachix.org"]; + trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; + }; + registry.nixpkgs.flake = inputs.nixpkgs; + }; +} diff --git a/hosts.nix b/hosts.nix @@ -0,0 +1,51 @@ +{ + hosts = { + void = { + system = "x86_64-linux"; + }; + proton = { + system = "x86_64-linux"; + }; + nixaran = { + system = "x86_64-linux"; + hostname = "nixaran"; + nixos = true; + disko = true; + }; + work = import ./hosts/work/host.nix; + DESKTOP-0A5N7UT = { + system = "x86_64-linux"; + }; + }; + users = { + miro = { + authorizedKeys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEShZSmhIjIXf0DbFG8fZQFBy6CgDU2tFMMTAvCF5/ca" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILJH1fGikWCKXpp0RUqagYbAfpmDcVeAKUyYBTxoyLop" + ]; + configs = { + void = { + pkgSets = [ + ./modules/mixins/dotfiles + ./hosts/void/overlays + ./hosts/void + ]; + }; + proton = { + pkgSets = [ + ./modules/mixins/dotfiles + ./hosts/proton/overlays + ./hosts/proton + ]; + }; + DESKTOP-0A5N7UT = { + pkgSets = [ + ./modules/mixins/dotfiles + ./hosts/wsl/overlays + ./hosts/wsl + ]; + }; + }; + }; + }; +} diff --git a/hosts/nixaran/configuration.nix b/hosts/nixaran/configuration.nix Binary files differ. diff --git a/hosts/nixaran/disk-config.nix b/hosts/nixaran/disk-config.nix Binary files differ. diff --git a/hosts/nixaran/flake.lock b/hosts/nixaran/flake.lock Binary files differ. diff --git a/hosts/nixaran/flake.nix b/hosts/nixaran/flake.nix Binary files differ. diff --git a/hosts/nixaran/hardware-configuration.nix b/hosts/nixaran/hardware-configuration.nix Binary files differ. diff --git a/hosts/proton/default.nix b/hosts/proton/default.nix @@ -0,0 +1,198 @@ +{pkgs, ...}: let + core = with pkgs; [ + bat + eza + fd + fzf + neovim + ripgrep + moor + tmux + ncurses + tree-sitter + unzip + zoxide + pass + passExtensions.pass-otp + ]; + + utils = with pkgs; [ + borgbackup + fdupes + gocryptfs + inotify-tools + ncdu + restic + ansible + ansible-lint + awscli2 + hadolint + woodpecker-cli + tealdeer + libvarlink + bandit + ruff + shellcheck + shfmt + sops + zls + ]; + + data = with pkgs; [ + duckdb + gron + jaq + jless + jq + pandoc + slop + taplo + ]; + + vcs = with pkgs; [ + difftastic + git + git-bug + git-crypt + git-absorb + git-filter-repo + gitleaks + jujutsu + jjui + prek + ]; + + nix_tools = with pkgs; [ + alejandra + comma + deadnix + deploy-rs + nh + nil + nix-du + nixd + nixfmt + nixos-anywhere + nvd + ragenix + statix + ]; + + net_tools = with pkgs; [ + bore-cli + caddy + chisel + curl + dnscontrol + dnsmasq + hurl + inetutils + knot-dns + lftp + monolith + mosh + mosquitto + net-tools + newsraft + nmap + offpunk + rclone + rsync + sshfs + thrift + trickle + w3m + websocat + wget + whois + xh + ]; + + build_tools = with pkgs; [ + libgcc + bear + bmake + boost + clang + cmake + ctags + entr + just + act + lld + lldb + llvm + meson + mold + ninja + tre + libtermkey + ]; + + perf_utils = with pkgs; [ + bpftools + bpftrace + bpfmon + bpftop + libbpf + below + hyperfine + iotop + pwru + gdb + strace + perf + valgrind + aflplusplus + ]; + + beam28 = with pkgs.beam28Packages; [ + erlang + expert + rebar3 + ]; + + all = with pkgs; [ + babashka + biome + gleam + luaPackages.fennel + luaPackages.lpeg + fnlfmt + luarocks + bun + clj-kondo + clojure + gemini-cli-bin + qwen-code + deno + dune + go + gopls + leiningen + ocaml + # purescript + ]; +in { + programs.git = { + enable = true; + ignores = [ + ".crush/" + ".gemini/" + ".qwen/" + "AGENTS.md" + ]; + }; + + home.packages = + core + ++ utils + ++ data + ++ vcs + ++ nix_tools + ++ net_tools + ++ build_tools + ++ perf_utils + ++ beam28 + ++ all; +} diff --git a/hosts/proton/overlays/bin/.gitkeep b/hosts/proton/overlays/bin/.gitkeep diff --git a/hosts/proton/overlays/config/ghostty/config b/hosts/proton/overlays/config/ghostty/config @@ -0,0 +1,49 @@ +window-decoration = false + +scrollback-limit = 10000 +mouse-hide-while-typing = true + +font-family = "UW ttyp0" +font-size = 14 +font-style-bold = no-bold +font-style-bold-italic = no-bold-italic + +cursor-style = block +cursor-style-blink = false +cursor-color = #fd3333 +cursor-text = #15050f +shell-integration-features = no-cursor + +background = #000000 +foreground = #ffffff + +selection-background = #50447f +selection-foreground = #ffffff + +cursor-color = #ccaaee + +palette = 0=#332d38 +palette = 1=#eca28f +palette = 2=#b9d0aa +palette = 3=#c0b080 +palette = 4=#9fbfe7 +palette = 5=#e9acbf +palette = 6=#a0c0d0 +palette = 7=#ffffff +palette = 8=#332d38 +palette = 9=#eca28f +palette = 10=#b9d0aa +palette = 11=#c0b080 +palette = 12=#9fbfe7 +palette = 13=#e9acbf +palette = 14=#a0c0d0 +palette = 15=#ffffff + +keybind = ctrl+shift+c=copy_to_clipboard +keybind = ctrl+shift+v=paste_from_clipboard +keybind = shift+insert=paste_from_selection +keybind = ctrl+plus=increase_font_size:1 +keybind = ctrl+equal=increase_font_size:1 +keybind = ctrl+minus=decrease_font_size:1 +keybind = ctrl+0=reset_font_size +keybind = ctrl+shift+n=new_window diff --git a/hosts/proton/overlays/default.nix b/hosts/proton/overlays/default.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + inputs, + ... +}: let + date = inputs.self.lastModifiedDate or "19700101000000"; + year = lib.substring 0 4 date; + monthNum = lib.substring 4 2 date; + month = lib.elemAt [ + "january" + "february" + "march" + "april" + "may" + "june" + "july" + "august" + "september" + "october" + "november" + "december" + ] (lib.toInt (lib.removePrefix "0" monthNum) - 1); + + tmplArgs = { + inherit year month; + homeDir = config.home.homeDirectory; + }; + + mkMapping = path: prefix: let + scan = dir: rel: + lib.concatLists (lib.mapAttrsToList (name: type: let + newRel = + if rel == "" + then name + else "${rel}/${name}"; + newPath = dir + "/${name}"; + in + if type == "directory" + then scan newPath newRel + else [ + { + name = newRel; + path = newPath; + } + ]) + (builtins.readDir dir)); + in + builtins.listToAttrs (map (file: let + isNix = lib.hasSuffix ".nix" file.name; + target = prefix + (lib.removeSuffix ".nix" file.name); + in + lib.nameValuePair target ( + if isNix + then { + text = import file.path tmplArgs; + force = true; + } + else { + source = file.path; + force = true; + } + )) (scan path "")); +in { + config = { + home.file = lib.mapAttrs (_: lib.mkForce) ( + (mkMapping ./home ".") + // (lib.mapAttrs (_: v: v // {executable = true;}) (mkMapping ./bin "bin/")) + // (mkMapping ./local ".local/") + ); + + xdg.configFile = lib.mapAttrs (_: lib.mkForce) (mkMapping ./config ""); + + home.sessionPath = ["$HOME/bin"]; + }; +} diff --git a/hosts/proton/overlays/home/.gitkeep b/hosts/proton/overlays/home/.gitkeep diff --git a/hosts/proton/overlays/local/.gitkeep b/hosts/proton/overlays/local/.gitkeep diff --git a/hosts/void/default.nix b/hosts/void/default.nix @@ -0,0 +1,180 @@ +{pkgs, ...}: let + inherit (pkgs) lib; + + parts = { + utils = with pkgs; [ + libvarlink + bandit + ruff + shellcheck + shfmt + sops + zls + bear + bmake + ctags + entr + act + below + hyperfine + iotop + gdb + strace + perf + valgrind + aflplusplus + meson + ninja + cmake + moor + ]; + + mpd = with pkgs; [ + mpd + mpc + listenbrainz-mpd + libmpdclient + ashuffle + pms + ncmpcpp + mympd + clerk + sacad + ]; + + ops = with pkgs; [ + ansible + ansible-lint + awscli2 + hadolint + woodpecker-cli + ]; + + data = with pkgs; [ + duckdb + gron + jaq + jless + jq + pandoc + slop + taplo + datasette + ]; + + vcs = with pkgs; [ + difftastic + git-bug + git-crypt + git-absorb + git-filter-repo + gitleaks + jujutsu + jjui + prek + tig + ]; + + nix = with pkgs; [ + alejandra + comma + deadnix + deploy-rs + nh + nil + nix-du + nixd + nixfmt + nixos-anywhere + nvd + ragenix + statix + ]; + + net = with pkgs; [ + bore-cli + chisel + curl + dnscontrol + hurl + inetutils + lftp + monolith + mosh + mosquitto + net-tools + newsraft + nmap + offpunk + rclone + rsync + sshfs + thrift + trickle + w3m + websocat + wget + whois + xh + ]; + + bpf = with pkgs; [ + bpftools + bpftrace + bpfmon + bpftop + libbpf + pwru + ]; + + beam28 = with pkgs.beam28Packages; [ + erlang + rebar3 + expert + elixir_1_20 + ]; + + llm = with pkgs; [ + gemini-cli-bin + qwen-code + ]; + + lua = + (with pkgs.luaPackages; [ + luarocks + fennel + lua + ]) + ++ (with pkgs; [ + fnlfmt + ]); + + clj = with pkgs; [ + babashka + clojure + clj-kondo + leiningen + ]; + + go = with pkgs; [ + go + gopls + ]; + + ocaml = with pkgs; [ + ocaml + dune + ]; + + other = with pkgs; [ + biome + gleam + fnlfmt + bun + deno + # purescript + ]; + }; +in { + home.packages = lib.concatLists (lib.attrValues parts); +} diff --git a/hosts/void/overlays/bin/.gitkeep b/hosts/void/overlays/bin/.gitkeep diff --git a/hosts/void/overlays/bin/rinit b/hosts/void/overlays/bin/rinit @@ -0,0 +1,3 @@ +#!/bin/bash +keychain --eval --ssh-agent-socket "$XDG_RUNTIME_DIR/ssh-agent.socket" +dbus-run-session -- river 2>&1 | vlogger -t river-classic diff --git a/hosts/void/overlays/config/.gitkeep b/hosts/void/overlays/config/.gitkeep diff --git a/hosts/void/overlays/config/battery-notify/config.toml b/hosts/void/overlays/config/battery-notify/config.toml @@ -0,0 +1,6 @@ +sleep_command = "sudo zzz" +interval_secs = 30 +sleep_pct = 15 +low_pct = 40 +warn_on_mons_with_no_ac = 0 +bluetooth_low_pct = 40 diff --git a/hosts/void/overlays/config/shell/void b/hosts/void/overlays/config/shell/void Binary files differ. diff --git a/hosts/void/overlays/default.nix b/hosts/void/overlays/default.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + inputs, + ... +}: let + date = inputs.self.lastModifiedDate or "19700101000000"; + year = lib.substring 0 4 date; + monthNum = lib.substring 4 2 date; + month = lib.elemAt [ + "january" + "february" + "march" + "april" + "may" + "june" + "july" + "august" + "september" + "october" + "november" + "december" + ] (lib.toInt (lib.removePrefix "0" monthNum) - 1); + + tmplArgs = { + inherit year month; + homeDir = config.home.homeDirectory; + }; + + mkMapping = path: prefix: let + scan = dir: rel: + lib.concatLists (lib.mapAttrsToList (name: type: let + newRel = + if rel == "" + then name + else "${rel}/${name}"; + newPath = dir + "/${name}"; + in + if type == "directory" + then scan newPath newRel + else [ + { + name = newRel; + path = newPath; + } + ]) + (builtins.readDir dir)); + in + builtins.listToAttrs (map (file: let + isNix = lib.hasSuffix ".nix" file.name; + target = prefix + (lib.removeSuffix ".nix" file.name); + in + lib.nameValuePair target ( + if isNix + then { + text = import file.path tmplArgs; + force = true; + } + else { + source = file.path; + force = true; + } + )) (scan path "")); +in { + config = { + home.file = lib.mapAttrs (_: lib.mkForce) ( + (mkMapping ./home ".") + // (lib.mapAttrs (_: v: v // {executable = true;}) (mkMapping ./bin "bin/")) + // (mkMapping ./local ".local/") + ); + + xdg.configFile = lib.mapAttrs (_: lib.mkForce) (mkMapping ./config ""); + + home.sessionPath = ["$HOME/bin"]; + }; +} diff --git a/hosts/void/overlays/home/.gitkeep b/hosts/void/overlays/home/.gitkeep diff --git a/hosts/void/overlays/local/.gitkeep b/hosts/void/overlays/local/.gitkeep diff --git a/hosts/wsl/default.nix b/hosts/wsl/default.nix @@ -0,0 +1,198 @@ +{pkgs, ...}: let + core = with pkgs; [ + bat + eza + fd + fzf + neovim + ripgrep + moor + tmux + ncurses + tree-sitter + unzip + zoxide + pass + passExtensions.pass-otp + ]; + + utils = with pkgs; [ + borgbackup + fdupes + gocryptfs + inotify-tools + ncdu + restic + ansible + ansible-lint + awscli2 + hadolint + woodpecker-cli + tealdeer + libvarlink + bandit + ruff + shellcheck + shfmt + sops + zls + ]; + + data = with pkgs; [ + duckdb + gron + jaq + jless + jq + pandoc + slop + taplo + ]; + + vcs = with pkgs; [ + difftastic + git + git-bug + git-crypt + git-absorb + git-filter-repo + gitleaks + jujutsu + jjui + prek + ]; + + nix_tools = with pkgs; [ + alejandra + comma + deadnix + deploy-rs + nh + nil + nix-du + nixd + nixfmt + nixos-anywhere + nvd + ragenix + statix + ]; + + net_tools = with pkgs; [ + bore-cli + caddy + chisel + curl + dnscontrol + dnsmasq + hurl + inetutils + knot-dns + lftp + monolith + mosh + mosquitto + net-tools + newsraft + nmap + offpunk + rclone + rsync + sshfs + thrift + trickle + w3m + websocat + wget + whois + xh + ]; + + build_tools = with pkgs; [ + libgcc + bear + bmake + boost + clang + cmake + ctags + entr + just + act + lld + lldb + llvm + meson + mold + ninja + tre + libtermkey + ]; + + perf_utils = with pkgs; [ + bpftools + bpftrace + bpfmon + bpftop + libbpf + below + hyperfine + iotop + pwru + gdb + strace + perf + valgrind + aflplusplus + ]; + + beam28 = with pkgs.beam28Packages; [ + erlang + expert + rebar3 + ]; + + all = with pkgs; [ + babashka + biome + gleam + luaPackages.fennel + luaPackages.lpeg + fnlfmt + luarocks + bun + clj-kondo + clojure + gemini-cli-bin + qwen-code + deno + dune + go + gopls + leiningen + ocaml + # purescript + ]; +in { + programs.git = { + enable = true; + ignores = [ + ".crush/" + ".gemini/" + ".qwen/" + "AGENTS.md" + ]; + }; + + home.packages = + core + ++ utils + ++ data + ++ vcs + ++ nix_tools + ++ net_tools + ++ build_tools + ++ perf_utils + ++ beam28 + ++ all; +} diff --git a/hosts/wsl/overlays/bin/.gitkeep b/hosts/wsl/overlays/bin/.gitkeep diff --git a/hosts/wsl/overlays/config/.gitkeep b/hosts/wsl/overlays/config/.gitkeep diff --git a/hosts/wsl/overlays/config/ghostty/config b/hosts/wsl/overlays/config/ghostty/config @@ -0,0 +1,49 @@ +window-decoration = false + +scrollback-limit = 10000 +mouse-hide-while-typing = true + +font-family = "UW ttyp0" +font-size = 14 +font-style-bold = no-bold +font-style-bold-italic = no-bold-italic + +cursor-style = block +cursor-style-blink = false +cursor-color = #fd3333 +cursor-text = #15050f +shell-integration-features = no-cursor + +background = #000000 +foreground = #ffffff + +selection-background = #50447f +selection-foreground = #ffffff + +cursor-color = #ccaaee + +palette = 0=#332d38 +palette = 1=#eca28f +palette = 2=#b9d0aa +palette = 3=#c0b080 +palette = 4=#9fbfe7 +palette = 5=#e9acbf +palette = 6=#a0c0d0 +palette = 7=#ffffff +palette = 8=#332d38 +palette = 9=#eca28f +palette = 10=#b9d0aa +palette = 11=#c0b080 +palette = 12=#9fbfe7 +palette = 13=#e9acbf +palette = 14=#a0c0d0 +palette = 15=#ffffff + +keybind = ctrl+shift+c=copy_to_clipboard +keybind = ctrl+shift+v=paste_from_clipboard +keybind = shift+insert=paste_from_selection +keybind = ctrl+plus=increase_font_size:1 +keybind = ctrl+equal=increase_font_size:1 +keybind = ctrl+minus=decrease_font_size:1 +keybind = ctrl+0=reset_font_size +keybind = ctrl+shift+n=new_window diff --git a/hosts/wsl/overlays/default.nix b/hosts/wsl/overlays/default.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + inputs, + ... +}: let + date = inputs.self.lastModifiedDate or "19700101000000"; + year = lib.substring 0 4 date; + monthNum = lib.substring 4 2 date; + month = lib.elemAt [ + "january" + "february" + "march" + "april" + "may" + "june" + "july" + "august" + "september" + "october" + "november" + "december" + ] (lib.toInt (lib.removePrefix "0" monthNum) - 1); + + tmplArgs = { + inherit year month; + homeDir = config.home.homeDirectory; + }; + + mkMapping = path: prefix: let + scan = dir: rel: + lib.concatLists (lib.mapAttrsToList (name: type: let + newRel = + if rel == "" + then name + else "${rel}/${name}"; + newPath = dir + "/${name}"; + in + if type == "directory" + then scan newPath newRel + else [ + { + name = newRel; + path = newPath; + } + ]) + (builtins.readDir dir)); + in + builtins.listToAttrs (map (file: let + isNix = lib.hasSuffix ".nix" file.name; + target = prefix + (lib.removeSuffix ".nix" file.name); + in + lib.nameValuePair target ( + if isNix + then { + text = import file.path tmplArgs; + force = true; + } + else { + source = file.path; + force = true; + } + )) (scan path "")); +in { + config = { + home.file = lib.mapAttrs (_: lib.mkForce) ( + (mkMapping ./home ".") + // (lib.mapAttrs (_: v: v // {executable = true;}) (mkMapping ./bin "bin/")) + // (mkMapping ./local ".local/") + ); + + xdg.configFile = lib.mapAttrs (_: lib.mkForce) (mkMapping ./config ""); + + home.sessionPath = ["$HOME/bin"]; + }; +} diff --git a/hosts/wsl/overlays/home/.gitkeep b/hosts/wsl/overlays/home/.gitkeep diff --git a/hosts/wsl/overlays/local/.gitkeep b/hosts/wsl/overlays/local/.gitkeep diff --git a/justfile b/justfile @@ -0,0 +1,36 @@ +default: + @just --list + +check: + nix flake check --extra-experimental-features "nix-command flakes" --no-update-lock-file 2>&1 | grep -vE "unknown flake output '(deploy|configData)'" +show: + nix flake show --extra-experimental-features "nix-command flakes" + +fmt: + alejandra $(git rev-parse --show-toplevel) + +deadnix: + deadnix $(git rev-parse --show-toplevel) + +install host: + ./hack/install_anywhere {{host}} + +diff host="nixaran": + nix run github:serokell/deploy-rs -- --dry-activate .#{{host}} 2>&1 | grep -vE "unknown flake output '(deploy|configData)'" + +diff-local: + @nix build .#homeConfigurations."miro@amen".activationPackage --no-link --print-out-paths | xargs nvd diff ~/.local/state/nix/profiles/home-manager + +local: + nh home switch "$(git rev-parse --show-toplevel)" + +deploy host="nixaran": + @backup nix + nix run github:serokell/deploy-rs .#{{host}} 2>&1 | grep -vE "unknown flake output '(deploy|configData)'" + +update: + nix flake update --extra-experimental-features "nix-command flakes" + +gc: + nix-store --gc + nix-collect-garbage -d diff --git a/modules/mixins/default.nix b/modules/mixins/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./dotfiles + ]; +} diff --git a/modules/mixins/dotfiles/bin/amen-or-not b/modules/mixins/dotfiles/bin/amen-or-not @@ -0,0 +1,22 @@ +#!/bin/bash + +MODE="remote" + +case "$MODE" in +remote) + export MPD_PASS="$(pass show saturn/mpd-pass)" + export MPD_HOST="$MPD_PASS@$(pass show saturn/mpd-url)" + export MPD_PORT="$(pass show saturn/mpd-port)" + ;; +local) + export MPD_HOST=127.0.0.1 + export MPD_PORT=6695 + ;; +*) + echo "Unknown MPD_MODE: $MODE (use local or remote)" >&2 + exit 1 + ;; +esac + +echo "MPD_HOST=$MPD_HOST" +echo "MPD_PORT=$MPD_PORT" diff --git a/modules/mixins/dotfiles/bin/blissify b/modules/mixins/dotfiles/bin/blissify @@ -0,0 +1,4 @@ +#!/bin/sh +eval "$("$HOME/bin/amen-or-not")" + +exec "$HOME/.cargo/bin/blissify" "$@" diff --git a/modules/mixins/dotfiles/bin/btmenu b/modules/mixins/dotfiles/bin/btmenu @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +devices() { + bluetoothctl devices "$1" | while read -r _ mac name; do + echo "$mac $name" + done +} + +pick() { + local type="$1" + shift 1 + devices "$type" | dmenu "$@" | awk '{print $1}' +} + +get_name() { + bluetoothctl info "$1" | awk '/Name:/ {sub(/.*Name: /, ""); print}' +} + +case "$1" in +connect | con | c) + cmd=connect + mac=$(pick Paired "${@:2}") + ;; +disconnect | dis | d) + cmd=disconnect + mac=$(pick Connected "${@:2}") + ;; +*) + echo "Usage: $0 connect|disconnect [dmenu_args]" >&2 + exit 1 + ;; +esac + +[ -z "$mac" ] && exit 1 + +name=$(get_name "$mac") + +bluetoothctl "$cmd" "$mac" && notify-send "Bluetooth" "${cmd^}ed $name" diff --git a/modules/mixins/dotfiles/bin/clipmenu b/modules/mixins/dotfiles/bin/clipmenu @@ -0,0 +1,7 @@ +#!/bin/sh +cliphist list \ + | awk -F'\t' '{print $2 "\t" $1}' \ + | dmenu "$@" \ + | awk -F'\t' '{print $2 "\t" $1}' \ + | cliphist decode \ + | wl-copy diff --git a/modules/mixins/dotfiles/bin/dedupli b/modules/mixins/dotfiles/bin/dedupli @@ -0,0 +1,19 @@ +#! /bin/awk -f +{ + lines[NR] = $0 +} + +END { + for (i = 1; i <= NR; i++) { + is_prefix = 0 + for (j = 1; j <= NR; j++) { + if (i != j && length(lines[i]) < length(lines[j]) && index(lines[j], lines[i]) == 1) { + is_prefix = 1 + break + } + } + if (!is_prefix) { + print lines[i] + } + } +} diff --git a/modules/mixins/dotfiles/bin/dnsleak b/modules/mixins/dotfiles/bin/dnsleak @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# encoding=utf-8 +# Any questions: tutumbul@gmail.com +# https://bash.ws/dnsleak + +import os +import subprocess +import json +from random import randint +from platform import system as system_name +from subprocess import call as system_call + +try: + from urllib.request import urlopen +except ImportError: + from urllib2 import urlopen + + +def ping(host): + fn = open(os.devnull, 'w') + param = '-n' if system_name().lower() == 'windows' else '-c' + command = ['ping', param, '1', host] + retcode = system_call(command, stdout=fn, stderr=subprocess.STDOUT) + fn.close() + return retcode == 0 + + +response = urlopen("https://bash.ws/id") +data = response.read().decode("utf-8") + +leak_id = data +for x in range(0, 10): + ping('.'.join([str(x), leak_id, "bash.ws"])) + +response = urlopen("https://bash.ws/dnsleak/test/"+leak_id+"?json") +data = response.read().decode("utf-8") +parsed_data = json.loads(data) + +print("Your IP:") +for dns_server in parsed_data: + if dns_server['type'] == "ip": + if dns_server['country_name']: + if dns_server['asn']: + print(dns_server['ip']+" ["+dns_server['country_name']+", " + + dns_server['asn']+"]") + else: + print(dns_server['ip']+" ["+dns_server['country_name']+"]") + else: + print(dns_server['ip']) + +servers = 0 +for dns_server in parsed_data: + if dns_server['type'] == "dns": + servers = servers + 1 + +if servers == 0: + print("No DNS servers found") +else: + print("You use "+str(servers)+" DNS servers:") + for dns_server in parsed_data: + if dns_server['type'] == "dns": + if dns_server['country_name']: + if dns_server['asn']: + print(dns_server['ip']+" ["+dns_server['country_name'] + + ", " + dns_server['asn']+"]") + else: + print(dns_server['ip']+" ["+dns_server['country_name']+"]") + else: + print(dns_server['ip']) + +print("Conclusion:") +for dns_server in parsed_data: + if dns_server['type'] == "conclusion": + if dns_server['ip']: + print(dns_server['ip']) diff --git a/modules/mixins/dotfiles/bin/ff2mpv b/modules/mixins/dotfiles/bin/ff2mpv @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "json" + +len = $stdin.read(4).unpack1("L") +data = JSON.parse($stdin.read(len)) +url = data["url"] +options = data["options"] || [] + +args = %w[--no-terminal] +pid = spawn "mpv", *args, "--", url, in: :close, out: "/dev/null", err: "/dev/null" + +Process.detach pid diff --git a/modules/mixins/dotfiles/bin/ffpurge b/modules/mixins/dotfiles/bin/ffpurge @@ -0,0 +1,222 @@ +#!/usr/bin/env python3 +""" +ffpurge: remove cookies and associated site data not used in the last N days + +Usage: + python ffpurge # dry run + python ffpurge --purge # delete + python ffpurge --days 14 # threshold (default: 7) +""" + +import argparse +import shutil +import sqlite3 +import sys +import time +from pathlib import Path + + +def get_profiles() -> list[Path]: + base = Path.home() / ".mozilla/firefox" + if not base.exists(): + sys.exit(f"Firefox profiles not found: {base}") + return [p for p in base.iterdir() if p.is_dir()] + + +def get_cache_dirs(profile: Path) -> list[Path]: + cache_root = Path.home() / f".cache/mozilla/firefox/{profile.name}" + return [ + cache_root / "cache2", + cache_root / "startupCache", + cache_root / "thumbnails", + profile / "shader-cache", + ] + + +def days_to_us(days: int) -> int: + return int((time.time() - days * 86400) * 1_000_000) + + +def dir_size(path: Path) -> int: + return sum(f.stat().st_size for f in path.rglob("*") if f.is_file()) + + +def fmt_size(b: int) -> str: + f = float(b) + for u in ["B", "KB", "MB", "GB"]: + if f < 1024: + return f"{f:.1f} {u}" + f /= 1024 + return f"{f:.1f} GB" + + +def query_cookies(profile: Path, threshold: int) -> list[tuple[str, str, int]]: + db = profile / "cookies.sqlite" + if not db.exists(): + return [] + try: + con = sqlite3.connect(f"file:{db}?mode=ro", uri=True) + rows = con.execute( + "SELECT host, name, lastAccessed FROM moz_cookies WHERE lastAccessed < ? ORDER BY host", + (threshold,), + ).fetchall() + con.close() + return rows + except sqlite3.OperationalError as e: + print(f" cannot read cookies.sqlite: {e}") + return [] + + +def delete_cookies(profile: Path, threshold: int) -> int: + db = profile / "cookies.sqlite" + if not db.exists(): + return 0 + try: + con = sqlite3.connect(db) + n = con.execute( + "DELETE FROM moz_cookies WHERE lastAccessed < ?", (threshold,) + ).rowcount + con.commit() + con.close() + return n + except sqlite3.OperationalError as e: + print(f" cannot write cookies.sqlite: {e}") + return 0 + + +def get_ls_scopes(profile: Path, hosts: set[str]) -> list[str]: + db = profile / "webappsstore.sqlite" + if not db.exists(): + return [] + try: + con = sqlite3.connect(f"file:{db}?mode=ro", uri=True) + scopes = [ + r[0] # type: ignore[unknown-variable-type] + for r in con.execute("SELECT DISTINCT scope FROM webappsstore2").fetchall() + ] + con.close() + result: list[str] = [] + for scope in scopes: + rev = scope.split(":")[0].rstrip(".") # type: ignore[unknown-variable-type] + host = ".".join(reversed(rev.split("."))) # type: ignore[unknown-variable-type] + if any(h in host or host in h for h in hosts): + result.append(scope) # type: ignore[unknown-argument-type] + return result + except sqlite3.OperationalError: + return [] + + +def delete_ls(profile: Path, hosts: set[str]) -> int: + db = profile / "webappsstore.sqlite" + scopes = get_ls_scopes(profile, hosts) + if not scopes: + return 0 + try: + con = sqlite3.connect(db) + n = sum( + con.execute("DELETE FROM webappsstore2 WHERE scope = ?", (s,)).rowcount + for s in scopes + ) + con.commit() + con.close() + return n + except sqlite3.OperationalError as e: + print(f" cannot write webappsstore.sqlite: {e}") + return 0 + + +def get_stale_folders(profile: Path, hosts: set[str]) -> list[Path]: + root = profile / "storage/default" + if not root.exists(): + return [] + result: list[Path] = [] + for folder in root.iterdir(): + if not folder.is_dir(): + continue + fhost = folder.name.replace("https+++", "").replace("http+++", "").split("+")[0] + if any(h in fhost or fhost in h for h in hosts): + result.append(folder) + return result + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--purge", action="store_true") # type: ignore[unused-call-result] + ap.add_argument("--days", type=int, default=7) # type: ignore[unused-call-result] + args = ap.parse_args() + + threshold = days_to_us(args.days) # type: ignore[arg-type, unknown-variable-type] + cutoff = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(threshold / 1_000_000)) + purge = args.purge # type: ignore[attr-defined, unknown-variable-type] + days = args.days # type: ignore[attr-defined, unknown-variable-type] + print( + f"\nMode: {'PURGE' if purge else 'DRY RUN'} | threshold: {days} days (before {cutoff})\n" + ) + + profiles = get_profiles() + totals: dict[str, int] = dict(cookies=0, ls=0, storage=0, cache=0) + + for profile in profiles: + print(f"--- Profile: {profile.name} ---") + + # cookies + rows = query_cookies(profile, threshold) + hosts = set(r[0].lstrip(".") for r in rows) + print(f" cookies : {len(rows)} ({len(hosts)} hosts)") + for host, name, us in rows: + print( + f" {host} {name} last={time.strftime('%Y-%m-%d', time.localtime(us / 1e6))}" + ) + if purge: + n = delete_cookies(profile, threshold) + print(f" deleted {n} cookies") + totals["cookies"] += len(rows) + + # localStorage + scopes = get_ls_scopes(profile, hosts) + print(f" localStorage : {len(scopes)} scope(s)") + for s in scopes: + print(f" {s}") + if purge and scopes: + n = delete_ls(profile, hosts) + print(f" deleted {n} localStorage rows") + totals["ls"] += len(scopes) + + # site storage + folders = get_stale_folders(profile, hosts) + storage_bytes = sum(dir_size(f) for f in folders) + print(f" site storage : {len(folders)} folder(s), {fmt_size(storage_bytes)}") + for f in folders: + print(f" {f.name}") + if purge: + for f in folders: + shutil.rmtree(f, ignore_errors=True) + if folders: + print(f" deleted {len(folders)} folder(s)") + totals["storage"] += storage_bytes + + # cache + for cache_path in get_cache_dirs(profile): + if not cache_path.exists(): + continue + cache_size = dir_size(cache_path) + print(f" cache : {fmt_size(cache_size)} ({cache_path.name})") + if purge: + shutil.rmtree(cache_path, ignore_errors=True) + print(f" deleted {cache_path.name}") + totals["cache"] += cache_size + print() + + print("--- Summary ---") + action = "deleted" if purge else "would delete" + print( + f" {action}: {totals['cookies']} cookies, {totals['ls']} localStorage scopes, {fmt_size(totals['storage'])} site storage, {fmt_size(totals['cache'])} cache" + ) + if not purge: + print("\n dry run - use --purge to delete") + else: + print("\n done") + + +if __name__ == "__main__": + main() diff --git a/modules/mixins/dotfiles/bin/git-diff-upstream b/modules/mixins/dotfiles/bin/git-diff-upstream @@ -0,0 +1,54 @@ +#!/bin/bash +set -euo pipefail + +usage() { + echo "Usage: $0 --repo <url> --branch <branch> --prefix <path>" + exit 1 +} + +cleanup() { + [ -n "${upstream_dir:-}" ] && rm -rf "$upstream_dir" + [ -n "${upstream_dir:-}" ] && git remote remove "$remote_name" +} +trap cleanup EXIT + +repo_url="" +branch="" +prefix="" + +while [[ "$#" -gt 0 ]]; do + case $1 in + --repo) repo_url="$2"; shift ;; + --branch) branch="$2"; shift ;; + --prefix) prefix="$2"; shift ;; + *) echo "Unknown parameter: $1"; usage ;; + esac + shift +done + +[ -z "$repo_url" ] || [ -z "$branch" ] || [ -z "$prefix" ] && usage + +# Normalize prefix and vars +clean_prefix=${prefix%/} +remote_name="${clean_prefix}.upstream" +upstream_dir="${clean_prefix}.upstream" + +cd "$(git rev-parse --show-toplevel)" + +if ! git remote | grep -q "^${remote_name}$"; then + git remote add -f "$remote_name" "$repo_url" +else + git fetch "$remote_name" +fi + +[ -d "$upstream_dir" ] && rm -rf "$upstream_dir" +mkdir -p "$upstream_dir" + +git archive --format=tar "${remote_name}/${branch}" | tar -xf - -C "$upstream_dir" + +if ! command -v difft &> /dev/null; then + echo "Error: difft (difftastic) not found." >&2 + exit 1 +fi + +difft --color=always "$clean_prefix" "$upstream_dir" | less -R diff --git a/modules/mixins/dotfiles/bin/git-id b/modules/mixins/dotfiles/bin/git-id @@ -0,0 +1,187 @@ +#!/usr/bin/perl +# vim: sts=4 sw=4 ts=4 expandtab: +=pod + +=head1 NAME + +git-id + +=head1 SYNOPSIS + + git-id + +=head1 DESCRIPTION + +Runs git-status and prepends numeric ids to filenames. + +=head1 OPTIONS + +=over 4 + +=item -h + +Show this help message + +=item -s + +=item --column + +=item -u(no|normal|all) + +=item --color=(always|auto|never) + +These options are similar to git-status'. + +=back + +=head1 SEE ALSO + + git-number(1), git-list(1) + +=cut + +use strict; +use warnings; +use Cwd; + +my $red = "\e[31m"; +my $normal = "\e[0m"; +my $git_dir = `git rev-parse --git-dir`; +chomp $git_dir; + +my $gitids = "$git_dir/gitids.txt"; + +my $color = 'always'; +my $STATUS_DEFAULT = 0; +my $STATUS_SHORT = 1; +my $status_style = $STATUS_DEFAULT; +my $status_opt = ''; + +my $untracked_in_columns = 0; +while (scalar @ARGV && $ARGV[0] =~ /^-/) { + my $option = shift @ARGV; + last if $option eq '--'; + if ($option =~ /--color=(always|auto|never)/) { + $color = $1; + if ($color =~ /never/) { + $red = $normal = ''; + } + } elsif ($option eq '--short') { + $status_style = $STATUS_SHORT; + } elsif ($option =~ m{^-u(no|normal|all)$}) { + $status_opt .= " $option"; + } elsif ($option =~ /^--column/) { + if ($option eq '--column=never' || ($option =~ /--column(=auto)?$/ && ! -t STDOUT)) { + $untracked_in_columns = 0; + } else { + $untracked_in_columns = 1; + } + $status_opt .= " $option"; + } else { + print "Unknown option: $option\n"; + exit 1; + } +} + +if (! $untracked_in_columns) { + $status_opt .= " --column=never"; +} + +my @status_option_for = ( '', '--short' ); +my $status_format = $status_option_for[$status_style]; +my $git_cmd = "git -c color.status=$color status $status_opt $status_format " + . join(' ', @ARGV); +open my $git_status, "$git_cmd|" + or die "Error: $!"; + +open my $cache, ">$gitids" + or die "Error: $!"; + +# Headers +print $cache "cwd: " . getcwd . "\n"; +print $cache "status-format: $status_format\n"; +print $cache "\n"; + +my $seen_untracked = 0; +my @untracked; +my $c = 1; +while (my $line = <$git_status>) { + if ($line =~ /Untracked files:/) { + $seen_untracked = 1; + } + + if ($status_style == $STATUS_DEFAULT) { + if ($seen_untracked && $line =~ /\t/ && $untracked_in_columns) { + push @untracked, $line; + last; + } + + if ($line =~ /#\t/) { + $line =~ s/#\t/#$c\t/; + $c += 1; + } elsif ($line =~ /\t/) { + $line =~ s/\t/$c\t/; + $c += 1; + } + } elsif ($status_style == $STATUS_SHORT) { + if ($line !~ /^#/) { + $line =~ s/^/$c /; + $c += 1; + } + } + show_and_cache($line); +} + +if ($untracked_in_columns) { + my $seen_files = 0; + my @the_rest; + while (my $line = <$git_status>) { + if ($line =~ /\t/) { + $seen_files = 1; + push @untracked, $line; + } else { + push @the_rest, $line; + } + } + + my $rows = @untracked; + foreach my $line (@untracked) { + my $id = $c; + $line =~ s/([\t ])(\S)/add_number(\$id, $1, $2, $rows)/ge; + $line =~ s/^ +//; + show_and_cache($line); + $c += 1; + } + print join "", @the_rest; +} + +close $git_status; +close $cache; +exit 0; + +sub show_and_cache { + my ($line) = @_; + my $tocache = $line; + $tocache =~ s/{(\d+)}[\t ]{1,2}/\n$1\t/g; + $line =~ s/{(\d+)}/$1/g; + print $line; + $tocache =~ s/\e\[(\d*(;\d*)*)m//g; + if ($untracked_in_columns) { + $tocache =~ s/\s*\n/\n/gms; # Trailing spaces from columnar formatting + } + print $cache $tocache; +} + +sub add_number { + my ($nref, $space, $first_char, $incr) = @_; + + my $num = $$nref; + if ($num < 10 && $space eq ' ') { + $num = "{$num} "; + } else { + $num = "{$num}"; + } + my $str = "$normal$num$space$red$first_char"; + $$nref += $incr; + return $str; +} diff --git a/modules/mixins/dotfiles/bin/git-list b/modules/mixins/dotfiles/bin/git-list @@ -0,0 +1,202 @@ +#!/usr/bin/perl +# vim: sts=4 sw=4 ts=4 expandtab: +# gl - List files from .git/gitids.txt + +use strict; +use warnings; +use File::Spec; +use Cwd qw/getcwd abs_path/; + +=pod + +=head1 NAME + +git-list + +=head1 SYNOPSIS + + git-list [-h] [number pattern] + +=head1 DESCRIPTION + +git-list lists the corresponding filenames given their numbers that was +previously assigned by git-id. It lists one filename per line of output. Any +other argument or numbers that has no filenames associated with it will be +printed as is. + +[number pattern] can either be a single number or a range: + + git-list 1 5-6 + +=head1 OPTIONS + + -h Show this help message + +=head1 SEE ALSO + + git-number(1), git-id(1) + +=cut + +if (defined $ARGV[0] && $ARGV[0] eq '-h') { + system(qq[perldoc $0]); + exit 0; +} + +my $wanted_ids = explode_args(@ARGV); + +if (ref $wanted_ids eq 'ARRAY') { + my $file_for = get_file_ids(); + foreach my $id (@$wanted_ids) { + if (defined $file_for->{$id}) { + print $file_for->{$id}; + } else { + print $id; + } + print "\n"; + } +} elsif ($wanted_ids eq 'all') { + my @file_list = get_file_list(); + foreach my $entry (@file_list) { + print $entry->{filename} . "\n"; + } +} +exit 0; +# Add subs below this line + +sub get_file_list { + my $git_dir = `git rev-parse --git-dir`; + chomp $git_dir; + + my $gitids = "$git_dir/gitids.txt"; + if (! -f $gitids) { + print "Please run git-number first\n"; + exit 1; + } + + open my $cache, "<$gitids" or die "Error: $!"; + + my $headers = read_headers($cache); + my $cwd = getcwd(); + my $needfixdir = 0; + if ($headers->{cwd} ne $cwd) { + $needfixdir = 1; + $cwd = abs_path($cwd); + } + my @file_list; + my $status_processor_for = { + '' => sub { + while (my $line = <$cache>) { + next if $line !~ /^#?[0-9]+\t/; + chomp $line; + if (my ($number, $status, $filename) + = $line =~ /^#?([0-9]+)\t([^:]+:\s+)?(.*)/) { + + + + if ($filename =~ / \(.*\)$/ && ! -e $filename) { + # Looks like a submodule status, see if it really is a submodule + my ($dir) = $filename =~ /(.*) \(.*\)$/; + if (-d $dir && -e "$dir/.git") { + $filename = $dir; + } + } + + if ($needfixdir) { + $filename = fixdir($filename, $headers->{cwd}, $cwd); + } + push @file_list, { + number => $number, + status => $status, + filename => $filename, + }; + } + } + }, + '--short' => sub { + while (my $line = <$cache>) { + next if $line !~ /^[0-9]+\s/; + chomp $line; + if (my ($number, $status, $filename) + = $line =~ /^([0-9]+)\s+([^ ]+)\s+(.*)/) { + + if ($needfixdir) { + $filename = fixdir($filename, $headers->{cwd}, $cwd); + } + push @file_list, { + number => $number, + status => $status, + filename => $filename, + }; + } + } + }, + }; + + my $status_format = $headers->{'status-format'}; + $status_processor_for->{$status_format}->(); + close $cache; + return @file_list; +} + +sub read_headers { + my ($cache) = @_; + my %headers; + while (my $line = <$cache>) { + chomp $line; + last if length $line == 0; + my ($field, $value) = split(/:\s*/, $line, 2); + $headers{$field} = $value; + } + return \%headers; +} + +sub get_file_ids { + my @file_list = get_file_list(); + + my %file_for; + foreach my $entry (@file_list) { + my $filename = $entry->{filename}; + # First we escape characters that need escaping + if ($filename =~ /[`\$"]/) { + $filename =~ s/([`\$"])/\\$1/g; + } + # Then we double-quote the name if necessary + if ($filename =~ /[ '\[\]()&]/) { + $filename = '"' . $filename . '"'; + } + $file_for{$entry->{number}} = $filename; + } + return \%file_for; +} + +sub explode_args { + my (@ARGV) = @_; + if (scalar @ARGV == 0) { + return 'all'; + } + my @wanted_ids; + foreach my $arg (@ARGV) { + if ($arg =~ m/^[0-9]+$/) { + push @wanted_ids, $arg; + } elsif ($arg =~ m/^([0-9]+)-([0-9]+)/) { + my $a = $1; + my $b = $2; + if ($a > $b) { + $a = $b; + $b = $1; + } + push @wanted_ids, $a..$b; + } else { + push @wanted_ids, $arg; + } + } + return \@wanted_ids; +} + +sub fixdir { + my ($filename, $orig_cwd, $cwd) = @_; + my $abspath = File::Spec->catfile($orig_cwd, $filename); + $abspath = abs_path($abspath); + return File::Spec->abs2rel($abspath, $cwd); +} diff --git a/modules/mixins/dotfiles/bin/git-number b/modules/mixins/dotfiles/bin/git-number @@ -0,0 +1,161 @@ +#!/usr/bin/perl +use strict; +use warnings; +use File::Basename; + +# git-number: +# + +=pod + +=head1 NAME + +git-number + +=head1 SYNOPSIS + + git-number [-h|--color=<when>|-s] [<git-cmd|-c <cmd>> [git-or-cmd-options] [files or numbers]] [-- ...] + +=head1 DESCRIPTION + +When run without arguments, runs git-status and assign numeric ids to filenames shown by git-status. + +When run with arguments, runs <git-cmd> or <cmd>, and replaces any number in +the arguments with the corresponding filename from the previous run of +git-number. + +Any args given after `--' are passed to the underlying command verbatim. + +=head1 OPTIONS + +=over 4 + +=item -c <cmd> + +Runs I<E<lt>cmdE<gt>> instead of git on the given arguments. +All arguments that follows <cmd> will be passed on to <cmd>. + +=item -v + +Show version information + +=item -h + +Show this help message + +=item -s + +=item --column + +=item -u(no|normal|all) + +=item --color=(always|auto|never) + +These options are similar to git-status'. + +=back + +=head1 SEE ALSO + + git-id(1), git-list(1) + +=head1 VERSION + +1.0.1 +=cut +my $VERSION = '1.0.1'; # Don't forget to update the one in pod! + +my $me = basename(__FILE__); +sub show_usage_and_exit { + my ($exit_value) = @_; + $exit_value = 0 if ! defined $exit_value; + system(qq[perldoc "$0"]); + exit $exit_value; +} + +sub run_cmd { + my ($cmd) = @_; + system($cmd); + if ($? == -1) { + print STDERR "$me: $!\n"; + return 1; + } + return $? >> 8; +} + +my $run = 'git'; +my $color = 'always'; +my $status_opt = ''; +my $passthru_args = ''; +if (grep(/^--$/, @ARGV) == 0 && $ARGV[-1] && $ARGV[-1] eq '.') { + $ARGV[-1] = '--'; + push @ARGV, '.'; +} +while (scalar @ARGV && $ARGV[0] =~ /^-/) { + my $option = shift @ARGV; + if ($option eq '--') { + $passthru_args = join(' ', @ARGV); + @ARGV = (); + last; + } + if ($option eq '-h') { + show_usage_and_exit(); + } elsif ($option eq '-v') { + print "$VERSION\n"; + exit 0; + } elsif ($option eq '-c') { + $run = shift @ARGV; + last; + } elsif ($option =~ m{--color=(always|auto|never)}) { + $color = $1; + } elsif ($option eq '-s') { + $status_opt .= " --short"; + } elsif ($option =~ m{^-u(no|normal|all)$}) { + $status_opt .= " $option"; + } elsif ($option =~ m{^--column}) { + $status_opt .= " $option"; + } else { + print "Unknown option: $option\n"; + exit 1; + } +} + +if ($run eq 'git' && scalar @ARGV == 0) { + my $cmd = join(' ', + "git-id", + "--color=$color", + "$status_opt", + "-- $passthru_args", + ); + exit run_cmd($cmd); +} + +my @args; + +my $converted=0; +while (scalar @ARGV) { + my $arg = shift @ARGV; + if ($arg eq '--') { + push(@args, @ARGV); + last; + } + + if ( $arg =~ m/^[0-9][0-9]*$/ ) { + push @args, split("\n", `git-list $arg`); + $converted=1; + } elsif ( $arg =~ m/^[0-9][0-9]*-[0-9][0-9]*$/ ) { + push @args, split("\n", `git-list $arg`); + $converted=1; + } else { + if (index($arg, ' ') != -1) { + $arg = "\"$arg\""; + } + push @args, $arg; + } +} + +my $cmd = "$run " . join(' ', @args); +if (-t STDOUT && $converted) { + print $cmd . "\n"; +} +exit run_cmd($cmd); diff --git a/modules/mixins/dotfiles/bin/gotcover b/modules/mixins/dotfiles/bin/gotcover @@ -0,0 +1,21 @@ +#!/bin/bash +# Check media files for embedded cover art using ffmpeg/ffprobe + +SEARCH_DIR="${1:-.}" +EXTENSIONS=("flac" "mp3" "aiff" "aif" "m4a" "ogg" "wav") + +find_args=() +for i in "${!EXTENSIONS[@]}"; do + if [ "$i" -gt 0 ]; then + find_args+=(-o) + fi + find_args+=(-iname "*.${EXTENSIONS[$i]}") +done + +while IFS= read -r -d '' file; do + has_cover=$(ffprobe -v error -select_streams v -show_entries stream=codec_type -of csv=p=0 "$file" 2>/dev/null | grep -c "video") + + if [ "$has_cover" -eq 0 ]; then + echo "[✗] $file" + fi +done < <(find "$SEARCH_DIR" -type f \( "${find_args[@]}" \) -print0 | sort -z) diff --git a/modules/mixins/dotfiles/bin/habitual b/modules/mixins/dotfiles/bin/habitual @@ -0,0 +1,110 @@ +#!/usr/bin/env bb + +(ns habitual + (:require [clojure.string :as str] + [clojure.tools.cli :refer [parse-opts]] + [babashka.process :refer [shell]])) + +(defn parse-cron-field [field lo hi] + (let [all (set (range lo (inc hi)))] + (reduce + (fn [acc part] + (cond + (= part "*") + (into acc all) + + (re-matches #"\*/\d+" part) + (let [step (parse-long (subs part 2))] + (into acc (range lo (inc hi) step))) + + (re-matches #"\d+-\d+/\d+" part) + (let [[range-part step-part] (str/split part #"/") + [a b] (map parse-long (str/split range-part #"-")) + step (parse-long step-part)] + (into acc (range a (inc b) step))) + + (re-matches #"\d+-\d+" part) + (let [[a b] (map parse-long (str/split part #"-"))] + (into acc (range a (inc b)))) + + :else + (conj acc (parse-long part)))) + #{} + (str/split field #",")))) + +(defn parse-cron [expr] + (let [[minutes hours days months weekdays] (str/split expr #"\s+")] + {:minutes (parse-cron-field minutes 0 59) + :hours (parse-cron-field hours 0 23) + :days (parse-cron-field days 1 31) + :months (parse-cron-field months 1 12) + :weekdays (parse-cron-field weekdays 0 6)})) + +(defn next-cron-ms + "Returns milliseconds until the next matching habit" + [cron] + (let [now (System/currentTimeMillis) + start (-> now (quot 60000) inc (* 60000))] + (loop [t start] + (if (> t (+ start (* 4 366 24 60 60 1000))) + (throw (ex-info "No cron match found within 4 years" {:cron cron})) + (let [ldt (java.time.LocalDateTime/ofInstant + (java.time.Instant/ofEpochMilli t) + (java.time.ZoneId/systemDefault)) + month (.getMonthValue ldt) ; 1-12 + mday (.getDayOfMonth ldt) ; 1-31 + hour (.getHour ldt) ; 0-23 + minute (.getMinute ldt) ; 0-59 + weekday (-> ldt .getDayOfWeek .getValue (mod 7))] ; 0=Sun (ISO Mon=1, so Sun=7 mod 7=0) + (if (and ((:months cron) month) + ((:days cron) mday) + ((:weekdays cron) weekday) + ((:hours cron) hour) + ((:minutes cron) minute)) + (- t now) + (recur (+ t 60000)))))))) + +(defn run-job! [name cron prog] + (future + (loop [] + (let [delay-ms (next-cron-ms cron)] + (println (format "[INFO] Scheduling next run for '%s' in %d seconds" + name (quot delay-ms 1000))) + (Thread/sleep delay-ms) + (println (format "[INFO] Running notifier for '%s'" name)) + (let [result (shell {:continue true} prog name)] + (when (not= 0 (:exit result)) + (println (format "[WARN] Command returned %d: %s %s" + (:exit result) prog name)))) + (recur))))) + +(def cli-options + [["-p" "--prog PROG" "Program to send notifications to" + :default "notify-send"] + ["-h" "--help"]]) + +(defn -main [& args] + (let [{:keys [options summary errors]} (parse-opts args cli-options)] + (when errors + (println (str/join "\n" errors)) + (System/exit 1)) + (when (:help options) + (println "Usage: habitual [options]") + (println summary) + (System/exit 0)) + + (let [config-file (str (System/getProperty "user.home") + "/.config/habitual/habitual") + lines (-> config-file slurp str/split-lines) + prog (:prog options) + jobs (for [line lines + :let [line (str/trim line)] + :when (and (seq line) (not (str/starts-with? line "#"))) + :let [[schedule name] (str/split line #"\|" 2) + cron (parse-cron (str/trim schedule))]] + (run-job! (str/trim name) cron prog))] + (println (format "[INFO] Loaded %d job(s), running..." (count (doall jobs)))) + ;; Block forever — futures run the jobs + @(promise)))) + +(apply -main *command-line-args*) diff --git a/modules/mixins/dotfiles/bin/hakuna b/modules/mixins/dotfiles/bin/hakuna @@ -0,0 +1,2 @@ +#!/bin/sh +DISCOGS_TOKEN="$(pass show discogs-token)" /opt/tools/hakunadata "$@" diff --git a/modules/mixins/dotfiles/bin/harper_dict_update b/modules/mixins/dotfiles/bin/harper_dict_update @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +set -euo pipefail + +HARPER_DICT="${XDG_CONFIG_HOME:-$HOME/.config}/harper-ls/dictionary.txt" +BASE_URL="https://raw.githubusercontent.com/streetsidesoftware/cspell-dicts/main/dictionaries" + +DICTS=( + "software-terms/dict/softwareTerms.txt" + "typescript/dict/typescript.txt" + "node/dict/node.txt" + "css/dict/css.txt" + "html/dict/html.txt" + "python/dict/python.txt" + "rust/dict/rust.txt" + "bash/samples/bash-words.txt" + "golang/dict/go.txt" + "docker/dict/docker-words.txt" + "k8s/dict/k8s.txt" + "aws/dict/aws.txt" + "sql/src/sql.txt" + "zig/dict/zig.txt" + "php/dict/php.txt" + +) + +WORK_DIR=$(mktemp -d) +trap 'rm -rf "$WORK_DIR"' EXIT + +log() { echo "▸ $*"; } +warn() { echo "⚠ $*" >&2; } + +clean_cspell_words() { + # - blank lines and comments (#) + # - cspell flags: lines starting with !, *, ~, / + # - inline flags after words: word+, word!, word~ + # - leading/trailing whitespace + grep -v '^\s*$' \ + | grep -v '^\s*#' \ + | grep -v '^\s*[!*~/]' \ + | sed 's/[+!~*]$//' \ + | sed 's/^\s*//;s/\s*$//' \ + | grep -E '^[A-Za-z]' \ + | tr '[:upper:]' '[:lower:]' +} + +log "Fetching cspell dictionaries" + +MERGED="$WORK_DIR/merged.txt" + +for dict in "${DICTS[@]}"; do + url="$BASE_URL/$dict" + name=$(basename "$dict") + log " $name" + if curl -fsSL "$url" -o "$WORK_DIR/$name" 2>/dev/null; then + clean_cspell_words < "$WORK_DIR/$name" >> "$MERGED" + else + warn "Failed to fetch $url" + fi +done + +sort -u "$MERGED" -o "$MERGED" +FETCHED_COUNT=$(wc -l < "$MERGED") +log "Fetched $FETCHED_COUNT unique words from cspell-dicts" + +mkdir -p "$(dirname "$HARPER_DICT")" +touch "$HARPER_DICT" + +# Preserve any words added manually +USER_ONLY=$(comm -23 <(sort "$HARPER_DICT") <(sort "$MERGED") || true) + +{ cat "$MERGED"; echo "$USER_ONLY"; } | sort -u > "$WORK_DIR/final.txt" + +FINAL_COUNT=$(wc -l < "$WORK_DIR/final.txt") +cp "$WORK_DIR/final.txt" "$HARPER_DICT" + +log "Harper dictionary updated: $FINAL_COUNT words" diff --git a/modules/mixins/dotfiles/bin/huemenu b/modules/mixins/dotfiles/bin/huemenu @@ -0,0 +1,37 @@ +#!/bin/bash +set -euo pipefail + +if ! mode=$(echo -e "work\nsleep" | dmenu "$@"); then + exit 1 +fi +[ -z "$mode" ] && exit 1 + +if ! color=$(echo -e "relax\nconcentrate\nreading\ndimmed\nskip\noff" | dmenu "$@"); then + exit 1 +fi +[ -z "$color" ] && exit 1 + +brightness="skip" +if [ "$color" != "off" ]; then + if ! brightness=$(seq 100 -10 10 | sed 's/$/%/' | dmenu "$@"); then + exit 1 + fi + [ -z "$brightness" ] && exit 1 +fi + +case "$mode" in + work) light_id=2 ;; + sleep) light_id=1 ;; + *) echo "Error: Unknown mode '$mode'" >&2; exit 1 ;; +esac + +if [ "$color" = "off" ]; then + hue "$light_id" off || echo "Warning: Failed to turn off light $light_id" >&2 +else + if [ "$color" != "skip" ]; then + hue light "$light_id" "$color" || echo "Warning: Failed to set color '$color' for light $light_id" >&2 + fi + if [ "$brightness" != "skip" ]; then + hue "$light_id" brightness "$brightness" || echo "Warning: Failed to set brightness '$brightness' for light $light_id" >&2 + fi +fi diff --git a/modules/mixins/dotfiles/bin/langmenu b/modules/mixins/dotfiles/bin/langmenu @@ -0,0 +1,26 @@ +#!/bin/bash +set -euo pipefail + +choice=$(echo -e "en\nsk" | dmenu "$@") +[ -z "$choice" ] && exit 0 + +case "$choice" in + en) + if [ -n "${WAYLAND_DISPLAY:-}" ]; then + riverctl keyboard-layout us + else + setxkbmap us + fi + ;; + sk) + if [ -n "${WAYLAND_DISPLAY:-}" ]; then + riverctl keyboard-layout -variant qwerty sk + else + setxkbmap sk qwerty + fi + ;; + *) + echo "Error: Unknown layout '$choice'" >&2 + exit 1 + ;; +esac diff --git a/modules/mixins/dotfiles/bin/meq b/modules/mixins/dotfiles/bin/meq @@ -0,0 +1,3 @@ +#!/bin/sh +eval "$("$HOME/bin/amen-or-not")" +exec /opt/tools/mpd_edit_queue "$@" diff --git a/modules/mixins/dotfiles/bin/moshrc b/modules/mixins/dotfiles/bin/moshrc @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# moshrc is an alternative to sshrc for mosh users + + +function moshrc() { + local SSHHOME=${SSHHOME:=~} + if [ -f $SSHHOME/.sshrc ]; then + local files=.sshrc + if [ -d $SSHHOME/.sshrc.d ]; then + files="$files .sshrc.d" + fi + SIZE=$(tar cfz - -h -C $SSHHOME $files | wc -c) + if [ $SIZE -gt 65536 ]; then + echo >&2 $'.sshrc.d and .sshrc files must be less than 64kb\ncurrent size: '$SIZE' bytes' + exit 1 + fi + mosh "$@" -- /bin/bash -c " + command -v xxd >/dev/null 2>&1 || { echo >&2 \"sshrc requires xxd to be installed on the server, but it's not. Aborting.\"; exit 1; } + if [ -e /etc/motd ]; then cat /etc/motd; fi + if [ -e /etc/update-motd.d ]; then run-parts /etc/update-motd.d/; fi + export SSHHOME=\$(mktemp -d -t .$(whoami).sshrc.XXXX) + export SSHRCCLEANUP=\$SSHHOME + trap \"rm -rf \$SSHRCCLEANUP; exit\" 0 + echo $'$(cat $0 | xxd -p)' | xxd -p -r > \$SSHHOME/moshrc + chmod +x \$SSHHOME/moshrc + + echo $'$( cat << 'EOF' | xxd -p +if [ -e /etc/bash.bashrc ]; then source /etc/bash.bashrc; fi +if [ -e ~/.bashrc ]; then source ~/.bashrc; fi +source $SSHHOME/.sshrc; +export PATH=$PATH:$SSHHOME +EOF +)' | xxd -p -r > \$SSHHOME/sshrc.bashrc + + echo $'$( cat << 'EOF' | xxd -p +#!/usr/bin/env bash +exec bash --rcfile <(echo ' +if [ -e /etc/bash.bashrc ]; then source /etc/bash.bashrc; fi +if [ -e ~/.bashrc ]; then source ~/.bashrc; fi +source '$SSHHOME'/.sshrc; +export PATH=$PATH:'$SSHHOME' +') "$@" +EOF +)' | xxd -p -r > \$SSHHOME/bashsshrc + chmod +x \$SSHHOME/bashsshrc + + echo $'$(tar czf - -h -C $SSHHOME $files | xxd -p)' | xxd -p -r | tar mxzf - -C \$SSHHOME + export SSHHOME=\$SSHHOME + bash --rcfile \$SSHHOME/sshrc.bashrc + " + else + echo "No such file: $SSHHOME/.sshrc" + fi +} +if [ "$1" ]; then + command -v xxd >/dev/null 2>&1 || { echo >&2 "sshrc requires xxd to be installed locally, but it's not. Aborting."; exit 1; } + moshrc "$@" +else + ssh +fi diff --git a/modules/mixins/dotfiles/bin/mpc b/modules/mixins/dotfiles/bin/mpc @@ -0,0 +1,3 @@ +#!/bin/sh +eval "$("$HOME/bin/amen-or-not")" +exec /usr/local/bin/mpc "$@" diff --git a/modules/mixins/dotfiles/bin/napkins b/modules/mixins/dotfiles/bin/napkins @@ -0,0 +1,11 @@ +#!/bin/bash +set -euo pipefail + +BLOG_DIR="${HOME}/src/codeberg.org/mtmn/napkins" + +pushd "${BLOG_DIR}" > /dev/null + +"$EDITOR" "$BLOG_DIR"/content + +make deploy +popd > /dev/null diff --git a/modules/mixins/dotfiles/bin/ncm b/modules/mixins/dotfiles/bin/ncm @@ -0,0 +1,3 @@ +#!/bin/sh +eval "$("$HOME/bin/amen-or-not")" +exec /usr/sbin/ncmpcpp "$@" diff --git a/modules/mixins/dotfiles/bin/nota b/modules/mixins/dotfiles/bin/nota @@ -0,0 +1,73 @@ +#!/bin/bash + +shopt -s nullglob + +config=${XDG_CONFIG_HOME:-"$HOME/.config"}/nota +[[ -f "$config" ]] && . "$config" + +data_base_dir=${XDG_DATA_HOME:-"$HOME/misc/notes"} +data_dir=$data_base_dir/nota + +mkdir -p "$data_dir" +cd -- "$data_dir" || exit + +: "${NOTA_READ_ONLY=0}" +: "${GPG=0}" + +editor=${EDITOR:-${VISUAL:-vi}} +(( GPG )) && editor=${PGP_EDITOR:-"$editor"} + +if (( NOTA_READ_ONLY )); then + # The linter is wrong here, we don't want to do $(cat). + # shellcheck disable=SC2209 + editor=cat + (( GPG )) && editor='gpg -q -d' +fi + +unsanitised_basename=${1:-"$(date +%F)"} + +case $unsanitised_basename in + git|ls) exec "$@" ;; + *' days ago'|yesterday|tomorrow|today) + unsanitised_basename=$(date -d "$unsanitised_basename" +%F) + ;; +esac + +basename=${unsanitised_basename//\//_} +file=$data_dir/$basename +(( GPG )) && file=$file.gpg +(( MARKDOWN )) && file=$file.md + +lock_base="$file.lock" +lock="$lock_base.$$" + +if ! (( NOTA_READ_ONLY )); then + for existing_lock_file in "$lock_base".*; do + pid=${existing_lock_file##*.} + if [[ -d "/proc/$pid" ]]; then + printf 'Refusing to open %s as it is locked\n' "$file" >&2 + exit 6 + else + printf 'Removing stale lock %s\n' "$existing_lock_file" >&2 + rmdir -- "$existing_lock_file" + fi + done + + trap 'rmdir -- "$lock"' EXIT + mkdir -- "$lock" +fi + +$editor -- "$file" + +(( NOTA_READ_ONLY )) && exit 0 + +if ! [[ -f "$file" ]]; then + printf 'Not committing as %s is missing\n' "$unsanitised_basename" >&2 + exit 5 +fi + +git init +git add "$file" +rmdir -- "$lock" +trap - EXIT +git commit -m "Updated $unsanitised_basename" diff --git a/modules/mixins/dotfiles/bin/nsxiv-rifle b/modules/mixins/dotfiles/bin/nsxiv-rifle @@ -0,0 +1,51 @@ +#!/bin/sh + +TMPDIR="${TMPDIR:-/tmp}" +tmp="$TMPDIR/nsxiv_rifle_$$" + +is_img_extension() { + grep -iE '\.(jpe?g|png|gif|svg|jxl|webp|tiff|heif|avif|ico|bmp|pam|pbm|ppm|tga|qoi|ff)$' +} + +listfiles() { + find -L "$1" -maxdepth 1 -type f -print | + is_img_extension | sort | tee "$tmp" +} + +open_img() { + file="$1"; shift; + # only go through listfiles() if the file has a valid img extension + if echo "$file" | is_img_extension >/dev/null 2>&1; then + trap 'rm -f $tmp' EXIT + count="$(listfiles "///${file%/*}" | grep -nF "$file")" + fi + if [ -n "$count" ]; then + nsxiv -i -n "${count%%:*}" "$@" < "$tmp" + else + # fallback incase file didn't have a valid extension, or we couldn't + # find it inside the list + nsxiv "$file" "$@" + fi +} + +uri2path() { + python3 - "$@" <<'___HEREDOC' +from urllib.parse import unquote, urlparse +from sys import argv +for arg in argv[1:]: + print(unquote(urlparse(arg).path)) +___HEREDOC +} + +file="$1"; shift; +case "$file" in + "") echo "Usage: ${0##*/} PICTURE [OPTIONS...]" >&2; exit 1 ;; + /*) open_img "$file" "$@" ;; + "~"/*) open_img "$HOME/${file#"~"/}" "$@" ;; + file:///*) open_img "$(uri2path "$file")" "$@" ;; + trash:///*) + trash_dir="${XDG_DATA_HOME:-$HOME/.local/share}/Trash/files" + open_img "${trash_dir}$(uri2path "$file")" -N "nsxiv_trash" "$@" + ;; + *) open_img "$PWD/$file" "$@" ;; +esac diff --git a/modules/mixins/dotfiles/bin/passmenu b/modules/mixins/dotfiles/bin/passmenu @@ -0,0 +1,26 @@ +#!/bin/bash +set -euo pipefail + +export PASSWORD_STORE_CLIP_TIME=60 +shopt -s nullglob globstar + +prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store}" +prefix="${prefix%/}/" + +if [ ! -d "$prefix" ]; then + echo "Error: Password store '$prefix' not found" >&2 + exit 1 +fi + +password_files=( "$prefix"**/*.gpg ) +password_files=( "${password_files[@]#"$prefix"}" ) +password_files=( "${password_files[@]%.gpg}" ) + +password=$(printf '%s\n' "${password_files[@]}" | dmenu "$@") +[ -z "$password" ] && exit 0 + +if [[ "$password" == *otp* ]]; then + pass otp -c "$password" >/dev/null 2>&1 +else + pass show -c "$password" >/dev/null 2>&1 +fi diff --git a/modules/mixins/dotfiles/bin/pinentry-bemenu b/modules/mixins/dotfiles/bin/pinentry-bemenu @@ -0,0 +1,2 @@ +#!/bin/bash +BEMENU_OPTS="-b --fn 'Ttyp0 OTB'" /usr/sbin/pinentry-bemenu "$@" diff --git a/modules/mixins/dotfiles/bin/plsmenu b/modules/mixins/dotfiles/bin/plsmenu @@ -0,0 +1,34 @@ +#!/bin/bash +set -euo pipefail + +month=$(date "+%B" | tr '[:upper:]' '[:lower:]') +year=$(date "+%y") +month_sanitized=".${month}_${year}" + +options=( + "$month_sanitized" + "infame" + "ambient" + "experimental" + "club" + "mud" + "weird" + "bass" + "140" + "match" + "sad" + "happy" + "screenshots" +) + +choice=$(printf '%s\n' "${options[@]}" | dmenu "$@") + +[ -z "$choice" ] && exit 0 + +if [ "$choice" = "$month" ]; then + playlist="$current_month_playlist" +else + playlist="$choice" +fi + +eval "$("$HOME/bin/amen-or-not")" && zsh -c "mpd_add_to_playlist '$playlist'" diff --git a/modules/mixins/dotfiles/bin/ptn b/modules/mixins/dotfiles/bin/ptn @@ -0,0 +1,2 @@ +#!/bin/sh +eval "$("$HOME/bin/amen-or-not")" && mpd_add_to_queue "$@" diff --git a/modules/mixins/dotfiles/bin/qw b/modules/mixins/dotfiles/bin/qw @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +qemu-system-x86_64 -M q35,usb=on,acpi=on,hpet=off -m 2G \ + -cpu host,hv_relaxed,hv_frequencies,hv_vpindex,hv_ipi,hv_tlbflush,hv_spinlocks=0x1fff,hv_synic,hv_runtime,hv_time,hv_stimer,hv_vapic \ + -smp cores=2 -accel kvm -drive file="$HOME"/misc/random/win7.qcow2 -device usb-tablet \ + -device VGA,vgamem_mb=128 -nic user,model=e1000 -monitor stdio \ + -device usb-ehci,id=ehci \ + -device usb-host,bus=ehci.0,vendorid=0x0781,productid=0x5588 \ + -audiodev pipewire,id=snd0 -device intel-hda -device hda-duplex,audiodev=snd0 \ + -drive file=fat:rw:"$HOME"/misc/random/qemu_shared/,format=raw,media=disk diff --git a/modules/mixins/dotfiles/bin/reaktor b/modules/mixins/dotfiles/bin/reaktor @@ -0,0 +1,9 @@ +#!/bin/bash +export STEAM_COMPAT_CLIENT_INSTALL_PATH="$HOME/.local/share/reaktor" +export STEAM_COMPAT_DATA_PATH="$HOME/.local/share/reaktor" + +export WINE="/usr/share/steam/compatibilitytools.d/proton-ge-custom/files/bin/wine" +export WINEPREFIX="$HOME/.local/share/reaktor/pfx" + +# winetricks -q vcrun2022 dotnet48 corefonts +"$WINE" "$WINEPREFIX/drive_c/Program Files/Native Instruments/Reaktor 6/Reaktor 6.exe" diff --git a/modules/mixins/dotfiles/bin/reaper b/modules/mixins/dotfiles/bin/reaper @@ -0,0 +1,8 @@ +#!/bin/bash +export STEAM_COMPAT_DATA_PATH="$HOME/.local/share/reaktor" +export STEAM_COMPAT_CLIENT_INSTALL_PATH="$HOME/.local/share/reaktor" + +export WINE="/usr/share/steam/compatibilitytools.d/proton-ge-custom/files/bin/wine" +export WINEPREFIX="$HOME/.local/share/reaktor/pfx" + +exec /usr/bin/reaper "$@" diff --git a/modules/mixins/dotfiles/bin/record b/modules/mixins/dotfiles/bin/record @@ -0,0 +1,4 @@ +#!/bin/sh +mkdir -p "$HOME"/misc/recordings +wf-recorder -g "$(slurp)" -c libx264 -p ultrafast -f recording.mp4 --audio=alsa_output.pci-0000_07_00.6.HiFi__Speaker__sink.monitor.monitor +mv recording.mp4 "$HOME"/misc/recordings/"$(date +%s)".mp4 diff --git a/modules/mixins/dotfiles/bin/recup b/modules/mixins/dotfiles/bin/recup @@ -0,0 +1,10 @@ +#!/bin/sh +cd ~/misc/recordings || exit 1 + +PICKED=$(eza --oneline --reverse --sort=created | fzf --reverse --preview='stat {}') + +if [ -n "$PICKED" ]; then + aws s3 cp "$PICKED" "s3://mine/recordings/$PICKED" + shirt "$(aws s3 presign "s3://mine/recordings/$PICKED" --expires-in 604800 | tr -d '\n')" + +fi diff --git a/modules/mixins/dotfiles/bin/remind b/modules/mixins/dotfiles/bin/remind @@ -0,0 +1,70 @@ +#!/bin/bash + +# Simple reminder tool that stores reminders in a file and triggers notify-send alerts +# Usage: remind <time> "<message>" +# Examples: +# remind 30m "Take a break" +# remind 18:50 "Time to leave" + +# Configuration +REMINDER_FILE="$HOME/.reminders" +LOG_FILE="$HOME/.remind_history" + +# Check if parameters are provided +if [ $# -lt 2 ]; then + echo "Usage: remind <time> \"<message>\"" + echo "Time formats: 30s, 5m, 2h, 1d, or HH:MM" + exit 1 +fi + +# Parse time and message +TIME="$1" +MESSAGE="$2" + +# Check if the time is in HH:MM format +if [[ "$TIME" =~ ^([0-1][0-9]|2[0-3]):([0-5][0-9])$ ]]; then + # Calculate seconds until the specified time + CURRENT_TIME=$(date +%s) + TARGET_TIME=$(date -d "$(date +%Y-%m-%d) $TIME" +%s) + + # If the target time is already passed for today, schedule for tomorrow + if [ $TARGET_TIME -le $CURRENT_TIME ]; then + TARGET_TIME=$(date -d "$(date -d 'tomorrow' +%Y-%m-%d) $TIME" +%s) + fi + + SECONDS=$((TARGET_TIME - CURRENT_TIME)) + TRIGGER_TIME=$(date -d "@$TARGET_TIME" "+%Y-%m-%d %H:%M:%S") + SLEEP_ARG="${SECONDS}s" +else + # Handle relative time formats (30s, 5m, 2h, 1d) + case "$TIME" in + *s) SECONDS="${TIME%s}" ;; + *m) SECONDS=$((${TIME%m} * 60)) ;; + *h) SECONDS=$((${TIME%h} * 3600)) ;; + *d) SECONDS=$((${TIME%d} * 86400)) ;; + *) SECONDS="$TIME" ;; + esac + + TRIGGER_TIME=$(date -d "+$SECONDS seconds" "+%Y-%m-%d %H:%M:%S") + SLEEP_ARG="$TIME" +fi + +# Create the reminder files if they don't exist +touch "$REMINDER_FILE" +touch "$LOG_FILE" + +# Log the reminder +echo "[$TRIGGER_TIME] $MESSAGE" >> "$LOG_FILE" + +# Schedule the notification +( + sleep "$SLEEP_ARG" + notify-send -u critical "Reminder" "$MESSAGE" + echo "Completed: [$TRIGGER_TIME] $MESSAGE" >> "$LOG_FILE" + # Remove from active reminders file once completed + sed -i "\|^\[$TRIGGER_TIME\] $MESSAGE$|d" "$REMINDER_FILE" +) & + +# Show confirmation +echo "Reminder set for $TRIGGER_TIME: $MESSAGE" +echo "[$TRIGGER_TIME] $MESSAGE" >> "$REMINDER_FILE" diff --git a/modules/mixins/dotfiles/bin/screenshot b/modules/mixins/dotfiles/bin/screenshot @@ -0,0 +1,41 @@ +#!/bin/bash + +timestamp=$(date +%s) +screenshot_file="$HOME/misc/screenshots/${timestamp}.png" + +take_screenshot() { + local temp_file="$1" + + if [ -n "$WAYLAND_DISPLAY" ]; then + area=$(slurp 2>/dev/null) || return 1 + grim -g "$area" "$temp_file" || return 1 + else + selection=$(hacksaw -f "-i %i -g %g" 2>/dev/null) || return 1 + shotgun "$selection" "$temp_file" || return 1 + fi + + return 0 +} + +copy_to_clipboard() { + local file="$1" + + if [ -n "$WAYLAND_DISPLAY" ]; then + wl-copy < "$file" + else + xclip -t 'image/png' -selection clipboard < "$file" + fi +} + +if take_screenshot "$screenshot_file"; then + if [ -f "$screenshot_file" ] && [ -s "$screenshot_file" ]; then + copy_to_clipboard "$screenshot_file" + else + rm -f "$screenshot_file" + echo "no content captured" >&2 + exit 1 + fi +else + echo "screenshot cancelled or failed" + exit 1 +fi diff --git a/modules/mixins/dotfiles/bin/scup b/modules/mixins/dotfiles/bin/scup @@ -0,0 +1,9 @@ +#!/bin/sh +cd ~/misc/screenshots || exit 1 + +PICKED=$(eza --oneline --reverse --sort=created | fzf --reverse --preview='stat {}') + +if [ -n "$PICKED" ]; then + aws s3 cp "$PICKED" "s3://mine/screenshots/$PICKED" + shirt "$(aws s3 presign "s3://mine/screenshots/$PICKED" --expires-in 604800 | tr -d '\n')" +fi diff --git a/modules/mixins/dotfiles/bin/seek b/modules/mixins/dotfiles/bin/seek @@ -0,0 +1,54 @@ +#!/bin/bash + + +if [ $# -eq 0 ]; then + echo "Usage: $0 <percentage>" + echo "Example: $0 25 # seeks to 25% of current track" + exit 1 +fi + +percentage=$1 + +if ! [[ "$percentage" =~ ^[0-9]+(\.[0-9]+)?$ ]] || (( $(echo "$percentage > 100" | bc -l) )); then + echo "Error: Please provide a valid percentage (0-100)" + exit 1 +fi + +status=$(mpc status) + +if ! echo "$status" | grep -q "playing\|paused"; then + echo "Error: No track is currently loaded" + exit 1 +fi + +time_info=$(echo "$status" | grep -o '[0-9]*:[0-9]*/[0-9]*:[0-9]*') + +if [ -z "$time_info" ]; then + echo "Error: Could not get track duration information" + exit 1 +fi + +total_time=$(echo "$time_info" | cut -d'/' -f2) + +# Convert total time to seconds +IFS=':' read -ra time_parts <<< "$total_time" +if [ ${#time_parts[@]} -eq 2 ]; then + # Format is MM:SS + total_seconds=$((${time_parts[0]} * 60 + ${time_parts[1]})) +elif [ ${#time_parts[@]} -eq 3 ]; then + # Format is HH:MM:SS + total_seconds=$((${time_parts[0]} * 3600 + ${time_parts[1]} * 60 + ${time_parts[2]})) +else + echo "Error: Could not parse time format" + exit 1 +fi + +# Calculate target position in seconds +target_seconds=$(echo "scale=0; $total_seconds * $percentage / 100" | bc) + +# Convert back to MM:SS format for mpc +target_minutes=$((target_seconds / 60)) +target_seconds_remainder=$((target_seconds % 60)) +target_time=$(printf "%d:%02d" $target_minutes $target_seconds_remainder) + +mpc seek "$target_time" diff --git a/modules/mixins/dotfiles/bin/sft b/modules/mixins/dotfiles/bin/sft @@ -0,0 +1,2 @@ +#!/bin/sh +eval "$("$HOME/bin/amen-or-not")" && saturn_fetch_tracks "$@" diff --git a/modules/mixins/dotfiles/bin/speedread b/modules/mixins/dotfiles/bin/speedread @@ -0,0 +1,283 @@ +#!/usr/bin/env perl +# +# speedread: A simple terminal-based open source spritz-alike +# +# Show input text as a per-word RSVP (rapid serial visual presentation) +# aligned on optimal reading points. This kind of input mode allows +# reading text at a much more rapid pace than usual as the eye can +# stay fixed on a single place. +# +# (c) Petr Baudis <pasky@ucw.cz> 2014 +# MIT licence +# +# Usage: cat file.txt | speedread [-w WORDSPERMINUTE] [-r RESUMEPOINT] [-m] +# +# The default of 250 words per minut is very timid, designed so that +# you get used to this. Be sure to try cranking this up, 500wpm +# should still be fairly easy to follow even for beginners. +# +# speedread can join short words together if you specify the -m switch. +# It did not work well for pasky so far, though. +# +# speedread is slightly interactive, with these controls accepted: +# +# [ - slow down by 10% +# ] - speed up by 10% +# space - pause (and show the last two lines) + +use warnings; +use strict; +use autodie; +use v5.14; + +my $wpm = 250; +my $resume = 0; +my $multiword = 0; + + +use utf8; +binmode(STDIN, ":encoding(UTF-8)"); +binmode(STDOUT, ":encoding(UTF-8)"); + +use Term::ANSIColor; +use POSIX qw(ceil floor); +use Time::HiRes qw(time sleep gettimeofday tv_interval); + +use Getopt::Long; +GetOptions("wpm|w=i" => \$wpm, + "resume|r=i" => \$resume, + "multiword|m" => \$multiword); + +my $wordtime = 0.9; # relative to wpm +my $lentime = 0.04; # * sqrt(length $word), relative to wpm +my $commatime = 2; # relative to wpm +my $fstoptime = 3; # relative to wpm +my $multitime = 1.2; # relative to wpm +my $firsttime = 0.2; # [s] +my $ORPloc = 0.35; +my $ORPmax = 0.2; +my $ORPvisualpos = 20; +my $cursorpos = 64; +my $paused = 0; +my $current_word; +my $current_orp; +my $next_word_time = 0; +my $next_input_time = 0; +my $skipped = 0; + +my @lastlines; +my $tty = rawinput->new(); +$| = 1; + +my $wordcounter = 0; +my $lettercounter = 0; +my $t0 = [gettimeofday]; +sub print_stats { + my $elapsed = tv_interval($t0, [gettimeofday]); + my $truewpm = $wordcounter / $elapsed * 60; + printf("\n %.2fs, %d words, %d letters, %s%.2f%s true wpm\n", + $elapsed, $wordcounter, $lettercounter, + color('bold green'), $truewpm, color('reset')); +} +$SIG{INT} = sub { + print_stats; + my $resume_word = $wordcounter + $resume; + say " To resume from this point run with argument -r $resume_word"; + exit; +}; + +main(); + +# ORP: Optical Recognition Point (the red-colored alignment pilot), +# the way Spritz probably does it. +sub find_ORP { + my ($word, $ORPloc) = @_; + + return 4 if (length($word) > 13); + return (0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3)[length($word)]; +} + +sub show_guide { + # Top visual guide + say(" "x$ORPvisualpos . color('red') . "v" . color('reset') . "\033[K"); +} + +sub show_word { + my ($word, $i) = @_; + + my $pivotch = substr($word, $i, 1); + $pivotch = "·" if $pivotch eq ' '; + + print("\r\033[K" + . " " x ($ORPvisualpos - $i) + . color("bold") + . substr($word, 0, $i) + . color("red") + . $pivotch + . color("reset") + . color("bold") + . substr($word, $i+1) + . color("reset") + . " " x ($cursorpos - (($ORPvisualpos - $i) + length($word))) + . "$wpm wpm" + . ($paused ? " ".color("yellow")."PAUSED".color("reset") : "")); +} + +sub word_time { + my ($word) = @_; + + my $time = $wordtime; + if ($word =~ /[.?!]\W*$/) { + $time = $fstoptime; + } elsif ($word =~ /[:;,]\W*$/) { + $time = $commatime; + } elsif ($word =~ / /) { + $time = $multitime; + } + $time += sqrt(length($word)) * $lentime; + $time *= 60 / $wpm; + + # Give user some time to focus on the first word, even with high wpm. + $time = $firsttime if ($wordcounter == 0 and $time < $firsttime); + + return $time; +} + +sub print_context { + my ($wn) = @_; + # One line up and to its beginning + print "\r\033[K\033[A\033[K"; + # First line of context + say $lastlines[1] if $lastlines[1]; + # In second line of context, highlight our word + my $line0 = $lastlines[0]; + my $c0 = color('yellow'); + my $c1 = color('reset'); + $line0 =~ s/^((?:.*?(?:-|\s)+){$wn})(.*?)(-|\s)/$1$c0$2$c1$3/; + say $line0; +} + +sub process_keys { + my ($word, $i, $wn) = @_; + while ($tty->key_pressed()) { + my $ch = $tty->getch(); + if ($ch eq '[') { + $wpm = int($wpm * 0.9); + + } elsif ($ch eq ']') { + $wpm = int($wpm * 1.1); + + } elsif ($ch eq ' ') { + $paused = not $paused; + if ($paused) { + # Print context. + print_context($wn); + show_guide(); + show_word($word, $i); + } + else { + $next_word_time = time(); + } + } + } +} + +sub main { + show_guide(); + + $next_word_time = time(); + $next_input_time = time(); + + while (<>) { + chomp; + + unshift @lastlines, $_; + pop @lastlines if @lastlines > 2; + + my (@words) = grep { /./ } split /(?:-|\s)+/; + + if ($multiword) { + # Join adjecent short words + for (my $i = 0; $i < $#words - 1; $i++) { + if (length($words[$i]) <= 3 and length($words[$i+1]) <= 3) { + $words[$i] .= ' ' . $words[$i+1]; + splice(@words, $i+1, 1); + } + } + } + + my $wn = 0; + while (scalar(@words) > 0) { + if ($skipped < $resume) { + $skipped++; + shift @words; + next; + } + + my $current_time = time(); + + if ($next_word_time <= $current_time and !$paused) { + $current_word = shift @words; + $current_orp = find_ORP($current_word, $ORPloc); + $next_word_time += word_time($current_word); + $wordcounter++; + $lettercounter += length($current_word); + $wn++; + } + + if ($next_input_time <= $current_time) { + process_keys($current_word, $current_orp, $wn); + $next_input_time += 0.05; # checking for input 20 times / second seems to give a reasonably responsive UI + } + + # redrawing the word on each "frame" gives a more responsive UI + # (we don't have to wait for the word to change to display changed stats like wpm) + show_word($current_word, $current_orp); + + my $sleep_time = ($next_word_time < $next_input_time and !$paused) ? $next_word_time-$current_time : $next_input_time-$current_time; + sleep($sleep_time) if ($sleep_time > 0); + } + } + + print_stats(); + sleep(1); +} + + +package rawinput; + +# An ad-hoc interface to interactive terminal input. Term::Screen *should* +# have been a natural choice here, unfortunately it is fixated at reading +# from stdin instead of /dev/tty. Tough. + +sub new { + my $class = shift; + my $self; + open $self, '/dev/tty'; + bless $self, $class; + stty('min 1', '-icanon', '-echo'); + return $self; +} + +sub DESTROY { + stty('cooked', 'echo'); +} + +sub stty { + my $self = shift; + eval { system('stty', $^O eq 'darwin' ? '-f' : '-F', '/dev/tty', @_); }; +} + +sub key_pressed { + my $self = shift; + my $readfields = ''; + vec($readfields, fileno($self), 1) = 1; + my $ready = 0; + eval { $ready = select($readfields, undef, undef, 0); }; + return $ready; +} + +sub getch { + my $self = shift; + getc($self); +} diff --git a/modules/mixins/dotfiles/bin/sshrc b/modules/mixins/dotfiles/bin/sshrc @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +function sshrc() { + local SSHHOME=${SSHHOME:=~} + if [ -f $SSHHOME/.sshrc ]; then + local files=.sshrc + if [ -d $SSHHOME/.sshrc.d ]; then + files="$files .sshrc.d" + fi + SIZE=$(tar cfz - -h -C $SSHHOME $files | wc -c) + if [ $SIZE -gt 65536 ]; then + echo >&2 $'.sshrc.d and .sshrc files must be less than 64kb\ncurrent size: '$SIZE' bytes' + exit 1 + fi + if [ -z "$CMDARG" -a ! -e ~/.sshrc.d/.hushlogin ]; then + WELCOME_MSG=" + if [ ! -e ~/.hushlogin ]; then + if [ -e /etc/motd ]; then cat /etc/motd; fi + if [ -e /etc/update-motd.d ]; then run-parts /etc/update-motd.d/ 2>/dev/null; fi + last -F \$USER 2>/dev/null | grep -v 'still logged in' | head -n1 | awk '{print \"Last login:\",\$4,\$5,\$6,\$7,\$8,\"from\",\$3;}' + fi + " + else + WELCOME_MSG="" + fi + ssh -t "$DOMAIN" $SSHARGS " + command -v openssl >/dev/null 2>&1 || { echo >&2 \"sshrc requires openssl to be installed on the server, but it's not. Aborting.\"; exit 1; } + $WELCOME_MSG + export SSHHOME=\$(mktemp -d -t .$(whoami).sshrc.XXXX) + export SSHRCCLEANUP=\$SSHHOME + trap \"rm -rf \$SSHRCCLEANUP; exit\" 0 + echo $'"$(cat "$0" | openssl enc -base64)"' | tr -s ' ' $'\n' | openssl enc -base64 -d > \$SSHHOME/sshrc + chmod +x \$SSHHOME/sshrc + echo $'"$( cat << 'EOF' | openssl enc -base64 + if [ -r /etc/profile ]; then source /etc/profile; fi + if [ -r ~/.bash_profile ]; then source ~/.bash_profile + elif [ -r ~/.bash_login ]; then source ~/.bash_login + elif [ -r ~/.profile ]; then source ~/.profile + fi + export PATH=$PATH:$SSHHOME + source $SSHHOME/.sshrc; +EOF + )"' | tr -s ' ' $'\n' | openssl enc -base64 -d > \$SSHHOME/sshrc.bashrc + echo $'"$( cat << 'EOF' | openssl enc -base64 +#!/usr/bin/env bash + exec bash --rcfile <(echo ' + [ -r /etc/profile ] && source /etc/profile + if [ -r ~/.bash_profile ]; then source ~/.bash_profile + elif [ -r ~/.bash_login ]; then source ~/.bash_login + elif [ -r ~/.profile ]; then source ~/.profile + fi + source '$SSHHOME'/.sshrc; + export PATH=$PATH:'$SSHHOME' + ') ${@:+"$@"} +EOF + )"' | tr -s ' ' $'\n' | openssl enc -base64 -d > \$SSHHOME/bashsshrc + chmod +x \$SSHHOME/bashsshrc + echo $'"$(tar czf - -h -C $SSHHOME $files | openssl enc -base64)"' | tr -s ' ' $'\n' | openssl enc -base64 -d | tar mxzf - -C \$SSHHOME + export SSHHOME=\$SSHHOME + echo \"$CMDARG\" >> \$SSHHOME/sshrc.bashrc + bash --rcfile \$SSHHOME/sshrc.bashrc + " + else + echo "No such file: $SSHHOME/.sshrc" >&2 + exit 1 + fi +} +function sshrc_parse() { + while [[ -n $1 ]]; do + case $1 in + -b | -c | -D | -E | -e | -F | -I | -i | -J | -L | -l | -m | -O | -o | -p | -Q | -R | -S | -W | -w ) + SSHARGS="$SSHARGS $1 $2"; shift ;; + -* ) + SSHARGS="$SSHARGS $1" ;; + *) + if [ -z "$DOMAIN" ]; then + DOMAIN="$1" + else + local SEMICOLON=$([[ "$@" = *[![:space:]]* ]] && echo '; ') + CMDARG="$@$SEMICOLON exit" + return; + fi + ;; + esac + shift + done + if [ -z $DOMAIN ]; then + ssh $SSHARGS; exit 1; + fi +} +command -v openssl >/dev/null 2>&1 || { echo >&2 "sshrc requires openssl to be installed locally, but it's not. Aborting."; exit 1; } +sshrc_parse "$@" +sshrc diff --git a/modules/mixins/dotfiles/bin/tempmenu b/modules/mixins/dotfiles/bin/tempmenu @@ -0,0 +1,24 @@ +#!/bin/bash +set -euo pipefail + +choices=$(echo "off"; seq 6000 -500 1000) +chosen=$(printf '%s\n' "$choices" | dmenu "$@") +[ -z "$chosen" ] && exit 0 + +if [ "$chosen" != "off" ] && ! [[ "$chosen" =~ ^[0-9]+$ ]]; then + echo "Error: Invalid temperature '$chosen'" >&2 + exit 1 +fi + +if [ -n "${WAYLAND_DISPLAY:-}" ]; then + pkill gammastep || true + if [ "$chosen" != "off" ]; then + gammastep -O "$chosen" & + fi +else + if [ "$chosen" = "off" ]; then + redshift -x + else + redshift -O "$chosen" + fi +fi diff --git a/modules/mixins/dotfiles/bin/todo-notify b/modules/mixins/dotfiles/bin/todo-notify @@ -0,0 +1,14 @@ +#!/bin/bash + +TODO_FILE="$HOME/misc/notes/nota/todo.txt" +current_date="" + +while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then + current_date="$line" + elif [[ "$line" =~ ^todo:\ (.*)$ ]]; then + todo_message="${BASH_REMATCH[1]}" + notify-send "$current_date" "$todo_message" + wait + fi +done < "$TODO_FILE" diff --git a/modules/mixins/dotfiles/bin/todomenu b/modules/mixins/dotfiles/bin/todomenu @@ -0,0 +1,6 @@ +#!/bin/sh +todo_file=~/misc/notes/nota/todo.txt + +if item=$(dmenu "$@" < /dev/null) && [ -n "$item" ]; then + printf "\n%s\ntodo: %s" "$(date --rfc-3339=s)" "$item" >> "$todo_file" +fi diff --git a/modules/mixins/dotfiles/bin/tw b/modules/mixins/dotfiles/bin/tw @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +import sys +import os +import urllib.request +import urllib.error +from typing import cast +from http.client import HTTPResponse +from concurrent.futures import ThreadPoolExecutor, as_completed + + +def read_channels_file(filepath: str) -> list[tuple[str, str]]: + channels: list[tuple[str, str]] = [] + if not os.path.isfile(filepath): + return channels + + with open(filepath, "r") as f: + for line in f: + line = line.strip() + if not line: + continue + parts = line.split(None, 1) + channel = parts[0] + description = parts[1] if len(parts) > 1 else "" + channels.append((channel, description)) + + return channels + + +def check_channel_status(channel: str, description: str) -> tuple[str, str, bool]: + try: + url = f"https://www.twitch.tv/{channel}" + req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) + with cast(HTTPResponse, urllib.request.urlopen(req, timeout=10)) as response: + content: str = response.read().decode("utf-8", errors="ignore") + is_online: bool = "isLiveBroadcast" in content + return (channel, description, is_online) + except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError): + return (channel, description, False) + + +def main(): + channels_file = os.path.expanduser("~/.config/twitch/channels") + if not os.path.isfile(channels_file): + print("Error: ~/.config/twitch/channels not found", file=sys.stderr) + sys.exit(1) + + channels = read_channels_file(channels_file) + if not channels: + return + + max_workers = 10 + + with ThreadPoolExecutor(max_workers=max_workers) as executor: + future_to_channel = { + executor.submit(check_channel_status, channel, description): ( + channel, + description, + ) + for channel, description in channels + } + + for future in as_completed(future_to_channel): + channel, description, is_online = future.result() + + if is_online: + if description: + print(f"{channel} ({description}) is online") + else: + print(f"{channel} is online") + + +if __name__ == "__main__": + main() diff --git a/modules/mixins/dotfiles/config/aerc/aerc.conf b/modules/mixins/dotfiles/config/aerc/aerc.conf @@ -0,0 +1,33 @@ +[general] +use-envelope-from = true +pgp-provider=gpg + +#log-file= +#log-level=info + +[ui] +border-char-vertical="│" +border-char-horizontal="─" +styleset-name=mine + +[viewer] +pager=moor +alternatives=text/html,text/plain +header-layout=From|To,Cc|Bcc,Date,Subject + +[compose] +address-book-cmd=khard email --parsable --remove-first-line %s +editor=nvim + +[filters] +text/plain=bat -P --style=plain +text/calendar=calendar +message/delivery-status=colorize +message/rfc822=colorize +text/html=pandoc -f html -t plain + +[openers] +x-scheme-handler/http*=printf '%s' {} | wl-copy + +[hooks] +mail-received=[ "$AERC_ACCOUNT" = "fastmail" ] && notify-send -a aerc "$AERC_FROM_ADDRESS" "$AERC_SUBJECT" || true diff --git a/modules/mixins/dotfiles/config/aerc/binds.conf b/modules/mixins/dotfiles/config/aerc/binds.conf @@ -0,0 +1,187 @@ +# Binds are of the form <key sequence> = <command to run> +# To use '=' in a key sequence, substitute it with "Eq": "<Ctrl+Eq>" +# If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit +<C-p> = :prev-tab<Enter> +<C-PgUp> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> +<C-PgDn> = :next-tab<Enter> +\[t = :prev-tab<Enter> +\]t = :next-tab<Enter> +<C-t> = :term<Enter> +? = :help keys<Enter> +<C-c> = :prompt 'Quit?' quit<Enter> +<C-q> = :prompt 'Quit?' quit<Enter> +<C-z> = :suspend<Enter> + +[messages] +q = :prompt 'Quit?' quit<Enter> + +j = :next<Enter> +<Down> = :next<Enter> +<C-d> = :next 50%<Enter> +<C-f> = :next 100%<Enter> +<PgDn> = :next 100%<Enter> + +k = :prev<Enter> +<Up> = :prev<Enter> +<C-u> = :prev 50%<Enter> +<C-b> = :prev 100%<Enter> +<PgUp> = :prev 100%<Enter> +g = :select 0<Enter> +G = :select -1<Enter> + +J = :next-folder<Enter> +<C-Down> = :next-folder<Enter> +K = :prev-folder<Enter> +<C-Up> = :prev-folder<Enter> +H = :collapse-folder<Enter> +<C-Left> = :collapse-folder<Enter> +L = :expand-folder<Enter> +<C-Right> = :expand-folder<Enter> + +v = :mark -t<Enter> +<Space> = :mark -t<Enter>:next<Enter> +V = :mark -v<Enter> + +T = :toggle-threads<Enter> +zc = :fold<Enter> +zo = :unfold<Enter> +za = :fold -t<Enter> +zM = :fold -a<Enter> +zR = :unfold -a<Enter> +<tab> = :fold -t<Enter> + +zz = :align center<Enter> +zt = :align top<Enter> +zb = :align bottom<Enter> + +<Enter> = :view<Enter> +d = :choose -o y 'Really delete this message' delete-message<Enter> +D = :delete<Enter> +a = :archive flat<Enter> +A = :unmark -a<Enter>:mark -T<Enter>:archive flat<Enter> + +C = :compose<Enter> +m = :compose<Enter> + +b = :bounce<space> + +rr = :reply -a<Enter> +rq = :reply -aq<Enter> +Rr = :reply<Enter> +Rq = :reply -q<Enter> + +c = :cf<space> +$ = :term<space> +! = :term<space> +| = :pipe<space> + +/ = :search<space> +\ = :filter<space> +n = :next-result<Enter> +N = :prev-result<Enter> +<Esc> = :clear<Enter> + +s = :split<Enter> +S = :vsplit<Enter> + +pl = :patch list<Enter> +pa = :patch apply <Tab> +pd = :patch drop <Tab> +pb = :patch rebase<Enter> +pt = :patch term<Enter> +ps = :patch switch <Tab> + +[messages:folder=Drafts] +<Enter> = :recall<Enter> + +[view] +/ = :toggle-key-passthrough<Enter>/ +q = :close<Enter> +O = :open<Enter> +o = :open<Enter> +S = :save<space> +| = :pipe<space> +D = :delete<Enter> +A = :archive flat<Enter> + +<C-y> = :copy-link <space> +<C-l> = :open-link <space> + +f = :forward<Enter> +rr = :reply -a<Enter> +rq = :reply -aq<Enter> +Rr = :reply<Enter> +Rq = :reply -q<Enter> + +H = :toggle-headers<Enter> +<C-k> = :prev-part<Enter> +<C-Up> = :prev-part<Enter> +<C-j> = :next-part<Enter> +<C-Down> = :next-part<Enter> +J = :next<Enter> +<C-Right> = :next<Enter> +K = :prev<Enter> +<C-Left> = :prev<Enter> + +[view::passthrough] +$noinherit = true +$ex = <C-x> +<Esc> = :toggle-key-passthrough<Enter> + +[compose] +# Keybindings used when the embedded terminal is not selected in the compose +# view +$noinherit = true +$ex = <C-x> +$complete = <C-o> +<C-k> = :prev-field<Enter> +<C-Up> = :prev-field<Enter> +<C-j> = :next-field<Enter> +<C-Down> = :next-field<Enter> +<A-p> = :switch-account -p<Enter> +<C-Left> = :switch-account -p<Enter> +<A-n> = :switch-account -n<Enter> +<C-Right> = :switch-account -n<Enter> +<tab> = :next-field<Enter> +<backtab> = :prev-field<Enter> +<C-p> = :prev-tab<Enter> +<C-PgUp> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> +<C-PgDn> = :next-tab<Enter> + +[compose::editor] +# Keybindings used when the embedded terminal is selected in the compose view +$noinherit = true +$ex = <C-x> +<C-k> = :prev-field<Enter> +<C-Up> = :prev-field<Enter> +<C-j> = :next-field<Enter> +<C-Down> = :next-field<Enter> +<C-p> = :prev-tab<Enter> +<C-PgUp> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> +<C-PgDn> = :next-tab<Enter> + +[compose::review] +# Keybindings used when reviewing a message to be sent +# Inline comments are used as descriptions on the review screen +y = :send<Enter> # Send +n = :abort<Enter> # Abort (discard message, no confirmation) +s = :sign<Enter> # Toggle signing +x = :encrypt<Enter> # Toggle encryption to all recipients +v = :preview<Enter> # Preview message +p = :postpone<Enter> # Postpone +q = :choose -o d discard abort -o p postpone postpone<Enter> # Abort or postpone +e = :edit<Enter> # Edit (body and headers) +a = :attach<space> # Add attachment +d = :detach<space> # Remove attachment + +[terminal] +$noinherit = true +$ex = <C-x> + +<C-p> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> +<C-PgUp> = :prev-tab<Enter> +<C-PgDn> = :next-tab<Enter> diff --git a/modules/mixins/dotfiles/config/aerc/stylesets/mine b/modules/mixins/dotfiles/config/aerc/stylesets/mine @@ -0,0 +1,61 @@ +*.default=true +*.normal=true +*.fg = #dfd0d5 +*.selected.bg = #15050f +*.selected.fg = #dfd0d5 +title.bg=#7a3f6a +title.fg=#dfd0d5 +title.bold=true +header.bold=true +header.fg=#3fafcf +header.bg=#15050f +border.bg=#282026 +border.fg=#282026 +tab.selected.fg=#dfd0d5 +tab.selected.bg=#7a3f6a +tab.selected.bold=true +dirlist*.selected.bg=#282026 +dirlist*.selected.fg=#dfd0d5 +dirlist*.selected.bold=false +*error.bold=true +*error.fg=#cf4f5f +*warning.fg=#df8f6f +*success.fg=#00b066 +statusline_*.bg=#282026 +statusline_*.fg=#dfd0d5 +statusline_error.fg=#cf4f5f +msglist_unread.fg=#c87ab0 +msglist_unread.bold=true +msglist_read.fg=#908890 +msglist_deleted.fg=#282026 +msglist_*.selected.bg=#282026 +msglist_marked.fg=#2fa526 +msglist_marked.selected.fg=#dfd0d5 +msglist_marked.bg=#7a3f6a +msglist_marked.selected.bg=#c87ab0 +completion_pill.reverse=false +selector_focused.bold=false +selector_focused.bg=#282026 +selector_focused.fg=#dfd0d5 +selector_chooser.bold=false +selector_chooser.bg=#282026 +selector_chooser.fg=#dfd0d5 +default.selected.bold=false +default.selected.bg=#282026 +default.selected.fg=#dfd0d5 +completion_default.selected.bg=#7a3f6a +[viewer] +*.default=true +*.normal=true +url.fg = #c87ab0 +header.fg = #3fafcf +signature.fg = #b0648f +diff_chunk.fg = #3fafcf +diff_chunk_func.fg = #c48702 +diff_add.fg = #00b066 +diff_del.fg = #cf4f5f +quote_1.fg = #00b066 +quote_2.fg = #3fafcf +quote_3.fg = #b0648f +quote_4.fg = #c48702 +quote_x.fg = #908890 diff --git a/modules/mixins/dotfiles/config/bash/.keep b/modules/mixins/dotfiles/config/bash/.keep diff --git a/modules/mixins/dotfiles/config/bash/rc/.keep b/modules/mixins/dotfiles/config/bash/rc/.keep diff --git a/modules/mixins/dotfiles/config/bash/rc/completion b/modules/mixins/dotfiles/config/bash/rc/completion @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ -r /usr/share/bash-completion/bash_completion ]]; then + . /usr/share/bash-completion/bash_completion +elif [[ -r /etc/bash_completion ]]; then + . /etc/bash_completion +fi diff --git a/modules/mixins/dotfiles/config/bash/rc/history b/modules/mixins/dotfiles/config/bash/rc/history @@ -0,0 +1,9 @@ +#!/bin/bash + +set +H + +HISTSIZE=50000 +HISTFILESIZE=$HISTSIZE +HISTCONTROL=ignoreboth + +shopt -s histappend diff --git a/modules/mixins/dotfiles/config/bash/rc/options b/modules/mixins/dotfiles/config/bash/rc/options @@ -0,0 +1,5 @@ +#!/bin/bash + +shopt -s extglob +shopt -s globstar +set -o noclobber diff --git a/modules/mixins/dotfiles/config/bat/config b/modules/mixins/dotfiles/config/bat/config @@ -0,0 +1,2 @@ +--theme="magnolia" +--color="always" diff --git a/modules/mixins/dotfiles/config/bat/themes/magnolia.tmTheme b/modules/mixins/dotfiles/config/bat/themes/magnolia.tmTheme @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>name</key> + <string>magnolia</string> + <key>settings</key> + <array> + <dict> + <key>settings</key> + <dict> + <key>background</key> + <string>#2a1f2e</string> + <key>divider</key> + <string>#3d2a42</string> + <key>foreground</key> + <string>#c8b8bf</string> + <key>caret</key> + <string>#f0dfe5</string> + <key>invisibles</key> + <string>#3d2a42</string> + <key>lineHighlight</key> + <string>#3d2a42</string> + <key>selection</key> + <string>#c084b8</string> + <key>selectionForeground</key> + <string>#f0dfe5</string> + </dict> + </dict> + <dict> + <key>name</key> + <string>Comments</string> + <key>scope</key> + <string>comment</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#7a6e7a</string> + </dict> + </dict> + <dict> + <key>name</key> + <string>Keywords</string> + <key>scope</key> + <string>keyword, storage.type, storage.modifier</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#c084b8</string> + </dict> + </dict> + <dict> + <key>name</key> + <string>Strings</string> + <key>scope</key> + <string>string</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#e08060</string> + </dict> + </dict> + <dict> + <key>name</key> + <string>Functions</string> + <key>scope</key> + <string>entity.name.function, support.function</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#7a9fd4</string> + </dict> + </dict> + <dict> + <key>name</key> + <string>Types</string> + <key>scope</key> + <string>entity.name.type, entity.other.inherited-class, support.type, support.class</string> + <key>settings</key> + <dict> + <key>foreground</key> + <string>#c4607a</string> + </dict> + </dict> + </array> +</dict> +</plist> diff --git a/modules/mixins/dotfiles/config/battery-notify/config.toml b/modules/mixins/dotfiles/config/battery-notify/config.toml @@ -0,0 +1,6 @@ +sleep_command = "systemctl suspend" +interval_secs = 30 +sleep_pct = 15 +low_pct = 40 +warn_on_mons_with_no_ac = 0 +bluetooth_low_pct = 40 diff --git a/modules/mixins/dotfiles/config/bcrc b/modules/mixins/dotfiles/config/bcrc @@ -0,0 +1 @@ +scale=2 diff --git a/modules/mixins/dotfiles/config/dunst/dunstrc b/modules/mixins/dotfiles/config/dunst/dunstrc @@ -0,0 +1,47 @@ +[global] +font = Comic Code 14 +word_wrap = yes +padding = 8 +horizontal_padding = 8 +separator_color = auto +timeout = 10 +follow = keyboard +icon_position = off +width = (0, 700) +height = (0, 800) +origin = top-right +offset = (15, 15) +scale = 0 +notification_limit = 5 +frame_width = 0 +show_indicators = no +stack_duplicates = no + +[urgency_low] + background = "#334c50" + foreground = "#d7dfd9" + timeout = 30 + +[urgency_normal] + background = "#334c50" + foreground = "#d7dfd9" + timeout = 30 + +[urgency_critical] + background = "#671822" + foreground = "#d7dfd9" + timeout = 0 + +[khal_notifier] + appname = khal_notifier + urgency = normal + background = "#7a3f6a" + foreground = "#d7dfd9" + timeout = 0 + +[aerc] + appname = aerc + urgency = normal + background = "#7a3f6a" + foreground = "#d7dfd9" + timeout = 0 diff --git a/modules/mixins/dotfiles/config/eza b/modules/mixins/dotfiles/config/eza @@ -0,0 +1,147 @@ +# Modus Themes for eza +# Auto generated with https://github.com/miikanissi/modus-themes.nvim/blob/master/lua/modus-themes/extras/eza.lua +colourful: true + +# base colors +define: &bg_main "#000000" +define: &bg_dim = "#1e1e1e" +define: &bg_alt = "#0f0f0f" +define: &fg_main = "#ffffff" +define: &fg_dim = "#989898" +define: &fg_alt = "#c6daff" +define: &border = "#646464" +define: &border_highlight = "#C4C4C4" + +# foreground colors +define: &red "#ff5f59" +define: &red_warmer "#ff6b55" +define: &red_cooler "#ff7f9f" +define: &red_faint "#ff9580" +define: &green "#44bc44" +define: &green_warmer "#70b900" +define: &green_cooler "#00c06f" +define: &green_faint "#88ca9f" +define: &yellow "#d0bc00" +define: &yellow_warmer "#fec43f" +define: &yellow_cooler "#dfaf7a" +define: &yellow_faint "#d2b580" +define: &blue "#2fafff" +define: &blue_warmer "#79a8ff" +define: &blue_cooler "#00bcff" +define: &blue_faint "#82b0ec" +define: &magenta "#feacd0" +define: &magenta_warmer "#f78fe7" +define: &magenta_cooler "#b6a0ff" +define: &magenta_faint "#caa6df" +define: &cyan "#00d3d0" +define: &cyan_warmer "#4ae2f0" +define: &cyan_cooler "#6ae4b9" +define: &cyan_faint "#9ac8e0" +define: &rust "#db7b5f" +define: &gold "#c0965b" +define: &olive "#9cbd6f" +define: &slate "#76afbf" +define: &indigo "#9099d9" +define: &maroon "#cf7fa7" +define: &pink "#d09dc0" + +filekinds: + normal: {foreground: *fg_main} + directory: {foreground: *blue_warmer} + symlink: {foreground: *blue} + pipe: {foreground: *fg_dim} + block_device: {foreground: *magenta_cooler} + char_device: {foreground: *yellow_warmer} + socket: {foreground: *magenta} + special: {foreground: *pink} + executable: {foreground: *green} + mount_point: {foreground: *cyan} + +perms: + user_read: {foreground: *fg_dim} + user_write: {foreground: *red} + user_execute_file: {foreground: *green} + user_execute_other: {foreground: *green} + group_read: {foreground: *fg_dim} + group_write: {foreground: *red} + group_execute: {foreground: *green} + other_read: {foreground: *fg_dim} + other_write: {foreground: *red} + other_execute: {foreground: *green} + special_user_file: {foreground: *magenta_cooler} + special_other: {foreground: *red} + attribute: {foreground: *pink} + +size: + major: {foreground: *fg_dim} + minor: {foreground: *blue_warmer} + number_byte: {foreground: *pink} + number_kilo: {foreground: *rust} + number_mega: {foreground: *blue_warmer} + number_giga: {foreground: *magenta_cooler} + number_huge: {foreground: *magenta} + unit_byte: {foreground: *pink} + unit_kilo: {foreground: *rust} + unit_mega: {foreground: *blue_warmer} + unit_giga: {foreground: *magenta_cooler} + unit_huge: {foreground: *magenta} + +users: + user_you: {foreground: *yellow_warmer} + user_root: {foreground: *red} + user_other: {foreground: *magenta_cooler} + group_yours: {foreground: *pink} + group_other: {foreground: *fg_dim} + group_root: {foreground: *red} + +links: + normal: {foreground: *blue} + multi_link_file: {foreground: *cyan} + +git: + new: {foreground: *green} + modified: {foreground: *yellow_warmer} + deleted: {foreground: *red} + renamed: {foreground: *cyan} + typechange: {foreground: *magenta_cooler} + ignored: {foreground: *pink} + conflicted: {foreground: *magenta} + +git_repo: + branch_main: {foreground: *fg_dim} + branch_other: {foreground: *magenta_cooler} + git_clean: {foreground: *green} + git_dirty: {foreground: *red} + +security_context: + colon: {foreground: *fg_dim} + user: {foreground: *blue_warmer} + role: {foreground: *magenta_cooler} + typ: {foreground: *pink} + range: {foreground: *magenta_cooler} + +file_type: + image: {foreground: *yellow_warmer} + video: {foreground: *magenta} + music: {foreground: *blue_warmer} + lossless: {foreground: *cyan} + crypto: {foreground: *pink} + document: {foreground: *fg_dim} + compressed: {foreground: *magenta_cooler} + temp: {foreground: *yellow_warmer} + compiled: {foreground: *cyan} + build: {foreground: *pink} + source: {foreground: *green} + +punctuation: {foreground: *pink} +date: {foreground: *cyan} +inode: {foreground: *fg_dim} +blocks: {foreground: *pink} +header: {foreground: *fg_dim} +octal: {foreground: *blue_warmer} +flags: {foreground: *magenta_cooler} + +symlink_path: {foreground: *blue} +control_char: {foreground: *cyan} +broken_symlink: {foreground: *red} +broken_path_overlay: {foreground: *pink} diff --git a/modules/mixins/dotfiles/config/foot/foot.ini b/modules/mixins/dotfiles/config/foot/foot.ini @@ -0,0 +1,55 @@ +[main] +font=Ttyp0 OTB:size=12 +font-bold=Ttyp0 OTB:size=12 +font-italic=Ttyp0 OTB:size=12 +font-bold-italic=Ttyp0 OTB:size=12 +pad=2x2 + +[scrollback] +lines=10000 + +[mouse] +hide-when-typing=yes + +[cursor] +style=block +blink=no + +[colors-dark] +alpha = 0.85 +cursor=000000 ccaaee + +background=000000 +foreground=ffffff + +selection-foreground=ffffff +selection-background=50447f + +regular0=332d38 +regular1=eca28f +regular2=b9d0aa +regular3=c0b080 +regular4=9fbfe7 +regular5=e9acbf +regular6=a0c0d0 +regular7=ffffff + +bright0=332d38 +bright1=eca28f +bright2=b9d0aa +bright3=c0b080 +bright4=9fbfe7 +bright5=e9acbf +bright6=a0c0d0 +bright7=ffffff + +[key-bindings] +clipboard-copy=Control+Shift+c +clipboard-paste=Control+Shift+v +primary-paste=Shift+Insert +search-start=Control+Shift+r +font-increase=Control+plus Control+equal +font-decrease=Control+minus +font-reset=Control+0 +spawn-terminal=Control+Shift+n +show-urls-launch=Alt+Control+o diff --git a/modules/mixins/dotfiles/config/gtk-3.0/settings.ini b/modules/mixins/dotfiles/config/gtk-3.0/settings.ini @@ -0,0 +1,17 @@ +[Settings] +gtk-application-prefer-dark-theme=1 +gtk-theme-name=Adwaita-dark +gtk-icon-theme-name=Adwaita +gtk-font-name=Cozette 8 +gtk-cursor-theme-name=OSX-ElCap +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle=hintfull +gtk-xft-rgba=rgb diff --git a/modules/mixins/dotfiles/config/gtk-4.0/settings.ini b/modules/mixins/dotfiles/config/gtk-4.0/settings.ini @@ -0,0 +1,17 @@ +[Settings] +gtk-application-prefer-dark-theme=1 +gtk-theme-name=Adwaita-dark +gtk-icon-theme-name=Adwaita +gtk-font-name=Cozette 8 +gtk-cursor-theme-name=Human +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle=hintfull +gtk-xft-rgba=rgb diff --git a/modules/mixins/dotfiles/config/helix/config.toml b/modules/mixins/dotfiles/config/helix/config.toml @@ -0,0 +1,77 @@ +theme = "mine" + +[editor] +line-number = "relative" +mouse = false +cursorline = true +true-color = true +bufferline = "never" +auto-pairs = true +idle-timeout = 50 +auto-info = false +completion-trigger-len = 2 + +default-yank-register = "+" + +gutters = ["line-numbers", "diagnostics"] + +[editor.file-picker] +hidden = false + +[editor.statusline] +left = ["mode", "spinner", "file-name", "file-modification-indicator"] +center = [] +right = ["diagnostics", "selections", "position", "file-encoding", "file-line-ending", "file-type"] +separator = "│" + +[editor.lsp] +display-messages = true +display-inlay-hints = true + +[keys.normal] +"#" = "toggle_comments" +"^" = "goto_first_nonwhitespace" +"$" = "goto_line_end" +";" = "command_mode" + +[keys.normal.space] +"space" = "file_picker" +"b" = "buffer_picker" +"w" = ":write" + +[keys.normal.space.f] +"f" = "file_picker" +"h" = "last_picker" +"g" = "global_search" + +[keys.normal.space.g] +"g" = "hover" +"d" = "goto_definition" +"D" = "goto_declaration" +"i" = "goto_implementation" +"t" = "goto_type_definition" +"r" = "goto_reference" +"s" = "signature_help" +"l" = ":reflow" +"p" = "goto_prev_diag" +"n" = "goto_next_diag" +"a" = "code_action" +"f" = "format_selections" + +[keys.normal.space.r] +"r" = "rename_symbol" + +[keys.normal.space.t] +"r" = "symbol_picker" + +[keys.insert] +"C-space" = "completion" + +[keys.select] +"f" = "select_regex" +"^" = "goto_first_nonwhitespace" +"$" = "goto_line_end" +";" = "command_mode" + +[keys.select.space.g] +"f" = "format_selections" diff --git a/modules/mixins/dotfiles/config/helix/languages.toml b/modules/mixins/dotfiles/config/helix/languages.toml @@ -0,0 +1,62 @@ +[[language]] +name = "python" +language-servers = ["basedpyright"] + +[language-server.basedpyright] +command = "basedpyright-langserver" +args = ["--stdio"] + +[[language]] +name = "go" +auto-format = true +language-servers = [ "gopls" ] + +[language-server.gopls] +command = "gopls" +config = { "analyses" = { "unusedparams" = true }, "staticcheck" = true, "gofumpt" = true } + +[[language]] +name = "zig" +auto-format = true + +[[language]] +name = "rust" +auto-format = true + +[[language]] +name = "cpp" +auto-format = true + +[[language]] +name = "c" +auto-format = true + +[[language]] +name = "php" +language-servers = ["intelephense"] + +[language-server.intelephense] +command = "intelephense" +args = ["--stdio"] + +[[language]] +name = "gleam" +auto-format = true + +[[language]] +name = "markdown" + +[language-server.tofu-ls] +command = "tofu-ls" +args = ["serve"] + +[[language]] +name = "hcl" +language-id = "opentofu" +scope = "source.hcl" +file-types = ["tf", "tofu", "tfvars"] +auto-format = true +comment-token = "#" +block-comment-tokens = { start = "/*", end = "*/" } +indent = { tab-width = 2, unit = " " } +language-servers = [ "tofu-ls" ] diff --git a/modules/mixins/dotfiles/config/helix/themes/mine.toml b/modules/mixins/dotfiles/config/helix/themes/mine.toml @@ -0,0 +1,2 @@ +inherits = "modus_vivendi_tritanopia" +"ui.background" = {} diff --git a/modules/mixins/dotfiles/config/iamb/config.toml b/modules/mixins/dotfiles/config/iamb/config.toml @@ -0,0 +1,3 @@ +[profiles."matrix.haravara.org"] +url = "https://matrix.haravara.org" +user_id = "@miro:matrix.haravara.org" diff --git a/modules/mixins/dotfiles/config/jj/config.toml b/modules/mixins/dotfiles/config/jj/config.toml @@ -0,0 +1,48 @@ +[user] +name = "mtmn" +email = "miro@haravara.org" + +[ui] +color = "auto" + +diff-editor = ["difft", "--color", "always", "$left", "$right"] + +merge-editor = "vimdiff" +log-format = 'separate(" ", format_short_change_id_with_hidden_and_divergent_info(self), bookmarks, description.first_line(), format_short_signature(author), "(" ++ format_timestamp(committer.timestamp()) ++ ")")' + +log-word-wrap = true +default-command = "log" + +[signing] +backend = "gpg" +sign-all = true +key = "miro@haravara.org" + +[git] +push-bookmark-prefix = "push-" # used when jj git push --change creates a bookmark +default-branch = "master" + +[merge-tools.vimdiff] +program = "nvim" +args = ["-f", "-d", "$left", "$merged", "$right", + "-c", "wincmd J", + "-c", "set modifiable", + "-c", "set write"] +merge-tool-edits-conflict-markers = false + +[merge-tools.difft] +program = "difft" +diff-args = ["--color", "always", "$left", "$right"] + +[revset-aliases] +"upstream()" = "latest(remote_bookmarks(remote=origin) & ancestors(@))" +"wip()" = "ancestors(@ | branches()) & mine()" +'closest_bookmark(to)' = 'heads(::to & bookmarks())' + +[aliases] +lg = ["log", "-r", "::@", "--template", 'separate(" ", format_short_change_id_with_hidden_and_divergent_info(self), format_short_signature(author), description.first_line(), "(" ++ format_timestamp(committer.timestamp()) ++ ")")'] +wip = ["bookmark", "list", "--all"] +tug = ["bookmark", "move", "--from", "closest_bookmark(@-)", "--to", "@-"] + +[remotes.origin] +auto-track-bookmarks = "*" diff --git a/modules/mixins/dotfiles/config/kanshi/config b/modules/mixins/dotfiles/config/kanshi/config @@ -0,0 +1,18 @@ +profile { + output "eDP-1" disable + output "HDMI-A-1" enable +} + +profile { + output "eDP-1" disable + output "DP-1" enable +} + +profile { + output "eDP-1" disable + output "DP-2" enable +} + +profile { + output "eDP-1" enable +} diff --git a/modules/mixins/dotfiles/config/khal/config.nix b/modules/mixins/dotfiles/config/khal/config.nix @@ -0,0 +1,18 @@ +{homeDir, ...}: '' + [calendars] + + [[23b7b447-b99f-43a2-ab19-705212272b75]] + path = ${homeDir}/.local/share/khal/calendars/23b7b447-b99f-43a2-ab19-705212272b75 + type = discover + color = dark blue + + [locale] + timeformat = %H:%M + dateformat = %Y-%m-%d + longdateformat = %Y-%m-%d + datetimeformat = %Y-%m-%d %H:%M + longdatetimeformat = %Y-%m-%d %H:%M + + [default] + default_calendar = 23b7b447-b99f-43a2-ab19-705212272b751 +'' diff --git a/modules/mixins/dotfiles/config/magdalena/config.json.nix b/modules/mixins/dotfiles/config/magdalena/config.json.nix @@ -0,0 +1,93 @@ +{ + homeDir, + year, + month, + ... +}: '' + { + "editor": "nvim", + "max_depth": 5, + "ignored_patterns": [ + ".git", + ".jj", + ".zig-cache", + "target", + "vendor", + "node_modules", + "composer.lock", + "deps", + "_build", + ".expert", + ".nix-data", + ".crush", + ".gemini", + ".qwen", + "saturn" + ], + "fzf_opts": [ + "--highlight-line", + "--ansi", + "--layout=reverse", + "--border=rounded", + "--color=bg+:#2a1f2e,bg:-1,spinner:#c084b8,hl:#e08060", + "--color=fg:#c8b8bf,header:#c4607a,info:#7a6e7a,pointer:#c084b8", + "--color=marker:#e06fad,fg+:#f0dfe5,prompt:#7a9fd4,hl+:#f0a070", + "--color=border:#3d2a42" + ], + "fav_dirs": [ + "${homeDir}/src", + "${homeDir}/src/misc", + "${homeDir}/misc/www", + "${homeDir}/misc/books", + "${homeDir}/misc/llm", + "${homeDir}/src/nix", + "${homeDir}/src/nix/modules/mixins/dotfiles", + "${homeDir}/src/tools", + "${homeDir}/src/tools/terraform", + "${homeDir}/src/releases", + "${homeDir}/src/releases/mixes", + "${homeDir}/src/releases/${year}", + "${homeDir}/src/releases/${year}/${month}", + "${homeDir}/.config/mpd/playlists", + "${homeDir}/misc", + "${homeDir}/misc/notes", + "${homeDir}/misc/notes/nota", + "${homeDir}/misc/screenshots", + "${homeDir}/misc/recordings", + "${homeDir}/misc/random", + "${homeDir}/misc/music", + "${homeDir}/misc/music/backlog", + "${homeDir}/misc/music/backlog/_todo", + "${homeDir}/misc/music/backlog/_done", + "${homeDir}/Downloads", + "${homeDir}/.tmux" + ], + "openers": [ + { + "extensions": ["mp4", "mkv", "avi", "webm"], + "action": "media_player", + "command": "mpv" + }, + { + "extensions": ["flac", "aiff", "aif", "mp3", "wav"], + "action": "audio_player", + "command": "mpv" + }, + { + "extensions": ["jpg", "jpeg", "png", "webp", "svg"], + "action": "image_viewer", + "command": "nsxiv-rifle" + }, + { + "extensions": ["pdf", "epub", "mobi"], + "action": "document_reader", + "command": "sioyek" + }, + { + "extensions": ["html"], + "action": "web_browser", + "command": "offpunk" + } + ] + } +'' diff --git a/modules/mixins/dotfiles/config/mpv/input.conf b/modules/mixins/dotfiles/config/mpv/input.conf @@ -0,0 +1,16 @@ +F1 af toggle "lavfi=[dynaudnorm=f=75:g=25:n=0:p=0.58]" + +WHEEL_UP add volume 5 +WHEEL_DOWN add volume -5 + +w add panscan -0.05 +W add panscan +0.05 + +c add sub-scale -0.05 +C add sub-scale +0.05 + +a apply-profile "dv" + +L cycle-values loop-playlist inf no ; show-text "Loop current playlist: ${?=loop-playlist==inf:yes}${?=loop-playlist==no:no}" + +P run "/bin/sh" "-c" "echo -n \"${path}\" | wl-copy"; show-text "Copied filename to clipboard" diff --git a/modules/mixins/dotfiles/config/mpv/mpv.conf b/modules/mixins/dotfiles/config/mpv/mpv.conf @@ -0,0 +1,36 @@ +sub-font="DejaVu Sans" +sub-font-size=60 + +cache=yes +cache-secs=20 +demuxer-max-back-bytes=200M + +screenshot-format=jpeg +screenshot-template="%F-%P" +screenshot-directory=~/misc/screenshots + +save-position-on-quit +save-watch-history +resume-playback + +# This makes things safer for F1 and similar videos with common titles after +# https://github.com/mpv-player/mpv/commit/e143966a7 +resume-playback-check-mtime + +script-opts=ytdl_hook-ytdl_path=yt-dlp +ytdl-format=bestvideo[height<=?720][fps<=?60][vcodec!=?vp9]+bestaudio/best + +# Without downmix sometimes speech is really drowned out by environmental +# noise. + +# For eac this may need to be adjusted to 3 to avoid shenanigans with +# https://github.com/mpv-player/mpv/issues/6300 +ad-lavc-downmix=yes +audio-channels=2 + +# Some sources are just too quiet, so allow increasing softvol to avoid +# twiddling with the speakers +volume-max=200 + +vd-lavc-threads=4 +demuxer-thread=yes diff --git a/modules/mixins/dotfiles/config/ncmpcpp/bindings b/modules/mixins/dotfiles/config/ncmpcpp/bindings @@ -0,0 +1,22 @@ +def_key "j" + scroll_down +def_key "k" + scroll_up +def_key "h" + previous_column +def_key "l" + next_column +def_key "ctrl-b" + page_up +def_key "ctrl-u" + page_up +def_key "ctrl-f" + page_down +def_key "ctrl-d" + page_down +def_key "G" + move_end +def_key "n" + next_found_item +def_key "N" + previous_found_item diff --git a/modules/mixins/dotfiles/config/nota b/modules/mixins/dotfiles/config/nota @@ -0,0 +1,3 @@ +GPG=0 +MARKDOWN=1 +EDITOR=nvim diff --git a/modules/mixins/dotfiles/config/nvim/README.md b/modules/mixins/dotfiles/config/nvim/README.md @@ -0,0 +1,22 @@ +To recompile `fnl` files into `lua` I use this shell function: + +```bash +nvimrecomp() { + nvim_config_path_path="$HOME/.config/nvim" + + mkdir -p "$nvim_config_path"/lua/config + + find "$nvim_config_path/fnl" -type f -name "*.fnl" | while read -r fnl_file; do + rel_path="${fnl_file#"$nvim_config_path"/fnl/}" + + if [ "$rel_path" = "init.fnl" ]; then + lua_file="$nvim_config_path/init.lua" + else + lua_file="$nvim_config_path/lua/${rel_path%.fnl}.lua" + fi + + fennel --compile "$fnl_file" | tee "$lua_file" > /dev/null + echo "$lua_file recompiled" + done +} +``` diff --git a/modules/mixins/dotfiles/config/nvim/fnl/aliases.fnl b/modules/mixins/dotfiles/config/nvim/fnl/aliases.fnl @@ -0,0 +1,21 @@ +(vim.cmd "cnoreabbrev nt botright vert new + cnoreabbrev sft %!sft + cnoreabbrev ptn %!ptn + cnoreabbrev mpc %!mpc clear + cnoreabbrev mpl %!mpc play") + +(local home (os.getenv :HOME)) + +(local oil-abbreviations + {:mi :/misc/ + :mu :/misc/music/ + :no :/misc/notes/nota/ + :www :/misc/notes/www/ + :rls :/misc/notes/releases/ + :src :/src/ + :cbg :/src/codeberg.org/mtmn + :nix :/src/haravara.org/nix + :tls :/src/haravara.org/tools}) + +(each [abbrev path (pairs oil-abbreviations)] + (vim.cmd (.. "cnoreabbrev " abbrev " Oil " home path))) diff --git a/modules/mixins/dotfiles/config/nvim/fnl/config/blink.fnl b/modules/mixins/dotfiles/config/nvim/fnl/config/blink.fnl @@ -0,0 +1,21 @@ +(fn config [] + (let [blink (require :blink.cmp)] + (blink.setup {:snippets {:preset :luasnip} + :appearance {:nerd_font_variant :none} + :keymap {:preset :none + :<C-p> [:select_prev :fallback] + :<C-n> [:select_next :fallback] + :<C-b> [:scroll_documentation_up :fallback] + :<C-b> [:scroll_documentation_up :fallback] + :<C-f> [:scroll_documentation_down :fallback] + :<C-Space> [:show + :show_documentation + :hide_documentation] + :<C-e> [:hide :fallback] + :<CR> [:accept :fallback]} + :completion {:menu {:winhighlight "Normal:CmpNormal"} + :documentation {:auto_show true + :window {:winhighlight "Normal:CmpNormal"}}} + :sources {:default [:lsp :snippets :path :buffer]}}))) + +{: config} diff --git a/modules/mixins/dotfiles/config/nvim/fnl/config/lsp.fnl b/modules/mixins/dotfiles/config/nvim/fnl/config/lsp.fnl @@ -0,0 +1,62 @@ +(local {: map} (require :std.functional)) +(local tbl (require :std.table)) + +(local {:nvim_create_augroup create-augroup + :nvim_create_autocmd create-autocmd + :nvim_clear_autocmds clear-autocmds + :nvim_get_current_buf get-current-buf} vim.api) + +(create-augroup :local-lsp-auto-format {:clear true}) + +(fn is-array [tbl] + (not (not (. tbl 1)))) + +(fn map-vals [func tbl] + (map #(func $2) tbl)) + +(fn create-auto-format-autocmd [extra-opts] + (let [extra-opts (or extra-opts {}) + all-extra-opts (if (is-array extra-opts) + extra-opts + [extra-opts]) + all-opts (map-vals #(tbl.merge {:formatting_options {:timeout_ms 5000}} + $1) + all-extra-opts) + auto-format-callback #(each [_ opts (ipairs all-opts)] + (vim.lsp.buf.format opts))] + (clear-autocmds {:event :BufWritePre + :buffer (get-current-buf) + :group :local-lsp-auto-format}) + (create-autocmd :BufWritePre + {:buffer (get-current-buf) + :callback auto-format-callback + :group :local-lsp-auto-format}) + nil)) + +(fn auto-format-on-save [filetypes extra-opts] + (let [callback #(create-auto-format-autocmd extra-opts)] + (each [_ filetype (ipairs filetypes)] + (create-autocmd :FileType {:pattern filetype : callback})))) + +(fn config [] + (let [servers {:basedpyright {} + :clangd {} + :gopls {:settings {:gopls {:analyses {:unusedparams true} + :staticcheck true + :gofumpt true}}} + :gleam {} + :intelephense {} + :rust_analyzer {} + :zls {}}] + (each [server config (pairs servers)] + (vim.lsp.enable server config)) + (let [open-floating-preview vim.lsp.util.open_floating_preview] + (set vim.lsp.util.open_floating_preview + (fn [contents syntax opts ...] + (let [opts (or opts {})] + (set opts.border (or opts.border :rounded)) + (open-floating-preview contents syntax opts ...)))))) + ;; Enable inline diagnostics + (vim.diagnostic.config {:virtual_text true})) + +{: auto-format-on-save : config} diff --git a/modules/mixins/dotfiles/config/nvim/fnl/config/treesitter.fnl b/modules/mixins/dotfiles/config/nvim/fnl/config/treesitter.fnl @@ -0,0 +1,24 @@ +(local {:nvim_command command :nvim_create_autocmd autocmd} vim.api) +(local {: keys} (require :std.table)) +(local ts (require :nvim-treesitter)) +(local all-parsers (keys (require :nvim-treesitter.parsers))) +(fn build [] + (: (ts.install all-parsers) :wait 300000) + (: (ts.update all-parsers) :wait 300000)) + +; To force rebuild: +; rm -rf ~/.local/share/nvim/site +; (ts.install all-parsers {:force true}) +;; Adapted from https://github.com/nvim-treesitter/nvim-treesitter/discussions/7894 +(fn config [] + (local parsers (require :nvim-treesitter.parsers)) + (ts.setup {:highlight {:enable true} :indent {:enable true}}) + (autocmd :FileType + {:callback (fn [] + (let [lang (vim.treesitter.language.get_lang vim.bo.filetype)] + (when (and lang + (pcall vim.treesitter.get_parser 0 lang)) + (set vim.wo.foldexpr + "v:lua.vim.treesitter.foldexpr()"))))})) + +{: build : config} diff --git a/modules/mixins/dotfiles/config/nvim/fnl/flsproject.fnl b/modules/mixins/dotfiles/config/nvim/fnl/flsproject.fnl @@ -0,0 +1,17 @@ +{:fennel-path "./?.fnl;./?/init.fnl;src/?.fnl;src/?/init.fnl" + :macro-path "./?.fnl;./?/init-macros.fnl;./?/init.fnl;src/?.fnl;src/?/init-macros.fnl;src/?/init.fnl" + :lua-version :lua5.4 + :libraries {} + :extra-globals "" + :lints {:unused-definition true + :unknown-module-field true + :unnecessary-method true + :unnecessary-tset true + :unnecessary-do true + :redundant-do true + :match-should-case true + :bad-unpack true + :var-never-set true + :op-with-no-arguments true + :multival-in-middle-of-call true + :no-decreasing-comparison false}} diff --git a/modules/mixins/dotfiles/config/nvim/fnl/functions.fnl b/modules/mixins/dotfiles/config/nvim/fnl/functions.fnl @@ -0,0 +1,52 @@ +(vim.api.nvim_create_autocmd [:BufRead :BufNewFile] + {:pattern [:*.m3u :*.m3u8] + :callback (fn [] + (set vim.bo.filetype :text) + (set vim.bo.syntax :text))}) + +(let [group (vim.api.nvim_create_augroup :MagdalenaLogFile {:clear true})] + (vim.api.nvim_create_autocmd [:BufReadPost :BufNewFile] + {: group + :callback (fn [ev] + (let [filename (vim.api.nvim_buf_get_name ev.buf)] + (when (and filename + (not= filename "") + (not (filename:match "^oil://"))) + (let [_job (vim.fn.jobstart [:magdalena + :log-file + filename] + {:detach true + :on_stderr (fn [_ + _]) + :on_exit (fn [_ + _])})] + nil))))})) + +(vim.api.nvim_create_autocmd :BufWritePre + {:callback (fn [ev] + (vim.lsp.buf.code_action {:apply true + :context {:only [:source.fixAll]}})) + :pattern [:*.zig :*.zon]}) + +(vim.api.nvim_create_autocmd :FileType + {:pattern :markdown + :callback (fn [] + (set vim.opt_local.suffixesadd :.md) + (set vim.opt_local.includeexpr + "v:lua.follow_md_link()") + (global follow_md_link + #(: vim.v.fname :gsub + "%[%[(.-)%]%]" "%1")) + (vim.keymap.set :n :gf + (fn [] + (let [line (vim.api.nvim_get_current_line) + col (. (vim.api.nvim_win_get_cursor 0) + 2) + link (line:match "%[([%w_%-][%w_%-]+)%]" + col)] + (if link + (vim.cmd (.. "edit " + link + :.md)) + (vim.cmd "normal! gf")))) + {:buffer true}))}) diff --git a/modules/mixins/dotfiles/config/nvim/fnl/init.fnl b/modules/mixins/dotfiles/config/nvim/fnl/init.fnl @@ -0,0 +1,108 @@ +(vim.loader.enable) + +(local {: g : env : fs} vim) +(local {:nvim_command command} vim.api) +(local {: stdpath : empty : glob} vim.fn) +(local {: format} string) + +(fn bootstrap-lazy [] + (local lazypath (.. (vim.fn.stdpath :data) :/lazy/lazy.nvim)) + (when (not (vim.uv.fs_stat lazypath)) + (local lazyrepo "https://github.com/folke/lazy.nvim.git") + (local out (vim.fn.system [:git + :clone + "--filter=blob:none" + :--branch=stable + lazyrepo + lazypath])) + (when (not= vim.v.shell_error 0) + (vim.fn.getchar) + (os.exit 1))) + (vim.opt.rtp:prepend lazypath) + (require :lazy)) + +;; fnlfmt: skip +(fn plugin_specs [] + (fn use [name opts] + (let [opts (or opts {})] + (tset opts 1 name) + opts)) + + [ + (use "aymenhafeez/doric-themes.nvim" + {:lazy false + :priority 1000 + :config (fn [] + (vim.cmd.colorscheme :doric-dark) + (vim.api.nvim_set_hl 0 :Normal {:bg :NONE}) + (vim.api.nvim_set_hl 0 :NormalFloat {:bg :NONE}) + (vim.api.nvim_set_hl 0 :NormalNC {:bg :NONE}))}) + + (use "windwp/nvim-autopairs" {:event :VeryLazy :config true}) + (use "ibhagwan/fzf-lua" {:config true}) + (use "smoka7/hop.nvim" {:version "*" :opts {:keys :etovxqpdygfblzhckisuran}}) + (use "stevearc/oil.nvim" + {:config (fn [] + ((. (require :oil) :setup) {:view_options {:show_hidden false}}) + (let [oil-cd-on-enter (fn [] + (let [oil (require :oil) + current-dir (oil.get_current_dir)] + (when current-dir + (vim.cmd (.. "cd " current-dir)))))] + (vim.api.nvim_create_autocmd :BufEnter + {:pattern "oil://*" + :callback oil-cd-on-enter})))}) + (use "neogitorg/neogit" + {:dependencies [:nvim-lua/plenary.nvim] + :config true}) + (use "sindrets/diffview.nvim" + {:config (fn [] + ((. (require :diffview) :setup) + {:diff_binaries false + :enhanced_diff_hl false + :git_cmd ["git"] + :use_icons false + :show_help_hints false + :watch_index true}))}) + (use "saghen/blink.cmp" + {:version :^1 + :lazy false + :dependencies [:L3MON4D3/LuaSnip] + :config #(: (require :config.blink) :config)}) + (use "mrcjkb/rustaceanvim" {:version :^7 :lazy false}) + (use "neovim/nvim-lspconfig" + {:event :VeryLazy + :branch :master + :config (fn [] + (: (require :config.lsp) :config))}) + (use "nvim-treesitter/nvim-treesitter" + {:branch :main + :build #(: (require :config.treesitter) :build) + :config #(: (require :config.treesitter) :config)}) + (use "tpope/vim-commentary") + (use "tpope/vim-repeat") + (use "tpope/vim-surround") + (use "troydm/zoomwintab.vim") + ]) + +(fn init [] + (let [vimrc (.. (vim.fn.stdpath :config) :/init_.vim) + vim-dir (.. (vim.fn.expand "~") :/.vim/)] + (vim.cmd.source vimrc) + (each [_ dir (ipairs [:backup :swap :undo])] + (let [path (.. vim-dir dir)] + (when (= (vim.fn.isdirectory path) 0) + (vim.fn.mkdir path :p)))) + (set vim.opt.backupdir (.. vim-dir :backup//)) + (set vim.opt.directory (.. vim-dir :swap//)) + (set vim.opt.undodir (.. vim-dir :undo//)) + (set vim.opt.undofile true)) + (set vim.opt.clipboard :unnamedplus) + (set package.path (.. (fs.normalize "~") "/.config/nvim/lua/?.lua," + package.path)) + (local lazy (bootstrap-lazy)) + (lazy.setup {:spec (plugin_specs) :checker {:enabled false}}) + (each [_ module (ipairs [:aliases :keymaps :functions])] + (require module))) + +(init) diff --git a/modules/mixins/dotfiles/config/nvim/fnl/keymaps.fnl b/modules/mixins/dotfiles/config/nvim/fnl/keymaps.fnl @@ -0,0 +1,64 @@ +(local opts {:noremap true :silent false}) + +(local fzf-keymaps {:<leader><leader> :files + :<leader>ff :git_status + :<leader>fh :oldfiles + :<leader>fg :grep_project + :<leader>b :buffers}) + +(each [key func (pairs fzf-keymaps)] + (vim.keymap.set :n key (.. "<cmd>lua require('fzf-lua')." func "()<CR>"))) + +(local single-keymaps {:<leader>g :<cmd>Neogit<CR> + :- :<cmd>Oil<CR> + :f :<cmd>HopWord<CR> + :mn :<cmd>Mnav<CR>}) + +(each [key cmd (pairs single-keymaps)] + (vim.keymap.set :n key cmd)) + +(local lsp-keymaps {:<leader>gg :hover + :<leader>gd :definition + :<leader>gD :declaration + :<leader>gi :implementation + :<leader>gt :type_definition + :<leader>gr :references + :<leader>gs :signature_help + :<leader>rr :rename + :<leader>ga :code_action + :<leader>tr :document_symbol}) + +(each [key func (pairs lsp-keymaps)] + (vim.keymap.set :n key (.. "<cmd>lua vim.lsp.buf." func "()<CR>"))) + +(vim.keymap.set :n :<leader>ta + (fn [] + (let [row (. (vim.api.nvim_win_get_cursor 0) 1)] + (vim.api.nvim_buf_set_lines 0 row row false ["- [ ] "]) + (vim.api.nvim_win_set_cursor 0 [(+ row 1) 5])))) + +(vim.keymap.set :n :<leader>tt + (fn [] + (let [line (vim.api.nvim_get_current_line)] + (var new-line nil) + (if (line:match "%[ %]") + (set new-line (line:gsub "%[ %]" "[-]" 1)) + (line:match "%[%-%]") + (set new-line (line:gsub "%[%-%]" "[x]" 1)) + (line:match "%[x%]") + (set new-line (line:gsub "%[x%]" "[ ]" 1))) + (when new-line (vim.api.nvim_set_current_line new-line))))) + +(local diagnostic-keymaps {:<leader>gl :open_float + :<leader>gp :goto_prev + :<leader>gn :goto_next}) + +(each [key func (pairs diagnostic-keymaps)] + (vim.keymap.set :n key (.. "<cmd>lua vim.diagnostic." func "()<CR>"))) + +(vim.keymap.set :v :<leader>gf + "<cmd>lua vim.lsp.buf.format({async = true})<CR>") + +(vim.keymap.set :i :<C-Space> "<cmd>lua vim.lsp.buf.completion()<CR>") + +(vim.keymap.set :n :x "\"_x") diff --git a/modules/mixins/dotfiles/config/nvim/init_.vim b/modules/mixins/dotfiles/config/nvim/init_.vim @@ -0,0 +1,3 @@ +set runtimepath^=~/.vim runtimepath+=~/.vim/after +let &packpath = &runtimepath +source ~/.vimrc diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/_base.lua b/modules/mixins/dotfiles/config/nvim/lua/std/_base.lua @@ -0,0 +1,204 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Prevent dependency loops with key function implementations. + + A few key functions are used in several stdlib modules; we implement those + functions in this internal module to prevent dependency loops in the first + instance, and to minimise coupling between modules where the use of one of + these functions might otherwise load a whole selection of other supporting + modules unnecessarily. + + Although the implementations are here for logistical reasons, we re-export + them from their respective logical modules so that the api is not affected + as far as client code is concerned. The functions in this file do not make + use of `argcheck` or similar, because we know that they are only called by + other stdlib functions which have already performed the necessary checking + and neither do we want to slow everything down by recheckng those argument + types here. + + This implies that when re-exporting from another module when argument type + checking is in force, we must export a wrapper function that can check the + user's arguments fully at the API boundary. +]] + + +local _ENV = require 'std.normalize' { + concat = 'table.concat', + dirsep = 'package.dirsep', + find = 'string.find', + gsub = 'string.gsub', + insert = 'table.insert', + min = 'math.min', + shallow_copy = 'table.merge', + sort = 'table.sort', + sub = 'string.sub', + table_maxn = table.maxn, + wrap = 'coroutine.wrap', + yield = 'coroutine.yield', +} + + + +--[[ ============================ ]]-- +--[[ Enhanced Core Lua functions. ]]-- +--[[ ============================ ]]-- + + +-- These come as early as possible, because we want the rest of the code +-- in this file to use these versions over the core Lua implementation +-- (which have slightly varying semantics between releases). + + +local maxn = table_maxn or function(t) + local n = 0 + for k in pairs(t) do + if type(k) == 'number' and k > n then + n = k + end + end + return n +end + + + +--[[ ============================ ]]-- +--[[ Shared Stdlib API functions. ]]-- +--[[ ============================ ]]-- + + +-- No need to recurse because functables are second class citizens in +-- Lua: +-- func = function() print 'called' end +-- func() --> 'called' +-- functable=setmetatable({}, {__call=func}) +-- functable() --> 'called' +-- nested=setmetatable({}, {__call=functable}) +-- nested() +-- --> stdin:1: attempt to call a table value(global 'd') +-- --> stack traceback: +-- --> stdin:1: in main chunk +-- --> [C]: in ? +local function callable(x) + if type(x) == 'function' then + return x + end + return (getmetatable(x) or {}).__call +end + + +local function catfile(...) + return concat({...}, dirsep) +end + + +local function compare(l, m) + local lenl, lenm = len(l), len(m) + for i = 1, min(lenl, lenm) do + local li, mi = tonumber(l[i]), tonumber(m[i]) + if li == nil or mi == nil then + li, mi = l[i], m[i] + end + if li < mi then + return -1 + elseif li > mi then + return 1 + end + end + if lenl < lenm then + return -1 + elseif lenl > lenm then + return 1 + end + return 0 +end + + +local function escape_pattern(s) + return (gsub(s, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%0')) +end + + +local function invert(t) + local i = {} + for k, v in pairs(t) do + i[v] = k + end + return i +end + + +local function leaves(it, tr) + local function visit(n) + if type(n) == 'table' then + for _, v in it(n) do + visit(v) + end + else + yield(n) + end + end + return wrap(visit), tr +end + + +local function split(s, sep) + local r, patt = {} + if sep == '' then + patt = '(.)' + insert(r, '') + else + patt = '(.-)' ..(sep or '%s+') + end + local b, slen = 0, len(s) + while b <= slen do + local e, n, m = find(s, patt, b + 1) + insert(r, m or sub(s, b + 1, slen)) + b = n or slen + 1 + end + return r +end + + +--[[ ============= ]]-- +--[[ Internal API. ]]-- +--[[ ============= ]]-- + + +-- For efficient use within stdlib, these functions have no type-checking. +-- In debug mode, type-checking wrappers are re-exported from the public- +-- facing modules as necessary. +-- +-- Also, to provide some sanity, we mirror the subtable layout of stdlib +-- public API here too, which means everything looks relatively normal +-- when importing the functions into stdlib implementation modules. +return { + io = { + catfile = catfile, + }, + + list = { + compare = compare, + }, + + object = { + Module = Module, + mapfields = mapfields, + }, + + string = { + escape_pattern = escape_pattern, + split = split, + }, + + table = { + invert = invert, + maxn = maxn, + }, + + tree = { + leaves = leaves, + }, +} diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/debug.lua b/modules/mixins/dotfiles/config/nvim/lua/std/debug.lua @@ -0,0 +1,156 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Additions to the core debug module. + + The module table returned by `std.debug` also contains all of the entries + from the core debug table. An hygienic way to import this module, then, is + simply to override the core `debug` locally: + + local debug = require 'std.debug' + + @corelibrary std.debug +]] + + +local _ENV = require 'std.normalize' { + 'debug', + _debug = require 'std._debug', + concat = 'table.concat', + huge = 'math.huge', + max = 'math.max', + merge = 'table.merge', + stderr = 'io.stderr', +} + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local function say(n, ...) + local level, argt = n, {...} + if type(n) ~= 'number' then + level, argt = 1, {n, ...} + end + if _debug.level ~= huge and + ((type(_debug.level) == 'number' and _debug.level >= level) or level <= 1) + then + local t = {} + for k, v in pairs(argt) do + t[k] = str(v) + end + stderr:write(concat(t, '\t') .. '\n') + end +end + + +local level = 0 + +local function trace(event) + local t = debug.getinfo(3) + local s = ' >>> ' + for i = 1, level do + s = s .. ' ' + end + if t ~= nil and t.currentline >= 0 then + s = s .. t.short_src .. ':' .. t.currentline .. ' ' + end + t = debug.getinfo(2) + if event == 'call' then + level = level + 1 + else + level = max(level - 1, 0) + end + if t.what == 'main' then + if event == 'call' then + s = s .. 'begin ' .. t.short_src + else + s = s .. 'end ' .. t.short_src + end + elseif t.what == 'Lua' then + s = s .. event .. ' ' ..(t.name or '(Lua)') .. ' <' .. + t.linedefined .. ':' .. t.short_src .. '>' + else + s = s .. event .. ' ' ..(t.name or '(C)') .. ' [' .. t.what .. ']' + end + stderr:write(s .. '\n') +end + +-- Set hooks according to _debug +if _debug.call then + debug.sethook(trace, 'cr') +end + + + +local M = { + --- Function Environments + -- @section environments + + --- Extend `debug.getfenv` to unwrap functables correctly. + -- @function getfenv + -- @tparam int|function|functable fn target function, or stack level + -- @treturn table environment of *fn* + getfenv = getfenv, + + --- Extend `debug.setfenv` to unwrap functables correctly. + -- @function setfenv + -- @tparam function|functable fn target function + -- @tparam table env new function environment + -- @treturn function *fn* + setfenv = setfenv, + + + --- Functions + -- @section functions + + --- Print a debugging message to `io.stderr`. + -- Display arguments passed through `std.tostring` and separated by tab + -- characters when `std._debug` hinting is `true` and *n* is 1 or less; + -- or `std._debug.level` is a number greater than or equal to *n*. If + -- `std._debug` hinting is false or nil, nothing is written. + -- @function say + -- @int[opt=1] n debugging level, smaller is higher priority + -- @param ... objects to print(as for print) + -- @usage + -- local _debug = require 'std._debug' + -- _debug.level = 3 + -- say(2, '_debug status level:', _debug.level) + say = say, + + --- Trace function calls. + -- Use as debug.sethook(trace, 'cr'), which is done automatically + -- when `std._debug.call` is set. + -- Based on test/trace-calls.lua from the Lua distribution. + -- @function trace + -- @string event event causing the call + -- @usage + -- local _debug = require 'std._debug' + -- _debug.call = true + -- local debug = require 'std.debug' + trace = trace, +} + + +--- Metamethods +-- @section metamethods + +--- Equivalent to calling `debug.say(1, ...)` +-- @function __call +-- @see say +-- @usage +-- local debug = require 'std.debug' +-- debug 'oh noes!' +local metatable = { + __call = function(self, ...) + M.say(1, ...) + end, +} + + +return setmetatable(merge(debug, M), metatable) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/_base.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/_base.lua @@ -0,0 +1,111 @@ +--[[ + Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 + Copyright (C) 2002-2022 std.functional authors +]] +--[[-- + Purely to break internal dependency cycles without introducing + multiple copies of base functions used in other modules. + + @module std.functional._base +]] + +local _ENV = require 'std.normalize' { + 'string.format', + 'table.concat', + 'table.keys', + 'table.sort', +} + + +local argscheck +do + local ok, typecheck = pcall(require, 'typecheck') + if ok then + argscheck = typecheck.argscheck + else + argscheck = function(decl, fn) + return fn + end + end +end + + + +--[[ ================= ]]-- +--[[ Shared Functions. ]]-- +--[[ ================= ]]-- + + +local function shallow_copy(t) + local r = {} + for k, v in next, t do + r[k] = v + end + return r +end + + +local function toqstring(x) + if type(x) ~= 'string' then + return tostring(x) + end + return format('%q', x) +end + + +local function keycmp(a, b) + if type(a) == 'number' then + return type(b) ~= 'number' or a < b + else + return type(b) ~= 'number' and tostring(a) < tostring(b) + end +end + + +local function sortedkeys(t, cmp) + local r = keys(t) + sort(r, cmp) + return r +end + + +local function serialize(x, roots) + roots = roots or {} + + local function stop_roots(x) + return roots[x] or serialize(x, shallow_copy(roots)) + end + + if type(x) ~= 'table' or getmetamethod(x, '__tostring') then + return toqstring(x) + + else + local buf = {'{'} -- pre-buffer table open + roots[x] = toqstring(x) -- recursion protection + + local kp -- previous key + for _, k in ipairs(sortedkeys(x, keycmp)) do + if kp ~= nil then + buf[#buf + 1] = ',' + end + buf[#buf + 1] = stop_roots(kp) .. '=' .. stop_roots(x[k]) + kp = k + end + buf[#buf + 1] = '}' -- buffer << table close + + return concat(buf) -- stringify buffer + end +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +return { + argscheck = argscheck, + serialize = serialize, + toqstring = toqstring, +} diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/init.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/init.lua @@ -0,0 +1,883 @@ +--[[ + Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 + Copyright (C) 2002-2022 std.functional authors +]] +--[[-- + Functional programming. + + A selection of higher-order functions to enable a functional style of + programming in Lua. + + @module std.functional +]] + + +local _ENV = require 'std.normalize' { + 'coroutine.wrap', + 'coroutine.yield', + 'math.ceil', + 'std.functional._base.argscheck', + 'std.functional._base.serialize', + 'table.concat', + 'table.remove', +} + + + +-- FIXME: Figure these two out: + +local function ielems(t) + -- capture ipairs iterator initial state + local fn, istate, ctrl = ipairs(t) + return function(state, _) + local v + ctrl, v = fn(state, ctrl) + if ctrl then + return v + end + end, istate, true -- wrapped initial state +end + + +local function leaves(it, tr) + local function visit(n) + if type(n) == 'table' then + for _, v in it(n) do + visit(v) + end + else + yield(n) + end + end + return wrap(visit), tr +end + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local function any(...) + local fns = pack(...) + + return function(...) + local argt = {n = 0} + for i = 1, fns.n do + argt = pack(fns[i](...)) + if argt[1] ~= nil then + return unpack(argt, 1, argt.n) + end + end + return unpack(argt, 1, argt.n) + end +end + + +local ceil = ceil -- FIXME: specl-14.x breaks function environments here :( + +local function bind(fn, bound) + return function(...) + local argt, unbound = {}, pack(...) + + -- Inline `argt = copy(bound)`... + local n = bound.n or 0 + for k, v in next, bound do + -- ...but only copy integer keys. + if type(k) == 'number' and ceil(k) == k then + argt[k] = v + n = k > n and k or n -- Inline `n = maxn(unbound)` in same pass. + end + end + + -- Bind *unbound* parameters sequentially into *argt* gaps. + local i = 1 + for j = 1, unbound.n do + while argt[i] ~= nil do + i = i + 1 + end + argt[i], i = unbound[j], i + 1 + end + + -- Even if there are gaps remaining above *i*, pass at least *n* args. + if n >= i then + return fn(unpack(argt, 1, n)) + end + + -- Otherwise, we filled gaps beyond *n*, and pass that many args. + return fn(unpack(argt, 1, i - 1)) + end +end + + +-- No need to recurse because functables are second class citizens in +-- Lua: +-- func=function() print 'called' end +-- func() --> 'called' +-- functable=setmetatable({}, {__call=func}) +-- functable() --> 'called' +-- nested=setmetatable({}, {__call=functable}) +-- nested() +-- --> stdin:1: attempt to call a table value(global 'd') +-- --> stack traceback: +-- --> stdin:1: in main chunk +-- --> [C]: in ? +local function callable(x) + if type(x) == 'function' then + return x + end + return (getmetatable(x) or {}).__call +end + + +local function case(with, branches) + local match = branches[with] or branches[1] + if callable(match) then + return match(with) + end + return match +end + + +local function collect(ifn, ...) + local r = {} + if not callable(ifn) then + -- No iterator behaves like npairs, which would collect all integer + -- key values from the first argument table: + local k, v = next(ifn) + repeat + if type(k) == 'number' then + r[k] = v + end + k, v = next(ifn, k) + until k == nil + return r + end + + -- Or else result depends on how many return values from ifn? + local arity = 1 + for e, v in ifn(...) do + if v then + arity, r = 2, {} + break + end + -- Build an arity-1 result table on first pass... + r[#r + 1] = e + end + + if arity == 2 then + -- ...oops, it was arity-2 all along, start again! + for k, v in ifn(...) do + r[k] = v + end + end + + return r +end + + +local function compose(...) + local fns = pack(...) + + return function(...) + local argt = pack(...) + for i = 1, fns.n do + argt = pack(fns[i](unpack(argt, 1, argt.n))) + end + return unpack(argt, 1, argt.n) + end +end + + +local function cond(expr, branch, ...) + if branch == nil and select('#', ...) == 0 then + expr, branch = true, expr + end + if expr then + if callable(branch) then + return branch(expr) + end + return branch + end + return cond(...) +end + + +local function curry(fn, n) + if n <= 1 then + return fn + else + return function(x) + return curry(bind(fn, {x}), n - 1) + end + end +end + + +local function filter(pfn, ifn, ...) + local argt, r = pack(...), {} + if not callable(ifn) then + ifn, argt = pairs, pack(ifn, ...) + end + + local nextfn, state, k = ifn(unpack(argt, 1, argt.n)) + + local t = pack(nextfn(state, k)) -- table of iteration 1 + local arity = #t -- How many return values from ifn? + + if arity == 1 then + local v = t[1] + while v ~= nil do -- until iterator returns nil + if pfn(unpack(t, 1, t.n)) then -- pass all iterator results to p + r[#r + 1] = v + end + + t = pack(nextfn(state, v)) -- maintain loop invariant + v = t[1] + + if #t > 1 then -- unless we discover arity is not 1 after all + arity, r = #t, {} break + end + end + end + + if arity > 1 then + -- No need to start over here, because either: + -- (i) arity was never 1, and the original value of t is correct + -- (ii) arity used to be 1, but we only consumed nil values, so the + -- current t with arity > 1 is the correct next value to use + while t[1] ~= nil do + local k = t[1] + if pfn(unpack(t, 1, t.n)) then + r[k] = t[2] + end + t = pack(nextfn(state, k)) + end + end + + return r +end + + +local function flatten(t) + return collect(leaves, ipairs, t) +end + + +local function reduce(fn, d, ifn, ...) + local argt + if not callable(ifn) then + ifn, argt = pairs, pack(ifn, ...) + else + argt = pack(...) + end + + local nextfn, state, k = ifn(unpack(argt, 1, argt.n)) + local t = pack(nextfn(state, k)) -- table of iteration 1 + + local r = d -- initialise accumulator + while t[1] ~= nil do -- until iterator returns nil + k = t[1] + r = fn(r, unpack(t, 1, t.n)) -- pass all iterator results to fn + t = pack(nextfn(state, k)) -- maintain loop invariant + end + return r +end + + +local function foldl(fn, d, t) + if t == nil then + local tail = {} + for i = 2, len(d) do + tail[#tail + 1] = d[i] + end + d, t = d[1], tail + end + return reduce(fn, d, ielems, t) +end + + +-- Be careful to reverse only the valid sequence part of a table. +local function ireverse(t) + local oob = 1 + while t[oob] ~= nil do + oob = oob + 1 + end + + local r = {} + for i = 1, oob - 1 do + r[oob - i] = t[i] + end + return r +end + + +local function foldr(fn, d, t) + if t == nil then + local u, last = {}, len(d) + for i = 1, last - 1 do + u[#u + 1] = d[i] + end + d, t = d[last], u + end + return reduce(function(x, y) return fn(y, x) end, d, ielems, ireverse(t)) +end + + +local function id(...) + return ... +end + + +local function multiserialize(...) + local seq = pack(...) + local buf = {} + for i = 1, seq.n do + buf[i] = serialize(seq[i]) + end + return concat(buf, ',') +end + + +local function memoize(fn, mnemonic) + mnemonic = mnemonic or multiserialize + + return setmetatable({}, { + __call = function(self, ...) + local k = mnemonic(...) + local t = self[k] + if t == nil then + t = pack(fn(...)) + self[k] = t + end + return unpack(t, 1, t.n) + end + }) +end + + +local lambda = memoize(function(s) + local expr + + -- Support '|args|expression' format. + local args, body = s:match '^%s*|%s*([^|]*)|%s*(.+)%s*$' + if args and body then + expr = 'return function(' .. args .. ') return ' .. body .. ' end' + end + + -- Support 'expression' format. + if not expr then + body = s:match '^%s*(_.*)%s*$' or s:match '^=%s*(.+)%s*$' + if body then + expr = [[ + return function(...) + local _1,_2,_3,_4,_5,_6,_7,_8,_9 = ... + local _ = _1 + return ]] .. body .. [[ + end + ]] + end + end + + local ok, fn + if expr then + ok, fn = pcall(load(expr)) + end + + -- Diagnose invalid input. + if not ok then + return nil, "invalid lambda string '" .. s .. "'" + end + + return setmetatable({}, { + __call = function(self, ...) return fn(...) end, + __tostring = function(self) return s end, + }) +end, id) + + +local function map(mapfn, ifn, ...) + local argt, r = pack(...), {} + if not callable(ifn) or argt.n == 0 then + ifn, argt = pairs, pack(ifn, ...) + end + + local nextfn, state, k = ifn(unpack(argt, 1, argt.n)) + local mapargs = pack(nextfn(state, k)) + + local arity = 1 + while mapargs[1] ~= nil do + local d, v = mapfn(unpack(mapargs, 1, mapargs.n)) + if v ~= nil then + arity, r = 2, {} break + end + r[#r + 1] = d + mapargs = {nextfn(state, mapargs[1])} + end + + if arity > 1 then + -- No need to start over here, because either: + -- (i) arity was never 1, and the original value of mapargs is correct + -- (ii) arity used to be 1, but we only consumed nil values, so the + -- current mapargs with arity > 1 is the correct next value to use + while mapargs[1] ~= nil do + local k, v = mapfn(unpack(mapargs, 1, mapargs.n)) + r[k] = v + mapargs = pack(nextfn(state, mapargs[1])) + end + end + return r +end + + +local function map_with(mapfn, tt) + local r = {} + for k, v in next, tt do + r[k] = mapfn(unpack(v, 1, len(v))) + end + return r +end + + +local function _product(x, l) + local r = {} + for v1 in ielems(x) do + for v2 in ielems(l) do + r[#r + 1] = {v1, unpack(v2, 1, len(v2))} + end + end + return r +end + +local function product(...) + local argt = {...} + if not next(argt) then + return argt + else + -- Accumulate a list of products, starting by popping the last + -- argument and making each member a one element list. + local d = map(lambda '={_1}', ielems, remove(argt)) + -- Right associatively fold in remaining argt members. + return foldr(_product, d, argt) + end +end + + +local function shape(dims, t) + t = flatten(t) + -- Check the shape and calculate the size of the zero, if any + local size = 1 + local zero + for i, v in ipairs(dims) do + if v == 0 then + if zero then -- bad shape: two zeros + return nil + else + zero = i + end + else + size = size * v + end + end + if zero then + dims[zero] = ceil(len(t) / size) + end + local function fill(i, d) + if d > len(dims) then + return t[i], i + 1 + else + local r = {} + for j = 1, dims[d] do + local e + e, i = fill(i, d + 1) + r[#r + 1] = e + end + return r, i + end + end + return(fill(1, 1)) +end + + +local function zip(tt) + local r = {} + for outerk, inner in pairs(tt) do + for k, v in pairs(inner) do + r[k] = r[k] or {} + r[k][outerk] = v + end + end + return r +end + + +local function zip_with(fn, tt) + return map_with(fn, zip(tt)) +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck('std.functional.' .. decl, fn) +end + +return { + --- Call a series of functions until one returns non-nil. + -- @function any + -- @func ... functions to call + -- @treturn function to call fn1 .. fnN until one returns non-nil. + -- @usage + -- old_object_type = any(std.object.type, io.type, type) + any = X('any(func...)', any), + + --- Partially apply a function. + -- @function bind + -- @func fn function to apply partially + -- @tparam table argt table of *fn* arguments to bind + -- @return function with *argt* arguments already bound + -- @usage + -- cube = bind(std.functional.operator.pow, {[2] = 3}) + bind = X('bind(func, table)', bind), + + --- Identify callable types. + -- @function callable + -- @param x an object or primitive + -- @return `true` if *x* can be called, otherwise `false` + -- @usage + -- if callable(functable) then functable(args) end + callable = X('callable(?any)', callable), + + --- A rudimentary case statement. + -- Match *with* against keys in *branches* table. + -- @function case + -- @param with expression to match + -- @tparam table branches map possible matches to functions + -- @return the value associated with a matching key, or the first non-key + -- value if no key matches. Function or functable valued matches are + -- called using *with* as the sole argument, and the result of that call + -- returned; otherwise the matching value associated with the matching + -- key is returned directly; or else `nil` if there is no match and no + -- default. + -- @see cond + -- @usage + -- return case(type(object), { + -- table = 'table', + -- string = function() return 'string' end, + -- function(s) error('unhandled type: ' .. s) end, + -- }) + case = X('case(?any, #table)', case), + + --- Collect the results of an iterator. + -- @function collect + -- @func[opt=std.npairs] ifn iterator function + -- @param ... *ifn* arguments + -- @treturn table of results from running *ifn* on *args* + -- @see filter + -- @see map + -- @usage + -- --> {'a', 'b', 'c'} + -- collect {'a', 'b', 'c', x=1, y=2, z=5} + collect = X('collect([func], ?any...)', collect), + + --- Compose functions. + -- @function compose + -- @func ... functions to compose + -- @treturn function composition of fnN .. fn1: note that this is the + -- reverse of what you might expect, but means that code like: + -- + -- compose(function(x) return f(x) end, + -- function(x) return g(x) end)) + -- + -- can be read from top to bottom. + -- @usage + -- vpairs = compose(table.invert, ipairs) + -- for v, i in vpairs {'a', 'b', 'c'} do process(v, i) end + compose = X('compose(func...)', compose), + + --- A rudimentary condition-case statement. + -- If *expr* is 'truthy' return *branch* if given, otherwise *expr* + -- itself. If the return value is a function or functable, then call it + -- with *expr* as the sole argument and return the result; otherwise + -- return it explicitly. If *expr* is 'falsey', then recurse with the + -- first two arguments stripped. + -- @function cond + -- @param expr a Lua expression + -- @param branch a function, functable or value to use if *expr* is + -- 'truthy' + -- @param ... additional arguments to retry if *expr* is 'falsey' + -- @see case + -- @usage + -- -- recursively calculate the nth triangular number + -- function triangle(n) + -- return cond( + -- n <= 0, 0, + -- n == 1, 1, + -- function() return n + triangle(n - 1) end) + -- end + cond = cond, -- any number of any type arguments! + + --- Curry a function. + -- @function curry + -- @func fn function to curry + -- @int n number of arguments + -- @treturn function curried version of *fn* + -- @usage + -- add = curry(function(x, y) return x + y end, 2) + -- incr, decr = add(1), add(-1) + curry = X('curry(func, int)', curry), + + --- Filter an iterator with a predicate. + -- @function filter + -- @tparam predicate pfn predicate function + -- @func[opt=std.pairs] ifn iterator function + -- @param ... iterator arguments + -- @treturn table elements e for which `pfn(e)` is not 'falsey'. + -- @see collect + -- @see map + -- @usage + -- --> {2, 4} + -- filter(lambda '|e|e%2==0', std.elems, {1, 2, 3, 4}) + filter = X('filter(func, [func], ?any...)', filter), + + --- Flatten a nested table into a list. + -- @function flatten + -- @tparam table t a table + -- @treturn table a list of all non-table elements of *t* + -- @usage + -- --> {1, 2, 3, 4, 5} + -- flatten {{1, {{2}, 3}, 4}, 5} + flatten = X('flatten(table)', flatten), + + --- Fold a binary function left associatively. + -- If parameter *d* is omitted, the first element of *t* is used, + -- and *t* treated as if it had been passed without that element. + -- @function foldl + -- @func fn binary function + -- @param[opt=t[1]] d initial left-most argument + -- @tparam table t a table + -- @return result + -- @see foldr + -- @see reduce + -- @usage + -- foldl(operator.quot, {10000, 100, 10}) == (10000 / 100) / 10 + foldl = X('foldl(function, [any], table)', foldl), + + --- Fold a binary function right associatively. + -- If parameter *d* is omitted, the last element of *t* is used, + -- and *t* treated as if it had been passed without that element. + -- @function foldr + -- @func fn binary function + -- @param[opt=t[1]] d initial right-most argument + -- @tparam table t a table + -- @return result + -- @see foldl + -- @see reduce + -- @usage + -- foldr(operator.quot, {10000, 100, 10}) == 10000 / (100 / 10) + foldr = X('foldr(function, [any], table)', foldr), + + --- Identity function. + -- @function id + -- @param ... arguments + -- @return *arguments* + id = id, -- any number of any type arguments! + + --- Return a new sequence with element order reversed. + -- + -- Apart from the order of the elements returned, this function follows + -- the same rules as @{ipairs} for determining first and last elements. + -- @function ireverse + -- @tparam table t a table + -- @treturn table a new table with integer keyed elements in reverse + -- order with respect to *t* + -- @see ipairs + -- @usage + -- local rielems = compose(ireverse, std.ielems) + -- --> bar + -- --> foo + -- map(print, rielems, {'foo', 'bar', [4]='baz', d=5}) + ireverse = X('ireverse(table)', ireverse), + + --- Compile a lambda string into a Lua function. + -- + -- A valid lambda string takes one of the following forms: + -- + -- 1. `'=expression'`: equivalent to `function(...) return expression end` + -- 1. `'|args|expression'`: equivalent to `function(args) return expression end` + -- + -- The first form (starting with `'='`) automatically assigns the first + -- nine arguments to parameters `'_1'` through `'_9'` for use within the + -- expression body. The parameter `'_1'` is aliased to `'_'`, and if the + -- first non-whitespace of the whole expression is `'_'`, then the + -- leading `'='` can be omitted. + -- + -- The results are memoized, so recompiling a previously compiled + -- lambda string is extremely fast. + -- @function lambda + -- @string s a lambda string + -- @treturn functable compiled lambda string, can be called like a function + -- @usage + -- -- The following are equivalent: + -- lambda '= _1 < _2' + -- lambda '|a,b| a<b' + lambda = X('lambda(string)', lambda), + + --- Map a function over an iterator. + -- @function map + -- @func fn map function + -- @func[opt=std.pairs] ifn iterator function + -- @param ... iterator arguments + -- @treturn table results + -- @see filter + -- @see map_with + -- @see zip + -- @usage + -- --> {1, 4, 9, 16} + -- map(lambda '=_1*_1', std.ielems, {1, 2, 3, 4}) + map = X('map(func, [func], ?any...)', map), + + --- Map a function over a table of argument lists. + -- @function map_with + -- @func fn map function + -- @tparam table tt a table of *fn* argument lists + -- @treturn table new table of *fn* results + -- @see map + -- @see zip_with + -- @usage + -- --> {'123', '45'}, {a='123', b='45'} + -- conc = bind(map_with, {lambda '|...|table.concat {...}'}) + -- conc {{1, 2, 3}, {4, 5}}, conc {a={1, 2, 3, x='y'}, b={4, 5, z=6}} + map_with = X('map_with(function, table of tables)', map_with), + + --- Memoize a function, by wrapping it in a functable. + -- + -- To ensure that memoize always returns the same results for the same + -- arguments, it passes arguments to *fn*. You can specify a more + -- sophisticated function if memoize should handle complicated argument + -- equivalencies. + -- @function memoize + -- @func fn pure function: a function with no side effects + -- @tparam[opt=std.tostring] mnemonic mnemonicfn how to remember the arguments + -- @treturn functable memoized function + -- @usage + -- local fast = memoize(function(...) --[[ slow code ]] end) + memoize = X('memoize(func, ?func)', memoize), + + --- No operation. + -- This function ignores all arguments, and returns no values. + -- @function nop + -- @see id + -- @usage + -- if unsupported then vtable['memrmem'] = nop end + nop = function() end, + + --- Functional list product. + -- + -- Return a list of each combination possible by taking a single + -- element from each of the argument lists. + -- @function product + -- @param ... operands + -- @return result + -- @usage + -- --> {'000', '001', '010', '011', '100', '101', '110', '111'} + -- map(table.concat, ielems, product({0,1}, {0, 1}, {0, 1})) + product = X('product(list...)', product), + + --- Fold a binary function into an iterator. + -- @function reduce + -- @func fn reduce function + -- @param d initial first argument + -- @func[opt=std.pairs] ifn iterator function + -- @param ... iterator arguments + -- @return result + -- @see foldl + -- @see foldr + -- @usage + -- --> 2 ^ 3 ^ 4 ==> 4096 + -- reduce(operator.pow, 2, std.ielems, {3, 4}) + reduce = X('reduce(func, any, [func], ?any...)', reduce), + + --- Shape a table according to a list of dimensions. + -- + -- Dimensions are given outermost first and items from the original + -- list are distributed breadth first; there may be one 0 indicating + -- an indefinite number. Hence, `{0}` is a flat list, + -- `{1}` is a singleton, `{2, 0}` is a list of + -- two lists, and `{0, 2}` is a list of pairs. + -- + -- Algorithm: turn shape into all positive numbers, calculating + -- the zero if necessary and making sure there is at most one; + -- recursively walk the shape, adding empty tables until the bottom + -- level is reached at which point add table items instead, using a + -- counter to walk the flattened original list. + -- + -- @todo Use ileaves instead of flatten (needs a while instead of a + -- for in fill function) + -- @function shape + -- @tparam table dims table of dimensions `{d1, ..., dn}` + -- @tparam table t a table of elements + -- @return reshaped list + -- @usage + -- --> {{'a', 'b'}, {'c', 'd'}, {'e', 'f'}} + -- shape({3, 2}, {'a', 'b', 'c', 'd', 'e', 'f'}) + shape = X('shape(table, table)', shape), + + --- Zip a table of tables. + -- Make a new table, with lists of elements at the same index in the + -- original table. This function is effectively its own inverse. + -- @function zip + -- @tparam table tt a table of tables + -- @treturn table new table with lists of elements of the same key + -- from *tt* + -- @see map + -- @see zip_with + -- @usage + -- --> {{1, 3, 5}, {2, 4}}, {a={x=1, y=3, z=5}, b={x=2, y=4}} + -- zip {{1, 2}, {3, 4}, {5}}, zip {x={a=1, b=2}, y={a=3, b=4}, z={a=5}} + zip = X('zip(table of tables)', zip), + + --- Zip a list of tables together with a function. + -- @function zip_with + -- @tparam function fn function + -- @tparam table tt table of tables + -- @treturn table a new table of results from calls to *fn* with arguments + -- made from all elements the same key in the original tables; effectively + -- the 'columns' in a simple list + -- of lists. + -- @see map_with + -- @see zip + -- @usage + -- --> {'135', '24'}, {a='1', b='25'} + -- conc = bind(zip_with, {lambda '|...|table.concat {...}'}) + -- conc {{1, 2}, {3, 4}, {5}}, conc {{a=1, b=2}, x={a=3, b=4}, {b=5}} + zip_with = X('zip_with(function, table of tables)', zip_with), +} + + +--- Types +-- @section Types + + +--- Signature of a @{memoize} argument normalization callback function. +-- @function mnemonic +-- @param ... arguments +-- @treturn string stable serialized arguments +-- @usage +-- local mnemonic = function(name, value, props) return name end +-- local intern = memoize(mksymbol, mnemonic) + + +--- Signature of a @{filter} predicate callback function. +-- @function predicate +-- @param ... arguments +-- @treturn boolean 'truthy' if the predicate condition succeeds, +-- 'falsey' otherwise +-- @usage +-- local predicate = lambda '|k,v|type(v)=="string"' +-- local strvalues = filter(predicate, std.pairs, {name='Roberto', id=12345}) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/operator.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/operator.lua @@ -0,0 +1,239 @@ +--[[ + Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 + Copyright (C) 2002-2022 std.functional authors +]] +--[[-- + Functional forms of Lua operators. + + @module std.functional.operator +]] + + +local _ENV = require 'std.normalize' { + 'std.functional._base.serialize', +} + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local function eqv(a, b) + -- If they are the same primitive value, or they share a metatable + -- with an __eq metamethod that says they are equivalent, we're done! + if a == b then + return true + end + + -- Unless we now have two tables, the previous line ensures a ~= b. + if type(a) ~= 'table' or type(b) ~= 'table' then + return false + end + + -- Otherwise, compare serializations of each. + return serialize(a) == serialize(b) +end + + +return { + --- Stringify and concatenate arguments. + -- @param a an argument + -- @param b another argument + -- @return concatenation of stringified arguments. + -- @usage + -- --> '=> 1000010010' + -- foldl(concat, '=> ', {10000, 100, 10}) + concat = function(a, b) + return tostring(a) .. tostring(b) + end, + + --- Equivalent to `#` operation, but respecting `__len` even on Lua 5.1. + -- @function len + -- @tparam object|string|table x operand + -- @treturn int length of list part of *t* + -- @usage + -- for i = 1, len(t) do process(t[i]) end + len = len, + + --- Dereference a table. + -- @tparam table t a table + -- @param k a key to lookup in *t* + -- @return value stored at *t[k]* if any, otherwise `nil` + -- @usage + -- --> 4 + -- foldl(get, {1, {{2, 3, 4}, 5}}, {2, 1, 3}) + get = function(t, k) + return t and t[k] or nil + end, + + --- Set a table element, honoring metamethods. + -- @tparam table t a table + -- @param k a key to lookup in *t* + -- @param v a value to set for *k* + -- @treturn table *t* + -- @usage + -- -- destructive table merge: + -- --> {'one', bar='baz', two=5} + -- reduce(set, {'foo', bar='baz'}, {'one', two=5}) + set = function(t, k, v) + t[k]=v + return t + end, + + --- Return the sum of the arguments. + -- @param a an argument + -- @param b another argument + -- @return the sum of the *a* and *b* + -- @usage + -- --> 10110 + -- foldl(sum, {10000, 100, 10}) + sum = function(a, b) + return a + b + end, + + --- Return the difference of the arguments. + -- @param a an argument + -- @param b another argument + -- @return the difference between *a* and *b* + -- @usage + -- --> 890 + -- foldl(diff, {10000, 100, 10}) + diff = function(a, b) + return a - b + end, + + --- Return the product of the arguments. + -- @param a an argument + -- @param b another argument + -- @return the product of *a* and *b* + -- @usage + -- --> 10000000 + -- foldl(prod, {10000, 100, 10}) + prod = function(a, b) + return a * b + end, + + --- Return the quotient of the arguments. + -- @param a an argument + -- @param b another argument + -- @return the quotient *a* and *b* + -- @usage + -- --> 1000 + -- foldr(quot, {10000, 100, 10}) + quot = function(a, b) + return a / b + end, + + --- Return the modulus of the arguments. + -- @param a an argument + -- @param b another argument + -- @return the modulus of *a* and *b* + -- @usage + -- --> 3 + -- foldl(mod, {65536, 100, 11}) + mod = function(a, b) + return a % b + end, + + --- Return the exponent of the arguments. + -- @param a an argument + -- @param b another argument + -- @return the *a* to the power of *b* + -- @usage + -- --> 4096 + -- foldl(pow, {2, 3, 4}) + pow = function(a, b) + return a ^ b + end, + + --- Return the logical conjunction of the arguments. + -- @param a an argument + -- @param b another argument + -- @return logical *a* and *b* + -- @usage + -- --> true + -- foldl(conj, {true, 1, 'false'}) + conj = function(a, b) + return a and b + end, + + --- Return the logical disjunction of the arguments. + -- @param a an argument + -- @param b another argument + -- @return logical *a* or *b* + -- @usage + -- --> true + -- foldl(disj, {true, 1, false}) + disj = function(a, b) + return a or b + end, + + --- Return the logical negation of the arguments. + -- @param a an argument + -- @return not *a* + -- @usage + -- --> {true, false, false, false} + -- bind(map, {std.ielems, neg}) {false, true, 1, 0} + neg = function(a) + return not a + end, + + --- Recursive table equivalence. + -- @param a an argument + -- @param b another argument + -- @treturn boolean whether *a* and *b* are recursively equivalent + eqv = eqv, + + --- Return the equality of the arguments. + -- @param a an argument + -- @param b another argument + -- @return `true` if *a* is *b*, otherwise `false` + eq = function(a, b) + return a == b + end, + + --- Return the inequality of the arguments. + -- @param a an argument + -- @param b another argument + -- @return `false` if *a* is *b*, otherwise `true` + -- @usage + -- --> true + -- local f = require 'std.functional' + -- table.empty(f.filter (f.bind(neq, {6}), std.ielems, {6, 6, 6}) + neq = function(a, b) + return a ~= b + end, + + --- Return whether the arguments are in ascending order. + -- @param a an argument + -- @param b another argument + -- @return `true` if *a* is less then *b*, otherwise `false` + lt = function(a, b) + return a < b + end, + + --- Return whether the arguments are not in descending order. + -- @param a an argument + -- @param b another argument + -- @return `true` if *a* is not greater then *b*, otherwise `false` + lte = function(a, b) + return a <= b + end, + + --- Return whether the arguments are in descending order. + -- @param a an argument + -- @param b another argument + -- @return `true` if *a* is greater then *b*, otherwise `false` + gt = function(a, b) + return a > b + end, + + --- Return whether the arguments are not in ascending order. + -- @param a an argument + -- @param b another argument + -- @return `true` if *a* is not greater then *b*, otherwise `false` + gte = function(a, b) + return a >= b + end, +} diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/functional/tuple.lua b/modules/mixins/dotfiles/config/nvim/lua/std/functional/tuple.lua @@ -0,0 +1,156 @@ +--[[ + Functional programming for Lua 5.1, 5.2, 5.3 & 5.4 + Copyright (C) 2002-2022 std.functional authors +]] +--[[-- + Tuple container. + + An interned, immutable, nil-preserving tuple object. + + Like Lua strings, tuples with the same elements can be quickly compared + with a straight-forward `==` comparison. + + The immutability guarantees only work if you don't change the contents + of tables after adding them to a tuple. Don't do that! + + @module std.functional.tuple +]] + + +local _ENV = require 'std.normalize' { + 'std.functional._base.toqstring', + 'string.format', + 'table.concat', +} + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +-- We maintain a weak table of all distinct Tuples, where each value is +-- the tuple object itself, and the associated key is the stringified +-- list of elements contained by the tuple, e.g the 0-tuple: +-- +-- intern[''] = setmetatable({n = 0}, Tuple) +-- +-- In order to make a tuple immutable, it needs to have a __newindex +-- metamethod that diagnoses attempts to insert new elements, which in +-- turn means that the actual elements need to be kept in a proxy table +-- (because if we stored the first element in the tuple table, then +-- __newindex would not fire when the first element was written to). +-- Rather that using metamethods to access a wholly separate proxy +-- table, we use the proxey table as a key in the tuple object proper +-- (it would be impossible to accidentally assign to a unique table +-- address key, so __newindex will still work) and use a copy of the +-- intern stringified elements key as the associated value there, e.g. +-- for the 0-tuple again: +-- +-- { [{n = 0}] = '' } +-- +-- This means we have a pleasant property to enable fast stringification +-- of any tuple we hold: +-- +-- proxy_table, stringified_element_list = next(tuple) + + +--- Immutable Tuple container. +-- @object Tuple +-- @string[opt='Tuple'] _type object name +-- @int n number of tuple elements +-- @usage +-- local Tuple = require 'std.functional.tuple' +-- function count(...) +-- argtuple = Tuple(...) +-- return argtuple.n +-- end +-- count() --> 0 +-- count(nil) --> 1 +-- count(false) --> 1 +-- count(false, nil, true, nil) --> 4 +local Tuple = { + _type = 'Tuple', + + --- Metamethods + -- @section metamethods + + --- Unpack tuple values between index *i* and *j*, inclusive. + -- @function __call + -- @int[opt=1] i first index to unpack + -- @int[opt=self.n] j last index to unpack + -- @return ... values at indices *i* through *j*, inclusive + -- @usage + -- tup = Tuple(1, 3, 2, 5) + -- --> 3, 2, 5 + -- tup(2) + __call = function(self, i, j) + return unpack(next(self), tonumber(i) or 1, tonumber(j) or self.n) + end, + + __index = function(self, k) + return next(self)[k] + end, + + --- Return the length of this tuple. + -- @function prototype:__len + -- @treturn int number of elements in *tup* + -- @usage + -- -- Only works on Lua 5.2 or newer: + -- #Tuple(nil, 2, nil) --> 3 + -- -- For compatibility with Lua 5.1, use @{operator.len} + -- len(Tuple(nil, 2, nil) + __len = function(self) + return self.n + end, + + --- Prevent mutation of *tup*. + -- @function prototype:__newindex + -- @param k tuple key + -- @param v tuple value + -- @raise cannot change immutable tuple object + __newindex = function(self, k, v) + error('cannot change immutable tuple object', 2) + end, + + --- Return a string representation of *tup* + -- @function prototype:__tostring + -- @treturn string representation of *tup* + -- @usage + -- -- "Tuple('nil', nil, false)" + -- print(Tuple('nil', nil, false)) + __tostring = function(self) + local _, argstr = next(self) + return format('%s(%s)', getmetatable(self)._type, argstr) + end, +} + + +-- Maintain a weak functable of all interned tuples. +-- @function intern +-- @int n number of elements in *t*, including trailing `nil`s +-- @tparam table t table of elements +-- @treturn table interned *n*-tuple *t* +local intern = setmetatable({}, { + __mode = 'kv', + + __call = function(self, k, t) + if self[k] == nil then + self[k] = setmetatable({[t] = k}, Tuple) + end + return self[k] + end, +}) + + +-- Call the value returned from requiring this module with a list of +-- elements to get an interned tuple made with those elements. +return function(...) + local n = select('#', ...) + local buf, tup = {}, {n = n, ...} + for i = 1, n do + buf[i] = toqstring(tup[i]) + end + return intern(concat(buf, ', '), tup) +end diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/init.lua b/modules/mixins/dotfiles/config/nvim/lua/std/init.lua @@ -0,0 +1,389 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Enhanced Lua core functions, and others. + + After requiring this module, simply referencing symbols in the submodule + hierarchy will load the necessary modules on demand. There are no + changes to any global symbols, or monkey patching of core module tables + and metatables. + + @todo Write a style guide(indenting/wrapping, capitalisation, + function and variable names); library functions should call + error, not die; OO vs non-OO(a thorny problem). + @todo pre-compile. + @corefunction std +]] + + +local _ = require 'std._base' + +local argscheck = _.typecheck and _.typecheck.argscheck +local compare = _.list.compare +local maxn = _.table.maxn +local split = _.string.split + +_ = nil + + +local _ENV = require 'std.normalize' { + format = 'string.format', + match = 'string.match', +} + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local M + + +local function _assert(expect, fmt, arg1, ...) + local msg =(arg1 ~= nil) and format(fmt, arg1, ...) or fmt or '' + return expect or error(msg, 2) +end + + +local function elems(t) + -- capture pairs iterator initial state + local fn, istate, ctrl = pairs(t) + return function(state, _) + local v + ctrl, v = fn(state, ctrl) + if ctrl then + return v + end + end, istate, true -- wrapped initial state +end + + +local function eval(s) + return load('return ' .. s)() +end + + +local function ielems(t) + -- capture pairs iterator initial state + local fn, istate, ctrl = ipairs(t) + return function(state, _) + local v + ctrl, v = fn(state, ctrl) + if ctrl then + return v + end + end, istate, true -- wrapped initial state +end + + +local function npairs(t) + local m = getmetamethod(t, '__len') + local i, n = 0, m and m(t) or maxn(t) + return function(t) + i = i + 1 + if i <= n then + return i, t[i] + end + end, + t, i +end + + +local function ripairs(t) + local oob = 1 + while t[oob] ~= nil do + oob = oob + 1 + end + + return function(t, n) + n = n - 1 + if n > 0 then + return n, t[n] + end + end, t, oob +end + + +local function rnpairs(t) + local m = getmetamethod(t, '__len') + local oob =(m and m(t) or maxn(t)) + 1 + + return function(t, n) + n = n - 1 + if n > 0 then + return n, t[n] + end + end, t, oob +end + + +local vconvert = setmetatable({ + string = function(x) + return split(x, '%.') + end, + number = function(x) + return {x} + end, + table = function(x) + return x + end, +}, { + __call = function(self, x) + local fn = self[type(x)] or function() + return 0 + end + return fn(x) + end, +}) + + +local function vcompare(a, b) + return compare(vconvert(a), vconvert(b)) +end + + +local function _require(module, min, too_big, pattern) + pattern = pattern or '([%.%d]+)%D*$' + + local s, m = '', require(module) + if type(m) == 'table' then + s = tostring(m.version or m._VERSION or '') + end + local v = match(s, pattern) or 0 + if min then + _assert(vcompare(v, min) >= 0, "require '" .. module .. + "' with at least version " .. min .. ', but found version ' .. v) + end + if too_big then + _assert(vcompare(v, too_big) < 0, "require '" .. module .. + "' with version less than " .. too_big .. ', but found version ' .. v) + end + return m +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck and argscheck('std.' .. decl, fn) or fn +end + +M = { + --- Release version string. + -- @field version + + + --- Core Functions + -- @section corefuncs + + --- Enhance core `assert` to also allow formatted arguments. + -- @function assert + -- @param expect expression, expected to be *truthy* + -- @string[opt=''] f format string + -- @param[opt] ... arguments to format + -- @return value of *expect*, if *truthy* + -- @usage + -- std.assert(expect == nil, '100% unexpected!') + -- std.assert(expect == 'expect', '%s the unexpected!', expect) + assert = X('assert(?any, ?string, [any...])', _assert), + + --- Evaluate a string as Lua code. + -- @function eval + -- @string s string of Lua code + -- @return result of evaluating `s` + -- @usage + -- --> 2 + -- std.eval 'math.min(2, 10)' + eval = X('eval(string)', eval), + + --- Return named metamethod, if any, otherwise `nil`. + -- The value found at the given key in the metatable of *x* must be a + -- function or have its own `__call` metamethod to qualify as a + -- callable. Any other value found at key *n* will cause this function + -- to return `nil`. + -- @function getmetamethod + -- @param x item to act on + -- @string n name of metamethod to lookup + -- @treturn callable|nil callable metamethod, or `nil` if no metamethod + -- @usage + -- clone = std.getmetamethod(std.object.prototype, '__call') + getmetamethod = X('getmetamethod(?any, string)', getmetamethod), + + + --- Module Functions + -- @section modulefuncs + + --- Enhance core `require` to assert version number compatibility. + -- By default match against the last substring of(dot-delimited) + -- digits in the module version string. + -- @function require + -- @string module module to require + -- @string[opt] min lowest acceptable version + -- @string[opt] too_big lowest version that is too big + -- @string[opt] pattern to match version in `module.version` or + -- `module._VERSION`(default: `'([%.%d]+)%D*$'`) + -- @usage + -- -- posix.version == 'posix library for Lua 5.2 / 32' + -- posix = require('posix', '29') + require = X('require(string, ?string, ?string, ?string)', _require), + + --- Iterator Functions + -- @section iteratorfuncs + + --- An iterator over all values of a table. + -- If *t* has a `__pairs` metamethod, use that to iterate. + -- @function elems + -- @tparam table t a table + -- @treturn function iterator function + -- @treturn table *t*, the table being iterated over + -- @return *key*, the previous iteration key + -- @see ielems + -- @see pairs + -- @usage + -- --> foo + -- --> bar + -- --> baz + -- --> 5 + -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5}) + elems = X('elems(table)', elems), + + --- An iterator over the integer keyed elements of a table. + -- + -- If *t* has a `__len` metamethod, iterate up to the index it + -- returns, otherwise up to the first `nil`. + -- + -- This function does **not** support the Lua 5.2 `__ipairs` metamethod. + -- @function ielems + -- @tparam table t a table + -- @treturn function iterator function + -- @treturn table *t*, the table being iterated over + -- @treturn int *index*, the previous iteration index + -- @see elems + -- @see ipairs + -- @usage + -- --> foo + -- --> bar + -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5}) + ielems = X('ielems(table)', ielems), + + --- An iterator over integer keyed pairs of a sequence. + -- + -- Like Lua 5.1 and 5.3, this iterator returns successive key-value + -- pairs with integer keys starting at 1, up to the first `nil` valued + -- pair. + -- + -- If there is a `_len` metamethod, keep iterating up to and including + -- that element, regardless of any intervening `nil` values. + -- + -- This function does **not** support the Lua 5.2 `__ipairs` metamethod. + -- @function ipairs + -- @tparam table t a table + -- @treturn function iterator function + -- @treturn table *t*, the table being iterated over + -- @treturn int *index*, the previous iteration index + -- @see ielems + -- @see npairs + -- @see pairs + -- @usage + -- --> 1 foo + -- --> 2 bar + -- std.functional.map(print, std.ipairs, {'foo', 'bar', [4]='baz', d=5}) + ipairs = X('ipairs(table)', ipairs), + + --- Ordered iterator for integer keyed values. + -- Like ipairs, but does not stop until the __len or maxn of *t*. + -- @function npairs + -- @tparam table t a table + -- @treturn function iterator function + -- @treturn table t + -- @see ipairs + -- @see rnpairs + -- @usage + -- --> 1 foo + -- --> 2 bar + -- --> 3 nil + -- --> 4 baz + -- std.functional.map(print, std.npairs, {'foo', 'bar', [4]='baz', d=5}) + npairs = X('npairs(table)', npairs), + + --- Enhance core `pairs` to respect `__pairs` even in Lua 5.1. + -- @function pairs + -- @tparam table t a table + -- @treturn function iterator function + -- @treturn table *t*, the table being iterated over + -- @return *key*, the previous iteration key + -- @see elems + -- @see ipairs + -- @usage + -- --> 1 foo + -- --> 2 bar + -- --> 4 baz + -- --> d 5 + -- std.functional.map(print, std.pairs, {'foo', 'bar', [4]='baz', d=5}) + pairs = X('pairs(table)', pairs), + + --- An iterator like ipairs, but in reverse. + -- Apart from the order of the elements returned, this function follows + -- the same rules as @{ipairs} for determining first and last elements. + -- @function ripairs + -- @tparam table t any table + -- @treturn function iterator function + -- @treturn table *t* + -- @treturn number `#t + 1` + -- @see ipairs + -- @see rnpairs + -- @usage + -- --> 2 bar + -- --> 1 foo + -- std.functional.map(print, std.ripairs, {'foo', 'bar', [4]='baz', d=5}) + ripairs = X('ripairs(table)', ripairs), + + --- An iterator like npairs, but in reverse. + -- Apart from the order of the elements returned, this function follows + -- the same rules as @{npairs} for determining first and last elements. + -- @function rnpairs + -- @tparam table t a table + -- @treturn function iterator function + -- @treturn table t + -- @see npairs + -- @see ripairs + -- @usage + -- --> 4 baz + -- --> 3 nil + -- --> 2 bar + -- --> 1 foo + -- std.functional.map(print, std.rnpairs, {'foo', 'bar', [4]='baz', d=5}) + rnpairs = X('rnpairs(table)', rnpairs), +} + + +--- Metamethods +-- @section Metamethods + +return setmetatable(M, { + --- Lazy loading of stdlib modules. + -- Don't load everything on initial startup, wait until first attempt + -- to access a submodule, and then load it on demand. + -- @function __index + -- @string name submodule name + -- @treturn table|nil the submodule that was loaded to satisfy the missing + -- `name`, otherwise `nil` if nothing was found + -- @usage + -- local std = require 'std' + -- local Object = std.object.prototype + __index = function(self, name) + local ok, t = pcall(require, 'std.' .. name) + if ok then + rawset(self, name, t) + return t + end + end, +}) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/io.lua b/modules/mixins/dotfiles/config/nvim/lua/std/io.lua @@ -0,0 +1,322 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Additions to the core io module. + + The module table returned by `std.io` also contains all of the entries from + the core `io` module table. An hygienic way to import this module, then, + is simply to override core `io` locally: + + local io = require 'std.io' + + @corelibrary std.io +]] + + +local _ = require 'std._base' + +local argscheck = _.typecheck and _.typecheck.argscheck +local catfile = _.io.catfile +local leaves = _.tree.leaves +local split = _.string.split + +_ = nil + + +local _ENV = require 'std.normalize' { + 'io', + _G = _G, -- FIXME: don't use the host _G as an API! + concat = 'table.concat', + dirsep = 'package.dirsep', + format = 'string.format', + gsub = 'string.gsub', + input = 'io.input', + insert = 'table.insert', + io_type = 'io.type', + merge = 'table.merge', + open = 'io.open', + output = 'io.output', + popen = 'io.popen', + stderr = 'io.stderr', + stdin = 'io.stdin', + write = 'io.write', +} + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local M + + +local function input_handle(h) + if h == nil then + return input() + elseif type(h) == 'string' then + return open(h) + end + return h +end + + +local function slurp(file) + local h, err = input_handle(file) + if h == nil then + argerror('std.io.slurp', 1, err, 2) + end + + if h then + local s = h:read('*a') + h:close() + return s + end +end + + +local function readlines(file) + local h, err = input_handle(file) + if h == nil then + argerror('std.io.readlines', 1, err, 2) + end + + local l = {} + for line in h:lines() do + l[#l + 1] = line + end + h:close() + return l +end + + +local function writelines(h, ...) + if io_type(h) ~= 'file' then + write(h, '\n') + h = output() + end + for v in leaves(ipairs, {...}) do + h:write(v, '\n') + end +end + + +local function process_files(fn) + -- N.B. 'arg' below refers to the global array of command-line args + if len(arg) == 0 then + insert(arg, '-') + end + for i, v in ipairs(arg) do + if v == '-' then + input(stdin) + else + input(v) + end + fn(v, i) + end +end + + +local function warnfmt(msg, ...) + local prefix = '' + local prog = rawget(_G, 'prog') or {} + local opts = rawget(_G, 'opts') or {} + if prog.name then + prefix = prog.name .. ':' + if prog.line then + prefix = prefix .. str(prog.line) .. ':' + end + elseif prog.file then + prefix = prog.file .. ':' + if prog.line then + prefix = prefix .. str(prog.line) .. ':' + end + elseif opts.program then + prefix = opts.program .. ':' + if opts.line then + prefix = prefix .. str(opts.line) .. ':' + end + end + if #prefix > 0 then + prefix = prefix .. ' ' + end + return prefix .. format(msg, ...) +end + + +local function warn(msg, ...) + writelines(stderr, warnfmt(msg, ...)) +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck and argscheck('std.io.' .. decl, fn) or fn +end + + +M = { + --- Diagnostic functions + -- @section diagnosticfuncs + + --- Die with error. + -- This function uses the same rules to build a message prefix + -- as @{warn}. + -- @function die + -- @string msg format string + -- @param ... additional arguments to plug format string specifiers + -- @see warn + -- @usage + -- die('oh noes!(%s)', tostring(obj)) + die = X('die(string, [any...])', function(...) + error(warnfmt(...), 0) + end), + + --- Give warning with the name of program and file(if any). + -- If there is a global `prog` table, prefix the message with + -- `prog.name` or `prog.file`, and `prog.line` if any. Otherwise + -- if there is a global `opts` table, prefix the message with + -- `opts.program` and `opts.line` if any. + -- @function warn + -- @string msg format string + -- @param ... additional arguments to plug format string specifiers + -- @see die + -- @usage + -- local OptionParser = require 'std.optparse' + -- local parser = OptionParser 'eg 0\nUsage: eg\n' + -- _G.arg, _G.opts = parser:parse(_G.arg) + -- if not _G.opts.keep_going then + -- require 'std.io'.warn 'oh noes!' + -- end + warn = X('warn(string, [any...])', warn), + + + --- Path Functions + -- @section pathfuncs + + --- Concatenate directory names into a path. + -- @function catdir + -- @string ... path components + -- @return path without trailing separator + -- @see catfile + -- @usage + -- dirpath = catdir('', 'absolute', 'directory') + catdir = X('catdir(string...)', function(...) + return(gsub(concat({...}, dirsep), '^$', dirsep)) + end), + + --- Concatenate one or more directories and a filename into a path. + -- @function catfile + -- @string ... path components + -- @treturn string path + -- @see catdir + -- @see splitdir + -- @usage + -- filepath = catfile('relative', 'path', 'filename') + catfile = X('catfile(string...)', catfile), + + --- Remove the last dirsep delimited element from a path. + -- @function dirname + -- @string path file path + -- @treturn string a new path with the last dirsep and following + -- truncated + -- @usage + -- dir = dirname '/base/subdir/filename' + dirname = X('dirname(string)', function(path) + return(gsub(path, catfile('', '[^', ']*$'), '')) + end), + + --- Split a directory path into components. + -- Empty components are retained: the root directory becomes `{'', ''}`. + -- @function splitdir + -- @param path path + -- @return list of path components + -- @see catdir + -- @usage + -- dir_components = splitdir(filepath) + splitdir = X('splitdir(string)', function(path) + return split(path, dirsep) + end), + + + --- IO Functions + -- @section iofuncs + + --- Process files specified on the command-line. + -- Each filename is made the default input source with `io.input`, and + -- then the filename and argument number are passed to the callback + -- function. In list of filenames, `-` means `io.stdin`. If no + -- filenames were given, behave as if a single `-` was passed. + -- @todo Make the file list an argument to the function. + -- @function process_files + -- @tparam fileprocessor fn function called for each file argument + -- @usage + -- #! /usr/bin/env lua + -- -- minimal cat command + -- local io = require 'std.io' + -- io.process_files(function() io.write(io.slurp()) end) + process_files = X('process_files(function)', process_files), + + --- Read a file or file handle into a list of lines. + -- The lines in the returned list are not `\n` terminated. + -- @function readlines + -- @tparam[opt=io.input()] file|string file file handle or name; + -- if file is a file handle, that file is closed after reading + -- @treturn list lines + -- @usage + -- list = readlines '/etc/passwd' + readlines = X('readlines(?file|string)', readlines), + + --- Perform a shell command and return its output. + -- @function shell + -- @string c command + -- @treturn string output, or nil if error + -- @see os.execute + -- @usage + -- users = shell [[cat /etc/passwd | awk -F: '{print $1;}']] + shell = X('shell(string)', function(c) return slurp(popen(c)) end), + + --- Slurp a file handle. + -- @function slurp + -- @tparam[opt=io.input()] file|string file file handle or name; + -- if file is a file handle, that file is closed after reading + -- @return contents of file or handle, or nil if error + -- @see process_files + -- @usage + -- contents = slurp(filename) + slurp = X('slurp(?file|string)', slurp), + + --- Write values adding a newline after each. + -- @function writelines + -- @tparam[opt=io.output()] file h open writable file handle; + -- the file is **not** closed after writing + -- @tparam string|number ... values to write(as for write) + -- @usage + -- writelines(io.stdout, 'first line', 'next line') + writelines = X('writelines(?file|string|number, [string|number...])', writelines), +} + + +return merge(io, M) + + + +--- Types +-- @section Types + +--- Signature of @{process_files} callback function. +-- @function fileprocessor +-- @string filename filename +-- @int i argument number of *filename* +-- @usage +-- local fileprocessor = function(filename, i) +-- io.write(tostring(i) .. ':\n===\n' .. io.slurp(filename) .. '\n') +-- end +-- io.process_files(fileprocessor) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/math.lua b/modules/mixins/dotfiles/config/nvim/lua/std/math.lua @@ -0,0 +1,92 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Additions to the core math module. + + The module table returned by `std.math` also contains all of the entries from + the core math table. An hygienic way to import this module, then, is simply + to override the core `math` locally: + + local math = require 'std.math' + + @corelibrary std.math +]] + + +local _ = require 'std._base' + +local argscheck = _.typecheck and _.typecheck.argscheck + +_ = nil + + +local _ENV = require 'std.normalize' { + 'math', + merge = 'table.merge', +} + + + +--[[ ================= ]]-- +--[[ Implementatation. ]]-- +--[[ ================= ]]-- + + +local M + + +local _floor = math.floor + +local function floor(n, p) + if(p or 0) == 0 then + return _floor(n) + end + local e = 10 ^ p + return _floor(n * e) / e +end + + +local function round(n, p) + local e = 10 ^(p or 0) + return _floor(n * e + 0.5) / e +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck and argscheck('std.math.' .. decl, fn) or fn +end + + +M = { + --- Core Functions + -- @section corefuncs + + --- Extend `math.floor` to take the number of decimal places. + -- @function floor + -- @number n number + -- @int[opt=0] p number of decimal places to truncate to + -- @treturn number `n` truncated to `p` decimal places + -- @usage + -- tenths = floor(magnitude, 1) + floor = X('floor(number, ?int)', floor), + + --- Round a number to a given number of decimal places. + -- @function round + -- @number n number + -- @int[opt=0] p number of decimal places to round to + -- @treturn number `n` rounded to `p` decimal places + -- @usage + -- roughly = round(exactly, 2) + round = X('round(number, ?int)', round), +} + + +return merge(math, M) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/normalize/init.lua b/modules/mixins/dotfiles/config/nvim/lua/std/normalize/init.lua @@ -0,0 +1,1342 @@ +--[[ + Normalized Lua API for Lua 5.1, 5.2, 5.3 & 5.4 + Copyright (C) 2002-2023 std.normalize authors +]] +--[[-- + Normalize API differences between supported Lua implementations. + + Respecting the values set in the `std._debug` settings module, inject + deterministic identically behaving cross-implementation low-level + functions into the callers environment. + + Writing Lua libraries that target several Lua implementations can be a + frustrating exercise in working around lots of small differences in APIs + and semantics they share (or rename, or omit). _normalize_ provides the + means to simply access deterministic implementations of those APIs that + have the the same semantics across all supported host Lua + implementations. Each function is as thin and fast an implementation as + is possible within that host Lua environment, evaluating to the Lua C + implementation with no overhead where host semantics allow. + + The core of this module is to transparently set the environment up with + a single API (as opposed to requiring caching functions from a module + table into module locals): + + local _ENV = require 'std.normalize' { + 'package', + 'std.prototype', + strict = 'std.strict', + } + + It is not yet complete, and in contrast to the kepler project + lua-compat libraries, neither does it attempt to provide you with as + nearly compatible an API as is possible relative to some specific Lua + implementation - rather it provides a variation of the "lowest common + denominator" that can be implemented relatively efficiently in the + supported Lua implementations, all in pure Lua. + + At the moment, only the functionality used by stdlib is implemented. + + @module std.normalize +]] + + +--[[ ====================== ]]-- +--[[ Load optional modules. ]]-- +--[[ ====================== ]]-- + + +local _debug = (function() + local ok, r = pcall(require, 'std._debug') + if not ok then + r = setmetatable({ + -- If this module was required, but there's no std._debug, safe to + -- assume we do want runtime argchecks! + argcheck = true, + -- Similarly, if std.strict is available, but there's no _std.debug, + -- then apply strict global symbol checks to this module! + strict = true, + }, { + __call = function(self, x) + self.argscheck = (x ~= false) + end, + }) + end + + return r +end)() + + +local strict = (function() + local setfenv = rawget(_G, 'setfenv') or function() end + + -- No strict global symbol checks with no std.strict module, even + -- if we found std._debug and requested that! + local r = function(env, level) + setfenv(1 + (level or 1), env) + return env + end + + if _debug.strict then + -- Specify `.init` submodule to make sure we only accept + -- lua-stdlib/strict, and not the old strict module from + -- lua-stdlib/lua-stdlib. + local ok, m = pcall(require, 'std.strict.init') + if ok then + r = m + end + end + return r +end)() + + +local typecheck = (function() + local format = string.format + + local ok, r = pcall(require, 'typecheck') + if ok then + return r + end + + return { + ARGCHECK_FRAME = 0, + + -- Return `inner` untouched, for no runtime overhead! + argscheck = function(decl, inner) + return inner or setmetatable({}, { + __concat = function(_, inner) + return inner + end, + }) + end, + + argerror = function(name, i, extramsg, level) + level = level or 1 + local s = format("bad argument #%d to '%s'", i, name) + if extramsg ~= nil then + s = s .. ' (' .. extramsg .. ')' + end + error(s, level > 0 and level + 2 or 0) + end, + } +end)() + + +local _ENV = strict(_G) + + +local ARGCHECK_FRAME = typecheck.ARGCHECK_FRAME +local argerror = typecheck.argerror +local argscheck = typecheck.argscheck +local concat = table.concat +local config = package.config +local debug_getfenv = debug.getfenv or false +local debug_getinfo = debug.getinfo +local debug_getupvalue = debug.getupvalue +local debug_setfenv = debug.setfenv or false +local debug_setupvalue = debug.setupvalue +local debug_upvaluejoin = debug.upvaluejoin +local exit = os.exit +local format = string.format +local getfenv = rawget(_G, 'getfenv') or false +local gmatch = string.gmatch +local gsub = string.gsub +local loadstring = rawget(_G, 'loadstring') or load +local match = string.match +local open = io.open +local remove = table.remove +local searchpath = package.searchpath or false +local setfenv = rawget(_G, 'setfenv') or false +local sort = table.sort +local unpack = table.unpack or unpack +local upper = string.upper + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +-- At this point, only the locals imported above are visible (even in +-- Lua 5.1). If 'std.strict' is available, we'll also get a runtime +-- error if any of the code below tries to use an undeclared variable. + + +local dirsep, pathsep, pathmark, execdir, igmark = + match(config, '^([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)') + + +local function callable(x) + -- Careful here! + -- Most versions of Lua don't recurse functables, so make sure you + -- always put a real function in __call metamethods. Consequently, + -- no reason to recurse here. + -- func=function() print 'called' end + -- func() --> 'called' + -- functable=setmetatable({}, {__call=func}) + -- functable() --> 'called' + -- nested=setmetatable({}, {__call=function(self, ...) return functable(...)end}) + -- nested() -> 'called' + -- notnested=setmetatable({}, {__call=functable}) + -- notnested() + -- --> stdin:1: attempt to call global 'nested' (a table value) + -- --> stack traceback: + -- --> stdin:1: in main chunk + -- --> [C]: in ? + if type(x) == 'function' or (getmetatable(x) or {}).__call then + return x + end +end + + +local tointeger = (function(f) + if f == nil then + -- No host tointeger implementationm use our own. + local floor = math.floor + return function(x) + if type(x) == 'number' and x - floor(x) == 0.0 then + return x + end + end + + elseif f '1' ~= nil then + -- Don't perform implicit string-to-number conversion! + return function(x) + if type(x) == 'number' then + return f(x) + end + end + end + + -- Host tointeger is good! + return f +end)(math.tointeger) + + +-- It's hard to test at require-time whether the host `os.exit` handles +-- boolean argument properly (ostensibly to defer to it in that case). +-- We're shutting down anyway, so sacrifice a bit of speed for timely +-- diagnosis of float and nil valued argument (with the argscheck +-- annotation, later in the file), since that probably indicates a bug +-- in your code! +local _exit = exit +local function exit(...) + local n, status = select('#', ...), ... + if tointeger(n) == 0 or status == true then + _exit(0) + elseif status == false then + _exit(1) + end + _exit(status) +end + + +local normalize_getfenv +if debug_getfenv then + + normalize_getfenv = function(fn) + local n = tointeger(fn or 1) + if n then + if n > 0 then + -- Adjust for this function's stack frame, if fn is non-zero. + n = n + 1 + ARGCHECK_FRAME + end + + -- Return an additional nil result to defeat tail call elimination + -- which would remove a stack frame and break numeric *fn* count. + return getfenv(n), nil + end + + if type(fn) ~= 'function' then + -- Unwrap functors: + -- No need to recurse because Lua doesn't support nested functors. + -- __call can only (sensibly) be a function, so no need to adjust + -- stack frame offset either. + fn =(getmetatable(fn) or {}).__call or fn + end + + -- In Lua 5.1, only debug.getfenv works on C functions; but it + -- does not work on stack counts. + return debug_getfenv(fn) + end + +else + + -- Thanks to http://lua-users.org/lists/lua-l/2010-06/msg00313.html + normalize_getfenv = function(fn) + if fn == 0 then + return _G + end + local n = tointeger(fn or 1) + if n then + fn = debug_getinfo(n + 1 + ARGCHECK_FRAME, 'f').func + elseif type(fn) ~= 'function' then + fn = (getmetatable(fn) or {}).__call or fn + end + + local name, env + local up = 0 + repeat + up = up + 1 + name, env = debug_getupvalue(fn, up) + until name == '_ENV' or name == nil + return env + end + +end + + +local function getmetamethod(x, n) + return callable((getmetatable(x) or {})[n]) +end + + +local function rawlen(x) + -- Lua 5.1 does not implement rawlen, and while # operator ignores + -- __len metamethod, `nil` in sequence is handled inconsistently. + if type(x) ~= 'table' then + return #x + end + + local n = #x + for i = 1, n do + if x[i] == nil then + return i -1 + end + end + return n +end + + +local function len(x) + return (getmetamethod(x, '__len') or rawlen)(x) +end + + +local function ipairs(l) + if getmetamethod(l, '__len') then + -- Use a closure to capture len metamethod result if necessary. + local n = len(l) + return function(l, i) + i = i + 1 + if i <= n then + return i, l[i] + end + end, l, 0 + end + + -- ...otherwise, find the last item as we go without calling `len()`. + return function(l, i) + i = i + 1 + if l[i] ~= nil then + return i, l[i] + end + end, l, 0 +end + + +local load = (function(ok) + if not ok then + return function(...) + if type(...) == 'string' then + return loadstring(...) + end + return _G.load(...) + end + end + + return _G.load +end)(pcall(load, '_=1')) + + +local function normalize_load(chunk, chunkname) + local m = getmetamethod(chunk, '__call') + if m then + chunk = m + elseif getmetamethod(chunk, '__tostring') then + chunk = tostring(chunk) + end + if getmetamethod(chunkname, '__tostring') then + chunkname = tostring(chunkname) + end + return load(chunk, chunkname) +end + + +local function merge(t, r) + r = r or {} + for k, v in next, t do + r[k] = r[k] or v + end + return r +end + + +local pack = (function(f) + local pack_mt = { + __len = function(self) + return self.n + end, + } + + local pack_fn = f or function(...) + return {n=select('#', ...), ...} + end + + return function(...) + return setmetatable(pack_fn(...), pack_mt) + end +end)(rawget(_G, "pack")) + + +local pairs = (function(b) + if b then + -- Add support for __pairs when missing. + return function (t) + return (getmetamethod(t, '__pairs') or pairs)(t) + end + end + + return _G.pairs +end)(not not pairs(setmetatable({},{__pairs=function() return false end}))) + + +local function keys(t) + local r = {} + for k in pairs(t) do + r[#r + 1] = k + end + return r +end + + +local pathmatch_patt = '[^' .. pathsep .. ']+' + +local searchpath = searchpath or function(name, path, sep, rep) + name = gsub(name, sep or '%.', rep or dirsep) + + local errbuf = {} + for template in gmatch(path, pathmatch_patt) do + local filename = gsub(template, pathmark, name) + local fh = open(filename, 'r') + if fh then + fh:close() + return filename + end + errbuf[#errbuf + 1] = "\tno file '" .. filename .. "'" + end + return nil, concat(errbuf, '\n') +end + + +local normalize_setfenv +if debug_setfenv then + + normalize_setfenv = function(fn, env) + local n = tointeger(fn or 1) + if n then + if n > 0 then + n = n + 1 + ARGCHECK_FRAME + end + return setfenv(n, env), nil + end + if type(fn) ~= 'function' then + fn =(getmetatable(fn) or {}).__call or fn + end + return debug_setfenv(fn, env) + end + +else + + -- Thanks to http://lua-users.org/lists/lua-l/2010-06/msg00313.html + normalize_setfenv = function(fn, env) + local n = tointeger(fn or 1) + if n then + if n > 0 then + n = n + 1 + ARGCHECK_FRAME + end + fn = debug_getinfo(n, 'f').func + elseif type(fn) ~= 'function' then + fn =(getmetatable(fn) or {}).__call or fn + end + + local up, name = 0 + repeat + up = up + 1 + name = debug_getupvalue(fn, up) + until name == '_ENV' or name == nil + if name then + debug_upvaluejoin(fn, up, function() return name end, 1) + debug_setupvalue(fn, up, env) + end + return n ~= 0 and fn or nil + end + +end + + +local shallow_copy = merge + + +local function render(x, vfns, roots) + if vfns.term(x) then + return vfns.elem(x) + end + + roots = roots or {} + + local function stop_roots(x) + return roots[x] or render(x, vfns, shallow_copy(roots)) + end + + local buf, pair, sep = {vfns.open(x)}, vfns.pair, vfns.sep + roots[x] = vfns.elem(x) -- recursion protection + + local seqp, kp, vp -- proper sequence?, previous key and value + local keylist = vfns.sort(keys(x)) + for i, k in ipairs(keylist) do + local v = x[k] + buf[#buf + 1] = sep(x, kp, vp, k, v, seqp) -- buffer << separator + if k == 1 then + seqp = true + else + seqp = seqp and type(kp) == 'number' and k == kp + 1 + end + buf[#buf + 1] = pair(x, kp, vp, k, v, stop_roots(k), stop_roots(v), seqp) + kp, vp = k, v + end + buf[#buf + 1] = sep(x, kp, vp) -- buffer << trailing separator + buf[#buf + 1] = vfns.close(x) -- buffer << table close + return concat(buf) -- stringify buffer +end + + +local function always(x) + return function(...) return x end +end + + +local function keysort(a, b) + if type(a) == 'number' then + return type(b) ~= 'number' or a < b + else + return type(b) ~= 'number' and tostring(a) < tostring(b) + end +end + + +local strvtable = { + open = always '{', + close = always '}', + + elem = setmetatable({ + ['\a'] = [[\a]], + ['\b'] = [[\b]], + ['\t'] = [[\t]], + ['\n'] = [[\n]], + ['\v'] = [[\v]], + ['\f'] = [[\f]], + ['\r'] = [[\r]], + ['\\'] = [[\\]], + }, { + __call = function(map, x) + return gsub(tostring(x), '[\a\b\t\n\v\f\r]', function(c) + return map[c] + end) + end, + }), + + pair = function(x, kp, vp, k, v, kstr, vstr, seqp) + if seqp then + return vstr + end + return kstr .. '=' .. vstr + end, + + sep = function(x, kp, vp, k, v, seqp) + if kp == nil or k == nil then + return '' + elseif seqp and type(kp) == 'number' and k ~= kp + 1 then + return '; ' + end + return ', ' + end, + + sort = function(keys) + sort(keys, keysort) + return keys + end, + + term = function(x) + return type(x) ~= 'table' or getmetamethod(x, '__tostring') + end, +} + + +local function str(x) + return render(x, strvtable) +end + + +local function math_type(x) + if type(x) ~= 'number' then + return nil + end + return tointeger(x) and 'integer' or 'float' +end + + +local _unpack = unpack +local function unpack(t, i, j) + return _unpack(t, tointeger(i) or 1, tointeger(j) or len(t)) +end + + +do + local have_xpcall_args = false + local function catch(arg) have_xpcall_args = arg end + xpcall(catch, function() end, true) + + if not have_xpcall_args then + local _xpcall = xpcall + xpcall = function(fn, errh, ...) + local argu = pack(...) + return _xpcall(function() + return fn(unpack(argu, 1, argu.n)) + end, errh) + end + end +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local F = { + _VERSION = _G._VERSION, + arg = _G.arg, + + --- Raise a bad argument error. + -- Equivalent to luaL_argerror in the Lua C API. This function does not + -- return. The `level` argument behaves just like the core `error` + -- function. + -- @function argerror + -- @string name function to callout in error message + -- @int i argument number + -- @string[opt] extramsg additional text to append to message inside + -- parentheses + -- @int[opt=1] level call stack level to blame for the error + -- @usage + -- local function slurp(file) + -- local h, err = input_handle(file) + -- if h == nil then + -- argerror('std.io.slurp', 1, err, 2) + -- end + -- ... + argerror = argerror, + + assert = _G.assert, + collectgarbage = _G.collectgarbage, + dofile = _G.dofile, + error = _G.error, + + --- Get a function or functor environment. + -- + -- This version of getfenv works on all supported Lua versions, and + -- knows how to unwrap functors (table's with a function valued + -- `__call` metamethod). + -- @function getfenv + -- @tparam[opt=1] function|int fn stack level, C or Lua function or + -- functor to act on + -- @treturn table the execution environment of *fn* + -- @usage + -- callers_environment = getfenv(1) + getfenv = argscheck 'getfenv([callable|integer])' + .. normalize_getfenv, + + --- Return named metamethod, if callable, otherwise `nil`. + -- @function getmetamethod + -- @param x item to act on + -- @string n name of metamethod to look up + -- @treturn function|nil metamethod function, or `nil` if no + -- metamethod + -- @usage + -- normalize = getmetamethod(require 'std.normalize', '__call') + getmetamethod = argscheck 'getmetamethod(?any, string)' + .. getmetamethod, + + getmetatable = _G.getmetatable, + + --- Iterate over elements of a sequence, until the first `nil` value. + -- + -- Returns successive key-value pairs with integer keys starting at 1, + -- up to the index returned by the `__len` metamethod if any, or else + -- up to last non-`nil` value. + -- + -- Unlike Lua 5.1, any `__index` metamethod is respected. + -- + -- Unlike Lua 5.2+, any `__ipairs` metamethod is **ignored**! + -- @function ipairs + -- @tparam table t table to iterate on + -- @treturn function iterator function + -- @treturn table *t* the table being iterated over + -- @treturn int the previous iteration index + -- @usage + -- t, u = {}, {} + -- for i, v in ipairs {1, 2, nil, 4} do t[i] = v end + -- assert(len(t) == 2) + -- + -- for i, v in ipairs(pack(1, 2, nil, 4)) do u[i] = v end + -- assert(len(u) == 4) + ipairs = argscheck 'ipairs(table)' + .. ipairs, + + --- Deterministic, functional version of core Lua `#` operator. + -- + -- Respects `__len` metamethod (like Lua 5.2+), or else if there is + -- a `__tostring` metamethod return the length of the string it + -- returns. Otherwise, always return one less than the lowest + -- integer index with a `nil` value in *x*, where the `#` operator + -- implementation might return the size of the array part of a table. + -- @function len + -- @param x item to act on + -- @treturn int the length of *x* + -- @usage + -- x = {1, 2, 3, nil, 5} + -- --> 5 3 + -- print(#x, len(x)) + len = argscheck 'len(string|table)' + .. len, + + --- Load a string or a function, just like Lua 5.2+. + -- @function load + -- @tparam string|function ld chunk to load + -- @string source name of the source of *ld* + -- @treturn function a Lua function to execute *ld* in global scope. + -- @usage + -- assert(load 'print "woo"')() + load = argscheck 'load(callable|string, [string])' + .. normalize_load, + + loadfile = _G.loadfile, + next = _G.next, + + --- Return a list of given arguments, with field `n` set to the length. + -- + -- The returned table also has a `__len` metamethod that returns `n`, so + -- `ipairs` and `unpack` behave sanely when there are `nil` valued elements. + -- @function pack + -- @param ... tuple to act on + -- @treturn table packed list of *...* values, with field `n` set to + -- number of tuple elements (including any explicit `nil` elements) + -- @see unpack + -- @usage + -- --> 5 + -- len(pack(nil, 2, 5, nil, nil)) + pack = pack, + + --- Like Lua `pairs` iterator, but respect `__pairs` even in Lua 5.1. + -- @function pairs + -- @tparam table t table to act on + -- @treturn function iterator function + -- @treturn table *t*, the table being iterated over + -- @return the previous iteration key + -- @usage + -- for k, v in pairs {'a', b='c', foo=42} do process(k, v) end + pairs = argscheck 'pairs(table)' + .. pairs, + + pcall = _G.pcall, + print = _G.print, + rawequal = _G.rawequal, + rawget = _G.rawget, + + --- Length of a string or table object without using any metamethod. + -- @function rawlen + -- @tparam string|table x object to act on + -- @treturn int raw length of *x* + -- @usage + -- --> 0 + -- rawlen(setmetatable({}, {__len=function() return 42})) + rawlen = argscheck 'rawlen(string|table)' + .. rawlen, + + rawset = _G.rawset, + select = _G.select, + + --- Set a function or functor environment. + -- + -- This version of setfenv works on all supported Lua versions, and + -- knows how to unwrap functors. + -- @function setfenv + -- @tparam function|int fn stack level, C or Lua function or functor + -- to act on + -- @tparam table env new execution environment for *fn* + -- @treturn function function acted upon + -- @usage + -- function clearenv(fn) return setfenv(fn, {}) end + setfenv = argscheck 'setfenv(integer|callable, table)' + .. normalize_setfenv, + + setmetatable = _G.setmetatable, + + --- Return a compact stringified representation of argument. + -- @function str + -- @param x item to act on + -- @treturn string compact string representing *x* + -- @usage + -- -- {baz,5,foo=bar} + -- print(str{foo='bar','baz', 5}) + str = str, + + tonumber = _G.tonumber, + tostring = _G.tostring, + type = _G.type, + + --- Either `table.unpack` in newer-, or `unpack` in older Lua implementations. + -- @function unpack + -- @tparam table t table to act on + -- @int[opt=1] i first index to unpack + -- @int[opt=len(t)] j last index to unpack + -- @return ... values of numeric indices of *t* + -- @see pack + -- @usage + -- local a, b, c = unpack(pack(nil, 2, nil)) + -- assert(a == nil and b == 2 and c == nil) + unpack = argscheck'unpack(table, [?integer], [integer])' + .. unpack, + + --- Support arguments to a protected function call, even on Lua 5.1. + -- @function xpcall + -- @tparam function f protect this function call + -- @tparam function errh error object handler callback if *f* raises + -- an error + -- @param ... arguments to pass to *f* + -- @treturn[1] boolean `false` when `f(...)` raised an error + -- @treturn[1] string error message + -- @treturn[2] boolean `true` when `f(...)` succeeded + -- @return ... all return values from *f* follow + -- @usage + -- -- Use errh to get a backtrack after curses exits abnormally + -- xpcall(main, errh, arg, opt) + xpcall = argscheck 'xpcall(callable, callable, [?any...])' + .. xpcall, +} + +local G = { + coroutine = { + create = _G.coroutine.create, + resume = _G.coroutine.resume, + running = _G.coroutine.running, + status = _G.coroutine.status, + wrap = _G.coroutine.wrap, + yield = _G.coroutine.yield, + }, + debug = { + debug = _G.debug.debug, + gethook = _G.debug.gethook, + getinfo = _G.debug.getinfo, + getlocal = _G.debug.getlocal, + getmetatable = _G.debug.getmetatable, + getregistry = _G.debug.getregistry, + getupvalue = _G.debug.getupvalue, + getuservalue = _G.debug.getuservalue, + sethook = _G.debug.sethook, + setmetatable = _G.debug.setmetatable, + setupvalue = _G.debug.setupvalue, + setuservalue = _G.debug.setuservalue, + traceback = _G.debug.traceback, + upvalueid = _G.debug.upvalueid, + upvaluejoin = _G.debug.upvaluejoin, + }, + io = { + close = _G.io.close, + flush = _G.io.flush, + input = _G.io.input, + lines = _G.io.lines, + open = _G.io.open, + output = _G.io.output, + popen = _G.io.popen, + read = _G.io.read, + stderr = _G.io.stderr, + stdin = _G.io.stdin, + stdout = _G.io.stdout, + tmpfile = _G.io.tmpfile, + type = _G.io.type, + write = _G.io.write, + }, + math = { + abs = _G.math.abs, + acos = _G.math.acos, + asin = _G.math.asin, + atan = _G.math.atan, + ceil = _G.math.ceil, + cos = _G.math.cos, + deg = _G.math.deg, + exp = _G.math.exp, + floor = _G.math.floor, + fmod = _G.math.fmod, + huge = _G.math.huge, + log = _G.math.log, + max = _G.math.max, + min = _G.math.min, + modf = _G.math.modf, + pi = _G.math.pi, + rad = _G.math.rad, + random = _G.math.random, + randomseed = _G.math.randomseed, + sin = _G.math.sin, + sqrt = _G.math.sqrt, + tan = _G.math.tan, + + --- Convert to an integer and return if possible, otherwise `nil`. + -- @function math.tointeger + -- @param x object to act on + -- @treturn[1] integer *x* converted to an integer if possible + -- @return[2] `nil` otherwise + tointeger = argscheck 'math.tointeger(?any)' + .. tointeger, + + --- Return 'integer', 'float' or `nil` according to argument type. + -- + -- To ensure the same behaviour on all host Lua implementations, + -- this function returns 'float' for integer-equivalent floating + -- values, even on Lua 5.3. + -- @function math.type + -- @param x object to act on + -- @treturn[1] string 'integer', if *x* is a whole number + -- @treturn[2] string 'float', for other numbers + -- @return[3] `nil` otherwise + type = argscheck 'math.type(?any)' + .. math_type, + }, + os = { + clock = _G.os.clock, + date = _G.os.date, + difftime = _G.os.difftime, + execute = _G.os.execute, + + --- Exit the program. + -- @function os.exit + -- @tparam bool|number[opt=true] status report back to parent process + -- @usage + -- exit(len(records.processed) > 0) + exit = argscheck 'os.exit([boolean|integer])' + .. exit, + + getenv = _G.os.getenv, + remove = _G.os.remove, + rename = _G.os.rename, + setlocale = _G.os.setlocale, + time = _G.os.time, + tmpname = _G.os.tmpname, + }, + package = { + config = _G.package.config, + cpath = _G.package.cpath, + + --- Package module constants for `package.config` substrings. + -- @table package + -- @string dirsep directory separator in path elements + -- @string execdir replaced by the executable's directory in a path + -- @string igmark ignore everything before this when building + -- `luaopen_` function name + -- @string pathmark mark substitution points in a path template + -- @string pathsep element separator in a path template + dirsep = dirsep, + execdir = execdir, + igmark = igmark, + pathmark = pathmark, + pathsep = pathsep, + + loadlib = _G.package.loadlib, + path = _G.package.path, + preload = _G.package.preload, + searchers = _G.package.searchers or _G.package.loaders, + + --- Searches for a named file in a given path. + -- + -- For each `package.pathsep` delimited template in the given path, + -- search for an readable file made by first substituting for *sep* + -- with `package.dirsep`, and then replacing any + -- `package.pathmark` with the result. The first such file, if any + -- is returned. + -- @function package.searchpath + -- @string name name of search file + -- @string path `package.pathsep` delimited list of full path templates + -- @string[opt='.'] sep *name* component separator + -- @string[opt=`package.dirsep`] rep *sep* replacement in template + -- @treturn[1] string first template substitution that names a file + -- that can be opened in read mode + -- @return[2] `nil` + -- @treturn[2] string error message listing all failed paths + searchpath = argscheck( + 'package.searchpath(string, string, [?string], [string])' + ) .. searchpath, + }, + string = { + byte = _G.string.byte, + char = _G.string.char, + dump = _G.string.dump, + find = _G.string.find, + format = _G.string.format, + gmatch = _G.string.gmatch, + gsub = _G.string.gsub, + lower = _G.string.lower, + match = _G.string.match, + rep = _G.string.rep, + + --- Low-level recursive data to string rendering. + -- @function string.render + -- @param x data to be renedered + -- @tparam RenderFns vfns table of virtual functions to control rendering + -- @tparam[opt] table roots used internally for cycle detection + -- @treturn string a text recursive rendering of *x* using *vfns* + -- @usage + -- function printarray(x) + -- return render(x, arrayvfns) + -- end + render = argscheck 'string.render(?any, table, [table])' + .. render, + + reverse = _G.string.reverse, + sub = _G.string.sub, + upper = _G.string.upper, + }, + table = { + concat = _G.table.concat, + insert = _G.table.insert, + + --- Return an unordered list of all keys in a table. + -- @function table.keys + -- @tparam table t table to operate on + -- @treturn table an unorderd list of keys in *t* + -- @usage + -- --> {'key2', 1, 42, 2, 'key1'} + -- keys{'a', 'b', key1=1, key2=2, [42]=3} + keys = argscheck 'table.keys(table)' + .. keys, + + --- Destructively merge keys and values from one table into another. + -- @function table.merge + -- @tparam table t take fields from this table + -- @tparam[opt={}] table u and copy them into here, unless they are set already + -- @treturn table *u* + -- @usage + -- --> {'a', 'b', d='d'} + -- merge({'a', 'b'}, {'c', d='d'}) + merge = argscheck 'table.merge(table, [table])' + .. merge, + + remove = _G.table.remove, + sort = _G.table.sort, + }, +} +F._G = G +G.package.loaded = { + _G = G, + coroutine = G.coroutine, + debug = G.debug, + io = G.io, + math = G.math, + os = G.os, + package = G.package, + string = G.string, + table = G.table, +} +for k, v in next, _G.package.loaded do + G.package.loaded[k] = G.package.loaded[k] or v +end +F.require = function(modname) + return G.package.loaded[modname] or _G.require(modname) +end +for k, v in next, F do + G[k] = G[k] or v +end + + +local function split(s, matching) + local r = {} + gsub(s, matching, function(segment) + r[#r + 1] = segment + end) + return r +end + + +-- Dereference table *env* with *keylist* making missing subtables as we go. +-- The last element of *keylist* is assumed to be the final key at which +-- some value will be loaded, and is not followed, but is the second return +-- value. +-- @tparam table env environment table to start from +-- @tparam table keylist a list of subtables to recursively walk from *env* +-- @treturn table innermost table having followed *keylist* from *env* +-- @treturn string the last element of *keylist* +local function mksubtables(env, keylist) + while #keylist > 1 do + local subkey = remove(keylist, 1) + env[subkey] = env[subkey] or {} + env = env[subkey] + end + keylist = remove(keylist, 1) + return env, keylist +end + + +-- Return dot-delimited segments of elements of t between indexes i and j. +-- @tparam table t a list of segments +-- @int i first element to return +-- @int j last element to return +-- @treturn string selected segments of *t* concatenated with '.'s between +local function slice(t, i, j) + return concat({unpack(t, i, j)}, '.') +end + + +-- Convert a string into a loadable module, optionally followed by table keys. +-- Initially with the whole of *spec* as a module name, then splitting *spec* +-- at each dot from right to left, search for a module named after the left +-- half and containing nested keys named after the right half, and return +-- that. +-- @string spec dot delimited symbol name to import +-- @int level call depth for error message stack traces +-- @return value of a module, after dereferencing optional following +-- table keys +local function stringimport(spec, level) + local v = split(spec, '[^%.]+') + local vlen, err = #v, {} + + for i = vlen, 1, -1 do + local module, j = slice(v, 1, i), i + 1 + local ok, pkg = pcall(G.require, module) + if not ok then + err[#err + 1] = pkg + else + while pkg ~= nil and j <= vlen do + local subkey = v[j] + pkg, j = pkg[subkey], j + 1 + end + if pkg == nil then + err[#err + 1] = format( + "\tno entry for '%s' in module '%s'", slice(v, i + 1, vlen), module + ) + else + return pkg + end + end + end + error(concat(err, '\n'), level + 1) +end + + +-- Import value into name key of env table. +-- String values are replaced by the equivalent symbol they name in the +-- normalized module table, except that strings assigned to ALLCAPS names +-- are treated as string constants and not looked up as module symbols. +-- @tparam table env environment table +-- @string name key to index into *env* +-- @param value value to store at *name* in *env* +-- @int level call depth for error message stack traces +-- @treturn table modified *env* +local function import(env, name, value, level) + local i = tointeger(name) + if i and type(value) == 'string' then + name = match(value, '[^%.]+$') + if name == nil then + error( + "could not infer name from module '" .. value .. "' at #" .. i, + level + 1 + ) + end + end + + local dst, k = mksubtables(env, split(name, '[^%.]+')) + if type(value) == 'string' and (i or upper(name) ~= name) then + value = stringimport(value, level + 1) + end + dst[k] = value + return env +end + + +-- Replace host Lua functions with normalized equivalents. +-- @tparam table userenv user's lexical environment table +-- @treturn table *userenv* with normalized functions +local function normalize(userenv, level) + -- Top level functions are always available. + local env = shallow_copy(F) + + -- Everything else must be requested by name. + for name, value in next, userenv do + env = import(env, name, value, level + 1) + end + + return env +end + + +return setmetatable(G, { + --- Metamethods + -- @section metamethods + + --- Normalize caller's lexical environment. + -- + -- Using 'std.strict' when available and selected, otherwise a (Lua 5.1 + -- compatible) function to set the given environment. + -- + -- With an empty table argument, the core (not-table) normalize + -- functions are loaded into the callers environment. For consistent + -- behaviour between supported host Lua implementations, the result + -- must always be assigned back to `_ENV`. Additional core modules + -- must be named to be loaded at all (i.e. no 'debug' table unless it + -- is explicitly listed in the argument table). + -- + -- Additionally, external modules are loaded using `require`, with `.` + -- separators in the module name translated to nested tables in the + -- module environment. For example 'std.prototype' in the usage below + -- will add to the environment table the equivalent of: + -- + -- local prototype = require 'std.prototype' + -- + -- Alternatively, you can assign a loaded module symbol to a specific + -- environment table symbol with `key=value` syntax. For example the + -- the 'math.tointeger' from the usage below is equivalent to: + -- + -- local int = require 'std.normalize.math'.tointeger + -- + -- Compare this to loading the non-normalized implementation from the + -- host Lua with a table entry such as: + -- + -- int = require 'math'.tointeger, + -- + -- Finally, explicit string assignment to ALLCAPS keys are not loaded + -- from modules at all, but behave as a constant string assignment: + -- + -- INT = 'math.tointeger', + -- @function __call + -- @tparam table env environment table + -- @tparam[opt=1] int level stack level for `setfenv`, 1 means set + -- caller's environment + -- @treturn table *env* with this module's functions merge id. Assign + -- back to `_ENV` + -- @usage + -- local _ENV = require 'std.normalize' { + -- 'string', + -- 'std.prototype', + -- int = 'math.tointeger', + -- } + __call = function(_, env, level) + level = 1 + (level or 1) + return strict(normalize(env, level), level), nil + end, + + --- Lazy loading of normalize modules. + -- Don't load everything on initial startup, wait until first attempt + -- to access a submodule, and then load it on demand. + -- @function __index + -- @string name submodule name + -- @treturn table|nil the submodule that was loaded to satisfy the missing + -- `name`, otherwise `nil` if nothing was found + -- @usage + -- local version = require 'std.normalize'.version + __index = function(self, name) + local ok, t = pcall(require, 'std.normalize.' .. name) + if ok then + rawset(self, name, t) + return t + end + end, +}) + + +--- Types +-- @section types + +--- Table of functions for string.render. +-- @table RenderFns +-- @tfield RenderElem elem return unique string representation of an element +-- @tfield RenderTerm term return true for elements that should not be +-- recursed +-- @tfield RenderSort sort return list of keys in order to be rendered +-- @tfield RenderOpen open return a string for before first element of a table +-- @tfield RenderClose close return a string for after last element of a table +-- @tfield RenderPair pair return a string rendering of a key value pair +-- element +-- @tfield RenderSep sep return a string to render between elements +-- @see string.render +-- @usage +-- arrayvfns = { +-- elem = tostring, +-- term = function(x) +-- return type(x) ~= 'table' or getmetamethod(x, '__tostring') +-- end, +-- sort = function(keys) +-- local r = {} +-- for i = 1, #keys do +-- if type(keys[i]) == 'number' then r[#r + 1] = keys[i] end +-- end +-- return r +-- end, +-- open = function(_) return '[' end, +-- close = function(_) return ']' end, +-- pair = function(x, kp, vp, k, v, kstr, vstr, seqp) +-- return seqp and vstr or '' +-- end, +-- sep = function(x, kp, vp, kn, vn, seqp) +-- return seqp and kp ~= nil and kn ~= nil and ', ' or '' +-- end, +-- ) + +--- Type of function for uniquely stringifying rendered element. +-- @function RenderElem +-- @param x element to operate on +-- @treturn string stringified *x* + +--- Type of predicate function for terminal elements. +-- @function RenderTerm +-- @param x element to operate on +-- @treturn bool true for terminal elements that should be rendered +-- immediately + +--- Type of function for sorting keys of a recursively rendered element. +-- @function RenderSort +-- @tparam table keys list of table keys, it's okay to mutate and return +-- this parameter +-- @treturn table sorted list of keys for pairs to be rendered + +--- Type of function to get string for before first element. +-- @function RenderOpen +-- @param x element to operate on +-- @treturn string string to render before first element + +--- Type of function te get string for after last element. +-- @function RenderClose +-- @param x element to operate on +-- @treturn string string to render after last element + +--- Type of function to render a key value pair. +-- @function RenderPair +-- @param x complete table elmeent being operated on +-- @param kp unstringified previous pair key +-- @param vp unstringified previous pair value +-- @param k unstringified pair key to render +-- @param v unstringified pair value to render +-- @param kstr already stringified pair key to render +-- @param vstr already stringified pair value to render +-- @param seqp true if all keys so far have been a contiguous range of +-- integers +-- @treturn string stringified rendering of pair *kstr* and *vstr* + +--- Type of function to render a separator between pairs. +-- @function RenderSep +-- @param x complet table element being operated on +-- @param kp unstringified previous pair key +-- @param vp unstringified previous pair value +-- @param kn unstringified next pair key +-- @param vn unstringified next pair value +-- @param seqp true if all keys so far have been a contiguous range of +-- integers +-- @treturn string stringified rendering of separator between previous and +-- next pairs diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/package.lua b/modules/mixins/dotfiles/config/nvim/lua/std/package.lua @@ -0,0 +1,263 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Additions to the core package module. + + The module table returned by `std.package` also contains all of the entries + from the core `package` table. An hygienic way to import this module, then, is + simply to override core `package` locally: + + local package = require 'std.package' + + Manage `package.path` with normalization, duplicate removal, + insertion & removal of elements and automatic folding of '/' and '?' + onto `package.dirsep` and `package.pathmark`, for easy addition of + new paths. For example, instead of all this: + + lib = std.io.catfile('.', 'lib', package.pathmark .. '.lua') + paths = std.string.split(package.path, package.pathsep) + for i, path in ipairs(paths) do + -- ... lots of normalization code... + end + i = 1 + while i <= #paths do + if paths[i] == lib then + table.remove(paths, i) + else + i = i + 1 + end + end + table.insert(paths, 1, lib) + package.path = table.concat(paths, package.pathsep) + + You can now write just: + + package.path = package.normalize('./lib/?.lua', package.path) + + @corelibrary std.package +]] + + +local _ = require 'std._base' + +local argscheck = _.typecheck and _.typecheck.argscheck +local catfile = _.io.catfile +local escape_pattern = _.string.escape_pattern +local invert = _.table.invert +local split = _.string.split + +_ = nil + +local _ENV = require 'std.normalize' { + 'package', + concat = 'table.concat', + dirsep = 'package.dirsep', + gsub = 'string.gsub', + merge = 'table.merge', + pathmark = 'package.pathmark', + pathsep = 'package.pathsep', + string_find = 'string.find', + table_insert = 'table.insert', + table_remove = 'table.remove', +} + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +--- Make named constants for `package.config` +-- (undocumented in 5.1; see luaconf.h for C equivalents). +-- @table package +-- @string dirsep directory separator +-- @string pathsep path separator +-- @string pathmark string that marks substitution points in a path template +-- @string execdir(Windows only) replaced by the executable's directory in a path +-- @string igmark Mark to ignore all before it when building `luaopen_` function name. + + +local function pathsub(path) + return gsub(path, '%%?.', function(capture) + if capture == '?' then + return pathmark + elseif capture == '/' then + return dirsep + else + return gsub(capture, '^%%', '', 1) + end + end) +end + + +local function find(pathstrings, patt, init, plain) + local paths = split(pathstrings, pathsep) + if plain then + patt = escape_pattern(patt) + end + init = init or 1 + if init < 0 then + init = #paths - init + end + for i = init, #paths do + if string_find(paths[i], patt) then + return i, paths[i] + end + end +end + + +local function normalize(...) + local i, paths, pathstrings = 1, {}, concat({...}, pathsep) + for _, path in ipairs(split(pathstrings, pathsep)) do + path = gsub(pathsub(path), catfile('^[^', ']'), catfile('.', '%0')) + path = gsub(path, catfile('', '%.', ''), dirsep) + path = gsub(path, catfile('', '%.$'), '') + path = gsub(path, catfile('^%.', '%..', ''), catfile('..', '')) + path = gsub(path, catfile('', '$'), '') + + -- Carefully remove redundant /foo/../ matches. + repeat + local again = false + path = gsub(path, catfile('', '([^', ']+)', '%.%.', ''), + function(dir1) + if dir1 == '..' then -- don't remove /../../ + return catfile('', '..', '..', '') + else + again = true + return dirsep + end + end) + path = gsub(path, catfile('', '([^', ']+)', '%.%.$'), + function(dir1) + if dir1 == '..' then -- don't remove /../.. + return catfile('', '..', '..') + else + again = true + return '' + end + end) + until again == false + + -- Build an inverted table of elements to eliminate duplicates after + -- normalization. + if not paths[path] then + paths[path], i = i, i + 1 + end + end + return concat(invert(paths), pathsep) +end + + +local function insert(pathstrings, ...) + local paths = split(pathstrings, pathsep) + table_insert(paths, ...) + return normalize(unpack(paths, 1, len(paths))) +end + + +local function mappath(pathstrings, callback, ...) + for _, path in ipairs(split(pathstrings, pathsep)) do + local r = callback(path, ...) + if r ~= nil then + return r + end + end +end + + +local function remove(pathstrings, pos) + local paths = split(pathstrings, pathsep) + table_remove(paths, pos) + return concat(paths, pathsep) +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck and argscheck('std.package.' .. decl, fn) or fn +end + + +local M = { + --- Look for a path segment match of *patt* in *pathstrings*. + -- @function find + -- @string pathstrings `pathsep` delimited path elements + -- @string patt a Lua pattern to search for in *pathstrings* + -- @int[opt=1] init element(not byte index!) to start search at. + -- Negative numbers begin counting backwards from the last element + -- @bool[opt=false] plain unless false, treat *patt* as a plain + -- string, not a pattern. Note that if *plain* is given, then *init* + -- must be given as well. + -- @return the matching element number(not byte index!) and full text + -- of the matching element, if any; otherwise nil + -- @usage + -- i, s = find(package.path, '^[^' .. package.dirsep .. '/]') + find = X('find(string, string, ?int, ?boolean|:plain)', find), + + --- Insert a new element into a `package.path` like string of paths. + -- @function insert + -- @string pathstrings a `package.path` like string + -- @int[opt=n+1] pos element index at which to insert *value*, where `n` is + -- the number of elements prior to insertion + -- @string value new path element to insert + -- @treturn string a new string with the new element inserted + -- @usage + -- package.path = insert(package.path, 1, install_dir .. '/?.lua') + insert = X('insert(string, [int], string)', insert), + + --- Call a function with each element of a path string. + -- @function mappath + -- @string pathstrings a `package.path` like string + -- @tparam mappathcb callback function to call for each element + -- @param ... additional arguments passed to *callback* + -- @return nil, or first non-nil returned by *callback* + -- @usage + -- mappath(package.path, searcherfn, transformfn) + mappath = X('mappath(string, function, [any...])', mappath), + + --- Normalize a path list. + -- Removing redundant `.` and `..` directories, and keep only the first + -- instance of duplicate elements. Each argument can contain any number + -- of `pathsep` delimited elements; wherein characters are subject to + -- `/` and `?` normalization, converting `/` to `dirsep` and `?` to + -- `pathmark`(unless immediately preceded by a `%` character). + -- @function normalize + -- @param ... path elements + -- @treturn string a single normalized `pathsep` delimited paths string + -- @usage + -- package.path = normalize(user_paths, sys_paths, package.path) + normalize = X('normalize(string...)', normalize), + + --- Remove any element from a `package.path` like string of paths. + -- @function remove + -- @string pathstrings a `package.path` like string + -- @int[opt=n] pos element index from which to remove an item, where `n` + -- is the number of elements prior to removal + -- @treturn string a new string with given element removed + -- @usage + -- package.path = remove(package.path) + remove = X('remove(string, ?int)', remove), +} + + +return merge(package, M) + + +--- Types +-- @section Types + +--- Function signature of a callback for @{mappath}. +-- @function mappathcb +-- @string element an element from a `pathsep` delimited string of +-- paths +-- @param ... additional arguments propagated from @{mappath} +-- @return non-nil to break, otherwise continue with the next element diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/string.lua b/modules/mixins/dotfiles/config/nvim/lua/std/string.lua @@ -0,0 +1,504 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Additions to the core string module. + + The module table returned by `std.string` also contains all of the entries + from the core string table. An hygienic way to import this module, then, is + simply to override the core `string` locally: + + local string = require 'std.string' + + @corelibrary std.string +]] + + +local _ = require 'std._base' + +local argscheck = _.typecheck and _.std.typecheck.argscheck +local escape_pattern = _.string.escape_pattern +local split = _.string.split + +_ = nil + + +local _ENV = require 'std.normalize' { + 'string', + abs = 'math.abs', + concat = 'table.concat', + find = 'string.find', + floor = 'math.floor', + format = 'string.format', + gsub = 'string.gsub', + insert = 'table.insert', + match = 'string.match', + merge = 'table.merge', + render = 'string.render', + sort = 'table.sort', + sub = 'string.sub', + upper = 'string.upper', +} + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local M + + +local function toqstring(x, xstr) + if type(x) ~= 'string' then + return xstr + end + return format('%q', x) +end + + +local concatvfns = { + elem = tostring, + term = function(x) + return type(x) ~= 'table' or getmetamethod(x, '__tostring') + end, + sort = function(keys) + return keys + end, + open = function(x) return '{' end, + close = function(x) return '}' end, + pair = function(x, kp, vp, k, v, kstr, vstr, seqp) + return toqstring(k, kstr) .. '=' .. toqstring(v, vstr) + end, + sep = function(x, kp, vp, kn, vn, seqp) + return kp ~= nil and kn ~= nil and ',' or '' + end, +} + + +local function __concat(s, o) + -- Don't use normalize.str here, because we don't want ASCII escape rendering. + return render(s, concatvfns) .. render(o, concatvfns) +end + + +local function __index(s, i) + if type(i) == 'number' then + return sub(s, i, i) + else + -- Fall back to module metamethods + return M[i] + end +end + + +local _format = string.format + +local function format(f, arg1, ...) + return(arg1 ~= nil) and _format(f, arg1, ...) or f +end + + +local function tpack(from, to, ...) + return from, to, {...} +end + +local function tfind(s, ...) + return tpack(find(s, ...)) +end + + +local function finds(s, p, i, ...) + i = i or 1 + local l = {} + local from, to, r + repeat + from, to, r = tfind(s, p, i, ...) + if from ~= nil then + insert(l, {from, to, capt=r}) + i = to + 1 + end + until not from + return l +end + + +local function caps(s) + return(gsub(s, '(%w)([%w]*)', function(l, ls) + return upper(l) .. ls + end)) +end + + +local function escape_shell(s) + return(gsub(s, '([ %(%)%\\%[%]\'"])', '\\%1')) +end + + +local function ordinal_suffix(n) + n = abs(n) % 100 + local d = n % 10 + if d == 1 and n ~= 11 then + return 'st' + elseif d == 2 and n ~= 12 then + return 'nd' + elseif d == 3 and n ~= 13 then + return 'rd' + else + return 'th' + end +end + + +local function pad(s, w, p) + p = string.rep(p or ' ', abs(w)) + if w < 0 then + return string.sub(p .. s, w) + end + return string.sub(s .. p, 1, w) +end + + +local function wrap(s, w, ind, ind1) + w = w or 78 + ind = ind or 0 + ind1 = ind1 or ind + assert(ind1 < w and ind < w, + 'the indents must be less than the line width') + local r = {string.rep(' ', ind1)} + local i, lstart, lens = 1, ind1, len(s) + while i <= lens do + local j = i + w - lstart + while len(s[j]) > 0 and s[j] ~= ' ' and j > i do + j = j - 1 + end + local ni = j + 1 + while s[j] == ' ' do + j = j - 1 + end + insert(r, sub(s, i, j)) + i = ni + if i < lens then + insert(r, '\n' .. string.rep(' ', ind)) + lstart = ind + end + end + return concat(r) +end + + +local function numbertosi(n) + local SIprefix = { + [-8]='y', [-7]='z', [-6]='a', [-5]='f', + [-4]='p', [-3]='n', [-2]='mu', [-1]='m', + [0]='', [1]='k', [2]='M', [3]='G', + [4]='T', [5]='P', [6]='E', [7]='Z', + [8]='Y' + } + local t = _format('% #.2e', n) + local _, _, m, e = find(t, '.(.%...)e(.+)') + local man, exp = tonumber(m), tonumber(e) + local siexp = floor(exp / 3) + local shift = exp - siexp * 3 + local s = SIprefix[siexp] or 'e' .. tostring(siexp) + man = man *(10 ^ shift) + return _format('%0.f', man) .. s +end + + +-- Ordor numbers first then asciibetically. +local function keycmp(a, b) + if type(a) == 'number' then + return type(b) ~= 'number' or a < b + end + return type(b) ~= 'number' and tostring(a) < tostring(b) +end + + +local render_fallbacks = { + __index = concatvfns, +} + + +local function prettytostring(x, indent, spacing) + indent = indent or '\t' + spacing = spacing or '' + return render(x, setmetatable({ + elem = function(x) + if type(x) ~= 'string' then + return tostring(x) + end + return format('%q', x) + end, + + sort = function(keylist) + sort(keylist, keycmp) + return keylist + end, + + open = function() + local s = spacing .. '{' + spacing = spacing .. indent + return s + end, + + close = function() + spacing = string.gsub(spacing, indent .. '$', '') + return spacing .. '}' + end, + + pair = function(x, _, _, k, v, kstr, vstr) + local type_k = type(k) + local s = spacing + if type_k ~= 'string' or match(k, '[^%w_]') then + s = s .. '[' + if type_k == 'table' then + s = s .. '\n' + end + s = s .. kstr + if type_k == 'table' then + s = s .. '\n' + end + s = s .. ']' + else + s = s .. k + end + s = s .. ' =' + if type(v) == 'table' then + s = s .. '\n' + else + s = s .. ' ' + end + s = s .. vstr + return s + end, + + sep = function(_, k) + local s = '\n' + if k then + s = ',' .. s + end + return s + end, + }, render_fallbacks)) +end + + +local function trim(s, r) + r = r or '%s+' + return (gsub(gsub(s, '^' .. r, ''), r .. '$', '')) +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck and argscheck('std.string.' .. decl, fn) or fn +end + +M = { + --- Metamethods + -- @section metamethods + + --- String concatenation operation. + -- @function __concat + -- @string s initial string + -- @param o object to stringify and concatenate + -- @return s .. tostring(o) + -- @usage + -- local string = setmetatable('', require 'std.string') + -- concatenated = 'foo' .. {'bar'} + __concat = __concat, + + --- String subscript operation. + -- @function __index + -- @string s string + -- @tparam int|string i index or method name + -- @return `sub(s, i, i)` if i is a number, otherwise + -- fall back to a `std.string` metamethod(if any). + -- @usage + -- getmetatable('').__index = require 'std.string'.__index + -- third =('12345')[3] + __index = __index, + + + --- Core Functions + -- @section corefuncs + + --- Capitalise each word in a string. + -- @function caps + -- @string s any string + -- @treturn string *s* with each word capitalized + -- @usage + -- userfullname = caps(input_string) + caps = X('caps(string)', caps), + + --- Remove any final newline from a string. + -- @function chomp + -- @string s any string + -- @treturn string *s* with any single trailing newline removed + -- @usage + -- line = chomp(line) + chomp = X('chomp(string)', function(s) + return(gsub(s, '\n$', '')) + end), + + --- Escape a string to be used as a pattern. + -- @function escape_pattern + -- @string s any string + -- @treturn string *s* with active pattern characters escaped + -- @usage + -- substr = match(inputstr, escape_pattern(literal)) + escape_pattern = X('escape_pattern(string)', escape_pattern), + + --- Escape a string to be used as a shell token. + -- Quotes spaces, parentheses, brackets, quotes, apostrophes and + -- whitespace. + -- @function escape_shell + -- @string s any string + -- @treturn string *s* with active shell characters escaped + -- @usage + -- os.execute('echo ' .. escape_shell(outputstr)) + escape_shell = X('escape_shell(string)', escape_shell), + + --- Repeatedly `string.find` until target string is exhausted. + -- @function finds + -- @string s target string + -- @string pattern pattern to match in *s* + -- @int[opt=1] init start position + -- @bool[opt] plain inhibit magic characters + -- @return list of `{from, to; capt={captures}}` + -- @see std.string.tfind + -- @usage + -- for t in std.elems(finds('the target string', '%S+')) do + -- print(tostring(t.capt)) + -- end + finds = X('finds(string, string, ?int, ?boolean|:plain)', finds), + + --- Extend to work better with one argument. + -- If only one argument is passed, no formatting is attempted. + -- @function format + -- @string f format string + -- @param[opt] ... arguments to format + -- @return formatted string + -- @usage + -- print(format '100% stdlib!') + format = X('format(string, [any...])', format), + + --- Remove leading matter from a string. + -- @function ltrim + -- @string s any string + -- @string[opt='%s+'] r leading pattern + -- @treturn string *s* with leading *r* stripped + -- @usage + -- print('got: ' .. ltrim(userinput)) + ltrim = X('ltrim(string, ?string)', function(s, r) + return (gsub(s, '^' ..(r or '%s+'), '')) + end), + + --- Write a number using SI suffixes. + -- The number is always written to 3 s.f. + -- @function numbertosi + -- @tparam number|string n any numeric value + -- @treturn string *n* simplifed using largest available SI suffix. + -- @usage + -- print(numbertosi(bitspersecond) .. 'bps') + numbertosi = X('numbertosi(number|string)', numbertosi), + + --- Return the English suffix for an ordinal. + -- @function ordinal_suffix + -- @tparam int|string n any integer value + -- @treturn string English suffix for *n* + -- @usage + -- local now = os.date '*t' + -- print('%d%s day of the week', now.day, ordinal_suffix(now.day)) + ordinal_suffix = X('ordinal_suffix(int|string)', ordinal_suffix), + + --- Justify a string. + -- When the string is longer than w, it is truncated(left or right + -- according to the sign of w). + -- @function pad + -- @string s a string to justify + -- @int w width to justify to(-ve means right-justify; +ve means + -- left-justify) + -- @string[opt=' '] p string to pad with + -- @treturn string *s* justified to *w* characters wide + -- @usage + -- print(pad(trim(outputstr, 78)) .. '\n') + pad = X('pad(string, int, ?string)', pad), + + --- Pretty-print a table, or other object. + -- @function prettytostring + -- @param x object to convert to string + -- @string[opt='\t'] indent indent between levels + -- @string[opt=''] spacing space before every line + -- @treturn string pretty string rendering of *x* + -- @usage + -- print(prettytostring(std, ' ')) + prettytostring = X('prettytostring(?any, ?string, ?string)', prettytostring), + + --- Remove trailing matter from a string. + -- @function rtrim + -- @string s any string + -- @string[opt='%s+'] r trailing pattern + -- @treturn string *s* with trailing *r* stripped + -- @usage + -- print('got: ' .. rtrim(userinput)) + rtrim = X('rtrim(string, ?string)', function(s, r) + return (gsub(s, (r or '%s+') .. '$', '')) + end), + + --- Split a string at a given separator. + -- Separator is a Lua pattern, so you have to escape active characters, + -- `^$()%.[]*+-?` with a `%` prefix to match a literal character in *s*. + -- @function split + -- @string s to split + -- @string[opt='%s+'] sep separator pattern + -- @return list of strings + -- @usage + -- words = split 'a very short sentence' + split = X('split(string, ?string)', split), + + --- Do `string.find`, returning a table of captures. + -- @function tfind + -- @string s target string + -- @string pattern pattern to match in *s* + -- @int[opt=1] init start position + -- @bool[opt] plain inhibit magic characters + -- @treturn int start of match + -- @treturn int end of match + -- @treturn table list of captured strings + -- @see std.string.finds + -- @usage + -- b, e, captures = tfind('the target string', '%s', 10) + tfind = X('tfind(string, string, ?int, ?boolean|:plain)', tfind), + + --- Remove leading and trailing matter from a string. + -- @function trim + -- @string s any string + -- @string[opt='%s+'] r trailing pattern + -- @treturn string *s* with leading and trailing *r* stripped + -- @usage + -- print('got: ' .. trim(userinput)) + trim = X('trim(string, ?string)', trim), + + --- Wrap a string into a paragraph. + -- @function wrap + -- @string s a paragraph of text + -- @int[opt=78] w width to wrap to + -- @int[opt=0] ind indent + -- @int[opt=ind] ind1 indent of first line + -- @treturn string *s* wrapped to *w* columns + -- @usage + -- print(wrap(copyright, 72, 4)) + wrap = X('wrap(string, ?int, ?int, ?int)', wrap), +} + + +return merge(string, M) diff --git a/modules/mixins/dotfiles/config/nvim/lua/std/table.lua b/modules/mixins/dotfiles/config/nvim/lua/std/table.lua @@ -0,0 +1,439 @@ +--[[ + General Lua Libraries for Lua 5.1, 5.2 & 5.3 + Copyright (C) 2002-2018 stdlib authors +]] +--[[-- + Extensions to the core table module. + + The module table returned by `std.table` also contains all of the entries from + the core table module. An hygienic way to import this module, then, is simply + to override the core `table` locally: + + local table = require 'std.table' + + @corelibrary std.table +]] + + +local _ = require 'std._base' + +local argscheck = _.typecheck and _.typecheck.argscheck +local invert = _.table.invert +local maxn = _.table.maxn + +_ = nil + +local _ENV = require 'std.normalize' { + 'table', + merge = 'table.merge', + min = 'math.min', +} + + + +--[[ =============== ]]-- +--[[ Implementation. ]]-- +--[[ =============== ]]-- + + +local M + + +local function merge_allfields(t, u, map, nometa) + if type(map) ~= 'table' then + map, nometa = nil, map + end + + if not nometa then + setmetatable(t, getmetatable(u)) + end + if map then + for k, v in pairs(u) do + t[map[k] or k] = v + end + else + for k, v in pairs(u) do + t[k] = v + end + end + return t +end + + +local function merge_namedfields(t, u, keys, nometa) + if type(keys) ~= 'table' then + keys, nometa = nil, keys + end + + if not nometa then + setmetatable(t, getmetatable(u)) + end + for _, k in pairs(keys or {}) do + t[k] = u[k] + end + return t +end + + +local function depair(ls) + local t = {} + for _, v in ipairs(ls) do + t[v[1]] = v[2] + end + return t +end + + +local function enpair(t) + local tt = {} + for i, v in pairs(t) do + tt[#tt + 1] = {i, v} + end + return tt +end + + +local _insert = table.insert + +local function insert(t, pos, v) + if v == nil then + pos, v = len(t) + 1, pos + end + if pos < 1 or pos > len(t) + 1 then + argerror('std.table.insert', 2, 'position ' .. pos .. ' out of bounds', 2) + end + _insert(t, pos, v) + return t +end + + +local function keys(t) + local l = {} + for k in pairs(t) do + l[#l + 1] = k + end + return l +end + + +local function new(x, t) + return setmetatable(t or {}, {__index = function(t, i) + return x + end}) +end + + +local function project(fkey, tt) + local r = {} + for _, t in ipairs(tt) do + r[#r + 1] = t[fkey] + end + return r +end + + +local function size(t) + local n = 0 + for _ in pairs(t) do + n = n + 1 + end + return n +end + + +-- Preserve core table sort function. +local _sort = table.sort + +local function sort(t, c) + _sort(t, c) + return t +end + + +local _remove = table.remove + +local function remove(t, pos) + local lent = len(t) + pos = pos or lent + if pos < min(1, lent) or pos > lent + 1 then -- +1? whu? that's what 5.2.3 does!?! + argerror('std.table.remove', 2, 'position ' .. pos .. ' out of bounds', 2) + end + return _remove(t, pos) +end + + +local _unpack = unpack + +local function unpack(t, i, j) + if j == nil then + -- if j was not given, respect __len, otherwise use maxn + local m = getmetamethod(t, '__len') + j = m and m(t) or maxn(t) + end + return _unpack(t, tonumber(i) or 1, tonumber(j)) +end + + +local function values(t) + local l = {} + for _, v in pairs(t) do + l[#l + 1] = v + end + return l +end + + + +--[[ ================= ]]-- +--[[ Public Interface. ]]-- +--[[ ================= ]]-- + + +local function X(decl, fn) + return argscheck and argscheck('std.table.' .. decl, fn) or fn +end + +M = { + --- Core Functions + -- @section corefuncs + + --- Enhance core *table.insert* to return its result. + -- If *pos* is not given, respect `__len` metamethod when calculating + -- default append. Also, diagnose out of bounds *pos* arguments + -- consistently on any supported version of Lua. + -- @function insert + -- @tparam table t a table + -- @int[opt=len(t)] pos index at which to insert new element + -- @param v value to insert into *t* + -- @treturn table *t* + -- @usage + -- --> {1, 'x', 2, 3, 'y'} + -- insert(insert({1, 2, 3}, 2, 'x'), 'y') + insert = X('insert(table, [int], any)', insert), + + --- Largest integer key in a table. + -- @function maxn + -- @tparam table t a table + -- @treturn int largest integer key in *t* + -- @usage + -- --> 42 + -- maxn {'a', b='c', 99, [42]='x', 'x', [5]=67} + maxn = X('maxn(table)', maxn), + + --- Turn a tuple into a list, with tuple-size in field `n` + -- @function pack + -- @param ... tuple + -- @return list-like table, with tuple-size in field `n` + -- @usage + -- --> {1, 2, 'ax', n=3} + -- pack(find('ax1', '(%D+)')) + pack = pack, + + --- Enhance core *table.remove* to respect `__len` when *pos* is omitted. + -- Also, diagnose out of bounds *pos* arguments consistently on any supported + -- version of Lua. + -- @function remove + -- @tparam table t a table + -- @int[opt=len(t)] pos index from which to remove an element + -- @return removed value, or else `nil` + -- @usage + -- --> {1, 2, 5} + -- t = {1, 2, 'x', 5} + -- remove(t, 3) == 'x' and t + remove = X('remove(table, ?int)', remove), + + --- Enhance core *table.sort* to return its result. + -- @function sort + -- @tparam table t unsorted table + -- @tparam[opt=std.operator.lt] comparator c ordering function callback + -- @return *t* with keys sorted according to *c* + -- @usage + -- table.concat(sort(object)) + sort = X('sort(table, ?function)', sort), + + --- Enhance core *table.unpack* to always unpack up to __len or maxn. + -- @function unpack + -- @tparam table t table to act on + -- @int[opt=1] i first index to unpack + -- @int[opt=table.maxn(t)] j last index to unpack + -- @return ... values of numeric indices of *t* + -- @usage + -- return unpack(results_table) + unpack = X('unpack(table, ?int, ?int)', unpack), + + + --- Accessor Functions + -- @section accessorfuncs + + --- Make a shallow copy of a table, including any metatable. + -- @function clone + -- @tparam table t source table + -- @tparam[opt={}] table map table of `{old_key=new_key, ...}` + -- @bool[opt] nometa if non-nil don't copy metatable + -- @return copy of *t*, also sharing *t*'s metatable unless *nometa* + -- is true, and with keys renamed according to *map* + -- @see merge + -- @see clone_select + -- @usage + -- shallowcopy = clone(original, {rename_this='to_this'}, ':nometa') + clone = X('clone(table, [table], ?boolean|:nometa)', function(...) + return merge_allfields({}, ...) + end), + + --- Make a partial clone of a table. + -- + -- Like `clone`, but does not copy any fields by default. + -- @function clone_select + -- @tparam table t source table + -- @tparam[opt={}] table keys list of keys to copy + -- @bool[opt] nometa if non-nil don't copy metatable + -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s + -- metatable unless *nometa* + -- @see clone + -- @see merge_select + -- @usage + -- partialcopy = clone_select(original, {'this', 'and_this'}, true) + clone_select = X('clone_select(table, [table], ?boolean|:nometa)', function(...) + return merge_namedfields({}, ...) + end), + + --- Turn a list of pairs into a table. + -- @todo Find a better name. + -- @function depair + -- @tparam table ls list of lists + -- @treturn table a flat table with keys and values from *ls* + -- @see enpair + -- @usage + -- --> {a=1, b=2, c=3} + -- depair {{'a', 1}, {'b', 2}, {'c', 3}} + depair = X('depair(list of lists)', depair), + + --- Turn a table into a list of pairs. + -- @todo Find a better name. + -- @function enpair + -- @tparam table t a table `{i1=v1, ..., in=vn}` + -- @treturn table a new list of pairs containing `{{i1, v1}, ..., {in, vn}}` + -- @see depair + -- @usage + -- --> {{1, 'a'}, {2, 'b'}, {3, 'c'}} + -- enpair {'a', 'b', 'c'} + enpair = X('enpair(table)', enpair), + + --- Return whether table is empty. + -- @function empty + -- @tparam table t any table + -- @treturn boolean `true` if *t* is empty, otherwise `false` + -- @usage + -- if empty(t) then error 'ohnoes' end + empty = X('empty(table)', function(t) + return not next(t) + end), + + --- Make a table with a default value for unset keys. + -- @function new + -- @param[opt=nil] x default entry value + -- @tparam[opt={}] table t initial table + -- @treturn table table whose unset elements are *x* + -- @usage + -- t = new(0) + new = X('new(?any, ?table)', new), + + --- Project a list of fields from a list of tables. + -- @function project + -- @param fkey field to project + -- @tparam table tt a list of tables + -- @treturn table list of *fkey* fields from *tt* + -- @usage + -- --> {1, 3, 'yy'} + -- project('xx', {{'a', xx=1, yy='z'}, {'b', yy=2}, {'c', xx=3}, {xx='yy'}) + project = X('project(any, list of tables)', project), + + --- Find the number of elements in a table. + -- @function size + -- @tparam table t any table + -- @treturn int number of non-nil values in *t* + -- @usage + -- --> 3 + -- size {foo=true, bar=true, baz=false} + size = X('size(table)', size), + + --- Make the list of values of a table. + -- @function values + -- @tparam table t any table + -- @treturn table list of values in *t* + -- @see keys + -- @usage + -- --> {'a', 'c', 42} + -- values {'a', b='c', [-1]=42} + values = X('values(table)', values), + + + --- Mutator Functions + -- @section mutatorfuncs + + --- Invert a table. + -- @function invert + -- @tparam table t a table with `{k=v, ...}` + -- @treturn table inverted table `{v=k, ...}` + -- @usage + -- --> {a=1, b=2, c=3} + -- invert {'a', 'b', 'c'} + invert = X('invert(table)', invert), + + --- Make the list of keys in table. + -- @function keys + -- @tparam table t a table + -- @treturn table list of keys from *t* + -- @see values + -- @usage + -- globals = keys(_G) + keys = X('keys(table)', keys), + + --- Destructively merge one table's fields into another. + -- @function merge + -- @tparam table t destination table + -- @tparam table u table with fields to merge + -- @tparam[opt={}] table map table of `{old_key=new_key, ...}` + -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable + -- @treturn table *t* with fields from *u* merged in + -- @see clone + -- @see merge_select + -- @usage + -- merge(_G, require 'std.debug', {say='log'}, ':nometa') + merge = X('merge(table, table, [table], ?boolean|:nometa)', merge_allfields), + + --- Destructively merge another table's named fields into *table*. + -- + -- Like `merge`, but does not merge any fields by default. + -- @function merge_select + -- @tparam table t destination table + -- @tparam table u table with fields to merge + -- @tparam[opt={}] table keys list of keys to copy + -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable + -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s + -- metatable unless *nometa* + -- @see merge + -- @see clone_select + -- @usage + -- merge_select(_G, require 'std.debug', {'say'}, false) + merge_select = X('merge_select(table, table, [table], ?boolean|:nometa)', + merge_namedfields), +} + + +return merge(table, M) + + + +--- Types +-- @section Types + +--- Signature of a @{sort} comparator function. +-- @function comparator +-- @param a any object +-- @param b any object +-- @treturn boolean `true` if *a* sorts before *b*, otherwise `false` +-- @see sort +-- @usage +-- local reversor = function(a, b) return a > b end +-- sort(t, reversor) diff --git a/modules/mixins/dotfiles/config/offpunk/offpunkrc b/modules/mixins/dotfiles/config/offpunk/offpunkrc @@ -0,0 +1,4 @@ +set ftr_site_config /home/miro/src/github.com/fivefilters/ftr-site-config +set images_size 40 +cookies import /home/miro/misc/www/cookies/ashmann.txt https://ashmann.co +cookies import /home/miro/misc/www/cookies/firstfloor.txt https://firstfloor.substack.com diff --git a/modules/mixins/dotfiles/config/pipewire/client.conf.d/resample.conf b/modules/mixins/dotfiles/config/pipewire/client.conf.d/resample.conf @@ -0,0 +1,3 @@ +stream.properties = { + resample.quality = 10 +} diff --git a/modules/mixins/dotfiles/config/plants/devices.toml b/modules/mixins/dotfiles/config/plants/devices.toml @@ -0,0 +1,17 @@ +[buds] +mac = "B8:7B:D4:19:2D:8D" + +[devices.qc35] +mac = "AC:BF:71:09:BF:FD" +text = "🎧" +device_type = "bluetooth" + +[devices.controller] +mac = "98:7A:14:C9:9A:90" +text = "🎮" +device_type = "bluetooth" + +[devices.mx] +mac = "D5:E4:1B:10:D6:77" +text = "🖱️" +device_type = "bluetooth" diff --git a/modules/mixins/dotfiles/config/psi-notify b/modules/mixins/dotfiles/config/psi-notify @@ -0,0 +1,6 @@ +update 60 +log_pressures false + +threshold cpu some avg10 50.00 +threshold memory some avg10 10.00 +threshold io some avg10 10.00 diff --git a/modules/mixins/dotfiles/config/rclone/rclone.conf b/modules/mixins/dotfiles/config/rclone/rclone.conf @@ -0,0 +1,4 @@ +# Encrypted rclone configuration File + +RCLONE_ENCRYPT_V0: +eckpfkF3feOB04DuLD7dgG8WusS14LjNuvIWTMz81j8ulkNrpRhXsSHVCv/rABf3OTN/UpZu96sxBz6jkEPGc0pIcCplydqpnuvlbJvH0syfDwjlG+3/Zu08Z+KhizE4XW5dIASZxgCyoQGsXi2vtwPG+gD5OmKLqAgmgPCaB/mYnJiBn0+mCd7sA/vQe4ROAx0EJVL3aywrvTwD+/ssMIII/bMgMzCejWGymkGX2rFXOzW9/nrx4xJXbMw3DESAmZQOT46jXGwu2e5UgD8DDeLMjXeX4UPMzB93PrdN5EXkyyaZ/kG5+FybiOWd diff --git a/modules/mixins/dotfiles/config/river/init b/modules/mixins/dotfiles/config/river/init @@ -0,0 +1,140 @@ +#!/bin/bash +set -x + +mod="Mod1" +alt="Mod4" + +term="foot" +wobsock="$XDG_RUNTIME_DIR/wob.sock" + +dmenu_args="-fn 'Ttyp0 OTB:size=10' -l 10 -h 20 -nb '#130911' -nf '#d0d0d0' -sb '#3f2f40' -sf '#d0d0d0' -nhb '#130911' -nhf '#1dbfcf'" + +rivertile -view-padding 0 -outer-padding 0 -main-ratio 0.50 & + +riverctl border-color-focused "0x50447f" +riverctl border-color-unfocused "0x332d38" +riverctl border-width 1 + +riverctl set-repeat 50 300 + +riverctl default-layout rivertile + +riverctl input "pointer-1189-32769-BenQ_ZOWIE_BenQ_ZOWIE_Gaming_Mouse" pointer-accel 0.0 +riverctl input "pointer-1133-45108-Logitech_MX_Master_3S" pointer-accel 0.0 +riverctl input "pointer-1133-16500-Logitech_G305" pointer-accel 0.0 + +riverctl attach-mode top +riverctl focus-follows-cursor normal + +riverctl map normal Super Return zoom + +riverctl map normal $mod+Shift Return spawn "$term" +riverctl map normal $alt+Shift Return spawn "$term" + +riverctl map normal $mod p spawn "dmenu_run $dmenu_args" +riverctl map normal $alt p spawn "dmenu_run $dmenu_args" + +riverctl map normal Control+$alt l spawn "waylock" +riverctl map normal Control+$mod l spawn "monofetch" + +riverctl map normal $mod+Shift o spawn "todomenu $dmenu_args" +riverctl map normal $alt+Shift d spawn "clipmenu $dmenu_args" +riverctl map normal $alt+Shift l spawn "langmenu $dmenu_args" +riverctl map normal $alt+Shift t spawn "tempmenu $dmenu_args" +riverctl map normal $alt+Shift m spawn "plsmenu $dmenu_args" +riverctl map normal $alt+Shift h spawn "huemenu $dmenu_args" + +riverctl map normal $mod+Shift b spawn "btmenu con $dmenu_args" +riverctl map normal $alt+Shift b spawn "btmenu dis $dmenu_args" + +riverctl map normal $mod+Shift p spawn "passmenu $dmenu_args" +riverctl map normal $alt+Shift p spawn "passmenu $dmenu_args" + +riverctl map normal $mod+Shift s spawn "screenshot" +riverctl map normal $alt+Shift s spawn "screenshot" + +riverctl map normal None XF86AudioMute spawn "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle && (wpctl get-volume @DEFAULT_AUDIO_SINK@ | grep -q MUTED && echo 0 > $wobsock) || wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/[^0-9]//g' > $wobsock" +riverctl map normal None XF86AudioLowerVolume spawn "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- && wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/[^0-9]//g' > $wobsock" +riverctl map normal None XF86AudioRaiseVolume spawn "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ && wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/[^0-9]//g' > $wobsock" + +riverctl map normal None XF86MonBrightnessUp spawn "brightnessctl set +5% | sed -En 's/.*\(([0-9]+)%\).*/\1/p' > $wobsock" +riverctl map normal None XF86MonBrightnessDown spawn "brightnessctl set 5%- | sed -En 's/.*\(([0-9]+)%\).*/\1/p' > $wobsock" + +riverctl map normal $mod+Shift c close +riverctl map normal $alt+Shift c close + +riverctl map normal $mod j focus-view next +riverctl map normal $mod k focus-view previous + +riverctl map normal $mod+Shift j swap next +riverctl map normal $mod+Shift k swap previous + +riverctl map normal $mod h send-layout-cmd rivertile "main-ratio -0.05" +riverctl map normal $mod l send-layout-cmd rivertile "main-ratio +0.05" + +riverctl map normal $mod i send-layout-cmd rivertile "main-count +1" +riverctl map normal $mod d send-layout-cmd rivertile "main-count -1" + +riverctl map normal $mod+Shift Space toggle-float + +riverctl map normal $mod+Shift f toggle-fullscreen +riverctl map normal $alt+Shift f toggle-fullscreen + +riverctl map normal $mod Space spawn "dunstctl close" +riverctl map normal $alt Space spawn "dunstctl history-pop" + +for i in $(seq 1 9); do + tags=$((1 << (i - 1))) + riverctl map normal $mod "$i" set-focused-tags "$tags" + riverctl map normal $mod+Shift "$i" set-view-tags "$tags" + riverctl map normal $mod+Control "$i" toggle-focused-tags "$tags" + riverctl map normal $mod+Shift+Control "$i" toggle-view-tags "$tags" + + riverctl map normal $alt "$i" set-focused-tags "$tags" + riverctl map normal $alt+Shift "$i" set-view-tags "$tags" + riverctl map normal $alt+Control "$i" toggle-focused-tags "$tags" + riverctl map normal $alt+Shift+Control "$i" toggle-view-tags "$tags" +done + +riverctl map normal $mod 0 set-focused-tags $(((1 << 32) - 1)) +riverctl map normal $mod 0 set-focused-tags $(((1 << 32) - 1)) +riverctl map normal $mod+Shift 0 set-view-tags $(((1 << 32) - 1)) + +riverctl map normal $alt 0 set-focused-tags $(((1 << 32) - 1)) +riverctl map normal $alt 0 set-focused-tags $(((1 << 32) - 1)) +riverctl map normal $alt+Shift 0 set-view-tags $(((1 << 32) - 1)) + +riverctl map-pointer normal $mod BTN_LEFT move-view +riverctl map-pointer normal $mod BTN_RIGHT resize-view +riverctl map-pointer normal $mod BTN_MIDDLE toggle-float + +riverctl map normal $mod period focus-output next +riverctl map normal $mod comma focus-output previous + +riverctl map normal $mod+Shift period send-to-output next +riverctl map normal $mod+Shift comma send-to-output previous + +riverctl map normal $alt Tab focus-previous-tags +riverctl map normal $alt+Shift Tab send-to-previous-tags + +riverctl map normal $mod Tab focus-previous-tags +riverctl map normal $mod+Shift Tab send-to-previous-tags + +riverctl xcursor-theme OSX-ElCap 16 + +swaybg -m fill -c "#120d15" -i "$HOME/misc/random/wallpapers/16.jpg" & +mkfifo "$wobsock" && tail -f "$wobsock" | wob & +wl-paste --watch cliphist store & + +services_to_start=( + battery-notify + dunst + pipewire + habitual + kanshi + psi-notify +) + +for s in "${services_to_start[@]}"; do + "$s" 2>&1 | vlogger -t "$s" & +done diff --git a/modules/mixins/dotfiles/config/shell/.keep b/modules/mixins/dotfiles/config/shell/.keep diff --git a/modules/mixins/dotfiles/config/shell/early-funcs b/modules/mixins/dotfiles/config/shell/early-funcs @@ -0,0 +1,18 @@ +# vim: ft=sh + +use_first_to_exist() { + for command; do + if command -v "$command" >/dev/null 2>&1; then + printf '%s\n' "$command" + return 0 + fi + done + + echo false + return 1 +} + +setopt NULL_GLOB >/dev/null 2>&1 + +# shellcheck disable=SC2039 +shopt -s nullglob >/dev/null 2>&1 diff --git a/modules/mixins/dotfiles/config/shell/profile/.keep b/modules/mixins/dotfiles/config/shell/profile/.keep diff --git a/modules/mixins/dotfiles/config/shell/profile/environment b/modules/mixins/dotfiles/config/shell/profile/environment @@ -0,0 +1,26 @@ +#!/bin/sh + +export LC_COLLATE=C +export EDITOR=nvim +export PAGER=less +export LESS=-R +export VISUAL=nvim +export PYTHONDONTWRITEBYTECODE=1 +export PYTHONSTARTUP="$HOME/.pythonrc" +export BROWSER=firefox +export NSS_DEFAULT_DB_TYPE=sql +export BC_ENV_ARGS="$HOME/.config/bcrc" +export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" +export GRAB_HOME="$HOME/src" +export GOPATH="$HOME/src/misc/go" +export MPD_HOST="127.0.0.1" +export MPD_PORT="6695" +export CARGO_TERM_COLOR="always" +export ZVM_INSTALL="$HOME/.zvm/self" + +# shellcheck disable=SC2154 +{ + export PATH="$config_home/.local/share/tools:$config_home/.local/share/gem/ruby/3.4.0/bin:$config_home/src/go/bin:$config_home/.zvm/bin:$config_home/.zvm/self:$config_home/src/misc/go/bin:$config_home/.node_modules/bin:$config_home/bin:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/bin/site_perl:config_home/bin:$config_home/.local/bin:$config_home/.cargo/bin:$config_home/go/bin:$config_home/.phpenv/versions/$PHP_VERSION/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/share/bcc:$config_home/.nix-profile/bin" +} + +umask 0022 diff --git a/modules/mixins/dotfiles/config/shell/profile/fzf b/modules/mixins/dotfiles/config/shell/profile/fzf @@ -0,0 +1,10 @@ +export FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS \ + --highlight-line \ + --ansi \ + --layout=reverse \ + --border=rounded \ + --color=bg+:#2a1f2e,bg:-1,spinner:#c084b8,hl:#e08060 \ + --color=fg:#c8b8bf,header:#c4607a,info:#7a6e7a,pointer:#c084b8 \ + --color=marker:#e06fad,fg+:#f0dfe5,prompt:#7a9fd4,hl+:#f0a070 \ + --color=border:#3d2a42 \ +" diff --git a/modules/mixins/dotfiles/config/shell/profile/less b/modules/mixins/dotfiles/config/shell/profile/less @@ -0,0 +1,19 @@ +# vim: ft=sh + +# normal=$(tput sgr0) +# green=$(tput setaf 2) +# yellow=$(tput setaf 3) +# blue=$(tput setaf 4) + +# # Headers and commands +# export LESS_TERMCAP_mb="$normal" +# export LESS_TERMCAP_md="$blue" +# export LESS_TERMCAP_me="$normal" + +# # Status bar +# export LESS_TERMCAP_so="$yellow" +# export LESS_TERMCAP_se="$normal" + +# # Arguments +# export LESS_TERMCAP_us="$green" +# export LESS_TERMCAP_ue="$normal" diff --git a/modules/mixins/dotfiles/config/shell/profile/nix b/modules/mixins/dotfiles/config/shell/profile/nix @@ -0,0 +1,4 @@ +#!/bin/sh +if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then + . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' +fi diff --git a/modules/mixins/dotfiles/config/shell/profile/woodpecker b/modules/mixins/dotfiles/config/shell/profile/woodpecker @@ -0,0 +1,6 @@ +#!/bin/sh + +{ + export WOODPECKER_SERVER="https://ci.codeberg.org" + export WOODPECKER_TOKEN="" +} diff --git a/modules/mixins/dotfiles/config/shell/rc/.keep b/modules/mixins/dotfiles/config/shell/rc/.keep diff --git a/modules/mixins/dotfiles/config/shell/rc/aliased-short-names b/modules/mixins/dotfiles/config/shell/rc/aliased-short-names @@ -0,0 +1,136 @@ +#!/bin/sh + +alias fg='cdg && magdalena look-file && cd -' + +alias f='magdalena look-file' +alias p='pmn' +alias l='ls' + +alias tailup='ss tailscaled && tailscale up --login-server https://head.saatana.cat:443' +alias metailup='ss tailscaled && tailscale up --login-server https://hs.metafori.com:443' + +alias tailno="ssh nixaran 'sudo headscale nodes list'" +alias metailno="ssh metafori-infra 'sudo headscale nodes list'" + +alias mgr='magdalena grep' +alias mgrf='cdg && magdalena grep && cd -' + +alias mrd='magdalena recent-dirs' +alias mrf='magdalena recent-files' + +alias pdm='pkill -f dmenu' + +alias nprg="alafont --font 'PragmataPro' --size '14.0'" +alias bprg="alafont --font 'PragmataPro' --size '18.0'" +alias ncom="alafont --font 'Comic Code' --size '14.0'" +alias bcom="alafont --font 'Comic Code' --size '16.0'" +alias nbit="alafont --font 'UW ttyp0' --size '12.0'" +alias bbit="alafont --font 'UW ttyp0' --size '22.0'" + +alias nixaran='ssh nixaran' + +alias pw='LC_ALL=C tr -dc a-zA-Z0-9 < /dev/urandom | head -c 20; echo' + +alias pcm='pcmanfm-qt' + +alias duh='du -hs' +alias dfh='df -h' + +alias q='sudo ' +alias lopri='nice -n 19 ionice -c2 -n7 ' +alias scan='sudo nmap -n -PN -sT -sU -p-' + +alias tls='tmux ls' +alias tma='tmux attach-session -t' + +alias ss='sudo systemctl start' +alias st='sudo systemctl stop' +alias sd='sudo systemctl -n 100 status' + +alias us='systemctl --user start' +alias ut='systemctl --user stop' +alias ud='systemctl --user -n 100 status' + +alias pps='podman ps' +alias plo='podman logs' +alias pst='podman stats' +alias pbu='podman build' + +alias pcu='podman-compose up' +alias pcd='podman-compose down' +alias pcs='podman-compose stop' + +alias foo='fooyin . & disown' +alias mpva='mpv --no-video' + +alias pp='mpc toggle' +alias qq='mpc playlist' + +alias no='nota' +alias nor='NOTA_READ_ONLY=1 nota' + +alias to='nota today' +alias ye='nota yesterday' +alias tom='nota tomorrow' + +alias todo='nota todo' +alias wish='nota wishlist' + +alias obs='obsidian "obsidian://open?vault=notes" & disown' +alias obsno='obsidian "obsidian://open?vault=nota" & disown' +alias obscpt='obsidian "obsidian://open?vault=counterpoint" & disown' + +alias kat='khal at' +alias kan='khal new' +alias khw='khal list now 7d' +alias khi='khal interactive' + +alias bpp='backup pass --push' +alias bnp='backup nota --push' +alias brr='backup releases --push' + +alias h='histdb' +alias hs='histdb-sync' + +alias nr='newsraft' +alias nre='$EDITOR ~/.config/newsraft/feeds && backup rss' + +alias age_decrypt='age --decrypt --identity "$HOME"/misc/random/key.txt' + +alias cbd='cargo build' +alias cbr='cargo build --release' +alias cip='cargo install --path .' +alias cup='cargo update --recursive' + +alias dups='fdupes -r . && find . -type f -regex ".* ([0-9][0-9]*).*$"' +alias gaf='fd --hidden --glob "*.flac" --exclude PIONEER' + +alias ap='ansible-playbook --diff' +alias apc='ansible-playbook --check --diff' + +alias yt_dlp_audio_url='yt-dlp -f bestaudio -g' +alias yt_dlp_audio='yt-dlp --embed-thumbnail --write-thumbnail --extract-audio --audio-format mp3 --audio-quality 0' + +alias matchamix='matchakey --mixxx ~/.mixxx/mixxxdb.sqlite' +alias datamix='datasette serve $HOME/.mixxx/mixxxdb.sqlite --setting sql_time_limit_ms 50000' + +alias nd='nix develop' +alias hms='nh home switch ~/src/nix' + +alias amsp='mpva https://radio.stereoscenic.com/asp-s --no-resume-playback' +alias nts1='mpva https://stream-relay-geo.ntslive.net/stream --no-resume-playback' +alias nts2='mpva https://stream-relay-geo.ntslive.net/stream2 --no-resume-playback' + +alias op='offpunk' +alias mf='monofetch' +alias sr='speedread -w 400' + +alias chop='perl -pe chop' +alias chomp='perl -pe chomp' + +alias cfp='source ./hack/creds-from-pass' + +alias cej='just check' +alias dpj='just deploy' + +alias jlr='jless --mode line' diff --git a/modules/mixins/dotfiles/config/shell/rc/command_overrides b/modules/mixins/dotfiles/config/shell/rc/command_overrides @@ -0,0 +1,67 @@ +# vim: ft=sh + +# GNU Coreutils that might not be installed with default names on OSX. +# Lint warning for expansion at definition is disabled as that's intentional. +# +# shellcheck disable=SC2139 +{ + alias grep="$(use_first_to_exist grep)" + alias ls="$(use_first_to_exist eza ls)" + alias sed="$(use_first_to_exist sed)" + alias awk="$(use_first_to_exist awk)" + alias diff="$(use_first_to_exist difft diff)" + alias vim="$(use_first_to_exist nvim vim vi)" +} +alias cp='cp --backup=numbered --reflink=auto --sparse=always' +alias mv='mv --backup=numbered' +alias ln='ln --backup=numbered' + +alias fd='fd --hidden --exclude .git --exclude $HOME/misc/mnt --exclude /nix' +alias rg='rg --hidden -i' + +alias eza='eza -a --sort=modified' + +alias startx='exec startx &>| /tmp/startx-$USER' + +# Disable sourcing systemwide vim configuration. Also set PYTHONPATH to +# include basedir so we can edit tests that get their sys.path munged by nose + +# $config_home comes from shell init + +# Do not disable raw control chars when running less +alias less='less -R' + +alias ipython='ipython --no-banner' + +# Do not pass a (potentially unsupported) locale when SSHing to random servers. +# In mosh, a UTF-8 aware locale is needed, so we use en_US.UTF-8 because +# there's a high likelihood that it will be available ('Murica baby!). +safe_termname() { + case $TERM in + rxvt*) echo rxvt ;; + xterm*) echo xterm ;; + *) echo linux ;; + esac +} + +for command in ssh{,rc}; do + # shellcheck disable=SC2139 + alias "$command"='LC_ALL=C TERM="$(safe_termname)" '"$command" +done + +alias mosh='LC_ALL=en_US.UTF-8 mosh' +alias sshrc='LC_ALL=en_US.UTF-8 sshrc' + +alias leafpad='mousepad' + +# Allow other aliases to be used after the program name +alias sudo='sudo ' +alias watch='watch ' + +alias gdb='gdb -q' + +alias dmesg='dmesg -T --color=always | less -R +G' +alias mksrcinfo='makepkg --printsrcinfo >| .SRCINFO' + +alias ncdu='sudo ncdu -x --exclude /nix --exclude $config_home/misc/mnt /' +alias pracomer='pracomer --file /tmp/pracomer.log' diff --git a/modules/mixins/dotfiles/config/shell/rc/functions b/modules/mixins/dotfiles/config/shell/rc/functions @@ -0,0 +1,172 @@ +#!/bin/sh + +nixpkgs_cache_index_update() { + filename="index-$(uname -m | sed 's/^arm64$/aarch64/')-$(uname | tr "[:upper:]" "[:lower:]")" + mkdir -p ~/.cache/nix-index && cd ~/.cache/nix-index || exit + wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/"$filename" + ln -f "$filename" files +} + +fetch_rss_youtube() { + CHANNEL_URL="$1" + if [ -n "$CHANNEL_URL" ]; then + curl -s "$CHANNEL_URL" | + grep -Po '<link rel="canonical" href="https://www.youtube.com/channel/\K.*?(?=">)' | + xargs -I@ echo 'https://www.youtube.com/feeds/videos.xml?channel_id=@' | wl-copy + fi +} + +nvimrecomp() { + nix_fennel_path="$HOME/src/nix/modules/mixins/dotfiles/config/nvim/fnl" + config_path="$HOME/.config/nvim" + + mkdir -p "$config_path"/lua/config + + find "$nix_fennel_path" -type f -name "*.fnl" | while read -r fnl_file; do + rel_path="${fnl_file#"$nix_fennel_path"/}" + + + if [ "$rel_path" = "init.fnl" ]; then + lua_file="$config_path/init.lua" + else + lua_file="$config_path/lua/${rel_path%.fnl}.lua" + fi + + fnlfmt --fix "$fnl_file" + fennel --compile "$fnl_file" | tee "$lua_file" >/dev/null + echo "$lua_file" + done +} + +bandsnatch() { + command bandsnatch run \ + -c "$HOME/misc/music/random/bandcamp-cookies.json" \ + -f flac \ + -o "$HOME/misc/music/backlog/_todo" \ + mtmnn && backup releases +} + +gotosleep() { + date + sleep "${1?}m" && systemctl suspend +} + +tracklist() { + total=0 + for ext in mp3 flac aif aiff; do + for f in *."$ext"; do + [ -f "$f" ] || continue + echo "$f" + done + done | sort -V | while read -r f; do + filename="${f%.*}" + printf "%s %d:%02d\n" "$filename" $((total / 60)) $((total % 60)) + duration=$(ffprobe -v quiet -show_entries format=duration -of csv=p=0 "$f" 2>/dev/null | cut -d. -f1) + total=$((total + duration)) + done +} + +taildo() { + if systemctl is-active --quiet tailscaled; then + tailscale down + sudo systemctl stop tailscaled + fi +} + +fetch_rss() { + url="${1?}" + curl -s "$url" | xmllint --html --xpath "//link[@type='application/rss+xml' or @type='application/atom+xml']/@href" - 2>/dev/null +} + +tempfox() { + profile_dir=$(mktemp -d) + trap 'rm -rf $profile_dir' EXIT + cp ~/src/tools/tempfox/user.js "$profile_dir"/user.js + firefox -no-remote -new-instance -profile "$profile_dir" +} + +labels() { + inputs="${*:-all.txt}" + mkdir -p ./labels + for input in $inputs; do + base=$(basename "$input" .txt) + cut -d'/' -f1 "$input" | sort | uniq | tee labels/"${base}_labels.txt" + done +} + +reval() { + eval "$(rbenv init - --no-rehash shell)" + ruby --version +} + +mirror() { + wget --mirror --page-requisites --no-parent --convert-links -P ./ "$@" +} + +cheat() { + curl cht.sh/"${1?}" +} + +mpas() { + mpc add "$(yt-dlp -f bestaudio -g "${1?}")" +} + +mpa() { + mpc add "${1?}" +} + +ae() { + if tmux has-session -t aerc 2>/dev/null; then + if [ -n "$TMUX" ]; then + tmux switch-client -t aerc + else + tmux attach -t aerc + fi + else + tmux new -s aerc aerc + fi +} + +cd() { + builtin cd "$@" && magdalena log-dir "$PWD" +} + +t() { + session="${1:=magnolia}" + + if [ -n "$TMUX" ]; then + tmux detach-client + fi + + if tmux has-session -t "${session}" 2>/dev/null; then + tmux attach -t "${session}" + else + tmux new -s "${session}" + fi +} + +u() { + if [ -n "$1" ]; then + unzip "$1" -d "${1%.zip}" + else + for a in *.zip; do + unzip -n "$a" -d "${a%.zip}" + done + fi +} + +o() { + if [ $# -eq 0 ]; then + nvim -c ":Oil $(pwd)" + else + nvim -c ":Oil $1" + fi +} + +d() { + target_dir=$(magdalena look-dir) + + if [ -n "$target_dir" ]; then + cd "$target_dir" && magdalena log-dir "$PWD" + fi +} diff --git a/modules/mixins/dotfiles/config/shell/rc/git b/modules/mixins/dotfiles/config/shell/rc/git @@ -0,0 +1,93 @@ +#!/bin/sh +alias cdg='cd "$(git rev-parse --show-toplevel)"' + +alias ng='nvim -c ":Neogit"' +alias gn='git number --column' +alias ga='git number add' +alias gb='gbf' +alias gc='git commit -v' +alias gco='git checkout' +alias gcp='git cherry-pick --strategy=recursive --strategy-option=diff-algorithm=histogram' +alias gd='git diff --no-prefix' +alias gl='git gol' +alias gm='git merge' +alias gmc='gm --no-ff' +alias gp='git push' +alias gs='git show --no-prefix' +alias gst='git status' +alias gref='git reflog --date=iso' + +alias grab='git grab' + +alias grr='git rebase -r' +alias gri='grr -i' +alias grrm='grr master@{u}' +alias gru='grr @{u}' +alias gabs='git absorb --and-rebase' + +alias gdm='git_diff_merge_base master@{u}' +alias gdma='git_diff_merge_base main@{u}' +alias gdd='git_diff_merge_base develop@{u}' +alias gdu='gd @{u}..' +alias gdc='gd --cached' +alias gdw='gd --color-words' + +# Logs +alias glm='gl master@{u}..' +alias gld='gl develop@{u}..' +alias glu='gl @{u}..' + +# Misc +alias gap='ga -p' +alias gca='gc -a' +alias gcaa='gca --amend' +alias grh='git reset --hard' +alias grhu='grh @{u}' +alias gpf='gp -f' +alias gu='gf && grrm' +alias gcl='git clean -dffx' + +# Functions +git_diff_merge_base() { + feature="${2:-HEAD}" + gd "$(git merge-base "$1" "$feature")..$feature" +} + +gcm() { + git "${1?}" "${2?}" +} + +gf() { + if [ "$1" ]; then + git fetch -p "$1" + else + git fetch -p --all + fi +} + +gcopr() { + git fetch origin pull/"${1?need pr num}"/head:pr"$1" && gco pr"$1" +} + +glf() { + git log \ + --color=always \ + --date=short \ + --pretty=format:"%cd %C(auto)%h %d %s %C(green)%cr %C(bold blue)<%an>" "$@" | + fzf \ + --ansi \ + --preview "git show --color=always {2}" | + awk '{print $2}' | wl-copy && + nvim -c ":DiffviewOpen $(wl-paste)" +} + +gbf() { + branch=$( + git branch --all | grep -v HEAD | sed 's/^[* ]*//' | sed 's/remotes\///' | sort -u | tac | fzf \ + --height=40% \ + --reverse \ + --preview 'git log --oneline --color=always {1} 2>/dev/null | head -20' \ + --preview-window=right:50% + ) + [ -n "$branch" ] && git switch "${branch#origin/}" +} diff --git a/modules/mixins/dotfiles/config/shell/rc/jujutsu b/modules/mixins/dotfiles/config/shell/rc/jujutsu @@ -0,0 +1,49 @@ +#!/bin/sh +alias jjf='jj-fzf' +alias jst='jj status' # git status +alias jd='jj diff' # git diff (gd) +alias jdc='jj diff --stat' # git diff --cached --stat (gdc) +alias jdw='jj diff --color-words' # git diff --color-words (gdw) +alias js='jj show' # git show +alias jl='jj log' # git log (gl) +alias jlo='jj log -r "..@"' # git log ..HEAD — ancestors of working copy (glu) +alias jop='jj op log' # git reflog +alias jops='jj op show' # git reflog show <entry> +alias jn='jj new' # git checkout -b <branch> (gco -b) +alias jne='jj new --no-edit' # git commit --allow-empty / branch without switching +alias jc='jj commit' # git add -A && git commit (gc) +alias jde='jj describe' # git commit --amend --only -m (gc --amend msg) +alias jsq='jj squash' # git commit --amend / git add && git commit --amend (gcaa) +alias ji='jj squash -i' # git rebase -i (gri) +alias jsp='jj split' # git add -p && git commit (no direct equivalent) +alias jdup='jj duplicate' # git cherry-pick (gcp) +alias je='jj edit' # git checkout <commit> (detached HEAD) +alias jnp='jj next --edit' # no direct equivalent — like git checkout HEAD~-1 +alias jpp='jj prev --edit' # git checkout HEAD~1 +alias jb='jj bookmark list' # git branch (gb) +alias jbc='jj bookmark create' # git branch <name> (gb <name>) +alias jbs='jj bookmark set' # git branch -f <name> +alias jbd='jj bookmark delete' # git branch -d (gb -d) +alias jbm='jj bookmark move' # git branch -f / git branch -m +alias jr='jj rebase' # git rebase (grr) +alias jrd='jj rebase -d' # git rebase <dest> +alias jrb='jj rebase -b' # git rebase --onto <dest> <base> +alias jgf='jj git fetch' # git fetch (gf) +alias jgfa='jj git fetch --all-remotes' # git fetch --all +alias jgp='jj git push' # git push (gp) +alias jgpf='jj git push --force-with-lease' # git push --force-with-lease (gpf) +alias jgpc='jj git push --change @' # git push origin HEAD:<branch> +alias jgl='jj git clone' # git clone +alias ju='jj undo' # git reset HEAD~ / git reflog + reset (grh / grhu) +alias juu='jj op undo' # git reflog + git reset --hard <hash> +alias jres='jj restore' # git checkout -- <file> / git restore (gco <file>) +alias jab='jj abandon' # git reset --hard && drop commit +alias jdu='jj diff -r @{u}..@' # git diff @{u}..HEAD (gdu) +alias jw='jj workspace list' # git worktree list +alias jwa='jj workspace add' # git worktree add +alias jabs='jj absorb' # git add -p + fixup rebase (no direct equivalent) + +jdm() { + bookmark="${1:-master@origin}" + jj diff -r "roots(${bookmark}..@)..@" # git diff main...HEAD — full branch diff +} diff --git a/modules/mixins/dotfiles/config/shell/rc/prompt-functions b/modules/mixins/dotfiles/config/shell/rc/prompt-functions @@ -0,0 +1,136 @@ +# vim: ft=sh +_C_RESET=$(tput sgr0) +_C_1=$(tput setaf 141) +_C_2=$(tput setaf 209) +_C_3=$(tput setaf 203) +_C_4=$(tput setaf 174) +_C_6=$(tput setaf 167) + +colour_part() { + local colour_val msg delim + msg="$2" + delim="${3- }" + [ "$msg" ] || return 1 + case $1 in + 1) colour_val=$_C_1 ;; + 2) colour_val=$_C_2 ;; + 3) colour_val=$_C_3 ;; + 4) colour_val=$_C_4 ;; + 6) colour_val=$_C_6 ;; + esac + if [ "$BASH" ]; then + printf '%s ' "$msg" + elif [ "$ZSH_VERSION" ]; then + printf '%%{%s%%}%s%%{%s%%}'"${delim}" "$colour_val" "$msg" "$_C_RESET" + fi +} + +_jj_prompt() { + local jj_wc jj_bookmarks jj_state + if ! jj root >/dev/null 2>&1; then + return 1 + fi + jj_wc=$(jj log -r @ --no-graph -T 'description.first_line()' 2>/dev/null | head -c 30) + jj_bookmarks=$(jj bookmark list --color never 2>/dev/null | awk '/^@ / { gsub(/:.*/, "", $2); print $2 }') + if jj status 2>/dev/null | grep -q 'conflict:'; then + jj_state='!' + fi + if [ "$jj_bookmarks" ]; then + colour_part 2 "$jj_bookmarks" + elif [ "$jj_wc" ]; then + colour_part 2 "$jj_wc" + fi + colour_part 1 "$jj_state" +} + +_git_prompt() { + local branch git_state git_head git_dir tag + if branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"; then + if [ "$branch" != HEAD ]; then + git_head=$branch + elif tag="$(git describe --tags --exact-match HEAD 2>/dev/null)"; then + git_head=$tag + else + git_head=$(git rev-parse --short HEAD) + fi + git_dir=$(git rev-parse --git-dir) + if [ -d "$git_dir/rebase-apply" ] || [ -d "$git_dir/rebase-merge" ]; then + git_state=rebase + elif [ -f "$git_dir/MERGE_HEAD" ]; then + git_state=merge + elif [ -f "$git_dir/CHERRY_PICK_HEAD" ] || [ -f .git/sequencer/todo ]; then + git_state=cherry-pick + elif [ -f "$git_dir/REVERT_HEAD" ]; then + git_state=revert + elif [ -f "$git_dir/BISECT_LOG" ]; then + git_state=bisect + fi + fi + [ "$git_head" = master ] && unset git_head + [ "$git_head" = main ] && unset git_head + colour_part 2 "$git_head" + colour_part 1 "$git_state" +} + +_virt_prompt() { + if [ "$_VIRT" ]; then + : + elif [ "${JUNEST_ENV:-0}" -eq 1 ]; then + _VIRT=junest + else + _VIRT=$(systemd-detect-virt 2>/dev/null) + [ "$_VIRT" = none ] && unset _VIRT + fi + colour_part 6 "$_VIRT" +} + +_hostname_prompt() { + [ "$SSH_CLIENT" ] || return + if ! [ "$_HOSTNAME" ]; then + _HOSTNAME=$(hostname) + _HOSTNAME="${_HOSTNAME%%.*}" + fi + colour_part 3 "$_HOSTNAME" +} + +_user_prompt() { + if ! [ "${_USER+x}" ]; then + local user + user=$(id -un) + case $user in + miro) _USER='' ;; + *) _USER=$user ;; + esac + fi + colour_part 3 "${_USER:+"$_USER@"}" '' +} + +_pwd_prompt() { + [ "$PWD" = "$HOME" ] && return + local stripped_pwd="${PWD##*/}" + colour_part 4 "${stripped_pwd:-/}" +} + +_vcs_prompt() { + if [ "$PWD" != "$_VCS_LAST_PWD" ]; then + _VCS_LAST_PWD=$PWD + _VCS_CACHE=$(_jj_prompt || _git_prompt) + fi + printf '%s' "$_VCS_CACHE" +} + +_get_ps1() { + local prompt_ender + if [ "$ZSH_VERSION" ]; then + prompt_ender="%(?:%%:%{${_C_1}%}%%%{${_C_RESET}%})" + else + prompt_ender=% + fi + printf '%s%s%s%s%s%s ' \ + "$(_user_prompt)" \ + "$(_hostname_prompt)" \ + "$(_pwd_prompt)" \ + "$(_vcs_prompt)" \ + "$(_virt_prompt)" \ + "$prompt_ender" +} diff --git a/modules/mixins/dotfiles/config/shell/rc/stty b/modules/mixins/dotfiles/config/shell/rc/stty @@ -0,0 +1,3 @@ +# vim: ft=sh + +stty -ixon -ixoff diff --git a/modules/mixins/dotfiles/config/shell/rc/todo b/modules/mixins/dotfiles/config/shell/rc/todo @@ -0,0 +1,21 @@ +#!/bin/sh + +alias tt='rg -N -B 1 "^todo:" ~/misc/notes/nota/todo.txt' +alias tn='todo-notify' + +ta() { + if [ $# -eq 0 ]; then + { + echo + date --rfc-3339=s + echo -n "todo: " + } >>~/misc/notes/nota/todo.txt + /usr/local/bin/ne + --macro "end-of-line" ~/misc/notes/nota/todo.txt + else + tma "$@" + fi +} + +te() { + /usr/local/bin/ne + ~/misc/notes/nota/todo.txt +} diff --git a/modules/mixins/dotfiles/config/twitch/channels b/modules/mixins/dotfiles/config/twitch/channels @@ -0,0 +1,73 @@ +sovietwomble +eslcs +eslcsb +hasanabi +gorgc dota +b4nny tf +firesidecasts tf +blastpremier cs +rglgg tf +franzj cs +paddie__ tf +limmy +alasdair +janetacarr programming +kujukuju programming +unicornowl tf +ster +stabbystabby tf +sin_k4rma_6s_demon tf +ornicar2 programming +essentialstf tf +travisvroman programming +vegas deadlock +vixentf2 tf +anthonywritescode programming +tsoding programming +llyyffee tf +wirtual trackmania +pebl3 hacking +valigo programming +shroud +ceejaey tf +39daph +f0rest cs +thunderpicktv cs +wahdtf tf +zerggyyyy valorant +andiduude tf +mr_sve tf +nubbi_ tf +jackie_codes programming +olofmeister cs +pgl cs +pgl_cs2 +dima_wallhacks cs +lastmiles programming +chiblee +dt_tf tf +surefour deadlock +peniferous tf +deadlocknightshift deadlock +tf2jump tf +t2sde programming +quel_solaar programming +feoramund programming +hempuli programming +myztroraisy quake +togglebit programming +amppisss tf +kritzkast tf +lcolonq programming +pgl_dota2 +starladder_cs_en +starladder_cs_en2 +stewsquared programming +dmmulroy programming +phish_tf2 tf +rahmed tf +arteezy dota +gamesdonequick +youwy souls +anthonywritescode programming +pushcx lobsters diff --git a/modules/mixins/dotfiles/config/vifm/colors/ef_tritanopia_dark b/modules/mixins/dotfiles/config/vifm/colors/ef_tritanopia_dark @@ -0,0 +1,47 @@ +highlight clear + +highlight Win ctermfg=252 ctermbg=none cterm=none guifg=#dfd0d5 guibg=#15050f gui=none +highlight Link ctermfg=80 ctermbg=none cterm=none guifg=#3fafcf guibg=none gui=none +highlight BrokenLink ctermfg=203 ctermbg=none cterm=none guifg=#cf4f5f guibg=none gui=bold +highlight Socket ctermfg=175 ctermbg=none cterm=none guifg=#b0648f guibg=none gui=none +highlight Device ctermfg=178 ctermbg=none cterm=none guifg=#c48702 guibg=none gui=none +highlight Fifo ctermfg=36 ctermbg=none cterm=none guifg=#2fa526 guibg=none gui=none +highlight Executable ctermfg=35 ctermbg=none cterm=none guifg=#00b066 guibg=none gui=bold + +highlight Selected ctermfg=252 ctermbg=237 cterm=bold guifg=#dfd0d5 guibg=#293140 gui=bold +highlight CurrLine ctermfg=252 ctermbg=235 cterm=bold guifg=#dfd0d5 guibg=#282026 gui=bold +highlight TopLine ctermfg=252 ctermbg=235 cterm=none guifg=#dfd0d5 guibg=#282026 gui=none +highlight TopLineSel ctermfg=75 ctermbg=235 cterm=bold guifg=#379cf6 guibg=#282026 gui=bold + +highlight StatusLine ctermfg=252 ctermbg=235 cterm=none guifg=#dfd0d5 guibg=#282026 gui=none +highlight WildMenu ctermfg=16 ctermbg=75 cterm=bold guifg=#15050f guibg=#379cf6 gui=bold + +highlight CmdLine ctermfg=252 ctermbg=none cterm=none guifg=#dfd0d5 guibg=#15050f gui=none +highlight ErrorMsg ctermfg=203 ctermbg=none cterm=bold guifg=#cf4f5f guibg=none gui=bold + +highlight Border ctermfg=240 ctermbg=none cterm=none guifg=#554f4f guibg=none gui=none + +highlight OtherWin ctermfg=246 ctermbg=none cterm=none guifg=#908890 guibg=#15050f gui=none + +highlight JobLine ctermfg=252 ctermbg=235 cterm=bold guifg=#dfd0d5 guibg=#282026 gui=bold + +highlight SuggestBox ctermfg=252 ctermbg=235 cterm=none guifg=#dfd0d5 guibg=#282026 gui=none + +highlight OtherLine ctermfg=246 ctermbg=none cterm=none guifg=#908890 guibg=none gui=none +highlight LineNr ctermfg=240 ctermbg=none cterm=none guifg=#554f4f guibg=none gui=none + +highlight /^.*\.sh$/i ctermfg=35 ctermbg=none cterm=none guifg=#00b066 guibg=none gui=none +highlight /^.*\.py$/i ctermfg=75 ctermbg=none cterm=none guifg=#379cf6 guibg=none gui=none +highlight /^.*\.rb$/i ctermfg=203 ctermbg=none cterm=none guifg=#cf4f5f guibg=none gui=none +highlight /^.*\.md$/i ctermfg=178 ctermbg=none cterm=none guifg=#c48702 guibg=none gui=none +highlight /^.*\.json$/i ctermfg=178 ctermbg=none cterm=none guifg=#c48702 guibg=none gui=none +highlight /^.*\.vim$/i ctermfg=35 ctermbg=none cterm=none guifg=#2fa526 guibg=none gui=none + +highlight /^.*\.(zip|tar|gz|bz2|xz|7z|rar)$/i ctermfg=203 ctermbg=none cterm=none guifg=#d24f7f guibg=none gui=none + +highlight /^.*\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i ctermfg=175 ctermbg=none cterm=none guifg=#b0648f guibg=none gui=none +highlight /^.*\.(mp3|wav|flac|ogg|m4a)$/i ctermfg=80 ctermbg=none cterm=none guifg=#3fafcf guibg=none gui=none +highlight /^.*\.(mp4|mkv|avi|mov|webm|flv)$/i ctermfg=175 ctermbg=none cterm=none guifg=#a6699f guibg=none gui=none + +highlight /^.*\.(pdf|doc|docx|odt)$/i ctermfg=203 ctermbg=none cterm=none guifg=#d24f7f guibg=none gui=none +highlight /^.*\.(txt|log)$/i ctermfg=252 ctermbg=none cterm=none guifg=#dfd0d5 guibg=none gui=none diff --git a/modules/mixins/dotfiles/config/vifm/vifmrc b/modules/mixins/dotfiles/config/vifm/vifmrc @@ -0,0 +1,2 @@ +set vicmd=nvim +colorscheme ef_tritanopia_dark diff --git a/modules/mixins/dotfiles/config/xdg-desktop-portal/portals.conf b/modules/mixins/dotfiles/config/xdg-desktop-portal/portals.conf @@ -0,0 +1,3 @@ +[preferred] +default=wlr;gtk +org.freedesktop.impl.portal.ScreenSaver=gtk diff --git a/modules/mixins/dotfiles/config/yt-dlp/config.nix b/modules/mixins/dotfiles/config/yt-dlp/config.nix @@ -0,0 +1,3 @@ +{homeDir, ...}: '' + --cookies ${homeDir}/misc/random/youtube_cookies.txt +'' diff --git a/modules/mixins/dotfiles/config/zed/settings-nix.json b/modules/mixins/dotfiles/config/zed/settings-nix.json @@ -0,0 +1,37 @@ +{ + "agent_servers": { + "qwen-code": { + "type": "registry" + } + }, + "relative_line_numbers": "enabled", + "buffer_font_family": "Comic Code", + "telemetry": { + "diagnostics": false, + "metrics": false + }, + "title_bar": { + "show_user_picture": false, + "show_sign_in": false + }, + "toolbar": { + "breadcrumbs": false, + "quick_actions": false, + "selections_menu": false + }, + "icon_theme": "Zed (Default)", + "vim_mode": true, + "ui_font_size": 16, + "buffer_font_size": 16, + "theme": "Doric Dark", + "disable_ai": false, + "collaboration_panel": { + "button": false + }, + "chat_panel": { + "button": "never" + }, + "agent": { + "button": false + } +} diff --git a/modules/mixins/dotfiles/config/zed/themes/doris-dark.json b/modules/mixins/dotfiles/config/zed/themes/doris-dark.json @@ -0,0 +1,402 @@ +{ + "$schema": "https://zed.dev/schema/themes/v0.2.0.json", + "name": "Doric Dark", + "author": "Protesilaos Stavrou <info@protesilaos.com>", + "themes": [ + { + "name": "Doric Dark", + "appearance": "dark", + "style": { + "border": "#707070", + "border.variant": "#332d38", + "border.focused": "#9fbfe7", + "border.selected": "#cda4df", + "border.transparent": "#00000000", + "border.disabled": "#43404c", + "elevated_surface.background": "#0d0d0d", + "surface.background": "#0d0d0d", + "background": "#000000", + "element.background": "#43404c", + "element.hover": "#50447f", + "element.active": "#521e40", + "element.selected": "#521e40", + "element.disabled": "#332d38", + "drop_target.background": "#50447f55", + "ghost_element.background": "#00000000", + "ghost_element.hover": "#332d38", + "ghost_element.active": "#43404c", + "ghost_element.selected": "#50447f", + "ghost_element.disabled": "#332d38", + "text": "#ffffff", + "text.muted": "#a2a0b2", + "text.placeholder": "#707070", + "text.disabled": "#707070", + "text.accent": "#cda4df", + "icon": "#c5c7d4", + "icon.muted": "#a2a0b2", + "icon.disabled": "#707070", + "icon.placeholder": "#707070", + "icon.accent": "#cda4df", + "status_bar.background": "#0d0d0d", + "title_bar.background": "#000000", + "title_bar.inactive_background": "#0d0d0d", + "toolbar.background": "#000000", + "tab_bar.background": "#0d0d0d", + "tab.inactive_background": "#0d0d0d", + "tab.active_background": "#000000", + "search.match_background": "#50447f", + "panel.background": "#0d0d0d", + "panel.focused_border": "#9fbfe7", + "pane.focused_border": "#9fbfe7", + "pane.group_border": "#707070", + "scrollbar.thumb.background": "#43404c99", + "scrollbar.thumb.hover_background": "#a2a0b2", + "scrollbar.thumb.border": "#43404c", + "scrollbar.track.background": "#00000000", + "scrollbar.track.border": "#332d38", + "editor.foreground": "#ffffff", + "editor.background": "#000000", + "editor.gutter.background": "#000000", + "editor.subheader.background": "#0d0d0d", + "editor.active_line.background": "#0d0b0e", + "editor.highlighted_line.background": "#332d3855", + "editor.line_number": "#707070", + "editor.active_line_number": "#c5c7d4", + "editor.invisible": "#43404c", + "editor.wrap_guide": "#332d38", + "editor.active_wrap_guide": "#43404c", + "editor.indent_guide": "#332d38", + "editor.indent_guide_active": "#43404c", + "editor.document_highlight.read_background": "#50447f44", + "editor.document_highlight.write_background": "#521e4044", + "terminal.background": "#000000", + "terminal.foreground": "#ffffff", + "terminal.bright_foreground": "#ffffff", + "terminal.dim_foreground": "#a2a0b2", + "terminal.ansi.black": "#000000", + "terminal.ansi.bright_black": "#43404c", + "terminal.ansi.white": "#c5c7d4", + "terminal.ansi.bright_white": "#ffffff", + "terminal.ansi.red": "#eca28f", + "terminal.ansi.bright_red": "#eca28f", + "terminal.ansi.green": "#b9d0aa", + "terminal.ansi.bright_green": "#b9d0aa", + "terminal.ansi.yellow": "#c0b080", + "terminal.ansi.bright_yellow": "#c0b080", + "terminal.ansi.blue": "#9fbfe7", + "terminal.ansi.bright_blue": "#9fbfe7", + "terminal.ansi.magenta": "#e9acbf", + "terminal.ansi.bright_magenta": "#cda4df", + "terminal.ansi.cyan": "#a0c0d0", + "terminal.ansi.bright_cyan": "#a0c0d0", + "link_text.hover": "#9fbfe7", + "conflict": "#c0b080", + "conflict.background": "#504432", + "conflict.border": "#c0b080", + "created": "#b9d0aa", + "created.background": "#1f402e", + "created.border": "#b9d0aa", + "deleted": "#eca28f", + "deleted.background": "#4d1f20", + "deleted.border": "#eca28f", + "error": "#eca28f", + "error.background": "#4d1f20", + "error.border": "#eca28f", + "hidden": "#a2a0b2", + "hidden.background": "#332d38", + "hidden.border": "#707070", + "hint": "#a2a0b2", + "hint.background": "#332d38", + "hint.border": "#43404c", + "ignored": "#707070", + "ignored.background": "#000000", + "ignored.border": "#43404c", + "info": "#9fbfe7", + "info.background": "#223567", + "info.border": "#9fbfe7", + "modified": "#c0b080", + "modified.background": "#504432", + "modified.border": "#c0b080", + "predictive": "#a2a0b2", + "predictive.background": "#332d38", + "predictive.border": "#707070", + "renamed": "#cda4df", + "renamed.background": "#521e40", + "renamed.border": "#cda4df", + "success": "#b9d0aa", + "success.background": "#1f402e", + "success.border": "#b9d0aa", + "unreachable": "#707070", + "unreachable.background": "#332d38", + "unreachable.border": "#43404c", + "warning": "#c0b080", + "warning.background": "#504432", + "warning.border": "#c0b080", + "players": [ + { + "cursor": "#ccaaee", + "background": "#ccaaee", + "selection": "#ccaaee33" + }, + { + "cursor": "#9fbfe7", + "background": "#9fbfe7", + "selection": "#9fbfe733" + }, + { + "cursor": "#b9d0aa", + "background": "#b9d0aa", + "selection": "#b9d0aa33" + }, + { + "cursor": "#e9acbf", + "background": "#e9acbf", + "selection": "#e9acbf33" + }, + { + "cursor": "#a0c0d0", + "background": "#a0c0d0", + "selection": "#a0c0d033" + }, + { + "cursor": "#c0b080", + "background": "#c0b080", + "selection": "#c0b08033" + }, + { + "cursor": "#cda4df", + "background": "#cda4df", + "selection": "#cda4df33" + }, + { + "cursor": "#eca28f", + "background": "#eca28f", + "selection": "#eca28f33" + } + ], + "syntax": { + "attribute": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "boolean": { + "color": "#c0b080", + "font_style": null, + "font_weight": null + }, + "comment": { + "color": "#a2a0b2", + "font_style": "italic", + "font_weight": null + }, + "comment.doc": { + "color": "#cfcff8", + "font_style": "italic", + "font_weight": null + }, + "constant": { + "color": "#c0b080", + "font_style": null, + "font_weight": null + }, + "constructor": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + }, + "embedded": { + "color": "#cfcff8", + "font_style": null, + "font_weight": null + }, + "emphasis": { + "color": "#cda4df", + "font_style": "italic", + "font_weight": null + }, + "emphasis.strong": { + "color": "#cfcff8", + "font_style": null, + "font_weight": 700 + }, + "enum": { + "color": "#c0b080", + "font_style": null, + "font_weight": null + }, + "function": { + "color": "#9fbfe7", + "font_style": null, + "font_weight": null + }, + "function.builtin": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + }, + "function.method": { + "color": "#9fbfe7", + "font_style": null, + "font_weight": null + }, + "hint": { + "color": "#a2a0b2", + "font_style": "italic", + "font_weight": null + }, + "keyword": { + "color": "#e9acbf", + "font_style": null, + "font_weight": null + }, + "keyword.control": { + "color": "#e9acbf", + "font_style": null, + "font_weight": null + }, + "label": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "link_text": { + "color": "#9fbfe7", + "font_style": "italic", + "font_weight": null + }, + "link_uri": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + }, + "number": { + "color": "#c0b080", + "font_style": null, + "font_weight": null + }, + "operator": { + "color": "#c5c7d4", + "font_style": null, + "font_weight": null + }, + "predictive": { + "color": "#a2a0b2", + "font_style": "italic", + "font_weight": null + }, + "preproc": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "primary": { + "color": "#ffffff", + "font_style": null, + "font_weight": null + }, + "property": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + }, + "punctuation": { + "color": "#c5c7d4", + "font_style": null, + "font_weight": null + }, + "punctuation.bracket": { + "color": "#a2a0b2", + "font_style": null, + "font_weight": null + }, + "punctuation.delimiter": { + "color": "#a2a0b2", + "font_style": null, + "font_weight": null + }, + "punctuation.list_marker": { + "color": "#c0b080", + "font_style": null, + "font_weight": null + }, + "punctuation.special": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "string": { + "color": "#b9d0aa", + "font_style": null, + "font_weight": null + }, + "string.escape": { + "color": "#c0b080", + "font_style": null, + "font_weight": null + }, + "string.regex": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + }, + "string.special": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "string.special.symbol": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "tag": { + "color": "#9fbfe7", + "font_style": null, + "font_weight": null + }, + "text.literal": { + "color": "#b9d0aa", + "font_style": null, + "font_weight": null + }, + "title": { + "color": "#cfcff8", + "font_style": null, + "font_weight": 700 + }, + "type": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + }, + "type.builtin": { + "color": "#9fbfe7", + "font_style": null, + "font_weight": null + }, + "variable": { + "color": "#ffffff", + "font_style": null, + "font_weight": null + }, + "variable.builtin": { + "color": "#e9acbf", + "font_style": null, + "font_weight": null + }, + "variable.special": { + "color": "#cda4df", + "font_style": null, + "font_weight": null + }, + "variant": { + "color": "#a0c0d0", + "font_style": null, + "font_weight": null + } + } + } + } + ] +} diff --git a/modules/mixins/dotfiles/config/zsh/.keep b/modules/mixins/dotfiles/config/zsh/.keep diff --git a/modules/mixins/dotfiles/config/zsh/completion/_bazel b/modules/mixins/dotfiles/config/zsh/completion/_bazel @@ -0,0 +1,341 @@ +#compdef bazel + +# Copyright 2015 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Installation +# ------------ +# +# 1. Add this script to a directory on your $fpath: +# fpath[1,0]=~/.zsh/completion/ +# mkdir -p ~/.zsh/completion/ +# cp scripts/zsh_completion/_bazel ~/.zsh/completion +# +# 2. Optionally, add the following to your .zshrc. +# zstyle ':completion:*' use-cache on +# zstyle ':completion:*' cache-path ~/.zsh/cache +# +# This way, the completion script does not have to parse Bazel's options +# repeatedly. The directory in cache-path must be created manually. +# +# 3. Restart the shell +# +# Options +# ------- +# completion:init:bazel:* cache-lifetime +# Lifetime for the completion cache (if turned on, default: 1 week) + +local curcontext="$curcontext" state line + +: ${BAZEL_COMPLETION_PACKAGE_PATH:=%workspace%} +: ${BAZEL:=bazel} +_bazel_b() { ${BAZEL} --noblock_for_lock "$@" 2>/dev/null; } + +# Default cache lifetime is 1 week +zstyle -s ":completion:${curcontext}:" cache-lifetime lifetime +if [[ -z "${lifetime}" ]]; then + lifetime=$((60*60*24*7)) +fi + +_bazel_cache_policy() { + local -a oldp + oldp=( "$1"(Nms+${lifetime}) ) + (( $#oldp )) +} + +_set_cache_policy() { + zstyle -s ":completion:*:$curcontext*" cache-policy update_policy + + if [[ -z "$update_policy" ]]; then + zstyle ":completion:$curcontext*" cache-policy _bazel_cache_policy + fi +} + +# Skips over all global arguments. After invocation, OFFSET contains the +# position of the bazel command in $words. +_adapt_subcommand_offset() { + OFFSET=2 + for w in ${words[2,-1]}; do + if [[ $w == (#b)-* ]]; then + (( OFFSET++ )) + else + return + fi + done +} + +# Retrieve the cache but also check that the value is not empty. +_bazel_safe_retrieve_cache() { + _retrieve_cache $1 && [[ ${(P)#2} -gt 0 ]] +} + +# Puts the name of the variable that contains the options for the bazel +# subcommand handed in as the first argument into the global variable +# _bazel_cmd_options. +_bazel_get_options() { + local lcmd=$1 + _bazel_cmd_options=_bazel_${lcmd}_options + _bazel_cmd_args=_bazel_${lcmd}_args + if [[ ${(P)#_bazel_cmd_options} != 0 ]]; then + return + fi + if _cache_invalid BAZEL_${lcmd}_options || _cache_invalid BAZEL_${lcmd}_args \ + || ! _bazel_safe_retrieve_cache BAZEL_${lcmd}_options ${_bazel_cmd_options} \ + || ! _retrieve_cache BAZEL_${lcmd}_args ${_bazel_cmd_args}; then + if ! eval "$(_bazel_b help completion)"; then + return + fi + local opts_var + if [[ $lcmd == "startup_options" ]]; then + opts_var="BAZEL_STARTUP_OPTIONS" + else + opts_var="BAZEL_COMMAND_${lcmd:u}_FLAGS" + fi + local -a raw_options + if ! eval "raw_options=(\${(@f)$opts_var})"; then + return + fi + + local -a option_list + for opt in $raw_options; do + case $opt in + --*"={"*) + local lst="${${opt##*"={"}%"}"}" + local opt="${opt%%=*}=" + option_list+=("${opt}:string:_values '' ${lst//,/ }") ;; + --*=path) + option_list+=("${opt%path}:path:_files") ;; + --*=label) + option_list+=("${opt%label}:target:_bazel_complete_target") ;; + --*=*) + option_list+=("${opt}:string:") ;; + *) + option_list+=("$opt") ;; + esac + done + + local -a cmd_args + local cmd_type + if eval "cmd_type=\${BAZEL_COMMAND_${lcmd:u}_ARGUMENT}" && [[ -n $cmd_type ]]; then + case $cmd_type in + label|label-*) + cmd_args+=("*::${cmd_type}:_bazel_complete_target_${cmd_type//-/_}") ;; + info-key) + cmd_args+=('1::key:_bazel_info_key') ;; + path) + cmd_args+=('1::profile:_path_files') ;; + "command|{"*"}") + local lst=${${cmd_type#"command|{"}%"}"} + cmd_args+=("1::topic:_bazel_help_topic -- ${lst//,/ }") ;; + esac + fi + + typeset -g "${_bazel_cmd_options}"="${(pj:|:)option_list[*]}" + _store_cache BAZEL_${lcmd}_options ${_bazel_cmd_options} + typeset -g "${_bazel_cmd_args}"="${(pj:|:)cmd_args[*]}" + _store_cache BAZEL_${lcmd}_args ${_bazel_cmd_args} + fi +} + +_get_build_targets() { + local pkg=$1 + local rule_re + typeset -a completions + case $target_type in + test) + rule_re=".*_test" + ;; + build) + rule_re=".*" + ;; + bin) + rule_re=".*_test|.*_binary" + ;; + esac + completions=(${$(_bazel_b query "kind(\"${rule_re}\", ${pkg}:all)" 2>/dev/null)##*:}) + if ( (( ${#completions} > 0 )) && [[ $target_type != bin ]] ); then + completions+=(all) + fi + echo ${completions[*]} +} + +# Returns all packages that match $PREFIX. PREFIX may start with //, in which +# case the workspace roots are searched. Otherwise, they are completed based on +# PWD. +_get_build_packages() { + local workspace pfx + typeset -a package_roots paths final_paths + workspace=$PWD + package_roots=(${(ps.:.)BAZEL_COMPLETION_PACKAGE_PATH}) + package_roots=(${^package_roots//\%workspace\%/$workspace}) + if [[ "${(e)PREFIX}" == //* ]]; then + pfx=${(e)PREFIX[2,-1]} + else + pfx=${(e)PREFIX} + fi + paths=(${^package_roots}/${pfx}*(/)) + for p in ${paths[*]}; do + if [[ -f ${p}/BUILD || -f ${p}/BUILD.bazel ]]; then + final_paths+=(${p##*/}:) + fi + final_paths+=(${p##*/}/) + done + echo ${final_paths[*]} +} + +_package_remove_slash() { + if [[ $KEYS == ':' && $LBUFFER == */ ]]; then + LBUFFER=${LBUFFER[1,-2]} + fi +} + +# Completion function for BUILD targets, called by the completion system. +_bazel_complete_target() { + local expl + typeset -a packages targets + if [[ "${(e)PREFIX}" != *:* ]]; then + # There is no : in the prefix, completion can be either + # a package or a target, if the cwd is a package itself. + if [[ -f $PWD/BUILD || -f $PWD/BUILD.bazel ]]; then + targets=($(_get_build_targets "")) + _description build_target expl "BUILD target" + compadd "${expl[@]}" -a targets + fi + packages=($(_get_build_packages)) + _description build_package expl "BUILD package" + # Chop of the leading path segments from the prefix for display. + compset -P '*/' + compadd -R _package_remove_slash -S '' "${expl[@]}" -a packages + else + targets=($(_get_build_targets "${${(e)PREFIX}%:*}")) + _description build_target expl "BUILD target" + # Ignore the current prefix for the upcoming completion, since we only list + # the names of the targets, not the full path. + compset -P '*:' + compadd "${expl[@]}" -a targets + fi +} + +_bazel_complete_target_label() { + typeset -g target_type=build + _bazel_complete_target +} + +_bazel_complete_target_label_test() { + typeset -g target_type=test + _bazel_complete_target +} + +_bazel_complete_target_label_bin() { + typeset -g target_type=bin + _bazel_complete_target +} + +### Actual completion commands + +_bazel() { + _adapt_subcommand_offset + if (( CURRENT - OFFSET > 0 )); then + # Remember the subcommand name, stored globally so we can access it + # from any subsequent function + cmd=${words[OFFSET]//-/_} + + # Set the context for the subcommand. + curcontext="${curcontext%:*:*}:bazel-$cmd:" + _set_cache_policy + + # Narrow the range of words we are looking at to exclude cmd + # name and any leading options + (( CURRENT = CURRENT - OFFSET + 1 )) + shift $((OFFSET - 1)) words + # Run the completion for the subcommand + _bazel_get_options $cmd + _arguments : \ + ${(Pps:|:)_bazel_cmd_options} \ + ${(Pps:|:)_bazel_cmd_args} + else + _set_cache_policy + # Start special handling for global options, + # which can be retrieved by calling + # $ bazel help startup_options + _bazel_get_options startup_options + _arguments : \ + ${(Pps:|:)_bazel_cmd_options} \ + "*:commands:_bazel_commands" + fi + return +} + +_get_commands() { + # bazel_cmd_list is a global (g) array (a) + typeset -ga _bazel_cmd_list + # Use `bazel help` instead of `bazel help completion` to get command + # descriptions. + if _bazel_cmd_list=("${(@f)$(_bazel_b help | awk ' +/Available commands/ { command=1; } +/ [-a-z]+[ \t]+.+/ { if (command) { printf "%s:", $1; for (i=2; i<=NF; i++) printf "%s ", $i; print "" } } +/^$/ { command=0; }')}"); then + _store_cache BAZEL_commands _bazel_cmd_list + fi +} + +# Completion function for bazel subcommands, called by the completion system. +_bazel_commands() { + if [[ ${#_bazel_cmd_list} == 0 ]]; then + if _cache_invalid BAZEL_commands \ + || ! _bazel_safe_retrieve_cache BAZEL_commands _bazel_cmd_list; then + _get_commands + fi + fi + + _describe -t bazel-commands 'Bazel command' _bazel_cmd_list +} + +# Completion function for bazel help options, called by the completion system. +_bazel_help_topic() { + if [[ ${#_bazel_cmd_list} == 0 ]]; then + if _cache_invalid BAZEL_commands \ + || ! _bazel_safe_retrieve_cache BAZEL_commands _bazel_cmd_list; then + _get_commands + fi + fi + + while [[ $# -gt 0 ]]; do + if [[ $1 == -- ]]; then + shift + break + fi + shift + done + _bazel_help_list=($@) + _bazel_help_list+=($_bazel_cmd_list) + _describe -t bazel-help 'Help topic' _bazel_help_list +} + +# Completion function for bazel info keys, called by the completion system. +_bazel_info_key() { + if [[ ${#_bazel_info_keys_list} == 0 ]]; then + if _cache_invalid BAZEL_info_keys \ + || ! _bazel_safe_retrieve_cache BAZEL_info_keys _bazel_info_keys_list; then + typeset -ga _bazel_info_keys_list + # Use `bazel help` instead of `bazel help completion` to get info-key + # descriptions. + if _bazel_info_keys_list=("${(@f)$(_bazel_b help info-keys | awk ' + { printf "%s:", $1; for (i=2; i<=NF; i++) printf "%s ", $i; print "" }')}"); then + _store_cache BAZEL_info_keys _bazel_info_keys_list + fi + fi + fi + _describe -t bazel-info 'Key' _bazel_info_keys_list +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/twitch b/modules/mixins/dotfiles/config/zsh/plugins/twitch @@ -0,0 +1,25 @@ +#!/bin/zsh + +TWITCH_CHANNELS_FILE="$HOME/.config/twitch/channels" + +tww() { + local channel="${1?Usage: tww <channel>}" + mpv "https://twitch.tv/$channel" --no-terminal --no-resume-playback & + disown +} + +twe() { + "$EDITOR" "$TWITCH_CHANNELS_FILE" +} + +_twitch_completion() { + local -a channels + if [[ -f "$TWITCH_CHANNELS_FILE" ]]; then + while IFS= read -r line; do + channels+=("${line%% *}") + done <"$TWITCH_CHANNELS_FILE" + _describe 'twitch channels' channels + fi +} + +compdef _twitch_completion tww diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zoxide b/modules/mixins/dotfiles/config/zsh/plugins/zoxide @@ -0,0 +1,143 @@ +# shellcheck shell=bash + +# ============================================================================= +# +# Utility functions for zoxide. +# + +# pwd based on the value of _ZO_RESOLVE_SYMLINKS. +function __zoxide_pwd() { + \builtin pwd -L +} + +# cd + custom logic based on the value of _ZO_ECHO. +function __zoxide_cd() { + # shellcheck disable=SC2164 + \builtin cd -- "$@" +} + +# ============================================================================= +# +# Hook configuration for zoxide. +# + +# Hook to add new entries to the database. +function __zoxide_hook() { + # shellcheck disable=SC2312 + \command zoxide add -- "$(__zoxide_pwd)" +} + +# Initialize hook. +\builtin typeset -ga precmd_functions +\builtin typeset -ga chpwd_functions +# shellcheck disable=SC2034,SC2296 +precmd_functions=("${(@)precmd_functions:#__zoxide_hook}") +# shellcheck disable=SC2034,SC2296 +chpwd_functions=("${(@)chpwd_functions:#__zoxide_hook}") +chpwd_functions+=(__zoxide_hook) + +# Report common issues. +function __zoxide_doctor() { + [[ ${_ZO_DOCTOR:-1} -ne 0 ]] || return 0 + [[ ${chpwd_functions[(Ie)__zoxide_hook]:-} -eq 0 ]] || return 0 + + _ZO_DOCTOR=0 + \builtin printf '%s\n' \ + 'zoxide: detected a possible configuration issue.' \ + 'Please ensure that zoxide is initialized right at the end of your shell configuration file (usually ~/.zshrc).' \ + '' \ + 'If the issue persists, consider filing an issue at:' \ + 'https://github.com/ajeetdsouza/zoxide/issues' \ + '' \ + 'Disable this message by setting _ZO_DOCTOR=0.' \ + '' >&2 +} + +# ============================================================================= +# +# When using zoxide with --no-cmd, alias these internal functions as desired. +# + +# Jump to a directory using only keywords. +function __zoxide_z() { + __zoxide_doctor + if [[ "$#" -eq 0 ]]; then + __zoxide_cd ~ + elif [[ "$#" -eq 1 ]] && { [[ -d "$1" ]] || [[ "$1" = '-' ]] || [[ "$1" =~ ^[-+][0-9]$ ]]; }; then + __zoxide_cd "$1" + elif [[ "$#" -eq 2 ]] && [[ "$1" = "--" ]]; then + __zoxide_cd "$2" + else + \builtin local result + # shellcheck disable=SC2312 + result="$(\command zoxide query --exclude "$(__zoxide_pwd)" -- "$@")" && __zoxide_cd "${result}" + fi +} + +# Jump to a directory using interactive search. +function __zoxide_zi() { + __zoxide_doctor + \builtin local result + result="$(\command zoxide query --interactive -- "$@")" && __zoxide_cd "${result}" +} + +# ============================================================================= +# +# Commands for zoxide. Disable these using --no-cmd. +# + +function z() { + __zoxide_z "$@" +} + +function zi() { + __zoxide_zi "$@" +} + +# Completions. +if [[ -o zle ]]; then + __zoxide_result='' + + function __zoxide_z_complete() { + # Only show completions when the cursor is at the end of the line. + # shellcheck disable=SC2154 + [[ "${#words[@]}" -eq "${CURRENT}" ]] || return 0 + + if [[ "${#words[@]}" -eq 2 ]]; then + # Show completions for local directories. + _cd -/ + + elif [[ "${words[-1]}" == '' ]]; then + # Show completions for Space-Tab. + # shellcheck disable=SC2086 + __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd || \builtin true)" --interactive -- ${words[2,-1]})" || __zoxide_result='' + + # Set a result to ensure completion doesn't re-run + compadd -Q "" + + # Bind '\e[0n' to helper function. + \builtin bindkey '\e[0n' '__zoxide_z_complete_helper' + # Sends query device status code, which results in a '\e[0n' being sent to console input. + \builtin printf '\e[5n' + + # Report that the completion was successful, so that we don't fall back + # to another completion function. + return 0 + fi + } + + function __zoxide_z_complete_helper() { + if [[ -n "${__zoxide_result}" ]]; then + # shellcheck disable=SC2034,SC2296 + BUFFER="z ${(q-)__zoxide_result}" + __zoxide_result='' + \builtin zle reset-prompt + \builtin zle accept-line + else + \builtin zle reset-prompt + fi + } + \builtin zle -N __zoxide_z_complete_helper + + [[ "${+functions[compdef]}" -ne 0 ]] && \compdef __zoxide_z_complete z +fi diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.editorconfig b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.editorconfig @@ -0,0 +1,10 @@ +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[*.md] +indent_style = space diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.travis.yml b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.travis.yml @@ -0,0 +1,35 @@ +dist: trusty +sudo: required + +language: generic + +env: + - ZSH_VERSION=5.3.1 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.3.1/zsh-5.3.1.tar.xz + - ZSH_VERSION=5.2 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.2/zsh-5.2.tar.xz + - ZSH_VERSION=5.1.1 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.1.1/zsh-5.1.1.tar.xz + - ZSH_VERSION=5.0.8 URL=https://downloads.sourceforge.net/project/zsh/zsh/5.0.8/zsh-5.0.8.tar.gz + +addons: + apt: + packages: + - build-essential + +before_install: + - export LOCAL="$(mktemp --directory --tmpdir=${TMPDIR:/tmp} local.bin.XXXXXX)" + - wget $URL + - tar -xf zsh-$ZSH_VERSION.tar.* + - cd zsh-$ZSH_VERSION + - ./configure --prefix=$LOCAL + - make + - make install + - cd - + - export PATH="$LOCAL/bin:$HOME/bin:$PATH" + +before_script: + - mkdir -p ~/bin + - curl -L https://github.com/zunit-zsh/zunit/releases/download/v0.8.1/zunit > ~/bin/zunit + - curl -L https://raw.githubusercontent.com/molovo/revolver/master/revolver > ~/bin/revolver + - chmod u+x ~/bin/{revolver,zunit} + +script: + - zunit --verbose diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.zunit.yml b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/.zunit.yml @@ -0,0 +1,8 @@ +tap: false +directories: + tests: tests + output: tests/_output + support: tests/_support +time_limit: 0 +fail_fast: false +allow_risky: false diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/LICENSE b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016-24 Henrik Lissner. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/README.md b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/README.md @@ -0,0 +1,249 @@ +[![Made with Doom Emacs](https://img.shields.io/badge/Made_with-Doom_Emacs-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white)](https://github.com/hlissner/doom-emacs) +[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](./LICENSE) +![ZSH 5.0.2+](https://img.shields.io/badge/zsh-v5.0.2-orange.svg?style=flat-square) +[![Build Status](https://img.shields.io/travis/hlissner/zsh-autopair/master.svg?label=master&style=flat-square)](https://travis-ci.org/hlissner/zsh-autopair) + +# zsh-autopair +A simple plugin that auto-closes, deletes and skips over matching delimiters in +zsh intelligently. Hopefully. + +> NOTE: zsh-autopair is untested for versions of Zsh below 5.0.2. Please report +> any issues you have in earlier versions! + +Specifically, zsh-autopair does 5 things for you: + +1. It inserts matching pairs (by default, that means brackets, quotes and + spaces): + + e.g. `echo |` => <kbd>"</kbd> => `echo "|"` + +2. It skips over matched pairs: + + e.g. `cat ./*.{py,rb|}` => <kbd>}</kbd> => `cat ./*.{py,rb}|` + +3. It auto-deletes pairs on backspace: + + e.g. `git commit -m "|"` => <kbd>backspace</kbd> => `git commit -m |` + +4. And does all of the above only when it makes sense to do so. e.g. when the + pair is balanced and when the cursor isn't next to a boundary character: + + e.g. `echo "|""` => <kbd>backspace</kbd> => `echo |""` (doesn't aggressively eat up too many quotes) + +5. Spaces between brackets are expanded and contracted. + + e.g. `echo [|]` => <kbd>space</kbd> => `echo [ | ]` => <kbd>backspace</kbd> => `echo [|]` + + +<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc --> +**Table of Contents** + +- [Install](#install) + - [Antigen](#antigen) + - [zgen](#zgen) + - [zplug](#zplug) + - [Hombrew](#homebrew) + - [Oh My Zsh](#oh-my-zsh) +- [Configuration](#configuration) + - [Adding/Removing pairs](#addingremoving-pairs) +- [Troubleshooting & compatibility issues](#troubleshooting--compatibility-issues) + - [zgen & prezto compatibility](#zgen--prezto-compatibility) + - [text on right-side of cursor interfere with completion](#text-on-right-side-of-cursor-interfere-with-completion) + - [zsh-autopair & isearch?](#zsh-autopair--isearch) + - [Midnight Commander](#midnight-commander) +- [Other resources](#other-resources) + +<!-- markdown-toc end --> + +## Install +Download and source `autopair.zsh` + +```bash +if [[ ! -d ~/.zsh-autopair ]]; then + git clone https://github.com/hlissner/zsh-autopair ~/.zsh-autopair +fi + +source ~/.zsh-autopair/autopair.zsh +autopair-init +``` + +### Hoembrew +`brew install zsh-autopair` + +``` bash +# Add to .zshrc +source $HOMEBREW_PREFIX/share/zsh-autopair/autopair.zsh +``` + +### Antigen +`antigen bundle hlissner/zsh-autopair` + +### zgen +```bash +if ! zgen saved; then + echo "Creating a zgen save" + + # ... other plugins + zgen load hlissner/zsh-autopair + + zgen save +fi +``` + +### zplug +Load autopair _after compinit_, otherwise, the plugin won't work. +```bash +zplug "hlissner/zsh-autopair", defer:2 +``` + +### Homebrew +For Homebrew users, you can install it through the following command +```shell +brew install zsh-autopair +``` +Then source it in your `.zshrc` +```shell +source $(brew --prefix)/share/zsh-autopair/autopair.zsh +``` + +### Oh My Zsh +1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`) + + ```sh + git clone https://github.com/hlissner/zsh-autopair ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autopair + ``` + +2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`): + + ```sh + plugins=( + # other plugins... + zsh-autopair + ) + ``` + +3. Start a new terminal session. + +## Configuration +zsh-autopair sets itself up. You can prevent this by setting +`AUTOPAIR_INHIBIT_INIT`. + +**Options:** +* `AUTOPAIR_BETWEEN_WHITESPACE` (default: blank): if set, regardless of whether + delimiters are unbalanced or do not meet a boundary check, pairs will be + auto-closed if surrounded by whitespace, BOL or EOL. +* `AUTOPAIR_INHIBIT_INIT` (default: blank): if set, autopair will not + automatically set up keybinds. [Check out the initialization + code](autopair.zsh#L118) if you want to know what it does. +* `AUTOPAIR_PAIRS` (default: ``('`' '`' "'" "'" '"' '"' '{' '}' '[' ']' '(' ')' + ' ' ' ')``): An associative array that map pairs. Only one-character pairs are + supported. To modify this, see the "Adding/Removing pairs" section. +* `AUTOPAIR_LBOUNDS`/`AUTOPAIR_RBOUNDS` (default: see below): Associative lists + of regex character groups dictating the 'boundaries' for autopairing depending + on the delimiter. These are their default values: + + ```bash + AUTOPAIR_LBOUNDS=(all '[.:/\!]') + AUTOPAIR_LBOUNDS+=(quotes '[]})a-zA-Z0-9]') + AUTOPAIR_LBOUNDS+=(spaces '[^{([]') + AUTOPAIR_LBOUNDS+=(braces '') + AUTOPAIR_LBOUNDS+=('`' '`') + AUTOPAIR_LBOUNDS+=('"' '"') + AUTOPAIR_LBOUNDS+=("'" "'") + + AUTOPAIR_RBOUNDS=(all '[[{(<,.:?/%$!a-zA-Z0-9]') + AUTOPAIR_RBOUNDS+=(quotes '[a-zA-Z0-9]') + AUTOPAIR_RBOUNDS+=(spaces '[^]})]') + AUTOPAIR_RBOUNDS+=(braces '') + ``` + + For example, if `$AUTOPAIR_LBOUNDS[braces]="[a-zA-Z]"`, then braces (`{([`) won't be + autopaired if the cursor follows an alphabetical character. + + Individual delimiters can be used too. Setting `$AUTOPAIR_RBOUNDS['{']="[0-9]"` will + cause <kbd>{</kbd> specifically to not be autopaired when the cursor precedes a number. + +### Adding/Removing pairs +You can change the designated pairs in zsh-autopair by modifying the +`AUTOPAIR_PAIRS` envvar. This can be done _before_ initialization like so: + +``` sh +typeset -gA AUTOPAIR_PAIRS +AUTOPAIR_PAIRS+=("<" ">") +``` + +Or after initialization; however, you'll have to bind keys to `autopair-insert` +manually: + +```sh +AUTOPAIR_PAIRS+=("<" ">") +bindkey "<" autopair-insert +# prevents breakage in isearch +bindkey -M isearch "<" self-insert +``` + +To _remove_ pairs, use `unset 'AUTOPAIR_PAIRS[<]'`. Unbinding is optional. + +## Troubleshooting & compatibility issues +### zgen & prezto compatibility +Prezto's Editor module is known to reset autopair's bindings. A workaround is to +_defer autopair from initializing_ (by setting `AUTOPAIR_INHIBIT_INIT=1`) and +initialize it manually (by calling `autopair-init`): + +``` sh +source "$HOME/.zgen/zgen.zsh" + +# Add this +AUTOPAIR_INHIBIT_INIT=1 + +if ! zgen saved; then + zgen prezto + # ... + zgen load hlissner/zsh-autopair 'autopair.zsh' + #... + zgen save +fi + +# And this +autopair-init +``` + +### text on right-side of cursor interfere with completion +Bind <kbd>Tab</kbd> to `expand-or-complete-prefix` and completion will ignore +what's to the right of cursor: + +`bindkey '^I' expand-or-complete-prefix` + +This has the unfortunate side-effect of overwriting whatever's right of the +cursor, however. + +### zsh-autopair & isearch? +zsh-autopair silently disables itself in isearch, as the two are incompatible. + +### Midnight Commander +MC hangs when zsh-autopair tries to bind the space key. This also breaks the MC +subshell. + +Disable space expansion to work around this: `unset 'AUTOPAIR_PAIRS[ ]'` + +## Other resources +* Works wonderfully with [zsh-syntax-highlight] and + `ZSH_HIGHLIGHT_HIGHLIGHTERS+=brackets`, but zsh-syntax-highlight must be + loaded *after* zsh-autopair. +* Mixes well with these vi-mode zsh modules: [surround], [select-quoted], and + [select-bracketed] (they're built into zsh as of zsh-5.0.8) +* Other relevant repositories of mine: + + [dotfiles] + + [emacs.d] + + [vimrc] + + [zshrc] + + +[dotfiles]: https://github.com/hlissner/dotfiles +[vimrc]: https://github.com/hlissner/.vim +[emacs.d]: https://github.com/hlissner/doom-emacs +[zshrc]: https://github.com/hlissner/dotfiles/blob/master/config/zsh/.zshrc +[zsh-syntax-highlighting]: https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters/pattern.md +[surround]: https://github.com/zsh-users/zsh/blob/master/Functions/Zle/surround +[select-quoted]: https://github.com/zsh-users/zsh/blob/master/Functions/Zle/select-quoted +[select-bracketed]: https://github.com/zsh-users/zsh/blob/master/Functions/Zle/select-bracketed diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/autopair.plugin.zsh b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/autopair.plugin.zsh @@ -0,0 +1,4 @@ +# <https://github.com/zdharma-continuum/Zsh-100-Commits-Club/blob/master/Zsh-Plugin-Standard.adoc> +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" +source "${0:A:h}/autopair.zsh" diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/autopair.zsh b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/autopair.zsh @@ -0,0 +1,227 @@ +#!/usr/bin/env zsh + +AUTOPAIR_INHIBIT_INIT=${AUTOPAIR_INHIBIT_INIT:-} +AUTOPAIR_BETWEEN_WHITESPACE=${AUTOPAIR_BETWEEN_WHITESPACE:-} +AUTOPAIR_SPC_WIDGET=${AUTOPAIR_SPC_WIDGET:-"$(bindkey " " | cut -c5-)"} +AUTOPAIR_BKSPC_WIDGET=${AUTOPAIR_BKSPC_WIDGET:-"$(bindkey "^?" | cut -c6-)"} +AUTOPAIR_DELWORD_WIDGET=${AUTOPAIR_DELWORD_WIDGET:-"$(bindkey "^w" | cut -c6-)"} + +typeset -gA AUTOPAIR_PAIRS +AUTOPAIR_PAIRS=('`' '`' "'" "'" '"' '"' '{' '}' '[' ']' '(' ')' ' ' ' ') + +typeset -gA AUTOPAIR_LBOUNDS +AUTOPAIR_LBOUNDS=(all '[.:/\!]') +AUTOPAIR_LBOUNDS+=(quotes '[]})a-zA-Z0-9]') +AUTOPAIR_LBOUNDS+=(spaces '[^{([]') +AUTOPAIR_LBOUNDS+=(braces '') +AUTOPAIR_LBOUNDS+=('`' '`') +AUTOPAIR_LBOUNDS+=('"' '"') +AUTOPAIR_LBOUNDS+=("'" "'") + +typeset -gA AUTOPAIR_RBOUNDS +AUTOPAIR_RBOUNDS=(all '[[{(<,.:?/%$!a-zA-Z0-9]') +AUTOPAIR_RBOUNDS+=(quotes '[a-zA-Z0-9]') +AUTOPAIR_RBOUNDS+=(spaces '[^]})]') +AUTOPAIR_RBOUNDS+=(braces '') + + +### Helpers ############################ + +# Returns the other pair for $1 (a char), blank otherwise +_ap-get-pair() { + if [[ -n $1 ]]; then + echo ${AUTOPAIR_PAIRS[$1]} + elif [[ -n $2 ]]; then + local i + for i in ${(@k)AUTOPAIR_PAIRS}; do + [[ $2 == ${AUTOPAIR_PAIRS[$i]} ]] && echo $i && break + done + fi +} + +# Return 0 if cursor's surroundings match either regexp: $1 (left) or $2 (right) +_ap-boundary-p() { + [[ -n $1 && $LBUFFER =~ "$1$" ]] || [[ -n $2 && $RBUFFER =~ "^$2" ]] +} + +# Return 0 if the surrounding text matches any of the AUTOPAIR_*BOUNDS regexps +_ap-next-to-boundary-p() { + local -a groups + groups=(all) + case $1 in + \'|\"|\`) groups+=quotes ;; + \{|\[|\(|\<) groups+=braces ;; + " ") groups+=spaces ;; + esac + groups+=$1 + local group + for group in $groups; do + _ap-boundary-p ${AUTOPAIR_LBOUNDS[$group]} ${AUTOPAIR_RBOUNDS[$group]} && return 0 + done + return 1 +} + +# Return 0 if there are the same number of $1 as there are $2 (chars; a +# delimiter pair) in the buffer. +_ap-balanced-p() { + local lbuf="${LBUFFER//\\$1}" + local rbuf="${RBUFFER//\\$2}" + local llen="${#lbuf//[^$1]}" + local rlen="${#rbuf//[^$2]}" + if (( rlen == 0 && llen == 0 )); then + return 0 + elif [[ $1 == $2 ]]; then + if [[ $1 == " " ]]; then + # Silence WARN_CREATE_GLOBAL errors + local match= + local mbegin= + local mend= + # Balancing spaces is unnecessary. If there is at least one space on + # either side of the cursor, it is considered balanced. + [[ $LBUFFER =~ "[^'\"]([ ]+)$" && $RBUFFER =~ "^${match[1]}" ]] && return 0 + return 1 + elif (( llen == rlen || (llen + rlen) % 2 == 0 )); then + return 0 + fi + else + local l2len="${#lbuf//[^$2]}" + local r2len="${#rbuf//[^$1]}" + local ltotal=$((llen - l2len)) + local rtotal=$((rlen - r2len)) + + (( ltotal < 0 )) && ltotal=0 + (( ltotal < rtotal )) && return 1 + return 0 + fi + return 1 +} + +# Return 0 if the last keypress can be auto-paired. +_ap-can-pair-p() { + local rchar="$(_ap-get-pair $KEYS)" + + [[ -n $rchar ]] || return 1 + + if [[ $rchar != " " ]]; then + # Force pair if surrounded by space/[BE]OL, regardless of + # boundaries/balance + [[ -n $AUTOPAIR_BETWEEN_WHITESPACE && \ + $LBUFFER =~ "(^|[ ])$" && \ + $RBUFFER =~ "^($|[ ])" ]] && return 0 + + # Don't pair quotes if the delimiters are unbalanced + ! _ap-balanced-p $KEYS $rchar && return 1 + elif [[ $RBUFFER =~ "^[ ]*$" ]]; then + # Don't pair spaces surrounded by whitespace + return 1 + fi + + # Don't pair when in front of characters that likely signify the start of a + # string, path or undesirable boundary. + _ap-next-to-boundary-p $KEYS $rchar && return 1 + + return 0 +} + +# Return 0 if the adjacent character (on the right) can be safely skipped over. +_ap-can-skip-p() { + if [[ -z $LBUFFER ]]; then + return 1 + elif [[ $1 == $2 ]]; then + if [[ $1 == " " ]]; then + return 1 + elif ! _ap-balanced-p $1 $2; then + return 1 + fi + fi + if ! [[ -n $2 && ${RBUFFER[1]} == $2 && ${LBUFFER[-1]} != '\' ]]; then + return 1 + fi + return 0 +} + +# Return 0 if the adjacent character (on the right) can be safely deleted. +_ap-can-delete-p() { + local lchar="${LBUFFER[-1]}" + local rchar="$(_ap-get-pair $lchar)" + ! [[ -n $rchar && ${RBUFFER[1]} == $rchar ]] && return 1 + if [[ $lchar == $rchar ]]; then + if [[ $lchar == ' ' && ( $LBUFFER =~ "[^{([] +$" || $RBUFFER =~ "^ +[^]})]" ) ]]; then + # Don't collapse spaces unless in delimiters + return 1 + elif ! _ap-balanced-p $lchar $rchar; then + return 1 + fi + fi + return 0 +} + +# Insert $1 and add $2 after the cursor +_ap-self-insert() { + LBUFFER+=$1 + RBUFFER="$2$RBUFFER" +} + + +### Widgets ############################ + +autopair-insert() { + local rchar="$(_ap-get-pair $KEYS)" + if [[ $KEYS == (\'|\"|\`| ) ]] && _ap-can-skip-p $KEYS $rchar; then + zle forward-char + elif _ap-can-pair-p; then + _ap-self-insert $KEYS $rchar + elif [[ $rchar == " " ]]; then + zle ${AUTOPAIR_SPC_WIDGET:-self-insert} + else + zle self-insert + fi +} + +autopair-close() { + if _ap-can-skip-p "$(_ap-get-pair "" $KEYS)" $KEYS; then + zle forward-char + else + zle self-insert + fi +} + +autopair-delete() { + _ap-can-delete-p && RBUFFER=${RBUFFER:1} + zle ${AUTOPAIR_BKSPC_WIDGET:-backward-delete-char} +} + +autopair-delete-word() { + _ap-can-delete-p && RBUFFER=${RBUFFER:1} + zle ${AUTOPAIR_DELWORD_WIDGET:-backward-delete-word} +} + + +### Initialization ##################### + +autopair-init() { + zle -N autopair-insert + zle -N autopair-close + zle -N autopair-delete + zle -N autopair-delete-word + + local p + for p in ${(@k)AUTOPAIR_PAIRS}; do + bindkey "$p" autopair-insert + bindkey -M isearch "$p" self-insert + + local rchar="$(_ap-get-pair $p)" + if [[ $p != $rchar ]]; then + bindkey "$rchar" autopair-close + bindkey -M isearch "$rchar" self-insert + fi + done + + bindkey "^?" autopair-delete + bindkey "^h" autopair-delete + bindkey "^w" autopair-delete-word + bindkey -M isearch "^?" backward-delete-char + bindkey -M isearch "^h" backward-delete-char + bindkey -M isearch "^w" backward-delete-word +} +[[ -n $AUTOPAIR_INHIBIT_INIT ]] || autopair-init diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/_support/bootstrap b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/_support/bootstrap @@ -0,0 +1,15 @@ +#!/usr/bin/env zsh +source autopair.zsh +export KEYS= +export LBUFFER= +export RBUFFER= + +assert_true() { + run $@ + assert $state equals 0 +} + +assert_false() { + run $@ + assert $state equals 1 +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/balanced-p.zunit b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/balanced-p.zunit @@ -0,0 +1,16 @@ +#!/usr/bin/env zunit +@test 'basic boundary tests' { + LBUFFER="abc" + RBUFFER="123" + assert_false _ap-boundary-p " " " " + assert_true _ap-boundary-p "[^3]" "[^a]" + assert_false _ap-boundary-p "[^c]" "[^1]" + assert_true _ap-boundary-p "c" " " + assert_true _ap-boundary-p " " "1" +} + +@test 'no boundary on blank line' { + LBUFFER= + RBUFFER= + assert_false _ap-next-to-boundary-p "{" +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-delete-p.zunit b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-delete-p.zunit @@ -0,0 +1,24 @@ +#!/usr/bin/env zunit +@test 'delete if next to space and pair' { + LBUFFER="[ " RBUFFER=" ]" assert_true _ap-can-delete-p +} + +@test 'delete if next to homogeneous counter-pair' { + LBUFFER="'" RBUFFER="'" assert_true _ap-can-delete-p +} + +@test 'delete if next to heterogeneous counter-pair' { + LBUFFER="(" RBUFFER=")" assert_true _ap-can-delete-p +} + +@test 'do not delete if at eol' { + LBUFFER="'" assert_false _ap-can-delete-p +} + +@test 'do not delete if within too many spaces' { + LBUFFER="[ " RBUFFER=" ]" assert_false _ap-can-delete-p +} + +@test 'do not delete if only next to space' { + LBUFFER=" " RBUFFER=" " assert_false _ap-can-delete-p +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-pair-p.zunit b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-pair-p.zunit @@ -0,0 +1,59 @@ +#!/usr/bin/env zunit +@test 'pair if blank line' { + KEYS="'" LBUFFER="" RBUFFER="" assert_true _ap-can-pair-p +} + +@test 'pair if next to balanced delimiter' { # {{|}} + KEYS="{" LBUFFER="{" RBUFFER="}" assert_true _ap-can-pair-p +} + +@test 'pair space if next to brackets' { # { | } + KEYS=" " + LBUFFER="{" RBUFFER="}" assert_true _ap-can-pair-p + LBUFFER="[" RBUFFER="]" assert_true _ap-can-pair-p + LBUFFER="(" RBUFFER=")" assert_true _ap-can-pair-p +} + +@test 'pair brackets at the end of a word' { # abc{|} + KEYS='{' LBUFFER="hello" assert_true _ap-can-pair-p +} + +@test 'do not pair brackets at the beginning of a word' { # {|abc + KEYS='{' RBUFFER="hello" assert_false _ap-can-pair-p +} + +@test 'do not pair quotes next to a word' { + KEYS="'" + LBUFFER="hello" assert_false _ap-can-pair-p # abc"| + RBUFFER="hello" assert_false _ap-can-pair-p # "|abc +} + +@test 'do not pair the same quotes from inside quotes' { # ""|" + KEYS='"' LBUFFER='"' RBUFFER='"' assert_false _ap-can-pair-p +} + +@test 'do not pair if delimiter is invalid' { + KEYS="<" LBUFFER="<" RBUFFER=">" assert_false _ap-can-pair-p +} + +@test 'do not pair if next to unbalanced delimiter' { # {|} + KEYS="{" LBUFFER="" RBUFFER="}" assert_false _ap-can-pair-p +} + +@test 'do not pair if next to unbalanced delimiter after space' { # {| } + AUTOPAIR_BETWEEN_WHITESPACE= + KEYS="{" LBUFFER="" RBUFFER=" }" assert_false _ap-can-pair-p + KEYS="{" LBUFFER="" RBUFFER=" }" assert_false _ap-can-pair-p + KEYS="{" LBUFFER=" " RBUFFER=" }" assert_false _ap-can-pair-p +} + +@test 'do not pair space if next to non-brackets/spaces' { + KEYS=" " + LBUFFER="'" RBUFFER="'" assert_false _ap-can-pair-p # ' |' + LBUFFER="abc" RBUFFER="xyz" assert_false _ap-can-pair-p # abc |xyz' + LBUFFER="[ " RBUFFER=" ]" assert_false _ap-can-pair-p # [ | ] +} + +@test 'AUTOPAIR_BETWEEN_WHITESPACE=1' { + AUTOPAIR_BETWEEN_WHITESPACE=1 KEYS='{' LBUFFER=" " RBUFFER=" }" assert_true _ap-can-pair-p +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-skip-p.zunit b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/can-skip-p.zunit @@ -0,0 +1,25 @@ +#!/usr/bin/env zunit + +@test 'fail skip-check on blank line' { + LBUFFER='' RBUFFER='' assert_false _ap-can-skip-p '{' '}' +} + +@test 'fail skip-check on wrong pair' { + LBUFFER='"' RBUFFER='"' assert_false _ap-can-skip-p '{' '}' +} + +@test 'skip if next to homogeneous counter-pair' { + LBUFFER='"' RBUFFER='"' assert_true _ap-can-skip-p '"' '"' +} + +@test 'skip if next to heterogeneous counter-pair' { + LBUFFER='{' RBUFFER='}' assert_true _ap-can-skip-p '{' '}' +} + +@test 'do not skip if next to unbalanced, homogeneous counter-pair' { + LBUFFER='' RBUFFER='"' assert_false _ap-can-skip-p '"' '"' +} + +@test 'do not skip if next to unbalanced, heterogeneous counter-pair' { + LBUFFER='' RBUFFER='}' assert_false _ap-can-skip-p '{' '}' +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/get-pair.zunit b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/tests/get-pair.zunit @@ -0,0 +1,26 @@ +#!/usr/bin/env zunit +@test 'existing pair' { + assert $(_ap-get-pair "{") same_as "}" +} + +@test 'existing right-pair' { + assert $(_ap-get-pair "" "}") same_as "{" +} + +@test 'non-existent pair' { + assert $(_ap-get-pair "<") same_as "" +} + +@test 'non-existent right-pair' { + assert $(_ap-get-pair "" ">") same_as "" +} + +@test 'all default pairs' { + assert '"' in ${(@k)AUTOPAIR_PAIRS} + assert "'" in ${(@k)AUTOPAIR_PAIRS} + assert '`' in ${(@k)AUTOPAIR_PAIRS} + assert '{' in ${(@k)AUTOPAIR_PAIRS} + assert '[' in ${(@k)AUTOPAIR_PAIRS} + assert '(' in ${(@k)AUTOPAIR_PAIRS} + assert ' ' in ${(@k)AUTOPAIR_PAIRS} +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/zsh-autopair.plugin.zsh b/modules/mixins/dotfiles/config/zsh/plugins/zsh-autopair/zsh-autopair.plugin.zsh @@ -0,0 +1,4 @@ +# <https://github.com/zdharma-continuum/Zsh-100-Commits-Club/blob/master/Zsh-Plugin-Standard.adoc> +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" +source "${0:A:h}/autopair.zsh" diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/LICENSE b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Tom Hinton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/README.org b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/README.org @@ -0,0 +1,182 @@ +#+TITLE:ZSH History Database + +* News +- 13/10/21 :: Thanks to Aloxaf some subshell invocations have been removed which should make things quicker. Thanks to m42e (again) ~histdb-sync~ uses the remote database IDs as the canonical ones which should make syncing a bit less thrashy. Thanks to Chad Transtrum we use ~builtin which~ rather than ~which~, for systems which have an unusual which (?!), and an improvement to examples below in the README. Thanks to Klaus Ethgen the invocation of ~sqlite3~ is now unaffected by some potential confusions in your sqlite rc files. +- 30/06/20 :: Thanks to rolandwalker, add-zsh-hook is used so histdb is a better citizen. + Thanks to GreenArchon and phiresky the sqlite helper process is terminated on exit better, and the WAL is truncated before doing histdb sync. This should make things behave a bit better. Thanks to gabreal (and others, I think), some things have been changed to ~declare -ga~ which helps when using antigen or somesuch? Thanks to sheperdjerred and fuero there is now a file which might make antigen and oh-my-zsh work. + + There is a *breaking change*, which is that you no longer need to ~add-zsh-hook precmd histdb-update-outcome~ in your rc file. This now happens when you source ~sqlite-history.zsh~. +- 11/03/20 :: Thanks to phiresky (https://github.com/phiresky) history appends within a shell session are performed through a single long-running sqlite process rather than by starting a new process per history append. This reduces contention between shells that are trying to write, as sqlite always fsyncs on exit. +- 29/05/19 :: Thanks to Matthias Bilger (https://github.com/m42e/) a bug has been removed which would have broken the database if the vacuum command were used. Turns out, you can't use rowid as a foreign key unless you've given it a name. As a side-effect your database will need updating, in a non-backwards compatible way, so you'll need to update on all your installations at once if you share a history file. + Also, it's not impossible that this change will make a problem for someone somewhere, so be careful with this update. + + Also thanks to Matthias, the exit status of long-running commands is handled better. +- 05/04/18 :: I've done a bit of work to make a replacement reverse-isearch function, which is in a usable state now. + + If you want to use it, see the [[Reverse isearch]] section below which now covers it. + +- 09/09/17 :: If you have already installed and you want to get the right timings in the database, see the installation section again. Fix to issue #18. + +* What is this + +This is a small bit of zsh code that stores your history into a sqlite3 database. +It improves on the normal history by storing, for each history command: + +- The start and stop times of the command +- The working directory where the command was run +- The hostname of the machine +- A unique per-host session ID, so history from several sessions is not confused +- The exit status of the command + +It is also possible to merge multiple history databases together without conflict, so long as all your machines have different hostnames. + +* Installation + +You will need ~sqlite3~ and the usual coreutils commands installed on your ~PATH~. +To load and activate history recording you need to source ~sqlite-history.zsh~ from your shell in your zsh startup files. + +Example for installing in ~$HOME/.oh-my-zsh/custom/plugins/zsh-histdb~ (note that ~oh-my-zsh~ is not required): + +#+BEGIN_SRC zsh +mkdir -p $HOME/.oh-my-zsh/custom/plugins/ +git clone https://github.com/larkery/zsh-histdb $HOME/.oh-my-zsh/custom/plugins/zsh-histdb +#+END_SRC + +Add this to your ~$HOME/.zshrc~: + +#+BEGIN_SRC zsh +source $HOME/.oh-my-zsh/custom/plugins/zsh-histdb/sqlite-history.zsh +autoload -Uz add-zsh-hook +#+END_SRC + +in your zsh startup files. + +** Note for OS X users + +Add the following line before you source `sqlite-history.zsh`. See https://github.com/larkery/zsh-histdb/pull/31 for details. + +#+BEGIN_SRC zsh +HISTDB_TABULATE_CMD=(sed -e $'s/\x1f/\t/g') +#+END_SRC + +** Importing your old history + +[[https://github.com/drewis/go-histdbimport][go-histdbimport]] and [[https://github.com/phiresky/ts-histdbimport][ts-histdbimport]] are useful tools for doing this! Note that the imported history will not include metadata such as the working directory or the exit status, since that is not stored in the normal history file format, so queries using ~--in DIR~, etc. will not work as expected. + +* Configuration +histdb can be configured exactly as zsh: +- [[https://zsh.sourceforge.io/Doc/Release/Parameters.html#index-HISTORY_005fIGNORE][HISTORY_IGNORE]]: If set, is treated as a single glob pattern to match the commands that should be ignored. Ignored commands are not saved to the database. Example: ~(ls|cd|top|htop)~. + +* Querying history +You can query the history with the ~histdb~ command. +With no arguments it will print one screenful of history on the current host. + +With arguments, it will print history lines matching their concatenation. + +For wildcards within a history line, you can use the ~%~ character, which is like the shell glob ~*~, so ~histdb this%that~ will match any history line containing ~this~ followed by ~that~ with zero or more characters in-between. + +To search on particular hosts, directories, sessions, or time periods, see the help with ~histdb --help~. + +You can also run ~histdb-top~ to see your most frequent commands, and ~histdb-top dir~ to show your favourite directory for running commands in, but these commands are really a bit useless. +** Example: + +#+BEGIN_SRC text +$ histdb strace +time ses dir cmd +17/03 438 ~ strace conkeror +22/03 522 ~ strace apropos cake +22/03 522 ~ strace -e trace=file s +22/03 522 ~ strace -e trace=file ls +22/03 522 ~ strace -e trace=file cat temp/people.vcf +22/03 522 ~ strace -e trace=file cat temp/gammu.log +22/03 522 ~ run-help strace +24/03 547 ~ man strace +#+END_SRC + +These are all the history entries involving ~strace~ in my history. +If there was more than one screenful, I would need to say ~--limit 1000~ or some other large number. +The command does not warn you if you haven't seen all the results. +The ~ses~ column contains a unique session number, so all the ~522~ rows are from the same shell session. + +To see all hosts, add ~--host~ /after/ the query terms. +To see a specific host, add ~--host hostname~. +To see all of a specific session say e.g. ~-s 522 --limit 10000~. +** Integration with ~zsh-autosuggestions~ + +If you use [[https://github.com/zsh-users/zsh-autosuggestions][zsh-autosuggestions]] you can configure it to search the history database instead of the zsh history file thus: + +#+BEGIN_SRC sh + _zsh_autosuggest_strategy_histdb_top_here() { + local query="select commands.argv from + history left join commands on history.command_id = commands.rowid + left join places on history.place_id = places.rowid + where places.dir LIKE '$(sql_escape $PWD)%' + and commands.argv LIKE '$(sql_escape $1)%' + group by commands.argv order by count(*) desc limit 1" + suggestion=$(_histdb_query "$query") + } + + ZSH_AUTOSUGGEST_STRATEGY=histdb_top_here +#+END_SRC + +This query will find the most frequently issued command that is issued in the current directory or any subdirectory. You can get other behaviours by changing the query, for example + +#+BEGIN_SRC sh + _zsh_autosuggest_strategy_histdb_top() { + local query=" + select commands.argv from history + left join commands on history.command_id = commands.rowid + left join places on history.place_id = places.rowid + where commands.argv LIKE '$(sql_escape $1)%' + group by commands.argv, places.dir + order by places.dir != '$(sql_escape $PWD)', count(*) desc + limit 1 + " + suggestion=$(_histdb_query "$query") + } + + ZSH_AUTOSUGGEST_STRATEGY=histdb_top +#+END_SRC + +This will find the most frequently issued command issued exactly in this directory, or if there are no matches it will find the most frequently issued command in any directory. You could use other fields like the hostname to restrict to suggestions on this host, etc. +** Reverse isearch +If you want a history-reverse-isearch type feature there is one defined in ~histdb-interactive.zsh~. If you source that file you will get a new widget called _histdb-isearch which you can bind to a key, e.g. + +#+BEGIN_SRC sh +source histdb-interactive.zsh +bindkey '^r' _histdb-isearch +#+END_SRC + +This is like normal ~history-reverse-isearch~ except: +- The search will start with the buffer contents automatically +- The editing keys are all standard (because it does not really use the minibuffer). + + This means pressing ~C-a~ or ~C-e~ or similar will not exit the search like normal ~history-reverse-isearch~ +- The accept key (~RET~) does not cause the command to run immediately but instead lets you edit it + +There are also a few extra keybindings: + +- ~M-j~ will ~cd~ to the directory for the history entry you're looking at. + This means you can search for ./run-this-command and then ~M-j~ to go to the right directory before running. +- ~M-h~ will toggle limiting the search to the current host's history. +- ~M-d~ will toggle limiting the search to the current directory and subdirectories' histories +* Database schema +The database lives by default in ~$HOME/.histdb/zsh-history.db~. +You can look in it easily by running ~_histdb_query~, as this actually just fires up sqlite with the database. + +For inspiration you can also use ~histdb~ with the ~-d~ argument and it will print the SQL it's running. +* Synchronising history +You should be able to synchronise the history using ~git~; a 3-way merge driver is supplied in ~histdb-merge~. + +The 3-way merge will only work properly if all the computers on which you use the repository have different hostnames. + +The ~histdb-sync~ function will initialize git in the histdb directory and configure the merge driver for you first time you run it. +Subsequent times it will commit all changes, pull all changes, force a merge, and push all changes back again. +The commit message is useless, so if you find that kind of thing upsetting you will need to fix it. + +The reason for using ~histdb-sync~ instead of doing it by hand is that if you are running the git steps in your shell the history database will be changed each command, and so you will never be able to do a pull / merge. +* Completion +None, and I've used the names with underscores to mean something else. +* Pull requests / missing features +Happy to look at changes. +I did at one point have a reverse-isearch thing in here for searching the database interactively, but it didn't really make my life any better so I deleted it. diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/db_migrations/0to2.sql b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/db_migrations/0to2.sql @@ -0,0 +1,30 @@ +PRAGMA foreign_keys=OFF; +begin transaction; +create table commands_new (id integer primary key autoincrement, argv text, unique(argv) on conflict ignore); +create table places_new (id integer primary key autoincrement, host text, dir text, unique(host, dir) on conflict ignore); +create table history_new (id integer primary key autoincrement, + session int, + command_id int references commands (id), + place_id int references places (id), + exit_status int, + start_time int, + duration int); + +INSERT INTO commands_new (id, argv) SELECT rowid, argv FROM commands; +INSERT INTO places_new (id, host, dir) SELECT rowid, host, dir FROM places; + +INSERT INTO history_new (session, command_id, place_id, exit_status, start_time, duration) +SELECT H.session, C.rowid, P.rowid, H.exit_status, H.start_time, H.duration +FROM history H +LEFT JOIN places P ON H.place_id = P.rowid +LEFT JOIN commands C ON H.command_id = C.rowid; +drop table history; +drop table places; +drop table commands; +ALTER TABLE commands_new RENAME TO commands; +ALTER TABLE places_new RENAME TO places; +ALTER TABLE history_new RENAME TO history; +PRAGMA foreign_key_check ; +PRAGMA user_version=2; +commit; +PRAGMA foreign_keys=ON; diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-interactive.zsh b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-interactive.zsh @@ -0,0 +1,214 @@ +typeset -g HISTDB_ISEARCH_N +typeset -g HISTDB_ISEARCH_MATCH +typeset -g HISTDB_ISEARCH_DIR +typeset -g HISTDB_ISEARCH_HOST +typeset -g HISTDB_ISEARCH_DATE +typeset -g HISTDB_ISEARCH_MATCH_END + +typeset -g HISTDB_ISEARCH_THIS_HOST=1 +typeset -g HISTDB_ISEARCH_THIS_DIR=0 +typeset -g HISTDB_ISEARCH_LAST_QUERY="" +typeset -g HISTDB_ISEARCH_LAST_N="" + +# TODO Show more info about match (n, date, pwd, host) +# TODO Keys to limit match? + +# make a keymap for histdb isearch +bindkey -N histdb-isearch main + +_histdb_isearch_query () { + if [[ -z $BUFFER ]]; then + HISTDB_ISEARCH_MATCH="" + return + fi + + local new_query="$BUFFER $HISTDB_ISEARCH_THIS_HOST $HISTDB_ISEARCH_THIS_DIR" + if [[ $new_query == $HISTDB_ISEARCH_LAST_QUERY ]] && [[ $HISTDB_ISEARCH_N == $HISTDB_ISEARCH_LAST_N ]]; then + return + elif [[ $new_query != $HISTDB_ISEARCH_LAST_QUERY ]]; then + HISTDB_ISEARCH_N=0 + fi + + HISTDB_ISEARCH_LAST_QUERY=$new_query + HISTDB_ISEARCH_LAST_N=HISTDB_ISEARCH_N + + if (( $HISTDB_ISEARCH_N < 0 )); then + local maxmin="min" + local ascdesc="asc" + local offset=$(( - $HISTDB_ISEARCH_N )) + else + local maxmin="max" + local ascdesc="desc" + local offset=$(( $HISTDB_ISEARCH_N )) + fi + + if [[ $HISTDB_ISEARCH_THIS_DIR == 1 ]]; then + local where_dir="and places.dir like '$(sql_escape $PWD)%'" + else + local where_dir="" + fi + + + if [[ $HISTDB_ISEARCH_THIS_HOST == 1 ]]; then + local where_host="and places.host = '$(sql_escape $HOST)'" + else + local where_host="" + fi + + local query="select +commands.argv, +places.dir, +places.host, +datetime(max(history.start_time), 'unixepoch', 'localtime') +from history left join commands +on history.command_id = commands.rowid +left join places +on history.place_id = places.rowid +where commands.argv glob '*$(sql_escape ${BUFFER})*' +${where_host} +${where_dir} +group by commands.argv, places.dir, places.host +order by ${maxmin}(history.start_time) ${ascdesc} +limit 1 +offset ${offset}" + local result=$(_histdb_query -separator $'\n' "$query") + local lines=("${(f)result}") + HISTDB_ISEARCH_DATE=${lines[-1]} + HISTDB_ISEARCH_HOST=${lines[-2]} + HISTDB_ISEARCH_DIR=${lines[-3]} + lines[-1]=() + lines[-1]=() + lines[-1]=() + HISTDB_ISEARCH_MATCH=${(F)lines} +} + +_histdb_isearch_display () { + if [[ $HISTDB_ISEARCH_THIS_HOST == 1 ]]; then + local host_bit=" h" + else + local host_bit="" + fi + if [[ $HISTDB_ISEARCH_THIS_DIR == 1 ]]; then + local dir_bit=" d" + else + local dir_bit="" + fi + local top_bit="histdb ${HISTDB_ISEARCH_N}${host_bit}${dir_bit}: " + if [[ -z ${HISTDB_ISEARCH_MATCH} ]]; then + PREDISPLAY="(no match) +$top_bit" + else + local qbuffer="${(b)BUFFER}" + qbuffer="${${qbuffer//\\\*/*}//\\\?/?}" + local match_len="${#HISTDB_ISEARCH_MATCH}" + local prefix="${HISTDB_ISEARCH_MATCH%%${~qbuffer}*}" + local prefix_len="${#prefix}" + local suffix_len="${#${HISTDB_ISEARCH_MATCH:${prefix_len}}##${~qbuffer}}" + local match_end=$(( $match_len - $suffix_len )) + HISTDB_ISEARCH_MATCH_END=${match_end} + + if [[ $HISTDB_ISEARCH_HOST == $HOST ]]; then + local host="" + else + local host=" + host: $HISTDB_ISEARCH_HOST" + fi + region_highlight=("P${prefix_len} ${match_end} underline") + PREDISPLAY="${HISTDB_ISEARCH_MATCH} +→ in ${HISTDB_ISEARCH_DIR}$host +→ on ${HISTDB_ISEARCH_DATE} +$top_bit" + fi +} + +_histdb-isearch-up () { + HISTDB_ISEARCH_N=$(( $HISTDB_ISEARCH_N + 1 )) +} + +_histdb-isearch-down () { + HISTDB_ISEARCH_N=$(( $HISTDB_ISEARCH_N - 1 )) +} + +zle -N self-insert-histdb-isearch + +_histdb_line_redraw () { + _histdb_isearch_query + _histdb_isearch_display +} + +_histdb-isearch () { + local old_buffer=${BUFFER} + local old_cursor=${CURSOR} + HISTDB_ISEARCH_N=0 + echo -ne "\e[4 q" # switch to underline cursor + + zle -K histdb-isearch + zle -N zle-line-pre-redraw _histdb_line_redraw + _histdb_isearch_query + _histdb_isearch_display + zle recursive-edit; local stat=$? + zle -D zle-line-pre-redraw # TODO push/pop zle-line-pre-redraw and + # self-insert, rather than nuking + + zle -K main + PREDISPLAY="" + region_highlight=() + + echo -ne "\e[1 q" #box cursor + + if ! (( stat )); then + BUFFER="${HISTDB_ISEARCH_MATCH}" + CURSOR="${HISTDB_ISEARCH_MATCH_END}" + else + BUFFER=${old_buffer} + CURSOR=${old_cursor} + fi + + return 0 +} + +# this will work outside histdb-isearch if you want +# so you can recover from history and then cd afterwards +_histdb-isearch-cd () { + if [[ -d ${HISTDB_ISEARCH_DIR} ]]; then + cd "${HISTDB_ISEARCH_DIR}" + zle reset-prompt + fi +} + +_histdb-isearch-toggle-host () { + if [[ $HISTDB_ISEARCH_THIS_HOST == 1 ]]; then + HISTDB_ISEARCH_THIS_HOST=0 + else + HISTDB_ISEARCH_THIS_HOST=1 + fi +} + +_histdb-isearch-toggle-dir () { + if [[ $HISTDB_ISEARCH_THIS_DIR == 1 ]]; then + HISTDB_ISEARCH_THIS_DIR=0 + else + HISTDB_ISEARCH_THIS_DIR=1 + fi +} + +zle -N _histdb-isearch-up +zle -N _histdb-isearch-down +zle -N _histdb-isearch +zle -N _histdb-isearch-cd +zle -N _histdb-isearch-toggle-dir +zle -N _histdb-isearch-toggle-host + +bindkey -M histdb-isearch '' _histdb-isearch-up +bindkey -M histdb-isearch '^[[A' _histdb-isearch-up + +bindkey -M histdb-isearch '' _histdb-isearch-down +bindkey -M histdb-isearch '^[[B' _histdb-isearch-down + +bindkey -M histdb-isearch '^[j' _histdb-isearch-cd + +bindkey -M histdb-isearch '^[h' _histdb-isearch-toggle-host +bindkey -M histdb-isearch '^[d' _histdb-isearch-toggle-dir + +# because we are using BUFFER for output, we have to reimplement +# pretty much the whole set of buffer editing operations diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-merge b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-merge @@ -0,0 +1,62 @@ +#!/usr/bin/env zsh + +typeset -g HERE=$(dirname "${(%):-%N}") + +local ancestor=${1:?three databases required}; shift +local ours=${1:?three databases required}; shift +local theirs=${1:?three databases required} + +$HERE/histdb-migrate $ancestor # this is always reasonable to do +$HERE/histdb-migrate $ours # this also seems fine + +V_OURS=$(sqlite3 -batch -noheader $ours 'PRAGMA user_version') +V_THEIRS=$(sqlite3 -batch -noheader $theirs 'PRAGMA user_version') + +if [[ ${V_OURS} -lt ${V_THEIRS} ]] ; then + echo "Attempting to merge with a database from a future version (${V_THEIRS})." + echo "You need to update your histdb version to continue." + exit 1 +elif [[ ${V_THEIRS} -lt ${V_OURS} ]]; then + echo "Merging different database versions: ours ${V_OURS}, theirs ${V_THEIRS}." + echo "To continue merging, their database needs migrating to newer version." + echo "If you do this, and push the changes, then the remote version of histdb will need upgrading too." + + read -q "REPLY?Try migrating their database? [y/n] " + if [[ $REPLY != "y" ]]; then + echo "Cancelled." + exit 1 + fi +fi + +# for reasons I cannot use the encryption filter here. +# most annoying. +# +echo "Ancestor has $(sqlite3 ${ancestor} 'select count(*) from history') entries" +echo "We have $(sqlite3 ${ours} 'select count(*) from history') entries" +echo "Theirs have $(sqlite3 ${theirs} 'select count(*) from history') entries" + +sqlite3 -batch -noheader "${theirs}" <<EOF +ATTACH DATABASE '${ours}' AS n; +ATTACH DATABASE '${ancestor}' AS a; + +-- copy missing commands and places +INSERT INTO commands (argv) SELECT argv FROM n.commands as NC where NC.id > (SELECT max(id) FROM a.commands); +INSERT INTO places (host, dir) SELECT host, dir FROM n.places as NP where NP.id > (SELECT max(id) FROM a.places); + +-- insert missing history, rewriting IDs +-- could uniquify sessions by host in this way too + +INSERT INTO history (session, command_id, place_id, exit_status, start_time, duration) +SELECT NO.session, C.id, P.id, NO.exit_status, NO.start_time, NO.duration +FROM n.history NO +LEFT JOIN n.places PO ON NO.place_id = PO.id +LEFT JOIN n.commands CO ON NO.command_id = CO.id +LEFT JOIN commands C ON C.argv = CO.argv +LEFT JOIN places P ON (P.host = PO.host +AND P.dir = PO.dir) +WHERE NO.id > (SELECT MAX(id) FROM a.history) +; +VACUUM; +EOF +cp ${theirs} ${ours} +echo "Now we have $(sqlite3 ${ours} 'select count(*) from history') entries" diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-migrate b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/histdb-migrate @@ -0,0 +1,27 @@ +#!/usr/bin/env zsh + +typeset -g HISTDB_SCHEMA_VERSION=2 +typeset -g HISTDB_INSTALLED_IN="${(%):-%N}" + +local TARGET_FILE="$1" +local CURRENT_VERSION=$(sqlite3 -batch -noheader "${TARGET_FILE}" 'PRAGMA user_version') +if [[ ${CURRENT_VERSION} -lt ${HISTDB_SCHEMA_VERSION} ]]; then + echo "History database ${TARGET_FILE} is using an older schema (${CURRENT_VERSION}) and will be updated to version ${HISTDB_SCHEMA_VERSION}." + local MIGRATION_FILENAME="$(dirname ${HISTDB_INSTALLED_IN})/db_migrations/${CURRENT_VERSION}to${HISTDB_SCHEMA_VERSION}.sql" + if [[ -f $MIGRATION_FILENAME ]]; then + local BACKUP_FILE="${TARGET_FILE}-$(date +%s).bak" + echo "Backing up database to ${BACKUP_FILE} before migration" + cp ${BACKUP_FILE} ${HISTDB_FILE} + sqlite3 -batch -noheader "${TARGET_FILE}" < "${MIGRATION_FILENAME}" + local R="$?" + [[ "$R" -ne 0 ]] && (echo "Error during database conversion"; cp ${BACKUP_FILE} ${HISTDB_FILE}) || echo "Update successful (you may want to remove the backup)" + return "$R" + else + echo "There is no migration script from version ${CURRENT_VERSION} to ${HISTDB_SCHEMA_VERSION}." + return 1 + fi +elif [[ ${CURRENT_VERSION} -gt ${HISTDB_SCHEMA_VERSION} ]]; then + echo "History database ${TARGET_FILE} is using a newer schema (${CURRENT_VERSION}) than this version of histdb understands (${HISTDB_SCHEMA_VERSION})." + echo "Most likely, you have updated histdb on another machine which has updated your history database, and you need to update this copy of histdb." + return 1 +fi diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/sqlite-history.zsh b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/sqlite-history.zsh @@ -0,0 +1,503 @@ +which sqlite3 >/dev/null 2>&1 || return; + +zmodload zsh/datetime # for EPOCHSECONDS +zmodload zsh/system # for sysopen +builtin which sysopen &>/dev/null || return; # guard against zsh older than 5.0.8. + +zmodload -F zsh/stat b:zstat # just zstat +autoload -U add-zsh-hook + +typeset -g HISTDB_QUERY="" +if [[ -z ${HISTDB_FILE} ]]; then + typeset -g HISTDB_FILE="${HOME}/.histdb/zsh-history.db" +else + typeset -g HISTDB_FILE +fi + +typeset -g HISTDB_FD +typeset -g HISTDB_INODE=() +typeset -g HISTDB_SESSION="" +typeset -g HISTDB_HOST="" +typeset -g HISTDB_INSTALLED_IN="${(%):-%N}" + + + +sql_escape () { + print -r -- ${${@//\'/\'\'}//$'\x00'} +} + +_histdb_query () { + sqlite3 -batch -noheader -cmd ".timeout 1000" "${HISTDB_FILE}" "$@" + [[ "$?" -ne 0 ]] && echo "error in $@" +} + +_histdb_stop_sqlite_pipe () { + if [[ -n $HISTDB_FD ]]; then + if print -nu$HISTDB_FD; then + exec {HISTDB_FD}>&-; # https://stackoverflow.com/a/22794374/2639190 + fi + fi + # Sometimes, it seems like closing the fd does not terminate the + # sqlite batch process, so here is a horrible fallback. + # if [[ -n $HISTDB_SQLITE_PID ]]; then + # ps -o args= -p $HISTDB_SQLITE_PID | read -r args + # if [[ $args == "sqlite3 -batch ${HISTDB_FILE}" ]]; then + # kill -TERM $HISTDB_SQLITE_PID + # fi + # fi +} + +add-zsh-hook zshexit _histdb_stop_sqlite_pipe + +_histdb_start_sqlite_pipe () { + local PIPE==(<<<'') + setopt local_options no_notify no_monitor + mkfifo $PIPE + sqlite3 -batch -noheader "${HISTDB_FILE}" < $PIPE >/dev/null &| + sysopen -w -o cloexec -u HISTDB_FD -- $PIPE + command rm $PIPE + zstat -A HISTDB_INODE +inode ${HISTDB_FILE} +} + +_histdb_query_batch () { + local CUR_INODE + zstat -A CUR_INODE +inode ${HISTDB_FILE} + if [[ $CUR_INODE != $HISTDB_INODE ]]; then + _histdb_stop_sqlite_pipe + _histdb_start_sqlite_pipe + fi + cat >&$HISTDB_FD + echo ';' >&$HISTDB_FD # make sure last command is executed +} + +_histdb_init () { + if [[ -n "${HISTDB_SESSION}" ]]; then + return + fi + + if ! [[ -e "${HISTDB_FILE}" ]]; then + local hist_dir="${HISTDB_FILE:h}" + if ! [[ -d "$hist_dir" ]]; then + mkdir -p -- "$hist_dir" + fi + _histdb_query <<-EOF +create table commands (id integer primary key autoincrement, argv text, unique(argv) on conflict ignore); +create table places (id integer primary key autoincrement, host text, dir text, unique(host, dir) on conflict ignore); +create table history (id integer primary key autoincrement, + session int, + command_id int references commands (id), + place_id int references places (id), + exit_status int, + start_time int, + duration int); +PRAGMA user_version = 2; +EOF + fi + if [[ -z "${HISTDB_SESSION}" ]]; then + ${HISTDB_INSTALLED_IN:h}/histdb-migrate "${HISTDB_FILE}" + HISTDB_HOST=${HISTDB_HOST:-"'$(sql_escape ${HOST})'"} + HISTDB_SESSION=$(_histdb_query "select 1+max(session) from history inner join places on places.id=history.place_id where places.host = ${HISTDB_HOST}") + HISTDB_SESSION="${HISTDB_SESSION:-0}" + readonly HISTDB_SESSION + fi + + _histdb_start_sqlite_pipe + _histdb_query_batch >/dev/null <<EOF +create index if not exists hist_time on history(start_time); +create index if not exists place_dir on places(dir); +create index if not exists place_host on places(host); +create index if not exists history_command_place on history(command_id, place_id); +PRAGMA journal_mode = WAL; +PRAGMA synchronous=normal; +EOF +} + +declare -ga _BORING_COMMANDS +_BORING_COMMANDS=("^ls$" "^cd$" "^ " "^histdb" "^top$" "^htop$") + +if [[ -z "${HISTDB_TABULATE_CMD[*]:-}" ]]; then + declare -ga HISTDB_TABULATE_CMD + HISTDB_TABULATE_CMD=(column -t -s $'\x1f') +fi + +_histdb_update_outcome () { + local retval=$? + local finished=$EPOCHSECONDS + [[ -z "${HISTDB_SESSION}" ]] && return + + _histdb_init + _histdb_query_batch <<EOF &| +update history set + exit_status = ${retval}, + duration = ${finished} - start_time +where id = (select max(id) from history) and + session = ${HISTDB_SESSION} and + exit_status is NULL; +EOF +} + +_histdb_addhistory () { + local cmd="${1[0, -2]}" + + if [[ -o histignorespace && "$cmd" =~ "^ " ]]; then + return 0 + fi + if [[ ${cmd} == ${~HISTORY_IGNORE} ]]; then + return 0 + fi + local boring + for boring in "${_BORING_COMMANDS[@]}"; do + if [[ "$cmd" =~ $boring ]]; then + return 0 + fi + done + + local cmd="'$(sql_escape $cmd)'" + local pwd="'$(sql_escape ${PWD})'" + local started=$EPOCHSECONDS + _histdb_init + + if [[ "$cmd" != "''" ]]; then + _histdb_query_batch <<EOF &| +insert into commands (argv) values (${cmd}); +insert into places (host, dir) values (${HISTDB_HOST}, ${pwd}); +insert into history + (session, command_id, place_id, start_time) +select + ${HISTDB_SESSION}, + commands.id, + places.id, + ${started} +from + commands, places +where + commands.argv = ${cmd} and + places.host = ${HISTDB_HOST} and + places.dir = ${pwd} +; +EOF + fi + return 0 +} + +add-zsh-hook zshaddhistory _histdb_addhistory +add-zsh-hook precmd _histdb_update_outcome + +histdb-top () { + _histdb_init + local sep=$'\x1f' + local field + local join + local table + 1=${1:-cmd} + case "$1" in + dir) + field=places.dir + join='places.id = history.place_id' + table=places + ;; + cmd) + field=commands.argv + join='commands.id = history.command_id' + table=commands + ;;; + esac + _histdb_query -separator "$sep" \ + -header \ + "select count(*) as count, places.host, replace($field, ' +', ' +$sep$sep') as ${1:-cmd} from history left join commands on history.command_id=commands.id left join places on history.place_id=places.id group by places.host, $field order by count(*)" | \ + "${HISTDB_TABULATE_CMD[@]}" +} + +histdb-sync () { + _histdb_init + + # this ought to apply to other readers? + echo "truncating WAL" + echo 'pragma wal_checkpoint(truncate);' | _histdb_query_batch + + local hist_dir="${HISTDB_FILE:h}" + if [[ -d "$hist_dir" ]]; then + () { + setopt local_options no_pushd_ignore_dups + + pushd -q "$hist_dir" + if [[ $(git rev-parse --is-inside-work-tree) != "true" ]] || [[ "$(git rev-parse --show-toplevel)" != "${PWD:A}" ]]; then + git init + git config merge.histdb.driver "${HISTDB_INSTALLED_IN:h}/histdb-merge %O %A %B" + echo "${HISTDB_FILE:t} merge=histdb" >>! .gitattributes + git add .gitattributes + git add "${HISTDB_FILE:t}" + fi + _histdb_stop_sqlite_pipe # Stop in case of a merge, starting again afterwards + git commit -am "history" && git pull --no-edit && git push + _histdb_start_sqlite_pipe + popd -q + } + fi + + echo 'pragma wal_checkpoint(passive);' | _histdb_query_batch +} + +histdb () { + _histdb_init + local -a opts + local -a hosts + local -a indirs + local -a atdirs + local -a sessions + + zparseopts -E -D -a opts \ + -host+::=hosts \ + -in+::=indirs \ + -at+::=atdirs \ + -forget \ + -yes \ + -detail \ + -sep:- \ + -exact \ + d h -help \ + s+::=sessions \ + -from:- -until:- -limit:- \ + -status:- -desc + + local usage="usage:$0 terms [--desc] [--host[ x]] [--in[ x]] [--at] [-s n]+* [-d] [--detail] [--forget] [--yes] [--exact] [--sep x] [--from x] [--until x] [--limit n] [--status x] + --desc reverse sort order of results + --host print the host column and show all hosts (otherwise current host) + --host x find entries from host x + --in find only entries run in the current dir or below + --in x find only entries in directory x or below + --at like --in, but excluding subdirectories + -s n only show session n + -d debug output query that will be run + --detail show details + --forget forget everything which matches in the history + --yes don't ask for confirmation when forgetting + --exact don't match substrings + --sep x print with separator x, and don't tabulate + --from x only show commands after date x (sqlite date parser) + --until x only show commands before date x (sqlite date parser) + --limit n only show n rows. defaults to $LINES or 25 + --status x only show rows with exit status x. Can be 'error' to find all nonzero." + + local selcols="session as ses, dir" + local cols="session, replace(places.dir, '$HOME', '~') as dir" + local where="1" + if [[ -p /dev/stdout ]]; then + local limit="" + else + local limit="${$((LINES - 4)):-25}" + fi + + local forget="0" + local forget_accept=0 + local exact=0 + + if (( ${#hosts} )); then + local hostwhere="" + local host="" + for host ($hosts); do + host="${${host#--host}#=}" + hostwhere="${hostwhere}${host:+${hostwhere:+ or }places.host='$(sql_escape ${host})'}" + done + where="${where}${hostwhere:+ and (${hostwhere})}" + cols="${cols}, places.host as host" + selcols="${selcols}, host" + else + where="${where} and places.host=${HISTDB_HOST}" + fi + + if (( ${#indirs} + ${#atdirs} )); then + local dirwhere="" + local dir="" + for dir ($indirs); do + dir="${${${dir#--in}#=}:-$PWD}" + dirwhere="${dirwhere}${dirwhere:+ or }places.dir like '$(sql_escape $dir)%'" + done + for dir ($atdirs); do + dir="${${${dir#--at}#=}:-$PWD}" + dirwhere="${dirwhere}${dirwhere:+ or }places.dir = '$(sql_escape $dir)'" + done + where="${where}${dirwhere:+ and (${dirwhere})}" + fi + + if (( ${#sessions} )); then + local sin="" + local ses="" + for ses ($sessions); do + ses="${${${ses#-s}#=}:-${HISTDB_SESSION}}" + sin="${sin}${sin:+, }$ses" + done + where="${where}${sin:+ and session in ($sin)}" + fi + + local sep=$'\x1f' + local orderdir='asc' + local debug=0 + local opt="" + for opt ($opts); do + case $opt in + --desc) + orderdir='desc' + ;; + --sep*) + sep=${opt#--sep} + ;; + --from*) + local from=${opt#--from} + case $from in + -*) + from="datetime('now', '$from')" + ;; + today) + from="datetime('now', 'start of day')" + ;; + yesterday) + from="datetime('now', 'start of day', '-1 day')" + ;; + esac + where="${where} and datetime(start_time, 'unixepoch') >= $from" + ;; + --status*) + local xstatus=${opt#--status} + case $xstatus in + <->) + where="${where} and exit_status = $xstatus" + ;; + error) + where="${where} and exit_status <> 0" + ;; + esac + ;; + --until*) + local until=${opt#--until} + case $until in + -*) + until="datetime('now', '$until')" + ;; + today) + until="datetime('now', 'start of day')" + ;; + yesterday) + until="datetime('now', 'start of day', '-1 day')" + ;; + esac + where="${where} and datetime(start_time, 'unixepoch') <= $until" + ;; + -d) + debug=1 + ;; + --detail) + cols="${cols}, exit_status, duration " + selcols="${selcols}, exit_status as [?],duration as secs " + ;; + -h|--help) + echo "$usage" + return 0 + ;; + --forget) + forget=1 + ;; + --yes) + forget_accept=1 + ;; + --exact) + exact=1 + ;; + --limit*) + limit=${opt#--limit} + ;; + esac + done + + if [[ -n "$*" ]]; then + if [[ $exact -eq 0 ]]; then + where="${where} and commands.argv glob '*$(sql_escape $@)*'" + else + where="${where} and commands.argv = '$(sql_escape $@)'" + fi + fi + + if [[ $forget -gt 0 ]]; then + limit="" + fi + local seps=$(echo "$cols" | tr -c -d ',' | tr ',' $sep) + cols="${cols}, replace(commands.argv, ' +', ' +$seps') as argv, max(start_time) as max_start" + + local mst="datetime(max_start, 'unixepoch')" + local dst="datetime('now', 'start of day')" + local timecol="strftime(case when $mst > $dst then '%H:%M' else '%d/%m' end, max_start, 'unixepoch', 'localtime') as time" + + selcols="${timecol}, ${selcols}, argv as cmd" + + local r_order="asc" + if [[ $orderdir == "asc" ]]; then + r_order="desc" + fi + + local query="select ${selcols} from (select ${cols} +from + commands + join history on history.command_id = commands.id + join places on history.place_id = places.id +where ${where} +group by history.command_id, history.place_id +order by max_start ${r_order} +${limit:+limit $limit}) order by max_start ${orderdir}" + + ## min max date? + local count_query="select count(*) from (select ${cols} +from + commands + join history on history.command_id = commands.id + join places on history.place_id = places.id +where ${where} +group by history.command_id, history.place_id +order by max_start desc) order by max_start ${orderdir}" + + if [[ $debug = 1 ]]; then + echo "$query" + else + local count=$(_histdb_query "$count_query") + if [[ -p /dev/stdout ]]; then + buffer() { + ## this runs out of memory for big files I think perl -e 'local $/; my $stdin = <STDIN>; print $stdin;' + temp=$(mktemp) + cat >! "$temp" + cat -- "$temp" + rm -f -- "$temp" + } + else + buffer() { + cat + } + fi + if [[ $sep == $'\x1f' ]]; then + _histdb_query -header -separator $sep "$query" | iconv -f utf-8 -t utf-8 -c | buffer | "${HISTDB_TABULATE_CMD[@]}" + else + _histdb_query -header -separator $sep "$query" | buffer + fi + [[ -n $limit ]] && [[ $limit -lt $count ]] && echo "(showing $limit of $count results)" + fi + + if [[ $forget -gt 0 ]]; then + if [[ $forget_accept -gt 0 ]]; then + REPLY=y + else + read -q "REPLY?Forget all these results? [y/n] " + fi + if [[ $REPLY =~ "[yY]" ]]; then + _histdb_query "delete from history where +history.id in ( +select history.id from +history + left join commands on history.command_id = commands.id + left join places on history.place_id = places.id +where ${where})" + _histdb_query "delete from commands where commands.id not in (select distinct history.command_id from history)" + fi + fi +} diff --git a/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/zsh-histdb.plugin.zsh b/modules/mixins/dotfiles/config/zsh/plugins/zsh-histdb/zsh-histdb.plugin.zsh @@ -0,0 +1 @@ +source ${0:A:h}/sqlite-history.zsh diff --git a/modules/mixins/dotfiles/config/zsh/rc/.keep b/modules/mixins/dotfiles/config/zsh/rc/.keep diff --git a/modules/mixins/dotfiles/config/zsh/rc/completion b/modules/mixins/dotfiles/config/zsh/rc/completion @@ -0,0 +1,29 @@ +#!/bin/zsh + +autoload -U compinit + +# Checking the cached .zcompdump file to see if it must be regenerated adds a +# noticable delay to zsh startup. This little hack restricts it to once a day. +if [[ -n ${ZDOTDIR}/.zcompdump(#qN.mh+24) ]]; then + compinit; +else + compinit -C; +fi; + +LISTMAX=0 + +# zsh's git tab completion by default is extremely slow. This makes it use +# local files only. See http://stackoverflow.com/a/9810485/945780. +__git_files () { + _wanted files expl 'local files' _files +} + +# Fuzzy matching +# 0 -- vanilla completion (abc => abc) +# 1 -- smart case completion (abc => Abc) +# 2 -- word flex completion (abc => A-big-Car) +# 3 -- full flex completion (abc => ABraCadabra) +zstyle ':completion:*' matcher-list '' \ + 'm:{a-z\-}={A-Z\_}' \ + 'r:[^[:alpha:]]||[[:alpha:]]=** r:|=* m:{a-z\-}={A-Z\_}' \ + 'r:|?=** m:{a-z\-}={A-Z\_}' diff --git a/modules/mixins/dotfiles/config/zsh/rc/functions b/modules/mixins/dotfiles/config/zsh/rc/functions @@ -0,0 +1,80 @@ +#!/bin/zsh + +fzf_copy_from_cliphist() { + { cliphist list | fzf --no-sort | cliphist decode | wl-copy && zle reset-prompt || true } 2>/dev/null +} + +tms_open() { + tms && zle reset-prompt || true 2>/dev/null +} + +erg() { + $EDITOR \ + +'/\v'"${1/\//\\/}" \ + +':silent tabdo :1 | normal! n' \ + +':tabfirst' \ + -p $(rg "$@" | cut -d: -f1 | sort -u) +} + +efd() { + $EDITOR \ + +':tabfirst' \ + -p $(fd "$@") +} + +# https://news.ycombinator.com/item?id=29155825 +jog() { + sqlite3 "$HOME/.histdb/zsh-history.db" " + SELECT + replace(commands.argv, ' +', ' +') + FROM commands + JOIN history ON history.command_id = commands.id + JOIN places ON history.place_id = places.id + WHERE history.exit_status = 0 + AND dir = '${PWD}' + AND places.host = '${HOST}' + AND commands.argv != 'jog' + AND commands.argv != 'jog_run' + AND commands.argv != 'j' + AND commands.argv != 'jr' + AND commands.argv NOT LIKE 'z %' + AND commands.argv NOT LIKE 'cd %' + AND commands.argv != '..' + ORDER BY start_time DESC + " +} + +jog_run() { + local cmd + cmd=$(jog | uniq | fzf --no-sort) + [[ -n "$cmd" ]] && print -z "$cmd" +} + +histdb_run() { + if [ $# -eq 0 ]; then + local cmd + cmd=$(histdb --status 0 --sep "," | + cut -d"," -f4 | + grep -v "^(showing\|histdb" | + uniq | + tac | + fzf --no-sort) + [[ -n "$cmd" ]] && print -z "$cmd" + else + histdb "$@" + fi +} + +for b in $(seq 0 100); do + alias b"$b"="sudo brightnessctl set $b%" + +done +for t in $(seq 0 100); do + alias s"$t"="seek $t" + +done +for v in $(seq 0 100); do + alias v"$v"="mpc volume $v" +done diff --git a/modules/mixins/dotfiles/config/zsh/rc/global_aliases b/modules/mixins/dotfiles/config/zsh/rc/global_aliases @@ -0,0 +1,11 @@ +#!/bin/zsh +alias -g VV=' |& vim -' +alias -g LL=' |& less' +alias -g GG=' |& grep' +alias -g WW=' |& wc -l' + +if [[ -n "$WAYLAND_DISPLAY" ]]; then + alias -g CC=' |& wl-copy' +else + alias -g CC=' |& xclip -sel clip' +fi diff --git a/modules/mixins/dotfiles/config/zsh/rc/history b/modules/mixins/dotfiles/config/zsh/rc/history @@ -0,0 +1,8 @@ +#!/bin/zsh + +HISTFILE=$HOME/.zsh_history +HISTSIZE=10000000 +SAVEHIST=$HISTSIZE + +setopt append_history +setopt hist_ignore_space diff --git a/modules/mixins/dotfiles/config/zsh/rc/keybindings b/modules/mixins/dotfiles/config/zsh/rc/keybindings @@ -0,0 +1,61 @@ +#!/bin/zsh + +[[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char +[[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line +[[ -z "$terminfo[kend]" ]] || bindkey -M emacs "$terminfo[kend]" end-of-line +[[ -z "$terminfo[kich1]" ]] || bindkey -M emacs "$terminfo[kich1]" overwrite-mode +[[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char +[[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line +[[ -z "$terminfo[kend]" ]] || bindkey -M vicmd "$terminfo[kend]" vi-end-of-line +[[ -z "$terminfo[kich1]" ]] || bindkey -M vicmd "$terminfo[kich1]" overwrite-mode + +[[ -z "$terminfo[cuu1]" ]] || bindkey -M viins "$terminfo[cuu1]" vi-up-line-or-history +[[ -z "$terminfo[cuf1]" ]] || bindkey -M viins "$terminfo[cuf1]" vi-forward-char +[[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history +[[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history +[[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char +[[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char + +[[ "$terminfo[kcuu1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history +[[ "$terminfo[kcud1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history +[[ "$terminfo[kcuf1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char +[[ "$terminfo[kcub1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char +[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line +[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M viins "${terminfo[kend]/O/[}" end-of-line +[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line +[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M emacs "${terminfo[kend]/O/[}" end-of-line + +if [[ -n ${terminfo[smkx]} ]]; then + zle-line-init() { + echoti smkx + } + zle -N zle-line-init +fi + +if [[ -n ${terminfo[rmkx]} ]]; then + zle-line-finish() { + echoti rmkx + } + zle -N zle-line-finish +fi + +bindkey -e + +bindkey "$(tput kcuu1)" history-beginning-search-backward +bindkey "$(tput kcud1)" history-beginning-search-forward + +# tmux doesn't handle these, see xterm_keys_modifiers in xterm-keys.c +shift_left=$(tput kLFT 2>/dev/null) +[[ $shift_left ]] && bindkey "$shift_left" backward-word + +shift_right=$(tput kRIT 2>/dev/null) +[[ $shift_right ]] && bindkey "$shift_right" forward-word + +zle -N fzf_copy_from_cliphist +zle -N tms_open + +bindkey '^T' 'tms_open' +bindkey '^J' 'fzf_copy_from_cliphist' +bindkey '^F' 'magdalena_goto_file' +bindkey '^K' 'magdalena_goto_dir' +bindkey '^G' 'magdalena_fav_dirs' diff --git a/modules/mixins/dotfiles/config/zsh/rc/magdalena b/modules/mixins/dotfiles/config/zsh/rc/magdalena @@ -0,0 +1,17 @@ +#!/bin/zsh + +magdalena_goto_file() { + magdalena goto-file "$@" && zle reset-prompt 2>/dev/null || true +} + +magdalena_goto_dir() { + dir=$(magdalena goto-dir) && cd "$dir" && zle reset-prompt 2>/dev/null || true +} + +magdalena_fav_dirs() { + dir=$(magdalena fav-dirs) && cd "$dir" && zle reset-prompt 2>/dev/null || true +} + +zle -N magdalena_goto_file +zle -N magdalena_goto_dir +zle -N magdalena_fav_dirs diff --git a/modules/mixins/dotfiles/config/zsh/rc/options b/modules/mixins/dotfiles/config/zsh/rc/options @@ -0,0 +1,19 @@ +#!/bin/zsh + +set -o always_to_end +set -o append_history +set -o complete_in_word +set -o extendedglob +set -o histappend +set -o histignorealldups +set -o histignorespace +set -o interactivecomments +set -o ksh_glob +set -o no_bang_hist +set -o no_bare_glob_qual +set -o no_extended_glob +set -o noclobber +set -o nullglob +set -o prompt_subst +set -o rmstarsilent +set -o shwordsplit diff --git a/modules/mixins/dotfiles/config/zsh/rc/plugins b/modules/mixins/dotfiles/config/zsh/rc/plugins @@ -0,0 +1,36 @@ +#!/bin/zsh +# ~/.config/zsh/plugins/magnolia +if [[ -f $HOME/.config/zsh/plugins/magnolia ]]; then + . $HOME/.config/zsh/plugins/magnolia +fi + +# ~/.config/zsh/plugins/twitch +if [[ -f $HOME/.config/zsh/plugins/twitch ]]; then + . $HOME/.config/zsh/plugins/twitch +fi + +# ~/.config/zsh/plugins/fantomas +if [[ -f $HOME/.config/zsh/plugins/fantomas/fantomas ]]; then + . $HOME/.config/zsh/plugins/fantomas/fantomas +fi + +# https://github.com/hlissner/zsh-autopair +if [[ -f $HOME/.config/zsh/plugins/zsh-autopair/autopair.zsh ]]; then + . $HOME/.config/zsh/plugins/zsh-autopair/autopair.zsh +fi + +# https://github.com/zsh-users/zsh-autosuggestions +export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#ff9580,bold" + +if [[ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]]; then + . /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh +fi + +# https://github.com/larkery/zsh-histdb +source $HOME/.config/zsh/plugins/zsh-histdb/sqlite-history.zsh +source $HOME/.config/zsh/plugins/zsh-histdb/histdb-interactive.zsh +autoload -Uz add-zsh-hook +bindkey '^r' _histdb-isearch + +# https://github.com/ajeetdsouza/zoxide +eval "$(zoxide init zsh)" diff --git a/modules/mixins/dotfiles/config/zsh/rc/prompt b/modules/mixins/dotfiles/config/zsh/rc/prompt @@ -0,0 +1,4 @@ +#!/bin/zsh + +autoload -U promptinit +promptinit diff --git a/modules/mixins/dotfiles/default.nix b/modules/mixins/dotfiles/default.nix @@ -0,0 +1,91 @@ +{ + config, + lib, + inputs, + username, + configData, + ... +}: let + date = inputs.self.lastModifiedDate or "19700101000000"; + year = lib.substring 0 4 date; + monthNum = lib.substring 4 2 date; + month = lib.elemAt [ + "january" + "february" + "march" + "april" + "may" + "june" + "july" + "august" + "september" + "october" + "november" + "december" + ] (lib.toInt (lib.removePrefix "0" monthNum) - 1); + + tmplArgs = { + inherit year month; + homeDir = config.home.homeDirectory; + inherit (config.modules.dotfiles) shirtAuthToken shirtDomain; + }; + + mkMapping = path: prefix: let + scan = dir: rel: + lib.concatLists (lib.mapAttrsToList (name: type: let + newRel = + if rel == "" + then name + else "${rel}/${name}"; + newPath = dir + "/${name}"; + in + if type == "directory" + then scan newPath newRel + else [ + { + name = newRel; + path = newPath; + } + ]) + (builtins.readDir dir)); + in + builtins.listToAttrs (map (file: let + isNix = lib.hasSuffix ".nix" file.name; + target = prefix + (lib.removeSuffix ".nix" file.name); + in + lib.nameValuePair target ( + if isNix + then { + text = import file.path tmplArgs; + force = true; + } + else { + source = file.path; + force = true; + } + )) (scan path "")); +in { + options.modules.dotfiles = { + shirtAuthToken = lib.mkOption { + type = lib.types.str; + default = configData.users.${username}.shirt.token or ""; + description = "Auth token for the shirt link shortener"; + }; + shirtDomain = lib.mkOption { + type = lib.types.str; + default = configData.users.${username}.shirt.domain or ""; + description = "Domain for the shirt link shortener"; + }; + }; + + config = { + home.file = + (mkMapping ./home ".") + // (lib.mapAttrs (_: v: v // {executable = true;}) (mkMapping ./bin "bin/")) + // (mkMapping ./local ".local/"); + + xdg.configFile = mkMapping ./config ""; + + home.sessionPath = ["$HOME/bin"]; + }; +} diff --git a/modules/mixins/dotfiles/home/ad/bin/G b/modules/mixins/dotfiles/home/ad/bin/G @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# "grep open" +# +# Run ripgrep to search for a pattern with the current git repo if the +# current file is inside of one, otherwise the current directory. +source "$HOME/.ad/lib/ad.sh" + +requireAd +pat="$*" +if [[ -z "$*" ]]; then + adCtl "expand-dot" + pat="$(bufRead "$AD_BUFID" dot)" +fi + +dirname="$(git rev-parse --show-toplevel)" +if [[ ! -d "$dirname" ]]; then + fname="$(bufRead "$AD_BUFID" filename)" + if [[ -d "$fname" ]]; then + dirname="$fname" + else + dirname="$(dirname "$fname")" + fi +fi + +rg "$pat" "$dirname" \ + --column \ + --line-number \ + --no-heading + +#cd "$dirname" || exit +#rg "$pat" \ +# --column \ +# --line-number \ +# --no-heading | +# sed 's/\(.\+\):\([0-9]\+\):\([0-9]\+\):/\1:\2:\3 /g' diff --git a/modules/mixins/dotfiles/home/ad/bin/NextSlide b/modules/mixins/dotfiles/home/ad/bin/NextSlide @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Advance to the next slide in a 'Slide' presentation +Slide next diff --git a/modules/mixins/dotfiles/home/ad/bin/PrevSlide b/modules/mixins/dotfiles/home/ad/bin/PrevSlide @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Return to the previous slide in a 'Slide' presentation +Slide prev diff --git a/modules/mixins/dotfiles/home/ad/bin/Slide b/modules/mixins/dotfiles/home/ad/bin/Slide @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# A simple control program for running text based presentations within ad +# via an index file. +# +# To run the presentation within ad, execute 'Slide' in a directory with the +# structure shown below. From there the NextSlide and PrevSlide commands can +# be used to move between the slides. +# +# > Example directory structure: +# . +# body +# conclusion +# index +# intro +# +# > Example index content: +# intro +# body +# conclusion + +. "$HOME/.ad/lib/ad.sh" + +requireAd + +fname="$(bufRead "$AD_BUFID" filename)" +f="$(basename "$fname")" +d="$(dirname "$fname")" + +[ ! -f "$d/index" ] && adError "not in a slideshow directory" +toLoad="$(head -n1 "$d/index")" + +case "$1" in + next) + i="$(grep -n "^$f\$" "$d/index" | cut -d: -f1)" + j="$(( "$i" + 1 ))" + toLoad="$(nl "$d/index" | grep "\s$j\s" | cut -f2)" + [ -z "$toLoad" ] && adError "This is the last slide" + ;; + + prev) + i="$(grep -n "^$f\$" "$d/index" | cut -d: -f1)" + j="$(( "$i" - 1 ))" + toLoad="$(nl "$d/index" | grep "\s$j\s" | cut -f2)" + [ -z "$toLoad" ] && adError "This is first slide" + ;; +esac + +echo "$d/$toLoad" | bufWrite "$AD_BUFID" filename +adCtl "Get" +adEdit "0 i/[PrevSlide] [NextSlide]\n\n/" +curToBof "$AD_BUFID" +markClean "$AD_BUFID" diff --git a/modules/mixins/dotfiles/home/ad/bin/cs b/modules/mixins/dotfiles/home/ad/bin/cs @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Set the colorscheme to either a light or dark theme +source "$HOME/.ad/lib/ad.sh" + +lightTheme="\ +set bg-color=#EBDBB2 +set fg-color=#282828 +set dot-bg-color=#d5C4A1 +set load-bg-color=#957FB8 +set exec-bg-color=#BF616A +set bar-bg-color=#83a598 +set signcol-fg-color=#458488 +set minibuffer-hl-color=#458488 +set comment-color=#624354 +set keyword-color=#BF616A +set control-flow-color=#7E9CD8 +set definition-color=#957FB8 +set punctuation-color=#DCA561 +set string-color=#61DCA5" + +darkTheme="\ +set bg-color=#1B1720 +set fg-color=#E6D29E +set dot-bg-color=#336677 +set load-bg-color=#957FB8 +set exec-bg-color=#BF616A +set bar-bg-color=#4E415C +set signcol-fg-color=#544863 +set minibuffer-hl-color=#3E3549 +set comment-color=#624354 +set keyword-color=#BF616A +set control-flow-color=#7E9CD8 +set definition-color=#957FB8 +set punctuation-color=#DCA561 +set string-color=#61DCA5" + + +case "${1:-dark}" in + "light") adCtl "$lightTheme" ;; + "dark") adCtl "$darkTheme" ;; + *) adError "invalid theme name" ;; +esac diff --git a/modules/mixins/dotfiles/home/ad/bin/fmt b/modules/mixins/dotfiles/home/ad/bin/fmt @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Attempt to format the current buffer based on the filetype +source "$HOME/.ad/lib/ad.sh" + +requireAd +fname=$(bufRead "$AD_BUFID" filename) +addr=$(bufRead "$AD_BUFID" addr) +maybext="${fname##*.}" + +case $maybext in + dart) formatted=$(bufRead "$AD_BUFID" body | dart format) ;; + json) formatted=$(bufRead "$AD_BUFID" body | jq) ;; + rs) formatted=$(bufRead "$AD_BUFID" body | rustfmt --edition 2021) ;; + *) adError "no format rules found for '$maybext'" ;; +esac + +if [[ -n "$formatted" ]]; then + echo -n "," | bufWrite "$AD_BUFID" xaddr + echo -n "$formatted" | bufWrite "$AD_BUFID" xdot + echo -n "$addr" | bufWrite "$AD_BUFID" addr + adCtl "viewport-center" +fi diff --git a/modules/mixins/dotfiles/home/ad/bin/indent b/modules/mixins/dotfiles/home/ad/bin/indent @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +source "$HOME/.ad/lib/ad.sh" + +requireAd +addr="$(bufRead "$AD_BUFID" addr | sed -E 's/(.+):.+,(.+):.+/\1,\2/')" +adEdit '. x/.+/ i/ /' +echo "$addr" | bufWrite "$AD_BUFID" addr diff --git a/modules/mixins/dotfiles/home/ad/bin/lint b/modules/mixins/dotfiles/home/ad/bin/lint @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Run lint for the current project and show the results so errors can be jumped to +set -eou pipefail + +. "$HOME/.ad/lib/ad.sh" + +root="$(git rev-parse --show-toplevel)" + +# Determine project type +if [ -e "$root/Cargo.toml" ]; then + adCtl "echo running 'cargo clippy'..." + cmd="cd $root && cargo clippy -q --message-format=short --color=never --all-targets 2>&1" + line="$(tmux-select -c "$cmd" | cut -d' ' -f1)" + if [ -z "$line" ]; then + exit 0 + fi + fname="$(echo "$line" | cut -d':' -f1)" + lnum="$(echo "$line" | cut -d':' -f2)" + col="$(echo "$line" | cut -d':' -f3)" + adCtl "open $root/$fname" + bufid="$(currentBufferId)" + echo -n "$lnum:$col" | bufWrite "$bufid" "addr" + adCtl "viewport-center" +else + adCtl "echo not linters configured for this file/project type" + exit 1 +fi diff --git a/modules/mixins/dotfiles/home/ad/bin/mount-ad b/modules/mixins/dotfiles/home/ad/bin/mount-ad @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# mount the ad virtual filesystem using 9pfuse +source "$HOME/.ad/lib/ad.sh" + +9pfuse "/tmp/ns.$USER.:0/ad" "$HOME/.ad/mnt" +adCtl "echo mounted ad filesystem to $HOME/.ad/mnt" diff --git a/modules/mixins/dotfiles/home/ad/bin/rust-check b/modules/mixins/dotfiles/home/ad/bin/rust-check @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# A simple ad helper script to lint Rust files on change and support checking +# details of errors that are reported. + +. "$HOME/.ad/lib/ad.sh" + +CARGO_FORMAT="short" +WATCH_TESTS="WatchTests" +STOP_TESTS="StopTests" +TEST_BUTTON="$WATCH_TESTS" +ARGS="" + +header() { + [[ -z "$ARGS" ]] || s=" args='$ARGS'" + echo -e "(Clear) (SetCargoFormat) ($TEST_BUTTON$s)\n" +} + +clearOutput() { adEdit "x/\n>>>@*/ c/\n>>>/"; } + +updateTestOutput() { + clearOutput + cargo test "$ARGS" | bufWrite "$1" body +} + +updateCargoOutput() { + clearBuffer "$1" + header | bufWrite "$1" body + # ensure that the output from cargo streams rather than buffering + cargo clippy --all-targets --workspace --message-format="$CARGO_FORMAT" 2>&1 | bufWrite "$1" body + echo -en "\n\n>>>" | bufWrite "$1" body + content="$(bufRead "$1" body)" + if [[ "$content" =~ error|warning ]]; then + focusBuffer "$1" + adEdit 'x/(.+):(\d+):(\d+):/ c/$1:$2:$3/' + elif [[ "$TEST_BUTTON" = "$STOP_TESTS" ]]; then + updateTestOutput "$1" + fi + curToBof "$1" + markClean "$1" +} + +handleEvents() { + bufRead "$1" event | while read -r line; do + kind="$(echo "$line" | jq -r '.kind')" + target="$(echo "$line" | jq -r '.txt')" + + case "$kind" in + "L") + if [[ "$target" =~ E.... ]]; then + output="$(cargo --explain "$target")" + curToBof "$1" + adEdit "x/\n>>>@*/ d" + echo -en "\n>>> Explanation for error[$target] (Clear)\n$output" | bufWrite "$1" body + markClean "$1" + else + echo -n "$line" | bufWrite "$1" event + fi + ;; + "X") + if [[ "$target" = "SetCargoFormat" ]]; then + raw="$(echo -en "human\nshort" | minibufferSelect "output format> ")" + if [[ "$raw" =~ human|short ]]; then + CARGO_FORMAT="$raw" + updateCargoOutput "$1" + fi + elif [[ "$target" = "$WATCH_TESTS" ]]; then + ARGS="$(echo -n "$ARGS" | minibufferSelect "args> ")" + TEST_BUTTON="$STOP_TESTS" + updateCargoOutput "$1" + elif [[ "$target" = "$STOP_TESTS" ]]; then + TEST_BUTTON="$WATCH_TESTS" + ARGS="" + updateCargoOutput "$1" + elif [[ "$target" = "Clear" ]]; then + clearOutput + markClean "$1" + else + echo -n "$line" | bufWrite "$1" event + fi + ;; + esac + done +} + +currentId="$(currentBufferId)" +root="$(git rev-parse --show-toplevel)" +adCtl "open-in-new-window $root/+cargo" +id="$(adIndex | grep "+cargo" | cut -f1)" +focusBuffer "$currentId" +updateCargoOutput "$id" +handleEvents "$id" & + +adLog | while read -r line; do + action="$(echo "$line" | cut -d' ' -f2)" + if [ "$action" = "save" ]; then + updateCargoOutput "$id" + fi +done diff --git a/modules/mixins/dotfiles/home/ad/bin/toggle-comment b/modules/mixins/dotfiles/home/ad/bin/toggle-comment @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Toggle line commenting for the lines within dot based on the filetype. +# +# This script requires a data file containing mappings between ad filetype +# names and the comment string that should be used for adding and removing +# line comments. +# +# Each line in the file should be of the form "$filetype $comment_str". e.g. +# bash # +# rust // +# toml # + +source "$HOME/.ad/lib/ad.sh" + +FTYPE_COMMENT_STRS="$HOME/.ad/lib/ftype-comment-chars.txt" + +requireAd +addr="$(bufRead "$AD_BUFID" addr | sed -E 's/(.+):.+,(.+):.+/\1,\2/')" +ftype="$(bufRead "$AD_BUFID" filetype)" +comment_str="$(grep "$ftype" "$FTYPE_COMMENT_STRS" | cut -d' ' -f2)" + +if [ -z "$comment_str" ]; then + adCtl "echo no configured comment string for $ftype" + exit 1 +fi + +echo '-,/\n/' | bufWrite "$AD_BUFID" xaddr # expand xdot to full lines + +# If every line starts with the comment string then we're uncommenting otherwise +# we're commenting out everything, even lines that already start with the comment +# string +xdot="$(bufRead "$AD_BUFID" xdot)" +n_lines="$(echo "$xdot" | wc -l)" +n_comment_lines="$(echo "$xdot" | grep "^\\s*$comment_str" | wc -l)" + +if [ "$n_lines" != "$n_comment_lines" ]; then + # expand to lines -> for each line -> insert comment_str at the start + adEdit "-,/\\n/ x/.*\\n/ i:$comment_str :" +else + # expand to lines -> for each line start up to comment_str -> remove comment_str + adEdit "-,/\\n/ x/.+\\n/ n:^(\\s*?)$comment_str ?: c/{1}/" +fi + +echo "$addr" | bufWrite "$AD_BUFID" addr +adCtl "echo addr was '$addr'" diff --git a/modules/mixins/dotfiles/home/ad/bin/unindent b/modules/mixins/dotfiles/home/ad/bin/unindent @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +source "$HOME/.ad/lib/ad.sh" + +requireAd +addr="$(bufRead "$AD_BUFID" addr | sed -E 's/(.+):.+,(.+):.+/\1,\2/')" +adEdit '. x/.+/ n/^ / d' +echo "$addr" | bufWrite "$AD_BUFID" addr diff --git a/modules/mixins/dotfiles/home/ad/bin/wd b/modules/mixins/dotfiles/home/ad/bin/wd @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Use the users warprc to navigate to files in known projects + +. "$HOME/.ad/lib/ad.sh" + +requireAd + +opt="$(cat "$HOME/.warprc" | cut -d: -f1 | sort | minibufferSelect "project> ")" +if [[ -n "$opt" ]]; then + dirname=$(cat "$HOME/.warprc" | grep "^$opt" | cut -d: -f2 | sed "s:~/:$HOME/:g") + fname="$(cd "$dirname" && fd | minibufferSelect "file> ")" + if [[ -n "$fname" ]]; then + adCtl "open $dirname/$fname" + fi +fi diff --git a/modules/mixins/dotfiles/home/ad/colorschemes/default_dark.toml b/modules/mixins/dotfiles/home/ad/colorschemes/default_dark.toml @@ -0,0 +1,71 @@ +fg = "fg" +bg = "bg" +bar_bg = "#4E415C" +signcol_fg = "#544863" +minibuffer_hl = "#3E3549" + +[palette] +fg = "#E6D29E" +bg = "#1B1720" +bg2 = "#292532" +blue = "#8793B5" +brown = "#624354" +cyan = "#7AA89F" +dark-blue = "#2D4F67" +dark-yellow = "#DCA561" +gray = "#716E77" +green = "#76946A" +light-blue = "#9CABCA" +light-gray = "#908D96" +light-red = "#D27E99" +magenta = "#A292E8" +mint = "#61DCA5" +orange = "#FFA066" +pink = "#D27E99" +purple = "#957FB8" +red = "#C34043" +sage = "#9AB292" +salmon = "#Bf616A" +sea-blue = "#336677" +yellow = "#E6C384" + +[syntax] +default = { fg = "fg", bg = "bg" } +dot = { bg = "sea-blue" } +load = { bg = "purple" } +exec = { bg = "salmon" } + +boolean = { fg = "dark-yellow", bold = true } +character = { fg = "mint", italic = true } +comment = { fg = "brown", italic = true } +constant = { fg = "orange", bold = true } +function = { fg = "blue" } +keyword = { fg = "salmon" } +module = { fg = "dark-blue" } +number = { fg = "light-red" } +operator = { fg = "dark-yellow" } +punctuation = { fg = "light-blue" } +string = { fg = "mint" } +type = { fg = "sage" } +variable = { } + +# Specialisations + +"function.macro" = { fg = "orange", italic = true } +"function.operator" = { fg = "light-gray" } + +"markup.italic" = { italic = true } +"markup.bold" = { bold = true } +"markup.heading" = { fg = "blue", bold = true } +"markup.raw" = { fg = "brown", italic = true } +"markup.quote" = { fg = "purple", italic = true } +"markup.link.url" = { fg = "light-blue", underline = true } +"markup.link.label" = { fg = "dark-blue", bold = true } +"markup.list.unchecked" = { fg = "dark-yellow", bold = true } +"markup.list.checked" = { fg = "sage", bold = true } +"markup.list" = { fg = "light-blue", bold = true } + +"string.template" = { fg = "mint", bg = "bg2", bold = true } +"string.regex" = { fg = "sea-blue", bg = "bg", italic = true } + +label = { fg = "yellow" } diff --git a/modules/mixins/dotfiles/home/ad/colorschemes/default_light.toml b/modules/mixins/dotfiles/home/ad/colorschemes/default_light.toml @@ -0,0 +1,71 @@ +fg = "fg" +bg = "bg" +bar_bg = "#83A598" +signcol_fg = "#458488" +minibuffer_hl = "#8fafa2" + +[palette] +fg = "#644855" +bg = "#EBDBB2" +bg2 = "#DED0A4" +blue = "#4685c0" +brown = "#9b8391" +cyan = "#2D8A7A" +dark-blue = "#726a98" +dark-yellow = "#DCA561" +gray = "#7C7976" +green = "#5F8A3B" +light-blue = "#6B9BC3" +light-gray = "#9A9895" +light-red = "#D27E99" +magenta = "#8A6DB8" +mint = "#347e73" +orange = "#ce752c" +pink = "#D27E99" +purple = "#957FB8" +red = "#C34043" +sage = "#6A8A62" +salmon = "#a44860" +sea-blue = "#458488" +yellow = "#B8960C" + +[syntax] +default = { fg = "fg", bg = "bg" } +dot = { bg = "bg2" } +load = { bg = "purple" } +exec = { bg = "salmon" } + +boolean = { fg = "dark-yellow", bold = true } +character = { fg = "mint", italic = true } +comment = { fg = "brown", italic = true } +constant = { fg = "orange", bold = true } +function = { fg = "blue" } +keyword = { fg = "salmon" } +module = { fg = "dark-blue" } +number = { fg = "light-red" } +operator = { fg = "dark-yellow" } +punctuation = { fg = "light-blue" } +string = { fg = "mint" } +type = { fg = "sage" } +variable = { } + +# Specialisations + +"function.macro" = { fg = "orange", italic = true } +"function.operator" = { fg = "light-gray" } + +"markup.italic" = { italic = true } +"markup.bold" = { bold = true } +"markup.heading" = { fg = "blue", bold = true } +"markup.raw" = { fg = "brown", italic = true } +"markup.quote" = { fg = "purple", italic = true } +"markup.link.url" = { fg = "light-blue", underline = true } +"markup.link.label" = { fg = "dark-blue", bold = true } +"markup.list.unchecked" = { fg = "dark-yellow", bold = true } +"markup.list.checked" = { fg = "sage", bold = true } +"markup.list" = { fg = "light-blue", bold = true } + +"string.template" = { fg = "mint", bg = "bg2", bold = true } +"string.regex" = { fg = "sea-blue", bg = "bg", italic = true } + +label = { fg = "yellow" } diff --git a/modules/mixins/dotfiles/home/ad/colorschemes/doric_dark.toml b/modules/mixins/dotfiles/home/ad/colorschemes/doric_dark.toml @@ -0,0 +1,73 @@ +fg = "fg" +bg = "bg" +bar_bg = "neutral-bg" +signcol_fg = "border" +minibuffer_hl = "subtle-bg" + +[palette] +fg = "#ffffff" +bg = "#000000" +border = "#707070" +cursor = "#ccaaee" + +subtle-bg = "#332d38" +subtle-fg = "#a2a0b2" +neutral-bg = "#43404c" +neutral-fg = "#c5c7d4" +intense-bg = "#50447f" +intense-fg = "#cfcff8" +accent-bg = "#521e40" +accent-fg = "#cda4df" + +red = "#eca28f" +red-bg = "#4d1f20" +green = "#b9d0aa" +green-bg = "#1f402e" +yellow = "#c0b080" +yellow-bg = "#504432" +blue = "#9fbfe7" +blue-bg = "#223567" +magenta = "#e9acbf" +magenta-bg = "#603254" +cyan = "#a0c0d0" +cyan-bg = "#2f4f54" + +[syntax] +default = { fg = "fg", bg = "bg" } +dot = { bg = "cyan-bg" } +load = { bg = "magenta-bg" } +exec = { bg = "red-bg" } + +boolean = { fg = "yellow", bold = true } +character = { fg = "green", italic = true } +comment = { fg = "neutral-fg", italic = true } +constant = { fg = "accent-fg", bold = true } +function = { fg = "blue" } +keyword = { fg = "magenta" } +module = { fg = "blue-bg" } +number = { fg = "red" } +operator = { fg = "yellow" } +punctuation = { fg = "cyan" } +string = { fg = "green" } +type = { fg = "cyan" } +variable = { } + +# Specialisations +"function.macro" = { fg = "accent-fg", italic = true } +"function.operator" = { fg = "neutral-fg" } + +"markup.italic" = { italic = true } +"markup.bold" = { bold = true } +"markup.heading" = { fg = "blue", bold = true } +"markup.raw" = { fg = "yellow", italic = true } +"markup.quote" = { fg = "magenta", italic = true } +"markup.link.url" = { fg = "cyan", underline = true } +"markup.link.label" = { fg = "blue-bg", bold = true } +"markup.list.unchecked" = { fg = "yellow", bold = true } +"markup.list.checked" = { fg = "green", bold = true } +"markup.list" = { fg = "cyan", bold = true } + +"string.template" = { fg = "green", bg = "subtle-bg", bold = true } +"string.regex" = { fg = "cyan", bg = "bg", italic = true } + +label = { fg = "yellow" } diff --git a/modules/mixins/dotfiles/home/ad/config.toml b/modules/mixins/dotfiles/home/ad/config.toml @@ -0,0 +1,210 @@ +# Config file for the ad text editor +# For details of the TOML file format see https://toml.io/en/v1.0.0 + +# Top level config options +[editor] +# Display a welcome message when opening the editor without any files +show_splash = true +# Whether or not tab characters should be automatically replaced with `tabstop` spaces +expand_tab = true +# The number of spaces to render tab characters with +tabstop = 4 +# Whether or not leading whitespace should be copied to new lines on pressing Return +match_indent = true +# Number of seconds to persist status messages for +status_timeout = 3 +# Number of milliseconds allowed between left mouse clicks for registering a double click +double_click_ms = 200 +# Maximum number of lines used when rendering the minibuffer state +minibuffer_lines = 8 +# Shell command to be used for listing files when running the `find file` and `find repo file` commands +find_command = "fd --hidden" + + +[filesystem] +# Whether or not the 9p filesystem interface should be enabled or not +enabled = true +# Whether or not the 9p filesystem interface should attempt to automount via fuse on startup +auto_mount = false + + +# Configuration for tree-sitter based syntax highlighting. See :help for details on the required +# directory structure. +[tree_sitter] +# The directory to search for compiled *.so files for parsing each language. +parser_dir = "~/.ad/tree-sitter/parsers" +# The directory to search for syntax highlighting queries. +syntax_query_dir = "~/.ad/tree-sitter/queries" + + +# Global color scheme settings +# +# It is also possible to specify an absolute path to a colorscheme TOML file containing this section of the config +# like so: +[colorscheme] +fg = "fg" +bg = "bg" +bar_bg = "neutral-bg" +signcol_fg = "border" +minibuffer_hl = "subtle-bg" + +[colorscheme.palette] +fg = "#ffffff" +bg = "#000000" +border = "#707070" +cursor = "#ccaaee" + +subtle-bg = "#332d38" +subtle-fg = "#a2a0b2" +neutral-bg = "#43404c" +neutral-fg = "#c5c7d4" +intense-bg = "#50447f" +intense-fg = "#cfcff8" +accent-bg = "#521e40" +accent-fg = "#cda4df" + +red = "#eca28f" +red-bg = "#4d1f20" +green = "#b9d0aa" +green-bg = "#1f402e" +yellow = "#c0b080" +yellow-bg = "#504432" +blue = "#9fbfe7" +blue-bg = "#223567" +magenta = "#e9acbf" +magenta-bg = "#603254" +cyan = "#a0c0d0" +cyan-bg = "#2f4f54" + +[colorscheme.syntax] +default = { fg = "fg", bg = "bg" } +dot = { bg = "cyan-bg" } +load = { bg = "magenta-bg" } +exec = { bg = "red-bg" } + +boolean = { fg = "yellow", bold = true } +character = { fg = "green", italic = true } +comment = { fg = "neutral-fg", italic = true } +constant = { fg = "accent-fg", bold = true } +function = { fg = "blue" } +keyword = { fg = "magenta" } +module = { fg = "blue-bg" } +number = { fg = "red" } +operator = { fg = "yellow" } +punctuation = { fg = "cyan" } +string = { fg = "green" } +type = { fg = "cyan" } +variable = { } + +# Specialisations +"function.macro" = { fg = "accent-fg", italic = true } +"function.operator" = { fg = "neutral-fg" } + +"markup.italic" = { italic = true } +"markup.bold" = { bold = true } +"markup.heading" = { fg = "blue", bold = true } +"markup.raw" = { fg = "yellow", italic = true } +"markup.quote" = { fg = "magenta", italic = true } +"markup.link.url" = { fg = "cyan", underline = true } +"markup.link.label" = { fg = "blue-bg", bold = true } +"markup.list.unchecked" = { fg = "yellow", bold = true } +"markup.list.checked" = { fg = "green", bold = true } +"markup.list" = { fg = "cyan", bold = true } + +"string.template" = { fg = "green", bg = "subtle-bg", bold = true } +"string.regex" = { fg = "cyan", bg = "bg", italic = true } + +label = { fg = "yellow" } + +# Key mappings to programs that must be available on $PATH or commands. +# ~/.ad/bin is auto-added to the path +[keys.normal] +"<space> F" = { run = "fmt" } +">" = { run = "indent" } +"<" = { run = "unindent" } +# Window & Column management +"<space> w /" = { run = "new-column" } +"<space> w -" = { run = "new-window" } +"<space> w h" = { run = "prev-column" } +"<space> w j" = { run = "next-window" } +"<space> w k" = { run = "prev-window" } +"<space> w l" = { run = "next-column" } + + +# Filetype configuration + +[filetypes.awk] +extensions = ["awk"] +first_lines = ["#!/usr/bin/awk -f", "#!/usr/bin/env -S awk -f"] + +[filetypes.bash] +extensions = ["sh", "bash"] +first_lines = ["#!/usr/bin/bash", "#!/usr/bin/sh", "#!/usr/bin/env bash", "#!/usr/bin/env sh"] +lsp.command = "bash-language-server" +lsp.args = ["start"] +lsp.roots = [".git"] + +[filetypes.c] +extensions = ["c", "h"] + +[filetypes.dart] +extensions = ["dart"] +lsp.command = "dart" +lsp.args = ["language-server", "--protocol=lsp"] +lsp.roots = ["melos.yaml", "pubspec.yaml"] + +[filetypes.graphql] +extensions = ["graphql"] + +[filetypes.json] +extensions = ["json"] + +[filetypes.just] +filenames = ["justfile"] + +[filetypes.make] +filenames = ["Makefile"] + +[filetypes.markdown] +extensions = ["md"] + +[filetypes.plumbing_rules] +filenames = ["plumbing.rules"] + +[filetypes.proto] +extensions = ["proto"] + +[filetypes.python] +extensions = ["py"] +lsp.command = "pylsp" +lsp.roots = ["dummy.py"] + +[filetypes.r] +extensions = ["R"] +lsp.command = "R" +lsp.args = ["--slave", "-e", "languageserver::run()"] +lsp.roots = ["dummy.R"] + +[filetypes.rust] +extensions = ["rs"] +lsp.command = "rust-analyzer" +lsp.roots = ["Cargo.toml"] + +[filetypes.scheme] +extensions = ["scm"] + +[filetypes.sql] +extensions = ["sql"] + +[filetypes.swift] +extensions = ["swift"] + +[filetypes.toml] +extensions = ["toml"] + +# [filetypes.txtar] +# extensions = ["txtar"] +# re_syntax = "~/.ad/syntax/txtar.toml" + +[filetypes.yaml] +extensions = ["yaml", "yml"] diff --git a/modules/mixins/dotfiles/home/ad/lib/ad.sh b/modules/mixins/dotfiles/home/ad/lib/ad.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# Helper functions for writing scripts to interact with ad + +[ -e "$HOME/.profile" ] && source ~/.profile + +# Write a control message to ad. +# The format accepted is the same as when using the internal command line +adCtl() { echo -n "$*" | ad -9p write ad/ctl; } + +# Execute an Edit script within the current buffer +adEdit() { adCtl "Edit $*"; } + +# Read the contents of the index file +adIndex() { ad -9p read ad/buffers/index; } + +# Display an error in the editor status line and exit +adError() { + adCtl "echo $*" + exit 1 +} + +# Exit with an error message if this script was not launched from ad itself +requireAd() { + [[ -z "$AD_PID" ]] && adError "need to be run from inside of ad" +} + +# Read the contents of an fsys file for the specified buffer +bufRead() { ad -9p read "ad/buffers/$1/$2"; } + +# Write a string to the specified buffer file +bufWrite() { ad -9p write "ad/buffers/$1/$2"; } + +# Follow the ad log stream of ongoing buffer events +adLog() { ad -9p read ad/log; } + +# Fetch the id of the currently focused buffer +currentBufferId() { ad -9p read ad/buffers/current; } + +# Set focus to the buffer with the specified id +focusBuffer() { echo "$1" | ad -9p write ad/buffers/current; } + +# Clear the contents of the current buffer +clearBuffer() { + echo -n "," | bufWrite "$1" xaddr + echo -n "" | bufWrite "$1" xdot +} + +# Mark the buffer with the specified id as clean +markClean() { adCtl "mark-clean $1"; } + +# Set the cursor position for the specified buffer to the beginning of the file +curToBof() { echo -n 0 | bufWrite "$1" addr; } + +# Set the cursor position for the specified buffer to the end of the file +curToEof() { echo -n '$' | bufWrite "$1" addr; } + +# dmenu style selection from newline delimited input on stdin +minibufferSelect() { + ad -9p write ad/minibuffer + [ -n "$1" ] && adCtl "minibuffer-prompt $1" + ad -9p read ad/minibuffer +} + +# Prompt the user for input +minibufferPrompt() { echo '' | minibufferSelect "$@"; } diff --git a/modules/mixins/dotfiles/home/ad/lib/ftype-comment-chars.txt b/modules/mixins/dotfiles/home/ad/lib/ftype-comment-chars.txt @@ -0,0 +1,15 @@ +bash # +c // +dart // +graphql # +just # +make # +plumbingrules # +proto // +python # +rust // +scheme ; +sql -- +swift // +toml # +yaml # diff --git a/modules/mixins/dotfiles/home/ad/plumbing.rules b/modules/mixins/dotfiles/home/ad/plumbing.rules @@ -0,0 +1,45 @@ +# These are the default plumbing rules for ad + +editor = ad +addrelem = ((#?[0-9]+)|(/[A-Za-z0-9_\^]+/?)|[.$]) +addr = :($addrelem([,;+\-]$addrelem)*) + +# git commits, inspired by https://alexkarle.com/blog/plan9-acme-git-gui.html +data matches [a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+ +data from git -C $wdir show $0 +attr add action=showdata filename=/git/$0 +plumb to edit + +# urls go to a web browser +data matches https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*) +plumb to web +plumb start xdg-open $0 + +# image files go an image viewer +data matches [a-zA-Z¡-￿0-9_\-./@]+ +data matches ([a-zA-Z¡-￿0-9_\-./@]+)\.(jpe?g|JPE?G|gif|GIF|tiff?|TIFF?|ppm|bit|png|PNG) +arg isfile $0 +plumb to image +plumb start xdg-open $0 + +# pdfs go to a pdf viewer +data matches [a-zA-Z¡-￿0-9_\-./@]+ +data matches ([a-zA-Z¡-￿0-9_\-./@]+)\.[Pp][Dd][Ff] +arg isfile $0 +plumb to pdf +plumb start zathura $0 +plumb start xdg-open $0 + +# existing files tagged by line number:columnumber, go to editor +# data matches ([.a-zA-Z¡-￿0-9_/\-@]*[a-zA-Z¡-￿0-9_/\-]):([0-9]+):([0-9]+):? +data matches (.+):([0-9]+):([0-9]+):? +arg isfile $1 +data set $file +attr add addr=$2:$3 +plumb to edit + +# man index entries are synthesized +data matches ([a-zA-Z¡-￿0-9_\-./]+)\(([1-8])\) +data from man $2 $1 +attr add action=showdata filename=/man/$1($2) +plumb to edit diff --git a/modules/mixins/dotfiles/home/ad/syntax/ad.toml b/modules/mixins/dotfiles/home/ad/syntax/ad.toml @@ -0,0 +1,2 @@ +comment = "\\b#.*" +keyword = "\\b(x|y|g|v|p)/.+/\\b" diff --git a/modules/mixins/dotfiles/home/ad/syntax/plumbing-rules.toml b/modules/mixins/dotfiles/home/ad/syntax/plumbing-rules.toml @@ -0,0 +1,3 @@ +comment = "\\b#.*" +keyword = "\\b(data|attr|plumb|arg)\\b" +function = "\\b(matches|narrows|from|add|to|set|start|isfile|isdir)\\b" diff --git a/modules/mixins/dotfiles/home/ad/syntax/txtar.toml b/modules/mixins/dotfiles/home/ad/syntax/txtar.toml @@ -0,0 +1 @@ +"keyword" = "^-- .+ --$" diff --git a/modules/mixins/dotfiles/home/atoprc b/modules/mixins/dotfiles/home/atoprc @@ -0,0 +1 @@ +interval 1 diff --git a/modules/mixins/dotfiles/home/bash_profile b/modules/mixins/dotfiles/home/bash_profile @@ -0,0 +1,11 @@ +[[ "$-" == *i* ]] || return + +config_home="$HOME" + +. "$config_home"/.config/shell/early-funcs + +for file in "$config_home"/.config/{shell,bash}/profile/*; do + [[ -e $file ]] && . "$file" +done + +[[ -r "$config_home"/.bashrc ]] && . "$config_home"/.bashrc diff --git a/modules/mixins/dotfiles/home/bashrc b/modules/mixins/dotfiles/home/bashrc @@ -0,0 +1,13 @@ +#!/bin/bash + +[[ "$-" == *i* ]] || return + +config_home="$HOME" + +. "$config_home"/.config/shell/early-funcs + +for file in "$config_home"/.config/{shell,bash}/rc/*; do + [[ -e $file ]] && . "$file" +done + +PS1='$(_get_ps1)' diff --git a/modules/mixins/dotfiles/home/cargo/config.toml b/modules/mixins/dotfiles/home/cargo/config.toml @@ -0,0 +1,13 @@ +[build] +rustflags = ["-C", "target-cpu=native", "-C", "link-arg=-fuse-ld=mold"] + +[profile.release] +codegen-units = 1 +lto = "fat" + +[profile.profiling] +inherits = "release" +debug = true +codegen-units = 64 +lto = "off" +incremental = true diff --git a/modules/mixins/dotfiles/home/curlrc b/modules/mixins/dotfiles/home/curlrc @@ -0,0 +1,8 @@ +connect-timeout = 30 +show-error + +# When following a redirect, automatically set the previous URL as referer +referer = ";auto" + +continue-at = - +location diff --git a/modules/mixins/dotfiles/home/gitconfig b/modules/mixins/dotfiles/home/gitconfig @@ -0,0 +1,46 @@ +[includeIf "gitdir:~/src/"] + path = ~/misc/git/gitconfig-gpgsign-enabled + +[includeIf "gitdir:~/src/misc/"] + path = ~/misc/git/gitconfig-gpgsign-disabled + +[init] + defaultBranch = master + +[user] + name = mtmn + email = miro@haravara.org + +[color] + ui = auto + +[push] + default = current + +[merge] + tool = vimdiff + conflictstyle = diff3 + +[rebase] + autosquash = true + +[alias] + why-ignore = check-ignore -v + wip = for-each-ref --sort='authordate:iso8601' --format=' %(color:green)%(authordate:relative)%09%(color:white)%(refname:short)' refs/heads + gol = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit + +[pull] + rebase = false + +[merge] + conflictstyle = diff3 + +[diff] + colorMoved = default + external = difft + +[difftool] + prompt = false + +[worktree] + guessRemote = true diff --git a/modules/mixins/dotfiles/home/gnupg/gpg-agent.conf b/modules/mixins/dotfiles/home/gnupg/gpg-agent.conf @@ -0,0 +1,3 @@ +pinentry-program ~/bin/pinentry-bemenu +no-allow-external-cache +default-cache-ttl 3600 diff --git a/modules/mixins/dotfiles/home/gtkrc-2.0 b/modules/mixins/dotfiles/home/gtkrc-2.0 @@ -0,0 +1,15 @@ +gtk-theme-name="Adwaita-dark" +gtk-icon-theme-name="Arc" +gtk-font-name=Cozette 8 +gtk-cursor-theme-name="OSX-ElCap" +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle="hintfull" +gtk-xft-rgba="rgb" diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursor.theme b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursor.theme @@ -0,0 +1,2 @@ +[Icon Theme] +Inherits=OSX-ElCap diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/00008160000006810000408080010102 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/00008160000006810000408080010102 @@ -0,0 +1 @@ +v_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/028006030e0e7ebffc7f7070c0600140 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/028006030e0e7ebffc7f7070c0600140 @@ -0,0 +1 @@ +h_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/03b6e0fcb3499374a867c041f52298f0 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/03b6e0fcb3499374a867c041f52298f0 @@ -0,0 +1 @@ +crossed_circle +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/08e8e1c95fe2fc01f976f1e063a24ccd b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/08e8e1c95fe2fc01f976f1e063a24ccd @@ -0,0 +1 @@ +left_ptr_watch +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/1081e37283d90000800003c07f3ef6bf b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/1081e37283d90000800003c07f3ef6bf @@ -0,0 +1 @@ +copy +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/14fef782d02440884392942c11205230 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/14fef782d02440884392942c11205230 @@ -0,0 +1 @@ +sb_h_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/2870a09082c103050810ffdffffe0204 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/2870a09082c103050810ffdffffe0204 @@ -0,0 +1 @@ +sb_v_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/3085a0e285430894940527032f8b26df b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/3085a0e285430894940527032f8b26df @@ -0,0 +1 @@ +link +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/3ecb610c1bf2410f44200f48c40d3599 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/3ecb610c1bf2410f44200f48c40d3599 @@ -0,0 +1 @@ +left_ptr_watch +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/4498f0e0c1937ffe01fd06f973665830 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/4498f0e0c1937ffe01fd06f973665830 @@ -0,0 +1 @@ +move +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 @@ -0,0 +1 @@ +question_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/6407b0e94181790501fd1e167b474872 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/6407b0e94181790501fd1e167b474872 @@ -0,0 +1 @@ +copy +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/640fb0e74195791501fd1ed57b41487f b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/640fb0e74195791501fd1ed57b41487f @@ -0,0 +1 @@ +link +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/9081237383d90e509aa00f00170e968f b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/9081237383d90e509aa00f00170e968f @@ -0,0 +1 @@ +move +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/9d800788f1b08800ae810202380a0822 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/9d800788f1b08800ae810202380a0822 @@ -0,0 +1 @@ +hand2 +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/X_cursor b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/X_cursor Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/arrow @@ -0,0 +1 @@ +left_ptr +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bd_double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bd_double_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_left_corner b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_left_corner Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_right_corner b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_right_corner Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_side b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_side Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_tee b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/bottom_tee Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/c7088f0f3e6c8088236ef8e1e3e70000 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/c7088f0f3e6c8088236ef8e1e3e70000 @@ -0,0 +1 @@ +bd_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/circle b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/circle Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/color-picker b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/color-picker Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/copy b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/copy Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/cross b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/cross Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/cross_reverse b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/cross_reverse @@ -0,0 +1 @@ +cross +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/crossed_circle b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/crossed_circle Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/crosshair b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/crosshair Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/d9ce0ab605698f320427677b458ad60b b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/d9ce0ab605698f320427677b458ad60b @@ -0,0 +1 @@ +question_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/diamond_cross b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/diamond_cross @@ -0,0 +1 @@ +cross +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-ask b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-ask Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-copy b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-copy Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-link b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-link Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-move b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-move Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-none b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dnd-none Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dot_box_mask b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dot_box_mask @@ -0,0 +1 @@ +dotbox +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dotbox b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/dotbox Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/double_arrow @@ -0,0 +1 @@ +sb_v_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draft_large b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draft_large @@ -0,0 +1 @@ +right_ptr +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draft_small b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draft_small @@ -0,0 +1 @@ +right_ptr +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draped_box b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/draped_box @@ -0,0 +1 @@ +dotbox +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/e29285e634086352946a0e7090d73106 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/e29285e634086352946a0e7090d73106 @@ -0,0 +1 @@ +hand2 +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fcf1c3c7cd4491d801f1e1c78f100000 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fcf1c3c7cd4491d801f1e1c78f100000 @@ -0,0 +1 @@ +fd_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fd_double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fd_double_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fleur b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/fleur @@ -0,0 +1 @@ +grabbing +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/grabbing b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/grabbing Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/h_double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/h_double_arrow @@ -0,0 +1 @@ +sb_h_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand @@ -0,0 +1 @@ +hand2 +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand1 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand1 @@ -0,0 +1 @@ +hand2 +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand2 b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/hand2 Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/help b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/help @@ -0,0 +1 @@ +question_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/icon b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/icon @@ -0,0 +1 @@ +dotbox +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr_help b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr_help @@ -0,0 +1 @@ +question_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr_watch b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_ptr_watch Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_side b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_side Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_tee b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/left_tee Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/link b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/link Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ll_angle b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ll_angle Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/lr_angle b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/lr_angle Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/move b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/move Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/pencil b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/pencil Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/pirate b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/pirate @@ -0,0 +1 @@ +X_cursor +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/plus b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/plus Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/question_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/question_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_ptr b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_ptr Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_side b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_side Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_tee b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/right_tee Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_down_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_down_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_h_double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_h_double_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_left_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_left_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_right_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_right_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_up_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_up_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_v_double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/sb_v_double_arrow Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/target b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/target @@ -0,0 +1 @@ +dotbox +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/tcross b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/tcross Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_left_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_left_arrow @@ -0,0 +1 @@ +left_ptr +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_left_corner b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_left_corner Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_right_corner b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_right_corner Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_side b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_side Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_tee b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/top_tee Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ul_angle b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ul_angle Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ur_angle b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/ur_angle Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/v_double_arrow b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/v_double_arrow @@ -0,0 +1 @@ +sb_v_double_arrow +\ No newline at end of file diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/watch b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/watch Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/xterm b/modules/mixins/dotfiles/home/icons/OSX-ElCap/cursors/xterm Binary files differ. diff --git a/modules/mixins/dotfiles/home/icons/OSX-ElCap/index.theme b/modules/mixins/dotfiles/home/icons/OSX-ElCap/index.theme @@ -0,0 +1,3 @@ +[Icon Theme] +Name=OSX-ElCap +Comment=OSX El Capitan cursor theme by xxmmtrtxx diff --git a/modules/mixins/dotfiles/home/inputrc b/modules/mixins/dotfiles/home/inputrc @@ -0,0 +1,36 @@ +set bell-style none + +# Enable 8th bit input +set meta-flag on +set input-meta on +set output-meta on +set convert-meta off + +set show-all-if-unmodified on + +set editing-mode vi + +$if mode=vi + set keymap vi-insert + "jk": vi-movement-mode + "kj": vi-movement-mode + Control-a: beginning-of-line + Control-e: end-of-line + Control-n: next-history + Control-p: previous-history + Control-L: clear-screen + Control-k: kill-line + Control-w: unix-word-rubout + Control-d: delete-char + + set keymap vi-command + Control-e: vi-append-eol + Control-a: vi-insert-beg + Control-w: unix-word-rubout + Control-d: delete-char +$endif + +set keymap vi + +"\e[A": history-search-backward +"\e[B": history-search-forward diff --git a/modules/mixins/dotfiles/home/lftprc b/modules/mixins/dotfiles/home/lftprc @@ -0,0 +1 @@ +set sftp:connect-program "ssh -i ~/.ssh/id_ed25519" diff --git a/modules/mixins/dotfiles/home/local/share/applications/nsxiv.desktop b/modules/mixins/dotfiles/home/local/share/applications/nsxiv.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=nsxiv +GenericName=Image Viewer +Exec=nsxiv-rifle %F +MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-tga;image/x-xpixmap;image/webp;image/heic;image/svg+xml;application/postscript;image/jp2;image/jxl;image/avif;image/heif; +NoDisplay=true +Icon=nsxiv diff --git a/modules/mixins/dotfiles/home/ne/dot_keys b/modules/mixins/dotfiles/home/ne/dot_keys @@ -0,0 +1,17 @@ +# Ctrl+W +KEY 17 DeletePrevWord + +# Ctrl+D +KEY 4 Macro replace-todo-with-done + +# Ctrl+T +KEY 14 insert-todo + +# Ctrl-P +KEY 10 LineUp + +# Ctrl-N +KEY E LineDown + +# Ctrl+K +KEY B DeleteLine diff --git a/modules/mixins/dotfiles/home/ne/end-of-line b/modules/mixins/dotfiles/home/ne/end-of-line @@ -0,0 +1 @@ +eol diff --git a/modules/mixins/dotfiles/home/ne/insert-done b/modules/mixins/dotfiles/home/ne/insert-done @@ -0,0 +1 @@ +InsertString done: diff --git a/modules/mixins/dotfiles/home/ne/insert-todo b/modules/mixins/dotfiles/home/ne/insert-todo @@ -0,0 +1 @@ +InsertString todo: diff --git a/modules/mixins/dotfiles/home/ne/replace-todo-with-done b/modules/mixins/dotfiles/home/ne/replace-todo-with-done @@ -0,0 +1,4 @@ +MoveSOL +Find todo +ReplaceOnce done +MoveSOL diff --git a/modules/mixins/dotfiles/home/python-version b/modules/mixins/dotfiles/home/python-version @@ -0,0 +1 @@ +3.7.4 diff --git a/modules/mixins/dotfiles/home/pythonrc b/modules/mixins/dotfiles/home/pythonrc @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +def _setup_readline(): + import atexit + import os + import readline + import rlcompleter + + history_path = os.path.expanduser("~/.python_history") + + if not os.path.exists(history_path) and not os.path.isdir(history_path): + try: + open(history_path, 'w').close() + except IOError: + pass + + if os.access(history_path, os.W_OK): + atexit.register(lambda x=history_path: readline.write_history_file(x)) + + if os.access(history_path, os.R_OK): + readline.read_history_file(history_path) + + readline.parse_and_bind("tab: complete") + readline.set_history_length(100000) + +_setup_readline() + +# Default imports +from pprint import pprint as pp +import os +import sys diff --git a/modules/mixins/dotfiles/home/sshrc b/modules/mixins/dotfiles/home/sshrc @@ -0,0 +1,33 @@ +export PATH="$PATH:$HOME/go/bin" +export GOPATH="$HOME/go" + +alias q='sudo-rs ' +alias dfh='df -h /' +alias duh='du -hs .' + +alias lopri='nice -n 19 ionice -c2 -n7 ' +alias scan='sudo nmap -n -PN -sT -sU -p-' + +alias ss='sudo systemctl start' +alias st='sudo systemctl stop' +alias sd='sudo systemctl -n 100 status' + +alias us='systemctl --user start' +alias ut='systemctl --user stop' +alias ud='systemctl --user -n 100 status' + +mkdir -p ~/.config/shell/rc + +cp "$SSHHOME/.sshrc.d/vimrc" ~/.vimrc +cp "$SSHHOME/.sshrc.d/tmuxconf" ~/.config/.tmux.conf + +cp "$SSHHOME/.sshrc.d/early-funcs" ~/.config/shell + +cp "$SSHHOME/.sshrc.d/git" ~/.config/shell/rc +cp "$SSHHOME/.sshrc.d/jujutsu" ~/.config/shell/rc +cp "$SSHHOME/.sshrc.d/prompt-functions" ~/.config/shell/rc +cp "$SSHHOME/.sshrc.d/aliased-short-names" ~/.config/shell/rc + +cp "$SSHHOME/.sshrc.d/bashrc" ~/.bashrc + +source ~/.bashrc diff --git a/modules/mixins/dotfiles/home/sshrc.d/tmuxconf.nix b/modules/mixins/dotfiles/home/sshrc.d/tmuxconf.nix @@ -0,0 +1,3 @@ +{homeDir, ...}: '' + ${homeDir}/.tmux.conf +'' diff --git a/modules/mixins/dotfiles/home/sshrc.d/vimrc.nix b/modules/mixins/dotfiles/home/sshrc.d/vimrc.nix @@ -0,0 +1,3 @@ +{homeDir, ...}: '' + ${homeDir}/.vimrc +'' diff --git a/modules/mixins/dotfiles/home/tmux.conf b/modules/mixins/dotfiles/home/tmux.conf @@ -0,0 +1,47 @@ +set-option -g status-position top + +set -g base-index 1 +setw -g pane-base-index 1 + +set-option -g update-environment "WAYLAND_DISPLAY DISPLAY" + +set -g default-terminal "foot" + +set -g status-interval 30 +set -g status-style fg=#ffffff,bg=#332d38 + +set -g status-left '' +set -g status-right '#(test -f /tmp/pracomer.log && cat /tmp/pracomer.log) %a %h-%d %H:%M #(cat /sys/class/power_supply/BAT*/capacity 2>/dev/null)%% ' + +set -g pane-border-style fg=#332d38 +set -g pane-active-border-style fg=#50447f + +setw -g window-status-style fg=#a0c0d0,bg=#332d38 +setw -g window-status-current-style fg=#ffffff,bg=#50447f,bold + +set -g message-style fg=#ffffff,bg=#50447f +set -g message-command-style fg=#ffffff,bg=#50447f + +setw -g xterm-keys on +set -ga terminal-overrides ',xterm*:XT' + +set -g set-titles on +set -g set-titles-string "#S" +set -g renumber-windows on + +set -s escape-time 0 +set -g history-limit 10000 +set -g repeat-time 0 + +set -g mouse off +setw -g alternate-screen on + +bind-key q kill-pane +bind-key Q kill-window +bind c new-window -c "#{pane_current_path}" +bind '"' split-window -c "#{pane_current_path}" +bind % split-window -h -c "#{pane_current_path}" + +bind-key P run-shell 'tmux capture-pane -S -32768 ; tmux save-buffer ~/.tmux/$(date +%Y%m%d_%H%M%S).log ; tmux delete-buffer ; tmux display-message "$(date +%Y%m%d_%H%M%S).log"' + +bind-key o copy-mode \; send-keys -X search-backward diff --git a/modules/mixins/dotfiles/home/vim/colors/README.md b/modules/mixins/dotfiles/home/vim/colors/README.md @@ -0,0 +1,102 @@ +# Tempus Themes for Vim + +The theme files can be copied manually or installed as a bundle with a +plugin. + +## 1 Manual method: we use the command line + +Start by cloning the `tempus-themes-vim` repo and entering it (unless +you prefer copy-pasting, in which case adapt accordingly): + +```sh +git clone https://gitlab.com/protesilaos/tempus-themes-vim.git --depth 1 && cd tempus-themes-vim +``` + +### 1.1 Create destination directory + +The manual method requires you to copy the file to `~/.vim/colors/`. +Run the following command, while ignoring line that start with `#` +(those are just comments): + +```sh +# Create path to colors directory if it does not already exist +mkdir -p ~/.vim/colors/ +``` + +### 1.2 Copying to destination directory + +Now run the following command for the theme of your choice. The example +uses `tempus_winter.vim`: + +```sh +cp colors/tempus_winter.vim ~/.vim/colors/ +``` + +Done. + +**Pro tip.** To copy all the themes at once, run the following: + +```sh +cp colors/*.vim ~/.vim/colors/ +``` + +## 2 Plugin method + +Use your favourite plugin manager method. + +With [vim-plug](https://github.com/junegunn/vim-plug) add the following +line to your `.vimrc`: + +```vim +Plug "https://gitlab.com/protesilaos/tempus-themes-vim.git" +``` + +Then execute the plugin manager's command to update the plugin files. + +## 3 Applying the theme + +Once available, the theme is declared with the following options inside +the `.vimrc`: + +```vim +" Theme +syntax enable +colorscheme tempus_winter +``` + +Enjoy! + +Note that by default, the theme does not set the background color when +used in a terminal to play well with transparent terminals. The +background color can be set by adding the following option in the +`.vimrc`: + +```vim +let g:tempus_enforce_background_color=1 +``` + +## 4 GNU/Linux Package + +If you use Arch Linux or derivatives, you can get these themes from the +[AUR](https://aur.archlinux.org/packages/tempus-themes-vim-git/). + +## Additional resources + +For more information about this project, screenshots, and all available +ports, refer to the main [Tempus themes +repo](https://gitlab.com/protesilaos/tempus-themes). + +## License + +GNU General Public License Version 3. + +## Meta + +All theme files are created through scripts with the [Tempus themes +generator](https://gitlab.com/protesilaos/tempus-themes-generator). See +the generator's CONTRIBUTING.md. + +## Donations + +If you appreciate this work, consider [donating via +PayPal](https://www.paypal.me/protesilaos). diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_autumn.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_autumn.vim @@ -0,0 +1,254 @@ +" Name: Tempus Autumn +" Description: Dark theme with a palette inspired by earthly colours (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_autumn" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#302420 guifg=#a9a2a6 ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#302420 guifg=#a9a2a6 ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#a9a2a6 guifg=#302420 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#36302a guifg=#a9a2a6 cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#a8948a guifg=#302420 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#a9a2a6 guifg=#302420 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#36302a guifg=#a8948a cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#85a400 guifg=#302420 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#36302a guifg=#85a400 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#36302a guifg=#a8948a cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#52a885 guifg=#302420 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#a8948a cterm=none ctermfg=7 +hi Todo gui=bold guibg=#36302a guifg=#ba9400 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#b09640 guifg=#302420 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#b09640 guifg=#302420 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#f46f55 guifg=#302420 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#f46f55 guifg=#302420 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#36302a guifg=#a8948a cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#a8948a guifg=#302420 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#a8948a guifg=#302420 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#302420 guifg=#a9a2a6 term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#302420 guifg=#a9a2a6 term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#799aca ctermfg=4 +hi Number guifg=#799aca ctermfg=4 +hi Float guifg=#799aca ctermfg=4 +hi String guifg=#958fdf ctermfg=12 + +hi Function guifg=#df798e ctermfg=5 +hi Identifier guifg=#ce7dc4 term=none ctermfg=13 +hi Label guifg=#df798e ctermfg=5 +hi Tag guifg=#df798e ctermfg=5 +hi Keyword gui=bold guifg=#ce7dc4 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#2fa6b7 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#52a885 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#52a885 ctermfg=6 +hi StorageClass guifg=#52a885 ctermfg=6 +hi Structure guifg=#52a885 ctermfg=6 +hi Typedef gui=bold guifg=#2fa6b7 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#85a400 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#43aa7a cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#43aa7a cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#a9a2a6 cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#f46f55 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#e27e3d term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#e27e3d cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#e27e3d cterm=bold ctermfg=9 +hi Include guifg=#e27e3d ctermfg=9 +hi Define guifg=#e27e3d ctermfg=9 + +hi Title gui=bold guibg=#302420 guifg=#52a885 cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#df798e cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#df798e cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#df798e cterm=bold ctermfg=5 + +hi Debug guifg=#ce7dc4 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#36302a guifg=#a8948a term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#a9a2a6 guifg=#302420 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#36302a term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#36302a term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#a8948a guifg=#302420 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#36302a guifg=#a9a2a6 term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#36302a guifg=#a8948a term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#36302a guifg=#a8948a ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#36302a guifg=#a8948a ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#ba9400 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#36302a guifg=#a8948a cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#ba9400 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#36302a guifg=#a8948a cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#a8948a cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#85a400 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#ba9400 cterm=bold ctermfg=11 +hi MoreMsg guifg=#43aa7a ctermfg=10 +hi ModeMsg gui=bold guifg=#85a400 cterm=bold ctermfg=2 + +hi VimOption guifg=#df798e ctermfg=5 +hi VimGroup guifg=#df798e ctermfg=5 + +hi Underlined gui=underline guifg=#a9a2a6 cterm=underline ctermfg=15 +hi Ignore guibg=#36302a guifg=#a8948a ctermbg=8 ctermfg=7 +hi Conceal guibg=#a8948a guifg=#36302a ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#f46f55 guifg=#302420 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#b09640 guifg=#302420 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#ce7dc4 guifg=#302420 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#2fa6b7 guifg=#302420 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#36302a guifg=#a9a2a6 cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#a8948a guifg=#302420 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#36302a ctermbg=8 +hi PmenuThumb guibg=#a8948a ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#302420", + \ "#f46f55", + \ "#85a400", + \ "#b09640", + \ "#799aca", + \ "#df798e", + \ "#52a885", + \ "#a8948a", + \ "#36302a", + \ "#e27e3d", + \ "#43aa7a", + \ "#ba9400", + \ "#958fdf", + \ "#ce7dc4", + \ "#2fa6b7", + \ "#a9a2a6" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#302420" + let g:terminal_color_1 = "#f46f55" + let g:terminal_color_2 = "#85a400" + let g:terminal_color_3 = "#b09640" + let g:terminal_color_4 = "#799aca" + let g:terminal_color_5 = "#df798e" + let g:terminal_color_6 = "#52a885" + let g:terminal_color_7 = "#a8948a" + let g:terminal_color_8 = "#36302a" + let g:terminal_color_9 = "#e27e3d" + let g:terminal_color_10 = "#43aa7a" + let g:terminal_color_11 = "#ba9400" + let g:terminal_color_12 = "#958fdf" + let g:terminal_color_13 = "#ce7dc4" + let g:terminal_color_14 = "#2fa6b7" + let g:terminal_color_15 = "#a9a2a6" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#85a400 guifg=#302420 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#f46f55 guifg=#302420 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#36302a guifg=#a8948a cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#36302a guifg=#e27e3d cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#85a400 ctermfg=2 +hi diffRemoved guifg=#f46f55 ctermfg=1 +hi diffNewFile gui=none guifg=#799aca ctermfg=4 +hi diffFile gui=none guifg=#b09640 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#36302a guifg=#85a400 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#36302a guifg=#a8948a cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#36302a guifg=#f46f55 ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#36302a guifg=#f46f55 cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#f46f55 guifg=#302420 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#52a885 guifg=#302420 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#b09640 guifg=#302420 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#ba9400 guifg=#302420 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#2fa6b7 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#ba9400 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#b09640 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#f46f55 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#85a400 guifg=#302420 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#36302a guifg=#85a400 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#799aca guifg=#302420 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#f46f55 guifg=#302420 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#b09640 guifg=#302420 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#36302a guifg=#43aa7a cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#a9a2a6 cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#e27e3d cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#b09640 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#799aca cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#958fdf cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#a9a2a6 cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#df798e ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#a9a2a6 ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#85a400 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#f46f55 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#b09640 cterm=underline +hi SyntasticError gui=undercurl guisp=#f46f55 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#b09640 cterm=underline +hi SyntasticErrorSing guifg=#302420 guibg=#f46f55 ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#302420 guibg=#b09640 ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_classic.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_classic.vim @@ -0,0 +1,254 @@ +" Name: Tempus Classic +" Description: Dark theme with warm hues (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_classic" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#232323 guifg=#aeadaf ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#232323 guifg=#aeadaf ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#aeadaf guifg=#232323 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#312e30 guifg=#aeadaf cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#949d9f guifg=#232323 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#aeadaf guifg=#232323 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#312e30 guifg=#949d9f cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#8c9e3d guifg=#232323 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#312e30 guifg=#8c9e3d cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#312e30 guifg=#949d9f cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#6da280 guifg=#232323 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#949d9f cterm=none ctermfg=7 +hi Todo gui=bold guibg=#312e30 guifg=#a8a030 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#b1942b guifg=#232323 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#b1942b guifg=#232323 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#d4823d guifg=#232323 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#d4823d guifg=#232323 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#312e30 guifg=#949d9f cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#949d9f guifg=#232323 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#949d9f guifg=#232323 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#232323 guifg=#aeadaf term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#232323 guifg=#aeadaf term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#6e9cb0 ctermfg=4 +hi Number guifg=#6e9cb0 ctermfg=4 +hi Float guifg=#6e9cb0 ctermfg=4 +hi String guifg=#8e9cc0 ctermfg=12 + +hi Function guifg=#b58d88 ctermfg=5 +hi Identifier guifg=#d58888 term=none ctermfg=13 +hi Label guifg=#b58d88 ctermfg=5 +hi Tag guifg=#b58d88 ctermfg=5 +hi Keyword gui=bold guifg=#d58888 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#7aa880 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#6da280 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#6da280 ctermfg=6 +hi StorageClass guifg=#6da280 ctermfg=6 +hi Structure guifg=#6da280 ctermfg=6 +hi Typedef gui=bold guifg=#7aa880 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#8c9e3d cterm=bold ctermfg=2 +hi Statement gui=none guifg=#96a42d cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#96a42d cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#aeadaf cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#d4823d cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#d0913d term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#d0913d cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#d0913d cterm=bold ctermfg=9 +hi Include guifg=#d0913d ctermfg=9 +hi Define guifg=#d0913d ctermfg=9 + +hi Title gui=bold guibg=#232323 guifg=#6da280 cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#b58d88 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#b58d88 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#b58d88 cterm=bold ctermfg=5 + +hi Debug guifg=#d58888 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#312e30 guifg=#949d9f term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#aeadaf guifg=#232323 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#312e30 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#312e30 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#949d9f guifg=#232323 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#312e30 guifg=#aeadaf term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#312e30 guifg=#949d9f term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#312e30 guifg=#949d9f ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#312e30 guifg=#949d9f ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#a8a030 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#312e30 guifg=#949d9f cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#a8a030 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#312e30 guifg=#949d9f cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#949d9f cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#8c9e3d term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#a8a030 cterm=bold ctermfg=11 +hi MoreMsg guifg=#96a42d ctermfg=10 +hi ModeMsg gui=bold guifg=#8c9e3d cterm=bold ctermfg=2 + +hi VimOption guifg=#b58d88 ctermfg=5 +hi VimGroup guifg=#b58d88 ctermfg=5 + +hi Underlined gui=underline guifg=#aeadaf cterm=underline ctermfg=15 +hi Ignore guibg=#312e30 guifg=#949d9f ctermbg=8 ctermfg=7 +hi Conceal guibg=#949d9f guifg=#312e30 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#d4823d guifg=#232323 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#b1942b guifg=#232323 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#d58888 guifg=#232323 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#7aa880 guifg=#232323 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#312e30 guifg=#aeadaf cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#949d9f guifg=#232323 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#312e30 ctermbg=8 +hi PmenuThumb guibg=#949d9f ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#232323", + \ "#d4823d", + \ "#8c9e3d", + \ "#b1942b", + \ "#6e9cb0", + \ "#b58d88", + \ "#6da280", + \ "#949d9f", + \ "#312e30", + \ "#d0913d", + \ "#96a42d", + \ "#a8a030", + \ "#8e9cc0", + \ "#d58888", + \ "#7aa880", + \ "#aeadaf" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#232323" + let g:terminal_color_1 = "#d4823d" + let g:terminal_color_2 = "#8c9e3d" + let g:terminal_color_3 = "#b1942b" + let g:terminal_color_4 = "#6e9cb0" + let g:terminal_color_5 = "#b58d88" + let g:terminal_color_6 = "#6da280" + let g:terminal_color_7 = "#949d9f" + let g:terminal_color_8 = "#312e30" + let g:terminal_color_9 = "#d0913d" + let g:terminal_color_10 = "#96a42d" + let g:terminal_color_11 = "#a8a030" + let g:terminal_color_12 = "#8e9cc0" + let g:terminal_color_13 = "#d58888" + let g:terminal_color_14 = "#7aa880" + let g:terminal_color_15 = "#aeadaf" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#8c9e3d guifg=#232323 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#d4823d guifg=#232323 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#312e30 guifg=#949d9f cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#312e30 guifg=#d0913d cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#8c9e3d ctermfg=2 +hi diffRemoved guifg=#d4823d ctermfg=1 +hi diffNewFile gui=none guifg=#6e9cb0 ctermfg=4 +hi diffFile gui=none guifg=#b1942b cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#312e30 guifg=#8c9e3d ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#312e30 guifg=#949d9f cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#312e30 guifg=#d4823d ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#312e30 guifg=#d4823d cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#d4823d guifg=#232323 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#6da280 guifg=#232323 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#b1942b guifg=#232323 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#a8a030 guifg=#232323 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#7aa880 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#a8a030 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#b1942b ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#d4823d ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#8c9e3d guifg=#232323 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#312e30 guifg=#8c9e3d cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#6e9cb0 guifg=#232323 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#d4823d guifg=#232323 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#b1942b guifg=#232323 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#312e30 guifg=#96a42d cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#aeadaf cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#d0913d cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#b1942b cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#6e9cb0 cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#8e9cc0 cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#aeadaf cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#b58d88 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#aeadaf ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#8c9e3d cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#d4823d cterm=underline +hi YcmWarningSection gui=undercurl guisp=#b1942b cterm=underline +hi SyntasticError gui=undercurl guisp=#d4823d cterm=underline +hi SyntasticWarning gui=undercurl guisp=#b1942b cterm=underline +hi SyntasticErrorSing guifg=#232323 guibg=#d4823d ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#232323 guibg=#b1942b ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_dawn.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_dawn.vim @@ -0,0 +1,254 @@ +" Name: Tempus Dawn +" Description: Light theme with a soft, slightly desaturated palette (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=light +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_dawn" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#eff0f2 guifg=#4a4b4e ctermbg=15 ctermfg=0 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#eff0f2 guifg=#4a4b4e ctermbg=none ctermfg=0 +endif + +hi Visual guibg=#4a4b4e guifg=#eff0f2 ctermbg=0 ctermfg=15 +hi Search gui=underline,bold guibg=#dee2e0 guifg=#4a4b4e cterm=underline,bold ctermbg=7 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#676364 guifg=#eff0f2 term=none cterm=underline,bold ctermbg=8 ctermfg=15 + +hi StatusLine gui=none guibg=#4a4b4e guifg=#eff0f2 cterm=none ctermbg=0 ctermfg=15 +hi StatusLineNC gui=none guibg=#dee2e0 guifg=#676364 cterm=none ctermbg=7 ctermfg=8 +hi StatusLineTerm gui=none guibg=#206620 guifg=#eff0f2 cterm=none ctermbg=2 ctermfg=15 +hi StatusLineTermNC gui=none guibg=#dee2e0 guifg=#206620 cterm=none ctermbg=7 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#dee2e0 guifg=#676364 cterm=none ctermbg=7 ctermfg=8 +hi TabLineSel gui=none guibg=#086784 guifg=#eff0f2 cterm=none ctermbg=6 ctermfg=15 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#676364 cterm=none ctermfg=8 +hi Todo gui=bold guibg=#dee2e0 guifg=#8b590a cterm=bold ctermbg=7 ctermfg=11 + +hi Warning gui=none guibg=#745300 guifg=#eff0f2 cterm=none ctermbg=3 ctermfg=15 +hi WarningMsg gui=none guibg=#745300 guifg=#eff0f2 cterm=none ctermbg=3 ctermfg=15 +hi Error gui=none guibg=#a32a3a guifg=#eff0f2 cterm=none ctermbg=1 ctermfg=15 +hi ErrorMsg gui=none guibg=#a32a3a guifg=#eff0f2 cterm=none ctermbg=1 ctermfg=15 + +hi MatchParen gui=underline,bold guibg=#dee2e0 guifg=#676364 cterm=underline,bold ctermbg=7 ctermfg=8 + +hi ToolbarLine guibg=#676364 guifg=#eff0f2 term=none ctermbg=8 ctermfg=15 +hi ToolbarButton gui=bold guibg=#676364 guifg=#eff0f2 term=none cterm=bold ctermbg=8 ctermfg=15 + +hi WildMenu guibg=#eff0f2 guifg=#4a4b4e term=standout ctermbg=15 ctermfg=0 + +hi Terminal guibg=#eff0f2 guifg=#4a4b4e term=none ctermbg=15 ctermfg=0 + +" Constructs +" ---------- +hi Constant guifg=#4b529a ctermfg=4 +hi Number guifg=#4b529a ctermfg=4 +hi Float guifg=#4b529a ctermfg=4 +hi String guifg=#5c59b2 ctermfg=12 + +hi Function guifg=#8d377e ctermfg=5 +hi Identifier guifg=#8e45a8 term=none ctermfg=13 +hi Label guifg=#8d377e ctermfg=5 +hi Tag guifg=#8d377e ctermfg=5 +hi Keyword gui=bold guifg=#8e45a8 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#3f649c cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#086784 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#086784 ctermfg=6 +hi StorageClass guifg=#086784 ctermfg=6 +hi Structure guifg=#086784 ctermfg=6 +hi Typedef gui=bold guifg=#3f649c cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#206620 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#187408 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#187408 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#4a4b4e cterm=bold ctermfg=0 +hi Exception gui=bold guifg=#a32a3a cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#a64822 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#a64822 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#a64822 cterm=bold ctermfg=9 +hi Include guifg=#a64822 ctermfg=9 +hi Define guifg=#a64822 ctermfg=9 + +hi Title gui=bold guibg=#eff0f2 guifg=#086784 cterm=bold ctermbg=15 ctermfg=6 + +hi Delimeter gui=bold guifg=#8d377e cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#8d377e cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#8d377e cterm=bold ctermfg=5 + +hi Debug guifg=#8e45a8 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#dee2e0 guifg=#676364 term=none ctermbg=7 ctermfg=8 +hi Cursor guibg=#4a4b4e guifg=#eff0f2 ctermbg=0 ctermfg=15 +hi CursorLine gui=none guibg=#dee2e0 term=none cterm=none ctermbg=7 +hi CursorColumn gui=none guibg=#dee2e0 term=none cterm=none ctermbg=7 +hi CursorLineNr gui=bold guibg=#676364 guifg=#eff0f2 cterm=bold ctermbg=8 ctermfg=15 +hi ColorColumn guibg=#dee2e0 guifg=#4a4b4e term=none ctermbg=7 ctermfg=0 +hi SignColumn guibg=#dee2e0 guifg=#676364 term=none ctermbg=7 ctermfg=8 + +hi Folded guibg=#dee2e0 guifg=#676364 ctermbg=7 ctermfg=8 +hi FoldColumn guibg=#dee2e0 guifg=#676364 ctermbg=7 ctermfg=8 + +hi Special gui=bold guifg=#8b590a term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#dee2e0 guifg=#676364 cterm=none ctermbg=7 ctermfg=8 +hi SpecialChar gui=bold guifg=#8b590a cterm=bold ctermfg=11 +hi NonText gui=none guibg=#dee2e0 guifg=#676364 cterm=none ctermbg=7 ctermfg=8 +hi EndOfBuffer gui=bold guifg=#676364 cterm=bold ctermfg=8 + +hi Directory gui=none guifg=#206620 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#8b590a cterm=bold ctermfg=11 +hi MoreMsg guifg=#187408 ctermfg=10 +hi ModeMsg gui=bold guifg=#206620 cterm=bold ctermfg=2 + +hi VimOption guifg=#8d377e ctermfg=5 +hi VimGroup guifg=#8d377e ctermfg=5 + +hi Underlined gui=underline guifg=#4a4b4e cterm=underline ctermfg=0 +hi Ignore guibg=#dee2e0 guifg=#676364 ctermbg=7 ctermfg=8 +hi Conceal guibg=#676364 guifg=#dee2e0 ctermbg=8 ctermfg=7 + +hi SpellBad guibg=#a32a3a guifg=#eff0f2 ctermbg=1 ctermfg=15 +hi SpellCap guibg=#745300 guifg=#eff0f2 ctermbg=3 ctermfg=15 +hi SpellRare guibg=#8e45a8 guifg=#eff0f2 ctermbg=13 ctermfg=15 +hi SpellLocal guibg=#3f649c guifg=#eff0f2 ctermbg=14 ctermfg=15 + +hi Pmenu gui=italic guibg=#dee2e0 guifg=#4a4b4e cterm=none ctermbg=7 ctermfg=0 +hi PmenuSel gui=none,bold guibg=#676364 guifg=#eff0f2 cterm=none,bold ctermbg=8 ctermfg=15 +hi PmenuSbar guibg=#dee2e0 ctermbg=7 +hi PmenuThumb guibg=#676364 ctermbg=8 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#4a4b4e", + \ "#a32a3a", + \ "#206620", + \ "#745300", + \ "#4b529a", + \ "#8d377e", + \ "#086784", + \ "#dee2e0", + \ "#676364", + \ "#a64822", + \ "#187408", + \ "#8b590a", + \ "#5c59b2", + \ "#8e45a8", + \ "#3f649c", + \ "#eff0f2" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#4a4b4e" + let g:terminal_color_1 = "#a32a3a" + let g:terminal_color_2 = "#206620" + let g:terminal_color_3 = "#745300" + let g:terminal_color_4 = "#4b529a" + let g:terminal_color_5 = "#8d377e" + let g:terminal_color_6 = "#086784" + let g:terminal_color_7 = "#dee2e0" + let g:terminal_color_8 = "#676364" + let g:terminal_color_9 = "#a64822" + let g:terminal_color_10 = "#187408" + let g:terminal_color_11 = "#8b590a" + let g:terminal_color_12 = "#5c59b2" + let g:terminal_color_13 = "#8e45a8" + let g:terminal_color_14 = "#3f649c" + let g:terminal_color_15 = "#eff0f2" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#206620 guifg=#eff0f2 cterm=bold ctermbg=10 ctermfg=15 +hi DiffDelete gui=none guibg=#a32a3a guifg=#eff0f2 cterm=none ctermbg=9 ctermfg=15 +hi DiffChange gui=bold guibg=#dee2e0 guifg=#676364 cterm=bold ctermbg=7 ctermfg=8 +hi DiffText gui=bold guibg=#dee2e0 guifg=#a64822 cterm=bold ctermbg=7 ctermfg=1 + +hi diffAdded guifg=#206620 ctermfg=2 +hi diffRemoved guifg=#a32a3a ctermfg=1 +hi diffNewFile gui=none guifg=#4b529a ctermfg=4 +hi diffFile gui=none guifg=#745300 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#dee2e0 guifg=#206620 ctermbg=7 ctermfg=2 +hi GitGutterChange gui=bold guibg=#dee2e0 guifg=#676364 cterm=bold ctermbg=7 ctermfg=8 +hi GitGutterDelete guibg=#dee2e0 guifg=#a32a3a ctermbg=7 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#dee2e0 guifg=#a32a3a cterm=bold ctermbg=7 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#a32a3a guifg=#eff0f2 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeInfo gui=none guibg=#086784 guifg=#eff0f2 cterm=none ctermbg=6 ctermfg=15 +hi NeomakeWarning gui=none guibg=#745300 guifg=#eff0f2 cterm=none ctermbg=3 ctermfg=15 +hi NeomakeMessage gui=none guibg=#8b590a guifg=#eff0f2 cterm=none ctermbg=11 ctermfg=15 + +hi NeomakeVirtualtextInfoDefault guifg=#3f649c ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#8b590a ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#745300 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#a32a3a ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#206620 guifg=#eff0f2 cterm=none ctermbg=2 ctermfg=15 +hi NeomakeStatusGoodNC gui=none guibg=#dee2e0 guifg=#206620 cterm=none ctermbg=7 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#4b529a guifg=#eff0f2 cterm=none ctermbg=4 ctermfg=15 +hi NeomakeStatColorTypeE gui=none guibg=#a32a3a guifg=#eff0f2 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeStatColorTypeW gui=none guibg=#745300 guifg=#eff0f2 cterm=none ctermbg=3 ctermfg=15 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#dee2e0 guifg=#187408 cterm=bold ctermbg=7 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#4a4b4e cterm=bold ctermfg=0 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#a64822 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#745300 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#4b529a cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#5c59b2 cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#4a4b4e cterm=bold ctermfg=0 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#8d377e ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#4a4b4e ctermfg=0 + +hi MarkdownListMarker gui=none guifg=#206620 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#a32a3a cterm=underline +hi YcmWarningSection gui=undercurl guisp=#4b529a cterm=underline +hi SyntasticError gui=undercurl guisp=#a32a3a cterm=underline +hi SyntasticWarning gui=undercurl guisp=#4b529a cterm=underline +hi SyntasticErrorSing guifg=#eff0f2 guibg=#a32a3a ctermfg=15 ctermbg=1 +hi SyntasticWarningSign guifg=#eff0f2 guibg=#4b529a ctermfg=15 ctermbg=4 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_day.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_day.vim @@ -0,0 +1,254 @@ +" Name: Tempus Day +" Description: Light theme with warm colours (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=light +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_day" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#f8f2e5 guifg=#464340 ctermbg=15 ctermfg=0 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#f8f2e5 guifg=#464340 ctermbg=none ctermfg=0 +endif + +hi Visual guibg=#464340 guifg=#f8f2e5 ctermbg=0 ctermfg=15 +hi Search gui=underline,bold guibg=#e7e3d7 guifg=#464340 cterm=underline,bold ctermbg=7 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#68607d guifg=#f8f2e5 term=none cterm=underline,bold ctermbg=8 ctermfg=15 + +hi StatusLine gui=none guibg=#464340 guifg=#f8f2e5 cterm=none ctermbg=0 ctermfg=15 +hi StatusLineNC gui=none guibg=#e7e3d7 guifg=#68607d cterm=none ctermbg=7 ctermfg=8 +hi StatusLineTerm gui=none guibg=#107410 guifg=#f8f2e5 cterm=none ctermbg=2 ctermfg=15 +hi StatusLineTermNC gui=none guibg=#e7e3d7 guifg=#107410 cterm=none ctermbg=7 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#e7e3d7 guifg=#68607d cterm=none ctermbg=7 ctermfg=8 +hi TabLineSel gui=none guibg=#007070 guifg=#f8f2e5 cterm=none ctermbg=6 ctermfg=15 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#68607d cterm=none ctermfg=8 +hi Todo gui=bold guibg=#e7e3d7 guifg=#6f6600 cterm=bold ctermbg=7 ctermfg=11 + +hi Warning gui=none guibg=#806000 guifg=#f8f2e5 cterm=none ctermbg=3 ctermfg=15 +hi WarningMsg gui=none guibg=#806000 guifg=#f8f2e5 cterm=none ctermbg=3 ctermfg=15 +hi Error gui=none guibg=#c81000 guifg=#f8f2e5 cterm=none ctermbg=1 ctermfg=15 +hi ErrorMsg gui=none guibg=#c81000 guifg=#f8f2e5 cterm=none ctermbg=1 ctermfg=15 + +hi MatchParen gui=underline,bold guibg=#e7e3d7 guifg=#68607d cterm=underline,bold ctermbg=7 ctermfg=8 + +hi ToolbarLine guibg=#68607d guifg=#f8f2e5 term=none ctermbg=8 ctermfg=15 +hi ToolbarButton gui=bold guibg=#68607d guifg=#f8f2e5 term=none cterm=bold ctermbg=8 ctermfg=15 + +hi WildMenu guibg=#f8f2e5 guifg=#464340 term=standout ctermbg=15 ctermfg=0 + +hi Terminal guibg=#f8f2e5 guifg=#464340 term=none ctermbg=15 ctermfg=0 + +" Constructs +" ---------- +hi Constant guifg=#385dc4 ctermfg=4 +hi Number guifg=#385dc4 ctermfg=4 +hi Float guifg=#385dc4 ctermfg=4 +hi String guifg=#0f64c4 ctermfg=12 + +hi Function guifg=#b63052 ctermfg=5 +hi Identifier guifg=#8050a7 term=none ctermfg=13 +hi Label guifg=#b63052 ctermfg=5 +hi Tag guifg=#b63052 ctermfg=5 +hi Keyword gui=bold guifg=#8050a7 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#336c87 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#007070 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#007070 ctermfg=6 +hi StorageClass guifg=#007070 ctermfg=6 +hi Structure guifg=#007070 ctermfg=6 +hi Typedef gui=bold guifg=#336c87 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#107410 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#427040 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#427040 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#464340 cterm=bold ctermfg=0 +hi Exception gui=bold guifg=#c81000 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#b24000 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#b24000 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#b24000 cterm=bold ctermfg=9 +hi Include guifg=#b24000 ctermfg=9 +hi Define guifg=#b24000 ctermfg=9 + +hi Title gui=bold guibg=#f8f2e5 guifg=#007070 cterm=bold ctermbg=15 ctermfg=6 + +hi Delimeter gui=bold guifg=#b63052 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#b63052 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#b63052 cterm=bold ctermfg=5 + +hi Debug guifg=#8050a7 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#e7e3d7 guifg=#68607d term=none ctermbg=7 ctermfg=8 +hi Cursor guibg=#464340 guifg=#f8f2e5 ctermbg=0 ctermfg=15 +hi CursorLine gui=none guibg=#e7e3d7 term=none cterm=none ctermbg=7 +hi CursorColumn gui=none guibg=#e7e3d7 term=none cterm=none ctermbg=7 +hi CursorLineNr gui=bold guibg=#68607d guifg=#f8f2e5 cterm=bold ctermbg=8 ctermfg=15 +hi ColorColumn guibg=#e7e3d7 guifg=#464340 term=none ctermbg=7 ctermfg=0 +hi SignColumn guibg=#e7e3d7 guifg=#68607d term=none ctermbg=7 ctermfg=8 + +hi Folded guibg=#e7e3d7 guifg=#68607d ctermbg=7 ctermfg=8 +hi FoldColumn guibg=#e7e3d7 guifg=#68607d ctermbg=7 ctermfg=8 + +hi Special gui=bold guifg=#6f6600 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#e7e3d7 guifg=#68607d cterm=none ctermbg=7 ctermfg=8 +hi SpecialChar gui=bold guifg=#6f6600 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#e7e3d7 guifg=#68607d cterm=none ctermbg=7 ctermfg=8 +hi EndOfBuffer gui=bold guifg=#68607d cterm=bold ctermfg=8 + +hi Directory gui=none guifg=#107410 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#6f6600 cterm=bold ctermfg=11 +hi MoreMsg guifg=#427040 ctermfg=10 +hi ModeMsg gui=bold guifg=#107410 cterm=bold ctermfg=2 + +hi VimOption guifg=#b63052 ctermfg=5 +hi VimGroup guifg=#b63052 ctermfg=5 + +hi Underlined gui=underline guifg=#464340 cterm=underline ctermfg=0 +hi Ignore guibg=#e7e3d7 guifg=#68607d ctermbg=7 ctermfg=8 +hi Conceal guibg=#68607d guifg=#e7e3d7 ctermbg=8 ctermfg=7 + +hi SpellBad guibg=#c81000 guifg=#f8f2e5 ctermbg=1 ctermfg=15 +hi SpellCap guibg=#806000 guifg=#f8f2e5 ctermbg=3 ctermfg=15 +hi SpellRare guibg=#8050a7 guifg=#f8f2e5 ctermbg=13 ctermfg=15 +hi SpellLocal guibg=#336c87 guifg=#f8f2e5 ctermbg=14 ctermfg=15 + +hi Pmenu gui=italic guibg=#e7e3d7 guifg=#464340 cterm=none ctermbg=7 ctermfg=0 +hi PmenuSel gui=none,bold guibg=#68607d guifg=#f8f2e5 cterm=none,bold ctermbg=8 ctermfg=15 +hi PmenuSbar guibg=#e7e3d7 ctermbg=7 +hi PmenuThumb guibg=#68607d ctermbg=8 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#464340", + \ "#c81000", + \ "#107410", + \ "#806000", + \ "#385dc4", + \ "#b63052", + \ "#007070", + \ "#e7e3d7", + \ "#68607d", + \ "#b24000", + \ "#427040", + \ "#6f6600", + \ "#0f64c4", + \ "#8050a7", + \ "#336c87", + \ "#f8f2e5" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#464340" + let g:terminal_color_1 = "#c81000" + let g:terminal_color_2 = "#107410" + let g:terminal_color_3 = "#806000" + let g:terminal_color_4 = "#385dc4" + let g:terminal_color_5 = "#b63052" + let g:terminal_color_6 = "#007070" + let g:terminal_color_7 = "#e7e3d7" + let g:terminal_color_8 = "#68607d" + let g:terminal_color_9 = "#b24000" + let g:terminal_color_10 = "#427040" + let g:terminal_color_11 = "#6f6600" + let g:terminal_color_12 = "#0f64c4" + let g:terminal_color_13 = "#8050a7" + let g:terminal_color_14 = "#336c87" + let g:terminal_color_15 = "#f8f2e5" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#107410 guifg=#f8f2e5 cterm=bold ctermbg=10 ctermfg=15 +hi DiffDelete gui=none guibg=#c81000 guifg=#f8f2e5 cterm=none ctermbg=9 ctermfg=15 +hi DiffChange gui=bold guibg=#e7e3d7 guifg=#68607d cterm=bold ctermbg=7 ctermfg=8 +hi DiffText gui=bold guibg=#e7e3d7 guifg=#b24000 cterm=bold ctermbg=7 ctermfg=1 + +hi diffAdded guifg=#107410 ctermfg=2 +hi diffRemoved guifg=#c81000 ctermfg=1 +hi diffNewFile gui=none guifg=#385dc4 ctermfg=4 +hi diffFile gui=none guifg=#806000 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#e7e3d7 guifg=#107410 ctermbg=7 ctermfg=2 +hi GitGutterChange gui=bold guibg=#e7e3d7 guifg=#68607d cterm=bold ctermbg=7 ctermfg=8 +hi GitGutterDelete guibg=#e7e3d7 guifg=#c81000 ctermbg=7 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#e7e3d7 guifg=#c81000 cterm=bold ctermbg=7 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#c81000 guifg=#f8f2e5 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeInfo gui=none guibg=#007070 guifg=#f8f2e5 cterm=none ctermbg=6 ctermfg=15 +hi NeomakeWarning gui=none guibg=#806000 guifg=#f8f2e5 cterm=none ctermbg=3 ctermfg=15 +hi NeomakeMessage gui=none guibg=#6f6600 guifg=#f8f2e5 cterm=none ctermbg=11 ctermfg=15 + +hi NeomakeVirtualtextInfoDefault guifg=#336c87 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#6f6600 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#806000 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#c81000 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#107410 guifg=#f8f2e5 cterm=none ctermbg=2 ctermfg=15 +hi NeomakeStatusGoodNC gui=none guibg=#e7e3d7 guifg=#107410 cterm=none ctermbg=7 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#385dc4 guifg=#f8f2e5 cterm=none ctermbg=4 ctermfg=15 +hi NeomakeStatColorTypeE gui=none guibg=#c81000 guifg=#f8f2e5 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeStatColorTypeW gui=none guibg=#806000 guifg=#f8f2e5 cterm=none ctermbg=3 ctermfg=15 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#e7e3d7 guifg=#427040 cterm=bold ctermbg=7 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#464340 cterm=bold ctermfg=0 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#b24000 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#806000 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#385dc4 cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#0f64c4 cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#464340 cterm=bold ctermfg=0 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#b63052 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#464340 ctermfg=0 + +hi MarkdownListMarker gui=none guifg=#107410 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#c81000 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#385dc4 cterm=underline +hi SyntasticError gui=undercurl guisp=#c81000 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#385dc4 cterm=underline +hi SyntasticErrorSing guifg=#f8f2e5 guibg=#c81000 ctermfg=15 ctermbg=1 +hi SyntasticWarningSign guifg=#f8f2e5 guibg=#385dc4 ctermfg=15 ctermbg=4 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_dusk.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_dusk.vim @@ -0,0 +1,254 @@ +" Name: Tempus Dusk +" Description: Dark theme with a deep blue-ish, slightly desaturated palette (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_dusk" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#1f252d guifg=#a2a8ba ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#1f252d guifg=#a2a8ba ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#a2a8ba guifg=#1f252d ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#2c3150 guifg=#a2a8ba cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#a29899 guifg=#1f252d term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#a2a8ba guifg=#1f252d cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#2c3150 guifg=#a29899 cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#8ba089 guifg=#1f252d cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#2c3150 guifg=#8ba089 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#2c3150 guifg=#a29899 cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#8e9aba guifg=#1f252d cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#a29899 cterm=none ctermfg=7 +hi Todo gui=bold guibg=#2c3150 guifg=#bda75a cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#a79c46 guifg=#1f252d cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#a79c46 guifg=#1f252d cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#cb8d56 guifg=#1f252d cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#cb8d56 guifg=#1f252d cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#2c3150 guifg=#a29899 cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#a29899 guifg=#1f252d term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#a29899 guifg=#1f252d term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#1f252d guifg=#a2a8ba term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#1f252d guifg=#a2a8ba term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#8c9abe ctermfg=4 +hi Number guifg=#8c9abe ctermfg=4 +hi Float guifg=#8c9abe ctermfg=4 +hi String guifg=#9ca5de ctermfg=12 + +hi Function guifg=#b190af ctermfg=5 +hi Identifier guifg=#c69ac6 term=none ctermfg=13 +hi Label guifg=#b190af ctermfg=5 +hi Tag guifg=#b190af ctermfg=5 +hi Keyword gui=bold guifg=#c69ac6 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#8caeb6 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#8e9aba term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#8e9aba ctermfg=6 +hi StorageClass guifg=#8e9aba ctermfg=6 +hi Structure guifg=#8e9aba ctermfg=6 +hi Typedef gui=bold guifg=#8caeb6 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#8ba089 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#80b48f cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#80b48f cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#a2a8ba cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#cb8d56 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#d39d74 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#d39d74 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#d39d74 cterm=bold ctermfg=9 +hi Include guifg=#d39d74 ctermfg=9 +hi Define guifg=#d39d74 ctermfg=9 + +hi Title gui=bold guibg=#1f252d guifg=#8e9aba cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#b190af cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#b190af cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#b190af cterm=bold ctermfg=5 + +hi Debug guifg=#c69ac6 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#2c3150 guifg=#a29899 term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#a2a8ba guifg=#1f252d ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#2c3150 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#2c3150 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#a29899 guifg=#1f252d cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#2c3150 guifg=#a2a8ba term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#2c3150 guifg=#a29899 term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#2c3150 guifg=#a29899 ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#2c3150 guifg=#a29899 ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#bda75a term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#2c3150 guifg=#a29899 cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#bda75a cterm=bold ctermfg=11 +hi NonText gui=none guibg=#2c3150 guifg=#a29899 cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#a29899 cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#8ba089 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#bda75a cterm=bold ctermfg=11 +hi MoreMsg guifg=#80b48f ctermfg=10 +hi ModeMsg gui=bold guifg=#8ba089 cterm=bold ctermfg=2 + +hi VimOption guifg=#b190af ctermfg=5 +hi VimGroup guifg=#b190af ctermfg=5 + +hi Underlined gui=underline guifg=#a2a8ba cterm=underline ctermfg=15 +hi Ignore guibg=#2c3150 guifg=#a29899 ctermbg=8 ctermfg=7 +hi Conceal guibg=#a29899 guifg=#2c3150 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#cb8d56 guifg=#1f252d ctermbg=1 ctermfg=0 +hi SpellCap guibg=#a79c46 guifg=#1f252d ctermbg=3 ctermfg=0 +hi SpellRare guibg=#c69ac6 guifg=#1f252d ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#8caeb6 guifg=#1f252d ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#2c3150 guifg=#a2a8ba cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#a29899 guifg=#1f252d cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#2c3150 ctermbg=8 +hi PmenuThumb guibg=#a29899 ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#1f252d", + \ "#cb8d56", + \ "#8ba089", + \ "#a79c46", + \ "#8c9abe", + \ "#b190af", + \ "#8e9aba", + \ "#a29899", + \ "#2c3150", + \ "#d39d74", + \ "#80b48f", + \ "#bda75a", + \ "#9ca5de", + \ "#c69ac6", + \ "#8caeb6", + \ "#a2a8ba" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#1f252d" + let g:terminal_color_1 = "#cb8d56" + let g:terminal_color_2 = "#8ba089" + let g:terminal_color_3 = "#a79c46" + let g:terminal_color_4 = "#8c9abe" + let g:terminal_color_5 = "#b190af" + let g:terminal_color_6 = "#8e9aba" + let g:terminal_color_7 = "#a29899" + let g:terminal_color_8 = "#2c3150" + let g:terminal_color_9 = "#d39d74" + let g:terminal_color_10 = "#80b48f" + let g:terminal_color_11 = "#bda75a" + let g:terminal_color_12 = "#9ca5de" + let g:terminal_color_13 = "#c69ac6" + let g:terminal_color_14 = "#8caeb6" + let g:terminal_color_15 = "#a2a8ba" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#8ba089 guifg=#1f252d cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#cb8d56 guifg=#1f252d cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#2c3150 guifg=#a29899 cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#2c3150 guifg=#d39d74 cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#8ba089 ctermfg=2 +hi diffRemoved guifg=#cb8d56 ctermfg=1 +hi diffNewFile gui=none guifg=#8c9abe ctermfg=4 +hi diffFile gui=none guifg=#a79c46 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#2c3150 guifg=#8ba089 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#2c3150 guifg=#a29899 cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#2c3150 guifg=#cb8d56 ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#2c3150 guifg=#cb8d56 cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#cb8d56 guifg=#1f252d cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#8e9aba guifg=#1f252d cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#a79c46 guifg=#1f252d cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#bda75a guifg=#1f252d cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#8caeb6 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#bda75a ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#a79c46 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#cb8d56 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#8ba089 guifg=#1f252d cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#2c3150 guifg=#8ba089 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#8c9abe guifg=#1f252d cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#cb8d56 guifg=#1f252d cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#a79c46 guifg=#1f252d cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#2c3150 guifg=#80b48f cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#a2a8ba cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#d39d74 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#a79c46 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#8c9abe cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#9ca5de cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#a2a8ba cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#b190af ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#a2a8ba ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#8ba089 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#cb8d56 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#a79c46 cterm=underline +hi SyntasticError gui=undercurl guisp=#cb8d56 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#a79c46 cterm=underline +hi SyntasticErrorSing guifg=#1f252d guibg=#cb8d56 ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#1f252d guibg=#a79c46 ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_fugit.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_fugit.vim @@ -0,0 +1,254 @@ +" Name: Tempus Fugit +" Description: Light, pleasant theme optimised for long writing/coding sessions (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=light +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_fugit" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#fff5f3 guifg=#4d595f ctermbg=15 ctermfg=0 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#fff5f3 guifg=#4d595f ctermbg=none ctermfg=0 +endif + +hi Visual guibg=#4d595f guifg=#fff5f3 ctermbg=0 ctermfg=15 +hi Search gui=underline,bold guibg=#efe6e4 guifg=#4d595f cterm=underline,bold ctermbg=7 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#796271 guifg=#fff5f3 term=none cterm=underline,bold ctermbg=8 ctermfg=15 + +hi StatusLine gui=none guibg=#4d595f guifg=#fff5f3 cterm=none ctermbg=0 ctermfg=15 +hi StatusLineNC gui=none guibg=#efe6e4 guifg=#796271 cterm=none ctermbg=7 ctermfg=8 +hi StatusLineTerm gui=none guibg=#357200 guifg=#fff5f3 cterm=none ctermbg=2 ctermfg=15 +hi StatusLineTermNC gui=none guibg=#efe6e4 guifg=#357200 cterm=none ctermbg=7 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#efe6e4 guifg=#796271 cterm=none ctermbg=7 ctermfg=8 +hi TabLineSel gui=none guibg=#007072 guifg=#fff5f3 cterm=none ctermbg=6 ctermfg=15 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#796271 cterm=none ctermfg=8 +hi Todo gui=bold guibg=#efe6e4 guifg=#985900 cterm=bold ctermbg=7 ctermfg=11 + +hi Warning gui=none guibg=#825e00 guifg=#fff5f3 cterm=none ctermbg=3 ctermfg=15 +hi WarningMsg gui=none guibg=#825e00 guifg=#fff5f3 cterm=none ctermbg=3 ctermfg=15 +hi Error gui=none guibg=#c61a14 guifg=#fff5f3 cterm=none ctermbg=1 ctermfg=15 +hi ErrorMsg gui=none guibg=#c61a14 guifg=#fff5f3 cterm=none ctermbg=1 ctermfg=15 + +hi MatchParen gui=underline,bold guibg=#efe6e4 guifg=#796271 cterm=underline,bold ctermbg=7 ctermfg=8 + +hi ToolbarLine guibg=#796271 guifg=#fff5f3 term=none ctermbg=8 ctermfg=15 +hi ToolbarButton gui=bold guibg=#796271 guifg=#fff5f3 term=none cterm=bold ctermbg=8 ctermfg=15 + +hi WildMenu guibg=#fff5f3 guifg=#4d595f term=standout ctermbg=15 ctermfg=0 + +hi Terminal guibg=#fff5f3 guifg=#4d595f term=none ctermbg=15 ctermfg=0 + +" Constructs +" ---------- +hi Constant guifg=#1666b0 ctermfg=4 +hi Number guifg=#1666b0 ctermfg=4 +hi Float guifg=#1666b0 ctermfg=4 +hi String guifg=#485adf ctermfg=12 + +hi Function guifg=#a83884 ctermfg=5 +hi Identifier guifg=#a234c0 term=none ctermfg=13 +hi Label guifg=#a83884 ctermfg=5 +hi Tag guifg=#a83884 ctermfg=5 +hi Keyword gui=bold guifg=#a234c0 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#00756a cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#007072 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#007072 ctermfg=6 +hi StorageClass guifg=#007072 ctermfg=6 +hi Structure guifg=#007072 ctermfg=6 +hi Typedef gui=bold guifg=#00756a cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#357200 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#437520 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#437520 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#4d595f cterm=bold ctermfg=0 +hi Exception gui=bold guifg=#c61a14 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#b93f1a term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#b93f1a cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#b93f1a cterm=bold ctermfg=9 +hi Include guifg=#b93f1a ctermfg=9 +hi Define guifg=#b93f1a ctermfg=9 + +hi Title gui=bold guibg=#fff5f3 guifg=#007072 cterm=bold ctermbg=15 ctermfg=6 + +hi Delimeter gui=bold guifg=#a83884 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#a83884 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#a83884 cterm=bold ctermfg=5 + +hi Debug guifg=#a234c0 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#efe6e4 guifg=#796271 term=none ctermbg=7 ctermfg=8 +hi Cursor guibg=#4d595f guifg=#fff5f3 ctermbg=0 ctermfg=15 +hi CursorLine gui=none guibg=#efe6e4 term=none cterm=none ctermbg=7 +hi CursorColumn gui=none guibg=#efe6e4 term=none cterm=none ctermbg=7 +hi CursorLineNr gui=bold guibg=#796271 guifg=#fff5f3 cterm=bold ctermbg=8 ctermfg=15 +hi ColorColumn guibg=#efe6e4 guifg=#4d595f term=none ctermbg=7 ctermfg=0 +hi SignColumn guibg=#efe6e4 guifg=#796271 term=none ctermbg=7 ctermfg=8 + +hi Folded guibg=#efe6e4 guifg=#796271 ctermbg=7 ctermfg=8 +hi FoldColumn guibg=#efe6e4 guifg=#796271 ctermbg=7 ctermfg=8 + +hi Special gui=bold guifg=#985900 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#efe6e4 guifg=#796271 cterm=none ctermbg=7 ctermfg=8 +hi SpecialChar gui=bold guifg=#985900 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#efe6e4 guifg=#796271 cterm=none ctermbg=7 ctermfg=8 +hi EndOfBuffer gui=bold guifg=#796271 cterm=bold ctermfg=8 + +hi Directory gui=none guifg=#357200 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#985900 cterm=bold ctermfg=11 +hi MoreMsg guifg=#437520 ctermfg=10 +hi ModeMsg gui=bold guifg=#357200 cterm=bold ctermfg=2 + +hi VimOption guifg=#a83884 ctermfg=5 +hi VimGroup guifg=#a83884 ctermfg=5 + +hi Underlined gui=underline guifg=#4d595f cterm=underline ctermfg=0 +hi Ignore guibg=#efe6e4 guifg=#796271 ctermbg=7 ctermfg=8 +hi Conceal guibg=#796271 guifg=#efe6e4 ctermbg=8 ctermfg=7 + +hi SpellBad guibg=#c61a14 guifg=#fff5f3 ctermbg=1 ctermfg=15 +hi SpellCap guibg=#825e00 guifg=#fff5f3 ctermbg=3 ctermfg=15 +hi SpellRare guibg=#a234c0 guifg=#fff5f3 ctermbg=13 ctermfg=15 +hi SpellLocal guibg=#00756a guifg=#fff5f3 ctermbg=14 ctermfg=15 + +hi Pmenu gui=italic guibg=#efe6e4 guifg=#4d595f cterm=none ctermbg=7 ctermfg=0 +hi PmenuSel gui=none,bold guibg=#796271 guifg=#fff5f3 cterm=none,bold ctermbg=8 ctermfg=15 +hi PmenuSbar guibg=#efe6e4 ctermbg=7 +hi PmenuThumb guibg=#796271 ctermbg=8 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#4d595f", + \ "#c61a14", + \ "#357200", + \ "#825e00", + \ "#1666b0", + \ "#a83884", + \ "#007072", + \ "#efe6e4", + \ "#796271", + \ "#b93f1a", + \ "#437520", + \ "#985900", + \ "#485adf", + \ "#a234c0", + \ "#00756a", + \ "#fff5f3" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#4d595f" + let g:terminal_color_1 = "#c61a14" + let g:terminal_color_2 = "#357200" + let g:terminal_color_3 = "#825e00" + let g:terminal_color_4 = "#1666b0" + let g:terminal_color_5 = "#a83884" + let g:terminal_color_6 = "#007072" + let g:terminal_color_7 = "#efe6e4" + let g:terminal_color_8 = "#796271" + let g:terminal_color_9 = "#b93f1a" + let g:terminal_color_10 = "#437520" + let g:terminal_color_11 = "#985900" + let g:terminal_color_12 = "#485adf" + let g:terminal_color_13 = "#a234c0" + let g:terminal_color_14 = "#00756a" + let g:terminal_color_15 = "#fff5f3" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#357200 guifg=#fff5f3 cterm=bold ctermbg=10 ctermfg=15 +hi DiffDelete gui=none guibg=#c61a14 guifg=#fff5f3 cterm=none ctermbg=9 ctermfg=15 +hi DiffChange gui=bold guibg=#efe6e4 guifg=#796271 cterm=bold ctermbg=7 ctermfg=8 +hi DiffText gui=bold guibg=#efe6e4 guifg=#b93f1a cterm=bold ctermbg=7 ctermfg=1 + +hi diffAdded guifg=#357200 ctermfg=2 +hi diffRemoved guifg=#c61a14 ctermfg=1 +hi diffNewFile gui=none guifg=#1666b0 ctermfg=4 +hi diffFile gui=none guifg=#825e00 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#efe6e4 guifg=#357200 ctermbg=7 ctermfg=2 +hi GitGutterChange gui=bold guibg=#efe6e4 guifg=#796271 cterm=bold ctermbg=7 ctermfg=8 +hi GitGutterDelete guibg=#efe6e4 guifg=#c61a14 ctermbg=7 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#efe6e4 guifg=#c61a14 cterm=bold ctermbg=7 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#c61a14 guifg=#fff5f3 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeInfo gui=none guibg=#007072 guifg=#fff5f3 cterm=none ctermbg=6 ctermfg=15 +hi NeomakeWarning gui=none guibg=#825e00 guifg=#fff5f3 cterm=none ctermbg=3 ctermfg=15 +hi NeomakeMessage gui=none guibg=#985900 guifg=#fff5f3 cterm=none ctermbg=11 ctermfg=15 + +hi NeomakeVirtualtextInfoDefault guifg=#00756a ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#985900 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#825e00 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#c61a14 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#357200 guifg=#fff5f3 cterm=none ctermbg=2 ctermfg=15 +hi NeomakeStatusGoodNC gui=none guibg=#efe6e4 guifg=#357200 cterm=none ctermbg=7 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#1666b0 guifg=#fff5f3 cterm=none ctermbg=4 ctermfg=15 +hi NeomakeStatColorTypeE gui=none guibg=#c61a14 guifg=#fff5f3 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeStatColorTypeW gui=none guibg=#825e00 guifg=#fff5f3 cterm=none ctermbg=3 ctermfg=15 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#efe6e4 guifg=#437520 cterm=bold ctermbg=7 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#4d595f cterm=bold ctermfg=0 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#b93f1a cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#825e00 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#1666b0 cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#485adf cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#4d595f cterm=bold ctermfg=0 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#a83884 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#4d595f ctermfg=0 + +hi MarkdownListMarker gui=none guifg=#357200 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#c61a14 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#1666b0 cterm=underline +hi SyntasticError gui=undercurl guisp=#c61a14 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#1666b0 cterm=underline +hi SyntasticErrorSing guifg=#fff5f3 guibg=#c61a14 ctermfg=15 ctermbg=1 +hi SyntasticWarningSign guifg=#fff5f3 guibg=#1666b0 ctermfg=15 ctermbg=4 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_future.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_future.vim @@ -0,0 +1,254 @@ +" Name: Tempus Future +" Description: Dark theme with colours inspired by concept art of outer space (WCAG AAA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_future" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#090a18 guifg=#b4abac ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#090a18 guifg=#b4abac ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#b4abac guifg=#090a18 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#2b1329 guifg=#b4abac cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#a7a2c4 guifg=#090a18 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#b4abac guifg=#090a18 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#2b1329 guifg=#a7a2c4 cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#6aba39 guifg=#090a18 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#2b1329 guifg=#6aba39 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#2b1329 guifg=#a7a2c4 cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#2ab7bb guifg=#090a18 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#a7a2c4 cterm=none ctermfg=7 +hi Todo gui=bold guibg=#2b1329 guifg=#de9b1d cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#bfa51a guifg=#090a18 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#bfa51a guifg=#090a18 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#ff7e8f guifg=#090a18 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#ff7e8f guifg=#090a18 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#2b1329 guifg=#a7a2c4 cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#a7a2c4 guifg=#090a18 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#a7a2c4 guifg=#090a18 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#090a18 guifg=#b4abac term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#090a18 guifg=#b4abac term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#4ab2d7 ctermfg=4 +hi Number guifg=#4ab2d7 ctermfg=4 +hi Float guifg=#4ab2d7 ctermfg=4 +hi String guifg=#8ba7ea ctermfg=12 + +hi Function guifg=#e58f84 ctermfg=5 +hi Identifier guifg=#e08bd6 term=none ctermfg=13 +hi Label guifg=#e58f84 ctermfg=5 +hi Tag guifg=#e58f84 ctermfg=5 +hi Keyword gui=bold guifg=#e08bd6 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#2cbab6 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#2ab7bb term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#2ab7bb ctermfg=6 +hi StorageClass guifg=#2ab7bb ctermfg=6 +hi Structure guifg=#2ab7bb ctermfg=6 +hi Typedef gui=bold guifg=#2cbab6 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#6aba39 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#60ba80 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#60ba80 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#b4abac cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#ff7e8f cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#f78e2f term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#f78e2f cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#f78e2f cterm=bold ctermfg=9 +hi Include guifg=#f78e2f ctermfg=9 +hi Define guifg=#f78e2f ctermfg=9 + +hi Title gui=bold guibg=#090a18 guifg=#2ab7bb cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#e58f84 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#e58f84 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#e58f84 cterm=bold ctermfg=5 + +hi Debug guifg=#e08bd6 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#2b1329 guifg=#a7a2c4 term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#b4abac guifg=#090a18 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#2b1329 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#2b1329 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#a7a2c4 guifg=#090a18 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#2b1329 guifg=#b4abac term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#2b1329 guifg=#a7a2c4 term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#2b1329 guifg=#a7a2c4 ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#2b1329 guifg=#a7a2c4 ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#de9b1d term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#2b1329 guifg=#a7a2c4 cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#de9b1d cterm=bold ctermfg=11 +hi NonText gui=none guibg=#2b1329 guifg=#a7a2c4 cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#a7a2c4 cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#6aba39 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#de9b1d cterm=bold ctermfg=11 +hi MoreMsg guifg=#60ba80 ctermfg=10 +hi ModeMsg gui=bold guifg=#6aba39 cterm=bold ctermfg=2 + +hi VimOption guifg=#e58f84 ctermfg=5 +hi VimGroup guifg=#e58f84 ctermfg=5 + +hi Underlined gui=underline guifg=#b4abac cterm=underline ctermfg=15 +hi Ignore guibg=#2b1329 guifg=#a7a2c4 ctermbg=8 ctermfg=7 +hi Conceal guibg=#a7a2c4 guifg=#2b1329 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#ff7e8f guifg=#090a18 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#bfa51a guifg=#090a18 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#e08bd6 guifg=#090a18 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#2cbab6 guifg=#090a18 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#2b1329 guifg=#b4abac cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#a7a2c4 guifg=#090a18 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#2b1329 ctermbg=8 +hi PmenuThumb guibg=#a7a2c4 ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#090a18", + \ "#ff7e8f", + \ "#6aba39", + \ "#bfa51a", + \ "#4ab2d7", + \ "#e58f84", + \ "#2ab7bb", + \ "#a7a2c4", + \ "#2b1329", + \ "#f78e2f", + \ "#60ba80", + \ "#de9b1d", + \ "#8ba7ea", + \ "#e08bd6", + \ "#2cbab6", + \ "#b4abac" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#090a18" + let g:terminal_color_1 = "#ff7e8f" + let g:terminal_color_2 = "#6aba39" + let g:terminal_color_3 = "#bfa51a" + let g:terminal_color_4 = "#4ab2d7" + let g:terminal_color_5 = "#e58f84" + let g:terminal_color_6 = "#2ab7bb" + let g:terminal_color_7 = "#a7a2c4" + let g:terminal_color_8 = "#2b1329" + let g:terminal_color_9 = "#f78e2f" + let g:terminal_color_10 = "#60ba80" + let g:terminal_color_11 = "#de9b1d" + let g:terminal_color_12 = "#8ba7ea" + let g:terminal_color_13 = "#e08bd6" + let g:terminal_color_14 = "#2cbab6" + let g:terminal_color_15 = "#b4abac" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#6aba39 guifg=#090a18 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#ff7e8f guifg=#090a18 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#2b1329 guifg=#a7a2c4 cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#2b1329 guifg=#f78e2f cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#6aba39 ctermfg=2 +hi diffRemoved guifg=#ff7e8f ctermfg=1 +hi diffNewFile gui=none guifg=#4ab2d7 ctermfg=4 +hi diffFile gui=none guifg=#bfa51a cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#2b1329 guifg=#6aba39 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#2b1329 guifg=#a7a2c4 cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#2b1329 guifg=#ff7e8f ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#2b1329 guifg=#ff7e8f cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#ff7e8f guifg=#090a18 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#2ab7bb guifg=#090a18 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#bfa51a guifg=#090a18 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#de9b1d guifg=#090a18 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#2cbab6 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#de9b1d ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#bfa51a ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#ff7e8f ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#6aba39 guifg=#090a18 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#2b1329 guifg=#6aba39 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#4ab2d7 guifg=#090a18 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#ff7e8f guifg=#090a18 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#bfa51a guifg=#090a18 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#2b1329 guifg=#60ba80 cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#b4abac cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#f78e2f cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#bfa51a cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#4ab2d7 cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#8ba7ea cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#b4abac cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#e58f84 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#b4abac ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#6aba39 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#ff7e8f cterm=underline +hi YcmWarningSection gui=undercurl guisp=#bfa51a cterm=underline +hi SyntasticError gui=undercurl guisp=#ff7e8f cterm=underline +hi SyntasticWarning gui=undercurl guisp=#bfa51a cterm=underline +hi SyntasticErrorSing guifg=#090a18 guibg=#ff7e8f ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#090a18 guibg=#bfa51a ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_night.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_night.vim @@ -0,0 +1,254 @@ +" Name: Tempus Night +" Description: High contrast dark theme with bright colours (WCAG AAA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_night" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#1a1a1a guifg=#e0e0e0 ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#1a1a1a guifg=#e0e0e0 ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#e0e0e0 guifg=#1a1a1a ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#242536 guifg=#e0e0e0 cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#c4bdaf guifg=#1a1a1a term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#e0e0e0 guifg=#1a1a1a cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#242536 guifg=#c4bdaf cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#5fc940 guifg=#1a1a1a cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#242536 guifg=#5fc940 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#242536 guifg=#c4bdaf cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#1dc5c3 guifg=#1a1a1a cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#c4bdaf cterm=none ctermfg=7 +hi Todo gui=bold guibg=#242536 guifg=#d7ae00 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#c5b300 guifg=#1a1a1a cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#c5b300 guifg=#1a1a1a cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#ff929f guifg=#1a1a1a cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#ff929f guifg=#1a1a1a cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#242536 guifg=#c4bdaf cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#c4bdaf guifg=#1a1a1a term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#c4bdaf guifg=#1a1a1a term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#1a1a1a guifg=#e0e0e0 term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#1a1a1a guifg=#e0e0e0 term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#5fb8ff ctermfg=4 +hi Number guifg=#5fb8ff ctermfg=4 +hi Float guifg=#5fb8ff ctermfg=4 +hi String guifg=#8cb4f0 ctermfg=12 + +hi Function guifg=#ef91df ctermfg=5 +hi Identifier guifg=#de99f0 term=none ctermfg=13 +hi Label guifg=#ef91df ctermfg=5 +hi Tag guifg=#ef91df ctermfg=5 +hi Keyword gui=bold guifg=#de99f0 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#00ca9a cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#1dc5c3 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#1dc5c3 ctermfg=6 +hi StorageClass guifg=#1dc5c3 ctermfg=6 +hi Structure guifg=#1dc5c3 ctermfg=6 +hi Typedef gui=bold guifg=#00ca9a cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#5fc940 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#88c400 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#88c400 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#e0e0e0 cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#ff929f cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#f69d6a term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#f69d6a cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#f69d6a cterm=bold ctermfg=9 +hi Include guifg=#f69d6a ctermfg=9 +hi Define guifg=#f69d6a ctermfg=9 + +hi Title gui=bold guibg=#1a1a1a guifg=#1dc5c3 cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#ef91df cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#ef91df cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#ef91df cterm=bold ctermfg=5 + +hi Debug guifg=#de99f0 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#242536 guifg=#c4bdaf term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#e0e0e0 guifg=#1a1a1a ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#242536 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#242536 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#c4bdaf guifg=#1a1a1a cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#242536 guifg=#e0e0e0 term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#242536 guifg=#c4bdaf term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#242536 guifg=#c4bdaf ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#242536 guifg=#c4bdaf ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#d7ae00 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#242536 guifg=#c4bdaf cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#d7ae00 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#242536 guifg=#c4bdaf cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#c4bdaf cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#5fc940 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#d7ae00 cterm=bold ctermfg=11 +hi MoreMsg guifg=#88c400 ctermfg=10 +hi ModeMsg gui=bold guifg=#5fc940 cterm=bold ctermfg=2 + +hi VimOption guifg=#ef91df ctermfg=5 +hi VimGroup guifg=#ef91df ctermfg=5 + +hi Underlined gui=underline guifg=#e0e0e0 cterm=underline ctermfg=15 +hi Ignore guibg=#242536 guifg=#c4bdaf ctermbg=8 ctermfg=7 +hi Conceal guibg=#c4bdaf guifg=#242536 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#ff929f guifg=#1a1a1a ctermbg=1 ctermfg=0 +hi SpellCap guibg=#c5b300 guifg=#1a1a1a ctermbg=3 ctermfg=0 +hi SpellRare guibg=#de99f0 guifg=#1a1a1a ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#00ca9a guifg=#1a1a1a ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#242536 guifg=#e0e0e0 cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#c4bdaf guifg=#1a1a1a cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#242536 ctermbg=8 +hi PmenuThumb guibg=#c4bdaf ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#1a1a1a", + \ "#ff929f", + \ "#5fc940", + \ "#c5b300", + \ "#5fb8ff", + \ "#ef91df", + \ "#1dc5c3", + \ "#c4bdaf", + \ "#242536", + \ "#f69d6a", + \ "#88c400", + \ "#d7ae00", + \ "#8cb4f0", + \ "#de99f0", + \ "#00ca9a", + \ "#e0e0e0" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#1a1a1a" + let g:terminal_color_1 = "#ff929f" + let g:terminal_color_2 = "#5fc940" + let g:terminal_color_3 = "#c5b300" + let g:terminal_color_4 = "#5fb8ff" + let g:terminal_color_5 = "#ef91df" + let g:terminal_color_6 = "#1dc5c3" + let g:terminal_color_7 = "#c4bdaf" + let g:terminal_color_8 = "#242536" + let g:terminal_color_9 = "#f69d6a" + let g:terminal_color_10 = "#88c400" + let g:terminal_color_11 = "#d7ae00" + let g:terminal_color_12 = "#8cb4f0" + let g:terminal_color_13 = "#de99f0" + let g:terminal_color_14 = "#00ca9a" + let g:terminal_color_15 = "#e0e0e0" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#5fc940 guifg=#1a1a1a cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#ff929f guifg=#1a1a1a cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#242536 guifg=#c4bdaf cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#242536 guifg=#f69d6a cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#5fc940 ctermfg=2 +hi diffRemoved guifg=#ff929f ctermfg=1 +hi diffNewFile gui=none guifg=#5fb8ff ctermfg=4 +hi diffFile gui=none guifg=#c5b300 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#242536 guifg=#5fc940 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#242536 guifg=#c4bdaf cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#242536 guifg=#ff929f ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#242536 guifg=#ff929f cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#ff929f guifg=#1a1a1a cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#1dc5c3 guifg=#1a1a1a cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#c5b300 guifg=#1a1a1a cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#d7ae00 guifg=#1a1a1a cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#00ca9a ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#d7ae00 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#c5b300 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#ff929f ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#5fc940 guifg=#1a1a1a cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#242536 guifg=#5fc940 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#5fb8ff guifg=#1a1a1a cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#ff929f guifg=#1a1a1a cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#c5b300 guifg=#1a1a1a cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#242536 guifg=#88c400 cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#e0e0e0 cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#f69d6a cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#c5b300 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#5fb8ff cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#8cb4f0 cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#e0e0e0 cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#ef91df ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#e0e0e0 ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#5fc940 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#ff929f cterm=underline +hi YcmWarningSection gui=undercurl guisp=#c5b300 cterm=underline +hi SyntasticError gui=undercurl guisp=#ff929f cterm=underline +hi SyntasticWarning gui=undercurl guisp=#c5b300 cterm=underline +hi SyntasticErrorSing guifg=#1a1a1a guibg=#ff929f ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#1a1a1a guibg=#c5b300 ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_past.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_past.vim @@ -0,0 +1,254 @@ +" Name: Tempus Past +" Description: Light theme inspired by old vaporwave concept art (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=light +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_past" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#f3f2f4 guifg=#53545b ctermbg=15 ctermfg=0 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#f3f2f4 guifg=#53545b ctermbg=none ctermfg=0 +endif + +hi Visual guibg=#53545b guifg=#f3f2f4 ctermbg=0 ctermfg=15 +hi Search gui=underline,bold guibg=#eae2de guifg=#53545b cterm=underline,bold ctermbg=7 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#80565d guifg=#f3f2f4 term=none cterm=underline,bold ctermbg=8 ctermfg=15 + +hi StatusLine gui=none guibg=#53545b guifg=#f3f2f4 cterm=none ctermbg=0 ctermfg=15 +hi StatusLineNC gui=none guibg=#eae2de guifg=#80565d cterm=none ctermbg=7 ctermfg=8 +hi StatusLineTerm gui=none guibg=#0a7040 guifg=#f3f2f4 cterm=none ctermbg=2 ctermfg=15 +hi StatusLineTermNC gui=none guibg=#eae2de guifg=#0a7040 cterm=none ctermbg=7 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#eae2de guifg=#80565d cterm=none ctermbg=7 ctermfg=8 +hi TabLineSel gui=none guibg=#096a83 guifg=#f3f2f4 cterm=none ctermbg=6 ctermfg=15 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#80565d cterm=none ctermfg=8 +hi Todo gui=bold guibg=#eae2de guifg=#8d554a cterm=bold ctermbg=7 ctermfg=11 + +hi Warning gui=none guibg=#a6403a guifg=#f3f2f4 cterm=none ctermbg=3 ctermfg=15 +hi WarningMsg gui=none guibg=#a6403a guifg=#f3f2f4 cterm=none ctermbg=3 ctermfg=15 +hi Error gui=none guibg=#c00c50 guifg=#f3f2f4 cterm=none ctermbg=1 ctermfg=15 +hi ErrorMsg gui=none guibg=#c00c50 guifg=#f3f2f4 cterm=none ctermbg=1 ctermfg=15 + +hi MatchParen gui=underline,bold guibg=#eae2de guifg=#80565d cterm=underline,bold ctermbg=7 ctermfg=8 + +hi ToolbarLine guibg=#80565d guifg=#f3f2f4 term=none ctermbg=8 ctermfg=15 +hi ToolbarButton gui=bold guibg=#80565d guifg=#f3f2f4 term=none cterm=bold ctermbg=8 ctermfg=15 + +hi WildMenu guibg=#f3f2f4 guifg=#53545b term=standout ctermbg=15 ctermfg=0 + +hi Terminal guibg=#f3f2f4 guifg=#53545b term=none ctermbg=15 ctermfg=0 + +" Constructs +" ---------- +hi Constant guifg=#1763aa ctermfg=4 +hi Number guifg=#1763aa ctermfg=4 +hi Float guifg=#1763aa ctermfg=4 +hi String guifg=#5559bb ctermfg=12 + +hi Function guifg=#b02874 ctermfg=5 +hi Identifier guifg=#b022a7 term=none ctermfg=13 +hi Label guifg=#b02874 ctermfg=5 +hi Tag guifg=#b02874 ctermfg=5 +hi Keyword gui=bold guifg=#b022a7 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#07707a cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#096a83 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#096a83 ctermfg=6 +hi StorageClass guifg=#096a83 ctermfg=6 +hi Structure guifg=#096a83 ctermfg=6 +hi Typedef gui=bold guifg=#07707a cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#0a7040 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#337243 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#337243 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#53545b cterm=bold ctermfg=0 +hi Exception gui=bold guifg=#c00c50 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#bd3133 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#bd3133 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#bd3133 cterm=bold ctermfg=9 +hi Include guifg=#bd3133 ctermfg=9 +hi Define guifg=#bd3133 ctermfg=9 + +hi Title gui=bold guibg=#f3f2f4 guifg=#096a83 cterm=bold ctermbg=15 ctermfg=6 + +hi Delimeter gui=bold guifg=#b02874 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#b02874 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#b02874 cterm=bold ctermfg=5 + +hi Debug guifg=#b022a7 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#eae2de guifg=#80565d term=none ctermbg=7 ctermfg=8 +hi Cursor guibg=#53545b guifg=#f3f2f4 ctermbg=0 ctermfg=15 +hi CursorLine gui=none guibg=#eae2de term=none cterm=none ctermbg=7 +hi CursorColumn gui=none guibg=#eae2de term=none cterm=none ctermbg=7 +hi CursorLineNr gui=bold guibg=#80565d guifg=#f3f2f4 cterm=bold ctermbg=8 ctermfg=15 +hi ColorColumn guibg=#eae2de guifg=#53545b term=none ctermbg=7 ctermfg=0 +hi SignColumn guibg=#eae2de guifg=#80565d term=none ctermbg=7 ctermfg=8 + +hi Folded guibg=#eae2de guifg=#80565d ctermbg=7 ctermfg=8 +hi FoldColumn guibg=#eae2de guifg=#80565d ctermbg=7 ctermfg=8 + +hi Special gui=bold guifg=#8d554a term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#eae2de guifg=#80565d cterm=none ctermbg=7 ctermfg=8 +hi SpecialChar gui=bold guifg=#8d554a cterm=bold ctermfg=11 +hi NonText gui=none guibg=#eae2de guifg=#80565d cterm=none ctermbg=7 ctermfg=8 +hi EndOfBuffer gui=bold guifg=#80565d cterm=bold ctermfg=8 + +hi Directory gui=none guifg=#0a7040 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#8d554a cterm=bold ctermfg=11 +hi MoreMsg guifg=#337243 ctermfg=10 +hi ModeMsg gui=bold guifg=#0a7040 cterm=bold ctermfg=2 + +hi VimOption guifg=#b02874 ctermfg=5 +hi VimGroup guifg=#b02874 ctermfg=5 + +hi Underlined gui=underline guifg=#53545b cterm=underline ctermfg=0 +hi Ignore guibg=#eae2de guifg=#80565d ctermbg=7 ctermfg=8 +hi Conceal guibg=#80565d guifg=#eae2de ctermbg=8 ctermfg=7 + +hi SpellBad guibg=#c00c50 guifg=#f3f2f4 ctermbg=1 ctermfg=15 +hi SpellCap guibg=#a6403a guifg=#f3f2f4 ctermbg=3 ctermfg=15 +hi SpellRare guibg=#b022a7 guifg=#f3f2f4 ctermbg=13 ctermfg=15 +hi SpellLocal guibg=#07707a guifg=#f3f2f4 ctermbg=14 ctermfg=15 + +hi Pmenu gui=italic guibg=#eae2de guifg=#53545b cterm=none ctermbg=7 ctermfg=0 +hi PmenuSel gui=none,bold guibg=#80565d guifg=#f3f2f4 cterm=none,bold ctermbg=8 ctermfg=15 +hi PmenuSbar guibg=#eae2de ctermbg=7 +hi PmenuThumb guibg=#80565d ctermbg=8 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#53545b", + \ "#c00c50", + \ "#0a7040", + \ "#a6403a", + \ "#1763aa", + \ "#b02874", + \ "#096a83", + \ "#eae2de", + \ "#80565d", + \ "#bd3133", + \ "#337243", + \ "#8d554a", + \ "#5559bb", + \ "#b022a7", + \ "#07707a", + \ "#f3f2f4" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#53545b" + let g:terminal_color_1 = "#c00c50" + let g:terminal_color_2 = "#0a7040" + let g:terminal_color_3 = "#a6403a" + let g:terminal_color_4 = "#1763aa" + let g:terminal_color_5 = "#b02874" + let g:terminal_color_6 = "#096a83" + let g:terminal_color_7 = "#eae2de" + let g:terminal_color_8 = "#80565d" + let g:terminal_color_9 = "#bd3133" + let g:terminal_color_10 = "#337243" + let g:terminal_color_11 = "#8d554a" + let g:terminal_color_12 = "#5559bb" + let g:terminal_color_13 = "#b022a7" + let g:terminal_color_14 = "#07707a" + let g:terminal_color_15 = "#f3f2f4" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#0a7040 guifg=#f3f2f4 cterm=bold ctermbg=10 ctermfg=15 +hi DiffDelete gui=none guibg=#c00c50 guifg=#f3f2f4 cterm=none ctermbg=9 ctermfg=15 +hi DiffChange gui=bold guibg=#eae2de guifg=#80565d cterm=bold ctermbg=7 ctermfg=8 +hi DiffText gui=bold guibg=#eae2de guifg=#bd3133 cterm=bold ctermbg=7 ctermfg=1 + +hi diffAdded guifg=#0a7040 ctermfg=2 +hi diffRemoved guifg=#c00c50 ctermfg=1 +hi diffNewFile gui=none guifg=#1763aa ctermfg=4 +hi diffFile gui=none guifg=#a6403a cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#eae2de guifg=#0a7040 ctermbg=7 ctermfg=2 +hi GitGutterChange gui=bold guibg=#eae2de guifg=#80565d cterm=bold ctermbg=7 ctermfg=8 +hi GitGutterDelete guibg=#eae2de guifg=#c00c50 ctermbg=7 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#eae2de guifg=#c00c50 cterm=bold ctermbg=7 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#c00c50 guifg=#f3f2f4 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeInfo gui=none guibg=#096a83 guifg=#f3f2f4 cterm=none ctermbg=6 ctermfg=15 +hi NeomakeWarning gui=none guibg=#a6403a guifg=#f3f2f4 cterm=none ctermbg=3 ctermfg=15 +hi NeomakeMessage gui=none guibg=#8d554a guifg=#f3f2f4 cterm=none ctermbg=11 ctermfg=15 + +hi NeomakeVirtualtextInfoDefault guifg=#07707a ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#8d554a ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#a6403a ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#c00c50 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#0a7040 guifg=#f3f2f4 cterm=none ctermbg=2 ctermfg=15 +hi NeomakeStatusGoodNC gui=none guibg=#eae2de guifg=#0a7040 cterm=none ctermbg=7 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#1763aa guifg=#f3f2f4 cterm=none ctermbg=4 ctermfg=15 +hi NeomakeStatColorTypeE gui=none guibg=#c00c50 guifg=#f3f2f4 cterm=none ctermbg=1 ctermfg=15 +hi NeomakeStatColorTypeW gui=none guibg=#a6403a guifg=#f3f2f4 cterm=none ctermbg=3 ctermfg=15 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#eae2de guifg=#337243 cterm=bold ctermbg=7 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#53545b cterm=bold ctermfg=0 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#bd3133 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#a6403a cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#1763aa cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#5559bb cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#53545b cterm=bold ctermfg=0 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#b02874 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#53545b ctermfg=0 + +hi MarkdownListMarker gui=none guifg=#0a7040 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#c00c50 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#1763aa cterm=underline +hi SyntasticError gui=undercurl guisp=#c00c50 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#1763aa cterm=underline +hi SyntasticErrorSing guifg=#f3f2f4 guibg=#c00c50 ctermfg=15 ctermbg=1 +hi SyntasticWarningSign guifg=#f3f2f4 guibg=#1763aa ctermfg=15 ctermbg=4 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_rift.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_rift.vim @@ -0,0 +1,254 @@ +" Name: Tempus Rift +" Description: Dark theme with a subdued palette on the green side of the spectrum (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_rift" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#162c22 guifg=#bbbcbc ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#162c22 guifg=#bbbcbc ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#bbbcbc guifg=#162c22 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#283431 guifg=#bbbcbc cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#ab9aa9 guifg=#162c22 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#bbbcbc guifg=#162c22 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#283431 guifg=#ab9aa9 cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#34b534 guifg=#162c22 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#283431 guifg=#34b534 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#283431 guifg=#ab9aa9 cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#5fad8f guifg=#162c22 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#ab9aa9 cterm=none ctermfg=7 +hi Todo gui=bold guibg=#283431 guifg=#82bd00 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#7fad00 guifg=#162c22 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#7fad00 guifg=#162c22 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#c19904 guifg=#162c22 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#c19904 guifg=#162c22 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#283431 guifg=#ab9aa9 cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#ab9aa9 guifg=#162c22 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#ab9aa9 guifg=#162c22 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#162c22 guifg=#bbbcbc term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#162c22 guifg=#bbbcbc term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#30aeb0 ctermfg=4 +hi Number guifg=#30aeb0 ctermfg=4 +hi Float guifg=#30aeb0 ctermfg=4 +hi String guifg=#56bdad ctermfg=12 + +hi Function guifg=#c8954c ctermfg=5 +hi Identifier guifg=#cca0ba term=none ctermfg=13 +hi Label guifg=#c8954c ctermfg=5 +hi Tag guifg=#c8954c ctermfg=5 +hi Keyword gui=bold guifg=#cca0ba gui=bold ctermfg=13 + +hi Character gui=bold guifg=#10c480 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#5fad8f term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#5fad8f ctermfg=6 +hi StorageClass guifg=#5fad8f ctermfg=6 +hi Structure guifg=#5fad8f ctermfg=6 +hi Typedef gui=bold guifg=#10c480 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#34b534 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#6ac134 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#6ac134 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#bbbcbc cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#c19904 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#d2a634 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#d2a634 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#d2a634 cterm=bold ctermfg=9 +hi Include guifg=#d2a634 ctermfg=9 +hi Define guifg=#d2a634 ctermfg=9 + +hi Title gui=bold guibg=#162c22 guifg=#5fad8f cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#c8954c cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#c8954c cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#c8954c cterm=bold ctermfg=5 + +hi Debug guifg=#cca0ba ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#283431 guifg=#ab9aa9 term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#bbbcbc guifg=#162c22 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#283431 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#283431 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#ab9aa9 guifg=#162c22 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#283431 guifg=#bbbcbc term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#283431 guifg=#ab9aa9 term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#283431 guifg=#ab9aa9 ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#283431 guifg=#ab9aa9 ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#82bd00 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#283431 guifg=#ab9aa9 cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#82bd00 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#283431 guifg=#ab9aa9 cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#ab9aa9 cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#34b534 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#82bd00 cterm=bold ctermfg=11 +hi MoreMsg guifg=#6ac134 ctermfg=10 +hi ModeMsg gui=bold guifg=#34b534 cterm=bold ctermfg=2 + +hi VimOption guifg=#c8954c ctermfg=5 +hi VimGroup guifg=#c8954c ctermfg=5 + +hi Underlined gui=underline guifg=#bbbcbc cterm=underline ctermfg=15 +hi Ignore guibg=#283431 guifg=#ab9aa9 ctermbg=8 ctermfg=7 +hi Conceal guibg=#ab9aa9 guifg=#283431 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#c19904 guifg=#162c22 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#7fad00 guifg=#162c22 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#cca0ba guifg=#162c22 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#10c480 guifg=#162c22 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#283431 guifg=#bbbcbc cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#ab9aa9 guifg=#162c22 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#283431 ctermbg=8 +hi PmenuThumb guibg=#ab9aa9 ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#162c22", + \ "#c19904", + \ "#34b534", + \ "#7fad00", + \ "#30aeb0", + \ "#c8954c", + \ "#5fad8f", + \ "#ab9aa9", + \ "#283431", + \ "#d2a634", + \ "#6ac134", + \ "#82bd00", + \ "#56bdad", + \ "#cca0ba", + \ "#10c480", + \ "#bbbcbc" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#162c22" + let g:terminal_color_1 = "#c19904" + let g:terminal_color_2 = "#34b534" + let g:terminal_color_3 = "#7fad00" + let g:terminal_color_4 = "#30aeb0" + let g:terminal_color_5 = "#c8954c" + let g:terminal_color_6 = "#5fad8f" + let g:terminal_color_7 = "#ab9aa9" + let g:terminal_color_8 = "#283431" + let g:terminal_color_9 = "#d2a634" + let g:terminal_color_10 = "#6ac134" + let g:terminal_color_11 = "#82bd00" + let g:terminal_color_12 = "#56bdad" + let g:terminal_color_13 = "#cca0ba" + let g:terminal_color_14 = "#10c480" + let g:terminal_color_15 = "#bbbcbc" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#34b534 guifg=#162c22 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#c19904 guifg=#162c22 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#283431 guifg=#ab9aa9 cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#283431 guifg=#d2a634 cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#34b534 ctermfg=2 +hi diffRemoved guifg=#c19904 ctermfg=1 +hi diffNewFile gui=none guifg=#30aeb0 ctermfg=4 +hi diffFile gui=none guifg=#7fad00 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#283431 guifg=#34b534 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#283431 guifg=#ab9aa9 cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#283431 guifg=#c19904 ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#283431 guifg=#c19904 cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#c19904 guifg=#162c22 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#5fad8f guifg=#162c22 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#7fad00 guifg=#162c22 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#82bd00 guifg=#162c22 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#10c480 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#82bd00 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#7fad00 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#c19904 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#34b534 guifg=#162c22 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#283431 guifg=#34b534 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#30aeb0 guifg=#162c22 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#c19904 guifg=#162c22 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#7fad00 guifg=#162c22 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#283431 guifg=#6ac134 cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#bbbcbc cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#d2a634 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#7fad00 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#30aeb0 cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#56bdad cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#bbbcbc cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#c8954c ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#bbbcbc ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#34b534 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#c19904 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#7fad00 cterm=underline +hi SyntasticError gui=undercurl guisp=#c19904 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#7fad00 cterm=underline +hi SyntasticErrorSing guifg=#162c22 guibg=#c19904 ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#162c22 guibg=#7fad00 ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_spring.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_spring.vim @@ -0,0 +1,254 @@ +" Name: Tempus Spring +" Description: Dark theme with a palette inspired by early spring colours (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_spring" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#283a37 guifg=#b5b8b7 ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#283a37 guifg=#b5b8b7 ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#b5b8b7 guifg=#283a37 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#2a453d guifg=#b5b8b7 cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#99afae guifg=#283a37 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#b5b8b7 guifg=#283a37 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#2a453d guifg=#99afae cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#5ec04d guifg=#283a37 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#2a453d guifg=#5ec04d cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#2a453d guifg=#99afae cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#36c08e guifg=#283a37 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#99afae cterm=none ctermfg=7 +hi Todo gui=bold guibg=#2a453d guifg=#c6a843 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#b0b01a guifg=#283a37 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#b0b01a guifg=#283a37 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#ff8b5f guifg=#283a37 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#ff8b5f guifg=#283a37 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#2a453d guifg=#99afae cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#99afae guifg=#283a37 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#99afae guifg=#283a37 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#283a37 guifg=#b5b8b7 term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#283a37 guifg=#b5b8b7 term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#39bace ctermfg=4 +hi Number guifg=#39bace ctermfg=4 +hi Float guifg=#39bace ctermfg=4 +hi String guifg=#70afef ctermfg=12 + +hi Function guifg=#e99399 ctermfg=5 +hi Identifier guifg=#d095e2 term=none ctermfg=13 +hi Label guifg=#e99399 ctermfg=5 +hi Tag guifg=#e99399 ctermfg=5 +hi Keyword gui=bold guifg=#d095e2 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#3cbfaf cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#36c08e term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#36c08e ctermfg=6 +hi StorageClass guifg=#36c08e ctermfg=6 +hi Structure guifg=#36c08e ctermfg=6 +hi Typedef gui=bold guifg=#3cbfaf cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#5ec04d cterm=bold ctermfg=2 +hi Statement gui=none guifg=#73be0d cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#73be0d cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#b5b8b7 cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#ff8b5f cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#e19e00 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#e19e00 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#e19e00 cterm=bold ctermfg=9 +hi Include guifg=#e19e00 ctermfg=9 +hi Define guifg=#e19e00 ctermfg=9 + +hi Title gui=bold guibg=#283a37 guifg=#36c08e cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#e99399 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#e99399 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#e99399 cterm=bold ctermfg=5 + +hi Debug guifg=#d095e2 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#2a453d guifg=#99afae term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#b5b8b7 guifg=#283a37 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#2a453d term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#2a453d term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#99afae guifg=#283a37 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#2a453d guifg=#b5b8b7 term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#2a453d guifg=#99afae term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#2a453d guifg=#99afae ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#2a453d guifg=#99afae ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#c6a843 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#2a453d guifg=#99afae cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#c6a843 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#2a453d guifg=#99afae cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#99afae cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#5ec04d term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#c6a843 cterm=bold ctermfg=11 +hi MoreMsg guifg=#73be0d ctermfg=10 +hi ModeMsg gui=bold guifg=#5ec04d cterm=bold ctermfg=2 + +hi VimOption guifg=#e99399 ctermfg=5 +hi VimGroup guifg=#e99399 ctermfg=5 + +hi Underlined gui=underline guifg=#b5b8b7 cterm=underline ctermfg=15 +hi Ignore guibg=#2a453d guifg=#99afae ctermbg=8 ctermfg=7 +hi Conceal guibg=#99afae guifg=#2a453d ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#ff8b5f guifg=#283a37 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#b0b01a guifg=#283a37 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#d095e2 guifg=#283a37 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#3cbfaf guifg=#283a37 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#2a453d guifg=#b5b8b7 cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#99afae guifg=#283a37 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#2a453d ctermbg=8 +hi PmenuThumb guibg=#99afae ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#283a37", + \ "#ff8b5f", + \ "#5ec04d", + \ "#b0b01a", + \ "#39bace", + \ "#e99399", + \ "#36c08e", + \ "#99afae", + \ "#2a453d", + \ "#e19e00", + \ "#73be0d", + \ "#c6a843", + \ "#70afef", + \ "#d095e2", + \ "#3cbfaf", + \ "#b5b8b7" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#283a37" + let g:terminal_color_1 = "#ff8b5f" + let g:terminal_color_2 = "#5ec04d" + let g:terminal_color_3 = "#b0b01a" + let g:terminal_color_4 = "#39bace" + let g:terminal_color_5 = "#e99399" + let g:terminal_color_6 = "#36c08e" + let g:terminal_color_7 = "#99afae" + let g:terminal_color_8 = "#2a453d" + let g:terminal_color_9 = "#e19e00" + let g:terminal_color_10 = "#73be0d" + let g:terminal_color_11 = "#c6a843" + let g:terminal_color_12 = "#70afef" + let g:terminal_color_13 = "#d095e2" + let g:terminal_color_14 = "#3cbfaf" + let g:terminal_color_15 = "#b5b8b7" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#5ec04d guifg=#283a37 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#ff8b5f guifg=#283a37 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#2a453d guifg=#99afae cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#2a453d guifg=#e19e00 cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#5ec04d ctermfg=2 +hi diffRemoved guifg=#ff8b5f ctermfg=1 +hi diffNewFile gui=none guifg=#39bace ctermfg=4 +hi diffFile gui=none guifg=#b0b01a cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#2a453d guifg=#5ec04d ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#2a453d guifg=#99afae cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#2a453d guifg=#ff8b5f ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#2a453d guifg=#ff8b5f cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#ff8b5f guifg=#283a37 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#36c08e guifg=#283a37 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#b0b01a guifg=#283a37 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#c6a843 guifg=#283a37 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#3cbfaf ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#c6a843 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#b0b01a ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#ff8b5f ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#5ec04d guifg=#283a37 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#2a453d guifg=#5ec04d cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#39bace guifg=#283a37 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#ff8b5f guifg=#283a37 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#b0b01a guifg=#283a37 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#2a453d guifg=#73be0d cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#b5b8b7 cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#e19e00 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#b0b01a cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#39bace cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#70afef cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#b5b8b7 cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#e99399 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#b5b8b7 ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#5ec04d cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#ff8b5f cterm=underline +hi YcmWarningSection gui=undercurl guisp=#b0b01a cterm=underline +hi SyntasticError gui=undercurl guisp=#ff8b5f cterm=underline +hi SyntasticWarning gui=undercurl guisp=#b0b01a cterm=underline +hi SyntasticErrorSing guifg=#283a37 guibg=#ff8b5f ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#283a37 guibg=#b0b01a ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_summer.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_summer.vim @@ -0,0 +1,254 @@ +" Name: Tempus Summer +" Description: Dark theme with colours inspired by summer evenings by the sea (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_summer" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#202c3d guifg=#a0abae ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#202c3d guifg=#a0abae ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#a0abae guifg=#202c3d ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#39304f guifg=#a0abae cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#949cbf guifg=#202c3d term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#a0abae guifg=#202c3d cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#39304f guifg=#949cbf cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#4eb075 guifg=#202c3d cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#39304f guifg=#4eb075 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#39304f guifg=#949cbf cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#3dae9f guifg=#202c3d cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#949cbf cterm=none ctermfg=7 +hi Todo gui=bold guibg=#39304f guifg=#be981f cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#ba9a0a guifg=#202c3d cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#ba9a0a guifg=#202c3d cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#fe6f70 guifg=#202c3d cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#fe6f70 guifg=#202c3d cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#39304f guifg=#949cbf cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#949cbf guifg=#202c3d term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#949cbf guifg=#202c3d term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#202c3d guifg=#a0abae term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#202c3d guifg=#a0abae term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#60a1e6 ctermfg=4 +hi Number guifg=#60a1e6 ctermfg=4 +hi Float guifg=#60a1e6 ctermfg=4 +hi String guifg=#8599ef ctermfg=12 + +hi Function guifg=#d285ad ctermfg=5 +hi Identifier guifg=#cc82d7 term=none ctermfg=13 +hi Label guifg=#d285ad ctermfg=5 +hi Tag guifg=#d285ad ctermfg=5 +hi Keyword gui=bold guifg=#cc82d7 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#2aacbf cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#3dae9f term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#3dae9f ctermfg=6 +hi StorageClass guifg=#3dae9f ctermfg=6 +hi Structure guifg=#3dae9f ctermfg=6 +hi Typedef gui=bold guifg=#2aacbf cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#4eb075 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#5baf4f cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#5baf4f cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#a0abae cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#fe6f70 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#ec7f4f term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#ec7f4f cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#ec7f4f cterm=bold ctermfg=9 +hi Include guifg=#ec7f4f ctermfg=9 +hi Define guifg=#ec7f4f ctermfg=9 + +hi Title gui=bold guibg=#202c3d guifg=#3dae9f cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#d285ad cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#d285ad cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#d285ad cterm=bold ctermfg=5 + +hi Debug guifg=#cc82d7 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#39304f guifg=#949cbf term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#a0abae guifg=#202c3d ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#39304f term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#39304f term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#949cbf guifg=#202c3d cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#39304f guifg=#a0abae term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#39304f guifg=#949cbf term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#39304f guifg=#949cbf ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#39304f guifg=#949cbf ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#be981f term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#39304f guifg=#949cbf cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#be981f cterm=bold ctermfg=11 +hi NonText gui=none guibg=#39304f guifg=#949cbf cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#949cbf cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#4eb075 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#be981f cterm=bold ctermfg=11 +hi MoreMsg guifg=#5baf4f ctermfg=10 +hi ModeMsg gui=bold guifg=#4eb075 cterm=bold ctermfg=2 + +hi VimOption guifg=#d285ad ctermfg=5 +hi VimGroup guifg=#d285ad ctermfg=5 + +hi Underlined gui=underline guifg=#a0abae cterm=underline ctermfg=15 +hi Ignore guibg=#39304f guifg=#949cbf ctermbg=8 ctermfg=7 +hi Conceal guibg=#949cbf guifg=#39304f ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#fe6f70 guifg=#202c3d ctermbg=1 ctermfg=0 +hi SpellCap guibg=#ba9a0a guifg=#202c3d ctermbg=3 ctermfg=0 +hi SpellRare guibg=#cc82d7 guifg=#202c3d ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#2aacbf guifg=#202c3d ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#39304f guifg=#a0abae cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#949cbf guifg=#202c3d cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#39304f ctermbg=8 +hi PmenuThumb guibg=#949cbf ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#202c3d", + \ "#fe6f70", + \ "#4eb075", + \ "#ba9a0a", + \ "#60a1e6", + \ "#d285ad", + \ "#3dae9f", + \ "#949cbf", + \ "#39304f", + \ "#ec7f4f", + \ "#5baf4f", + \ "#be981f", + \ "#8599ef", + \ "#cc82d7", + \ "#2aacbf", + \ "#a0abae" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#202c3d" + let g:terminal_color_1 = "#fe6f70" + let g:terminal_color_2 = "#4eb075" + let g:terminal_color_3 = "#ba9a0a" + let g:terminal_color_4 = "#60a1e6" + let g:terminal_color_5 = "#d285ad" + let g:terminal_color_6 = "#3dae9f" + let g:terminal_color_7 = "#949cbf" + let g:terminal_color_8 = "#39304f" + let g:terminal_color_9 = "#ec7f4f" + let g:terminal_color_10 = "#5baf4f" + let g:terminal_color_11 = "#be981f" + let g:terminal_color_12 = "#8599ef" + let g:terminal_color_13 = "#cc82d7" + let g:terminal_color_14 = "#2aacbf" + let g:terminal_color_15 = "#a0abae" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#4eb075 guifg=#202c3d cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#fe6f70 guifg=#202c3d cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#39304f guifg=#949cbf cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#39304f guifg=#ec7f4f cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#4eb075 ctermfg=2 +hi diffRemoved guifg=#fe6f70 ctermfg=1 +hi diffNewFile gui=none guifg=#60a1e6 ctermfg=4 +hi diffFile gui=none guifg=#ba9a0a cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#39304f guifg=#4eb075 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#39304f guifg=#949cbf cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#39304f guifg=#fe6f70 ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#39304f guifg=#fe6f70 cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#fe6f70 guifg=#202c3d cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#3dae9f guifg=#202c3d cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#ba9a0a guifg=#202c3d cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#be981f guifg=#202c3d cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#2aacbf ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#be981f ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#ba9a0a ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#fe6f70 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#4eb075 guifg=#202c3d cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#39304f guifg=#4eb075 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#60a1e6 guifg=#202c3d cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#fe6f70 guifg=#202c3d cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#ba9a0a guifg=#202c3d cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#39304f guifg=#5baf4f cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#a0abae cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#ec7f4f cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#ba9a0a cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#60a1e6 cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#8599ef cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#a0abae cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#d285ad ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#a0abae ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#4eb075 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#fe6f70 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#ba9a0a cterm=underline +hi SyntasticError gui=undercurl guisp=#fe6f70 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#ba9a0a cterm=underline +hi SyntasticErrorSing guifg=#202c3d guibg=#fe6f70 ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#202c3d guibg=#ba9a0a ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_tempest.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_tempest.vim @@ -0,0 +1,254 @@ +" Name: Tempus Tempest +" Description: A green-scale, subtle theme for late night hackers (WCAG AAA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_tempest" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#282b2b guifg=#b6e0ca ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#282b2b guifg=#b6e0ca ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#b6e0ca guifg=#282b2b ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#323535 guifg=#b6e0ca cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#b0c8ca guifg=#282b2b term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#b6e0ca guifg=#282b2b cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#323535 guifg=#b0c8ca cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#7ad97a guifg=#282b2b cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#323535 guifg=#7ad97a cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#323535 guifg=#b0c8ca cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#8bd0bf guifg=#282b2b cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#b0c8ca cterm=none ctermfg=7 +hi Todo gui=bold guibg=#323535 guifg=#bbde4f cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#bfcc4a guifg=#282b2b cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#bfcc4a guifg=#282b2b cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#cfc80a guifg=#282b2b cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#cfc80a guifg=#282b2b cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#323535 guifg=#b0c8ca cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#b0c8ca guifg=#282b2b term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#b0c8ca guifg=#282b2b term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#282b2b guifg=#b6e0ca term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#282b2b guifg=#b6e0ca term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#60d7cd ctermfg=4 +hi Number guifg=#60d7cd ctermfg=4 +hi Float guifg=#60d7cd ctermfg=4 +hi String guifg=#74e4cd ctermfg=12 + +hi Function guifg=#c5c4af ctermfg=5 +hi Identifier guifg=#d2d4aa term=none ctermfg=13 +hi Label guifg=#c5c4af ctermfg=5 +hi Tag guifg=#c5c4af ctermfg=5 +hi Keyword gui=bold guifg=#d2d4aa gui=bold ctermfg=13 + +hi Character gui=bold guifg=#9bdfc4 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#8bd0bf term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#8bd0bf ctermfg=6 +hi StorageClass guifg=#8bd0bf ctermfg=6 +hi Structure guifg=#8bd0bf ctermfg=6 +hi Typedef gui=bold guifg=#9bdfc4 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#7ad97a cterm=bold ctermfg=2 +hi Statement gui=none guifg=#99e299 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#99e299 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#b6e0ca cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#cfc80a cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#d1d933 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#d1d933 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#d1d933 cterm=bold ctermfg=9 +hi Include guifg=#d1d933 ctermfg=9 +hi Define guifg=#d1d933 ctermfg=9 + +hi Title gui=bold guibg=#282b2b guifg=#8bd0bf cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#c5c4af cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#c5c4af cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#c5c4af cterm=bold ctermfg=5 + +hi Debug guifg=#d2d4aa ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#323535 guifg=#b0c8ca term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#b6e0ca guifg=#282b2b ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#323535 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#323535 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#b0c8ca guifg=#282b2b cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#323535 guifg=#b6e0ca term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#323535 guifg=#b0c8ca term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#323535 guifg=#b0c8ca ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#323535 guifg=#b0c8ca ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#bbde4f term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#323535 guifg=#b0c8ca cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#bbde4f cterm=bold ctermfg=11 +hi NonText gui=none guibg=#323535 guifg=#b0c8ca cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#b0c8ca cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#7ad97a term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#bbde4f cterm=bold ctermfg=11 +hi MoreMsg guifg=#99e299 ctermfg=10 +hi ModeMsg gui=bold guifg=#7ad97a cterm=bold ctermfg=2 + +hi VimOption guifg=#c5c4af ctermfg=5 +hi VimGroup guifg=#c5c4af ctermfg=5 + +hi Underlined gui=underline guifg=#b6e0ca cterm=underline ctermfg=15 +hi Ignore guibg=#323535 guifg=#b0c8ca ctermbg=8 ctermfg=7 +hi Conceal guibg=#b0c8ca guifg=#323535 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#cfc80a guifg=#282b2b ctermbg=1 ctermfg=0 +hi SpellCap guibg=#bfcc4a guifg=#282b2b ctermbg=3 ctermfg=0 +hi SpellRare guibg=#d2d4aa guifg=#282b2b ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#9bdfc4 guifg=#282b2b ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#323535 guifg=#b6e0ca cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#b0c8ca guifg=#282b2b cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#323535 ctermbg=8 +hi PmenuThumb guibg=#b0c8ca ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#282b2b", + \ "#cfc80a", + \ "#7ad97a", + \ "#bfcc4a", + \ "#60d7cd", + \ "#c5c4af", + \ "#8bd0bf", + \ "#b0c8ca", + \ "#323535", + \ "#d1d933", + \ "#99e299", + \ "#bbde4f", + \ "#74e4cd", + \ "#d2d4aa", + \ "#9bdfc4", + \ "#b6e0ca" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#282b2b" + let g:terminal_color_1 = "#cfc80a" + let g:terminal_color_2 = "#7ad97a" + let g:terminal_color_3 = "#bfcc4a" + let g:terminal_color_4 = "#60d7cd" + let g:terminal_color_5 = "#c5c4af" + let g:terminal_color_6 = "#8bd0bf" + let g:terminal_color_7 = "#b0c8ca" + let g:terminal_color_8 = "#323535" + let g:terminal_color_9 = "#d1d933" + let g:terminal_color_10 = "#99e299" + let g:terminal_color_11 = "#bbde4f" + let g:terminal_color_12 = "#74e4cd" + let g:terminal_color_13 = "#d2d4aa" + let g:terminal_color_14 = "#9bdfc4" + let g:terminal_color_15 = "#b6e0ca" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#7ad97a guifg=#282b2b cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#cfc80a guifg=#282b2b cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#323535 guifg=#b0c8ca cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#323535 guifg=#d1d933 cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#7ad97a ctermfg=2 +hi diffRemoved guifg=#cfc80a ctermfg=1 +hi diffNewFile gui=none guifg=#60d7cd ctermfg=4 +hi diffFile gui=none guifg=#bfcc4a cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#323535 guifg=#7ad97a ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#323535 guifg=#b0c8ca cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#323535 guifg=#cfc80a ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#323535 guifg=#cfc80a cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#cfc80a guifg=#282b2b cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#8bd0bf guifg=#282b2b cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#bfcc4a guifg=#282b2b cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#bbde4f guifg=#282b2b cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#9bdfc4 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#bbde4f ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#bfcc4a ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#cfc80a ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#7ad97a guifg=#282b2b cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#323535 guifg=#7ad97a cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#60d7cd guifg=#282b2b cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#cfc80a guifg=#282b2b cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#bfcc4a guifg=#282b2b cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#323535 guifg=#99e299 cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#b6e0ca cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#d1d933 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#bfcc4a cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#60d7cd cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#74e4cd cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#b6e0ca cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#c5c4af ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#b6e0ca ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#7ad97a cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#cfc80a cterm=underline +hi YcmWarningSection gui=undercurl guisp=#bfcc4a cterm=underline +hi SyntasticError gui=undercurl guisp=#cfc80a cterm=underline +hi SyntasticWarning gui=undercurl guisp=#bfcc4a cterm=underline +hi SyntasticErrorSing guifg=#282b2b guibg=#cfc80a ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#282b2b guibg=#bfcc4a ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_totus.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_totus.vim @@ -0,0 +1,254 @@ +" Name: Tempus Totus +" Description: Light theme for prose or for coding in an open space (WCAG AAA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=light +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_totus" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#ffffff guifg=#4a484d ctermbg=15 ctermfg=0 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#ffffff guifg=#4a484d ctermbg=none ctermfg=0 +endif + +hi Visual guibg=#4a484d guifg=#ffffff ctermbg=0 ctermfg=15 +hi Search gui=underline,bold guibg=#efefef guifg=#4a484d cterm=underline,bold ctermbg=7 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#5e4b4f guifg=#ffffff term=none cterm=underline,bold ctermbg=8 ctermfg=15 + +hi StatusLine gui=none guibg=#4a484d guifg=#ffffff cterm=none ctermbg=0 ctermfg=15 +hi StatusLineNC gui=none guibg=#efefef guifg=#5e4b4f cterm=none ctermbg=7 ctermfg=8 +hi StatusLineTerm gui=none guibg=#005d26 guifg=#ffffff cterm=none ctermbg=2 ctermfg=15 +hi StatusLineTermNC gui=none guibg=#efefef guifg=#005d26 cterm=none ctermbg=7 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#efefef guifg=#5e4b4f cterm=none ctermbg=7 ctermfg=8 +hi TabLineSel gui=none guibg=#185570 guifg=#ffffff cterm=none ctermbg=6 ctermfg=15 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#5e4b4f cterm=none ctermfg=8 +hi Todo gui=bold guibg=#efefef guifg=#8a3600 cterm=bold ctermbg=7 ctermfg=11 + +hi Warning gui=none guibg=#714700 guifg=#ffffff cterm=none ctermbg=3 ctermfg=15 +hi WarningMsg gui=none guibg=#714700 guifg=#ffffff cterm=none ctermbg=3 ctermfg=15 +hi Error gui=none guibg=#a50000 guifg=#ffffff cterm=none ctermbg=1 ctermfg=15 +hi ErrorMsg gui=none guibg=#a50000 guifg=#ffffff cterm=none ctermbg=1 ctermfg=15 + +hi MatchParen gui=underline,bold guibg=#efefef guifg=#5e4b4f cterm=underline,bold ctermbg=7 ctermfg=8 + +hi ToolbarLine guibg=#5e4b4f guifg=#ffffff term=none ctermbg=8 ctermfg=15 +hi ToolbarButton gui=bold guibg=#5e4b4f guifg=#ffffff term=none cterm=bold ctermbg=8 ctermfg=15 + +hi WildMenu guibg=#ffffff guifg=#4a484d term=standout ctermbg=15 ctermfg=0 + +hi Terminal guibg=#ffffff guifg=#4a484d term=none ctermbg=15 ctermfg=0 + +" Constructs +" ---------- +hi Constant guifg=#1d3ccf ctermfg=4 +hi Number guifg=#1d3ccf ctermfg=4 +hi Float guifg=#1d3ccf ctermfg=4 +hi String guifg=#2d45b0 ctermfg=12 + +hi Function guifg=#88267a ctermfg=5 +hi Identifier guifg=#700dc9 term=none ctermfg=13 +hi Label guifg=#88267a ctermfg=5 +hi Tag guifg=#88267a ctermfg=5 +hi Keyword gui=bold guifg=#700dc9 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#005289 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#185570 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#185570 ctermfg=6 +hi StorageClass guifg=#185570 ctermfg=6 +hi Structure guifg=#185570 ctermfg=6 +hi Typedef gui=bold guifg=#005289 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#005d26 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#4a5500 cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#4a5500 cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#4a484d cterm=bold ctermfg=0 +hi Exception gui=bold guifg=#a50000 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#992030 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#992030 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#992030 cterm=bold ctermfg=9 +hi Include guifg=#992030 ctermfg=9 +hi Define guifg=#992030 ctermfg=9 + +hi Title gui=bold guibg=#ffffff guifg=#185570 cterm=bold ctermbg=15 ctermfg=6 + +hi Delimeter gui=bold guifg=#88267a cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#88267a cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#88267a cterm=bold ctermfg=5 + +hi Debug guifg=#700dc9 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#efefef guifg=#5e4b4f term=none ctermbg=7 ctermfg=8 +hi Cursor guibg=#4a484d guifg=#ffffff ctermbg=0 ctermfg=15 +hi CursorLine gui=none guibg=#efefef term=none cterm=none ctermbg=7 +hi CursorColumn gui=none guibg=#efefef term=none cterm=none ctermbg=7 +hi CursorLineNr gui=bold guibg=#5e4b4f guifg=#ffffff cterm=bold ctermbg=8 ctermfg=15 +hi ColorColumn guibg=#efefef guifg=#4a484d term=none ctermbg=7 ctermfg=0 +hi SignColumn guibg=#efefef guifg=#5e4b4f term=none ctermbg=7 ctermfg=8 + +hi Folded guibg=#efefef guifg=#5e4b4f ctermbg=7 ctermfg=8 +hi FoldColumn guibg=#efefef guifg=#5e4b4f ctermbg=7 ctermfg=8 + +hi Special gui=bold guifg=#8a3600 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#efefef guifg=#5e4b4f cterm=none ctermbg=7 ctermfg=8 +hi SpecialChar gui=bold guifg=#8a3600 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#efefef guifg=#5e4b4f cterm=none ctermbg=7 ctermfg=8 +hi EndOfBuffer gui=bold guifg=#5e4b4f cterm=bold ctermfg=8 + +hi Directory gui=none guifg=#005d26 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#8a3600 cterm=bold ctermfg=11 +hi MoreMsg guifg=#4a5500 ctermfg=10 +hi ModeMsg gui=bold guifg=#005d26 cterm=bold ctermfg=2 + +hi VimOption guifg=#88267a ctermfg=5 +hi VimGroup guifg=#88267a ctermfg=5 + +hi Underlined gui=underline guifg=#4a484d cterm=underline ctermfg=0 +hi Ignore guibg=#efefef guifg=#5e4b4f ctermbg=7 ctermfg=8 +hi Conceal guibg=#5e4b4f guifg=#efefef ctermbg=8 ctermfg=7 + +hi SpellBad guibg=#a50000 guifg=#ffffff ctermbg=1 ctermfg=15 +hi SpellCap guibg=#714700 guifg=#ffffff ctermbg=3 ctermfg=15 +hi SpellRare guibg=#700dc9 guifg=#ffffff ctermbg=13 ctermfg=15 +hi SpellLocal guibg=#005289 guifg=#ffffff ctermbg=14 ctermfg=15 + +hi Pmenu gui=italic guibg=#efefef guifg=#4a484d cterm=none ctermbg=7 ctermfg=0 +hi PmenuSel gui=none,bold guibg=#5e4b4f guifg=#ffffff cterm=none,bold ctermbg=8 ctermfg=15 +hi PmenuSbar guibg=#efefef ctermbg=7 +hi PmenuThumb guibg=#5e4b4f ctermbg=8 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#4a484d", + \ "#a50000", + \ "#005d26", + \ "#714700", + \ "#1d3ccf", + \ "#88267a", + \ "#185570", + \ "#efefef", + \ "#5e4b4f", + \ "#992030", + \ "#4a5500", + \ "#8a3600", + \ "#2d45b0", + \ "#700dc9", + \ "#005289", + \ "#ffffff" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#4a484d" + let g:terminal_color_1 = "#a50000" + let g:terminal_color_2 = "#005d26" + let g:terminal_color_3 = "#714700" + let g:terminal_color_4 = "#1d3ccf" + let g:terminal_color_5 = "#88267a" + let g:terminal_color_6 = "#185570" + let g:terminal_color_7 = "#efefef" + let g:terminal_color_8 = "#5e4b4f" + let g:terminal_color_9 = "#992030" + let g:terminal_color_10 = "#4a5500" + let g:terminal_color_11 = "#8a3600" + let g:terminal_color_12 = "#2d45b0" + let g:terminal_color_13 = "#700dc9" + let g:terminal_color_14 = "#005289" + let g:terminal_color_15 = "#ffffff" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#005d26 guifg=#ffffff cterm=bold ctermbg=10 ctermfg=15 +hi DiffDelete gui=none guibg=#a50000 guifg=#ffffff cterm=none ctermbg=9 ctermfg=15 +hi DiffChange gui=bold guibg=#efefef guifg=#5e4b4f cterm=bold ctermbg=7 ctermfg=8 +hi DiffText gui=bold guibg=#efefef guifg=#992030 cterm=bold ctermbg=7 ctermfg=1 + +hi diffAdded guifg=#005d26 ctermfg=2 +hi diffRemoved guifg=#a50000 ctermfg=1 +hi diffNewFile gui=none guifg=#1d3ccf ctermfg=4 +hi diffFile gui=none guifg=#714700 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#efefef guifg=#005d26 ctermbg=7 ctermfg=2 +hi GitGutterChange gui=bold guibg=#efefef guifg=#5e4b4f cterm=bold ctermbg=7 ctermfg=8 +hi GitGutterDelete guibg=#efefef guifg=#a50000 ctermbg=7 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#efefef guifg=#a50000 cterm=bold ctermbg=7 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#a50000 guifg=#ffffff cterm=none ctermbg=1 ctermfg=15 +hi NeomakeInfo gui=none guibg=#185570 guifg=#ffffff cterm=none ctermbg=6 ctermfg=15 +hi NeomakeWarning gui=none guibg=#714700 guifg=#ffffff cterm=none ctermbg=3 ctermfg=15 +hi NeomakeMessage gui=none guibg=#8a3600 guifg=#ffffff cterm=none ctermbg=11 ctermfg=15 + +hi NeomakeVirtualtextInfoDefault guifg=#005289 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#8a3600 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#714700 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#a50000 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#005d26 guifg=#ffffff cterm=none ctermbg=2 ctermfg=15 +hi NeomakeStatusGoodNC gui=none guibg=#efefef guifg=#005d26 cterm=none ctermbg=7 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#1d3ccf guifg=#ffffff cterm=none ctermbg=4 ctermfg=15 +hi NeomakeStatColorTypeE gui=none guibg=#a50000 guifg=#ffffff cterm=none ctermbg=1 ctermfg=15 +hi NeomakeStatColorTypeW gui=none guibg=#714700 guifg=#ffffff cterm=none ctermbg=3 ctermfg=15 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#efefef guifg=#4a5500 cterm=bold ctermbg=7 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#4a484d cterm=bold ctermfg=0 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#992030 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#714700 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#1d3ccf cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#2d45b0 cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#4a484d cterm=bold ctermfg=0 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#88267a ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#4a484d ctermfg=0 + +hi MarkdownListMarker gui=none guifg=#005d26 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#a50000 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#1d3ccf cterm=underline +hi SyntasticError gui=undercurl guisp=#a50000 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#1d3ccf cterm=underline +hi SyntasticErrorSing guifg=#ffffff guibg=#a50000 ctermfg=15 ctermbg=1 +hi SyntasticWarningSign guifg=#ffffff guibg=#1d3ccf ctermfg=15 ctermbg=4 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_warp.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_warp.vim @@ -0,0 +1,254 @@ +" Name: Tempus Warp +" Description: Dark theme with a vibrant palette (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_warp" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#001514 guifg=#a29fa0 ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#001514 guifg=#a29fa0 ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#a29fa0 guifg=#001514 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#261c2c guifg=#a29fa0 cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#968282 guifg=#001514 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#a29fa0 guifg=#001514 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#261c2c guifg=#968282 cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#169c16 guifg=#001514 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#261c2c guifg=#169c16 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#261c2c guifg=#968282 cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#009880 guifg=#001514 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#968282 cterm=none ctermfg=7 +hi Todo gui=bold guibg=#261c2c guifg=#ba8a00 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#9f8500 guifg=#001514 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#9f8500 guifg=#001514 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#ff3737 guifg=#001514 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#ff3737 guifg=#001514 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#261c2c guifg=#968282 cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#968282 guifg=#001514 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#968282 guifg=#001514 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#001514 guifg=#a29fa0 term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#001514 guifg=#a29fa0 term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#5781ef ctermfg=4 +hi Number guifg=#5781ef ctermfg=4 +hi Float guifg=#5781ef ctermfg=4 +hi String guifg=#8887f0 ctermfg=12 + +hi Function guifg=#da4ebf ctermfg=5 +hi Identifier guifg=#d85cf2 term=none ctermfg=13 +hi Label guifg=#da4ebf ctermfg=5 +hi Tag guifg=#da4ebf ctermfg=5 +hi Keyword gui=bold guifg=#d85cf2 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#1da1af cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#009880 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#009880 ctermfg=6 +hi StorageClass guifg=#009880 ctermfg=6 +hi Structure guifg=#009880 ctermfg=6 +hi Typedef gui=bold guifg=#1da1af cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#169c16 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#3aa73a cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#3aa73a cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#a29fa0 cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#ff3737 cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#F0681A term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#F0681A cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#F0681A cterm=bold ctermfg=9 +hi Include guifg=#F0681A ctermfg=9 +hi Define guifg=#F0681A ctermfg=9 + +hi Title gui=bold guibg=#001514 guifg=#009880 cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#da4ebf cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#da4ebf cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#da4ebf cterm=bold ctermfg=5 + +hi Debug guifg=#d85cf2 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#261c2c guifg=#968282 term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#a29fa0 guifg=#001514 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#261c2c term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#261c2c term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#968282 guifg=#001514 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#261c2c guifg=#a29fa0 term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#261c2c guifg=#968282 term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#261c2c guifg=#968282 ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#261c2c guifg=#968282 ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#ba8a00 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#261c2c guifg=#968282 cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#ba8a00 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#261c2c guifg=#968282 cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#968282 cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#169c16 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#ba8a00 cterm=bold ctermfg=11 +hi MoreMsg guifg=#3aa73a ctermfg=10 +hi ModeMsg gui=bold guifg=#169c16 cterm=bold ctermfg=2 + +hi VimOption guifg=#da4ebf ctermfg=5 +hi VimGroup guifg=#da4ebf ctermfg=5 + +hi Underlined gui=underline guifg=#a29fa0 cterm=underline ctermfg=15 +hi Ignore guibg=#261c2c guifg=#968282 ctermbg=8 ctermfg=7 +hi Conceal guibg=#968282 guifg=#261c2c ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#ff3737 guifg=#001514 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#9f8500 guifg=#001514 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#d85cf2 guifg=#001514 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#1da1af guifg=#001514 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#261c2c guifg=#a29fa0 cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#968282 guifg=#001514 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#261c2c ctermbg=8 +hi PmenuThumb guibg=#968282 ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#001514", + \ "#ff3737", + \ "#169c16", + \ "#9f8500", + \ "#5781ef", + \ "#da4ebf", + \ "#009880", + \ "#968282", + \ "#261c2c", + \ "#F0681A", + \ "#3aa73a", + \ "#ba8a00", + \ "#8887f0", + \ "#d85cf2", + \ "#1da1af", + \ "#a29fa0" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#001514" + let g:terminal_color_1 = "#ff3737" + let g:terminal_color_2 = "#169c16" + let g:terminal_color_3 = "#9f8500" + let g:terminal_color_4 = "#5781ef" + let g:terminal_color_5 = "#da4ebf" + let g:terminal_color_6 = "#009880" + let g:terminal_color_7 = "#968282" + let g:terminal_color_8 = "#261c2c" + let g:terminal_color_9 = "#F0681A" + let g:terminal_color_10 = "#3aa73a" + let g:terminal_color_11 = "#ba8a00" + let g:terminal_color_12 = "#8887f0" + let g:terminal_color_13 = "#d85cf2" + let g:terminal_color_14 = "#1da1af" + let g:terminal_color_15 = "#a29fa0" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#169c16 guifg=#001514 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#ff3737 guifg=#001514 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#261c2c guifg=#968282 cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#261c2c guifg=#F0681A cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#169c16 ctermfg=2 +hi diffRemoved guifg=#ff3737 ctermfg=1 +hi diffNewFile gui=none guifg=#5781ef ctermfg=4 +hi diffFile gui=none guifg=#9f8500 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#261c2c guifg=#169c16 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#261c2c guifg=#968282 cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#261c2c guifg=#ff3737 ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#261c2c guifg=#ff3737 cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#ff3737 guifg=#001514 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#009880 guifg=#001514 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#9f8500 guifg=#001514 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#ba8a00 guifg=#001514 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#1da1af ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#ba8a00 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#9f8500 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#ff3737 ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#169c16 guifg=#001514 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#261c2c guifg=#169c16 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#5781ef guifg=#001514 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#ff3737 guifg=#001514 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#9f8500 guifg=#001514 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#261c2c guifg=#3aa73a cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#a29fa0 cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#F0681A cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#9f8500 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#5781ef cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#8887f0 cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#a29fa0 cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#da4ebf ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#a29fa0 ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#169c16 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#ff3737 cterm=underline +hi YcmWarningSection gui=undercurl guisp=#9f8500 cterm=underline +hi SyntasticError gui=undercurl guisp=#ff3737 cterm=underline +hi SyntasticWarning gui=undercurl guisp=#9f8500 cterm=underline +hi SyntasticErrorSing guifg=#001514 guibg=#ff3737 ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#001514 guibg=#9f8500 ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vim/colors/tempus_winter.vim b/modules/mixins/dotfiles/home/vim/colors/tempus_winter.vim @@ -0,0 +1,254 @@ +" Name: Tempus Winter +" Description: Dark theme with a palette inspired by winter nights at the city (WCAG AA compliant) +" Author: Protesilaos Stavrou (https://protesilaos.com) +" Meta: Created with the Tempus Themes Generator +" URL: https://gitlab.com/protesilaos/tempus-themes-generator + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "tempus_winter" + +" General +" ------- +if exists("g:tempus_enforce_background_color") + hi Normal guibg=#202427 guifg=#8da3b8 ctermbg=0 ctermfg=15 +else + " NOTE the ctermbg=none is for terminals with transparency + hi Normal guibg=#202427 guifg=#8da3b8 ctermbg=none ctermfg=15 +endif + +hi Visual guibg=#8da3b8 guifg=#202427 ctermbg=15 ctermfg=0 +hi Search gui=underline,bold guibg=#2a2e38 guifg=#8da3b8 cterm=underline,bold ctermbg=8 ctermfg=3 +hi IncSearch gui=underline,bold guibg=#91959b guifg=#202427 term=none cterm=underline,bold ctermbg=7 ctermfg=0 + +hi StatusLine gui=none guibg=#8da3b8 guifg=#202427 cterm=none ctermbg=15 ctermfg=0 +hi StatusLineNC gui=none guibg=#2a2e38 guifg=#91959b cterm=none ctermbg=8 ctermfg=7 +hi StatusLineTerm gui=none guibg=#4aa920 guifg=#202427 cterm=none ctermbg=2 ctermfg=0 +hi StatusLineTermNC gui=none guibg=#2a2e38 guifg=#4aa920 cterm=none ctermbg=8 ctermfg=2 + +hi VertSplit gui=none cterm=none +hi TabLine gui=none guibg=#2a2e38 guifg=#91959b cterm=none ctermbg=8 ctermfg=7 +hi TabLineSel gui=none guibg=#4fa394 guifg=#202427 cterm=none ctermbg=6 ctermfg=0 +hi TabLineFill gui=none cterm=none + +hi Comment gui=italic guifg=#91959b cterm=none ctermfg=7 +hi Todo gui=bold guibg=#2a2e38 guifg=#af9155 cterm=bold ctermbg=8 ctermfg=11 + +hi Warning gui=none guibg=#9a9921 guifg=#202427 cterm=none ctermbg=3 ctermfg=0 +hi WarningMsg gui=none guibg=#9a9921 guifg=#202427 cterm=none ctermbg=3 ctermfg=0 +hi Error gui=none guibg=#ed6e5a guifg=#202427 cterm=none ctermbg=1 ctermfg=0 +hi ErrorMsg gui=none guibg=#ed6e5a guifg=#202427 cterm=none ctermbg=1 ctermfg=0 + +hi MatchParen gui=underline,bold guibg=#2a2e38 guifg=#91959b cterm=underline,bold ctermbg=8 ctermfg=7 + +hi ToolbarLine guibg=#91959b guifg=#202427 term=none ctermbg=7 ctermfg=0 +hi ToolbarButton gui=bold guibg=#91959b guifg=#202427 term=none cterm=bold ctermbg=7 ctermfg=0 + +hi WildMenu guibg=#202427 guifg=#8da3b8 term=standout ctermbg=0 ctermfg=15 + +hi Terminal guibg=#202427 guifg=#8da3b8 term=none ctermbg=0 ctermfg=15 + +" Constructs +" ---------- +hi Constant guifg=#7b91df ctermfg=4 +hi Number guifg=#7b91df ctermfg=4 +hi Float guifg=#7b91df ctermfg=4 +hi String guifg=#329fcb ctermfg=12 + +hi Function guifg=#d17e80 ctermfg=5 +hi Identifier guifg=#ca77c5 term=none ctermfg=13 +hi Label guifg=#d17e80 ctermfg=5 +hi Tag guifg=#d17e80 ctermfg=5 +hi Keyword gui=bold guifg=#ca77c5 gui=bold ctermfg=13 + +hi Character gui=bold guifg=#1ba6a4 cterm=bold ctermfg=14 + +hi Type gui=none,bold guifg=#4fa394 term=none cterm=none,bold ctermfg=6 +hi Boolean guifg=#4fa394 ctermfg=6 +hi StorageClass guifg=#4fa394 ctermfg=6 +hi Structure guifg=#4fa394 ctermfg=6 +hi Typedef gui=bold guifg=#1ba6a4 cterm=bold ctermfg=14 + +hi Conditional gui=bold guifg=#4aa920 cterm=bold ctermfg=2 +hi Statement gui=none guifg=#00ab5f cterm=none ctermfg=10 +hi Repeat gui=bold guifg=#00ab5f cterm=bold ctermfg=10 +hi Operator gui=bold guifg=#8da3b8 cterm=bold ctermfg=15 +hi Exception gui=bold guifg=#ed6e5a cterm=bold ctermfg=1 + +hi Preproc gui=none guifg=#de7b28 term=none cterm=none ctermfg=9 +hi PreCondit gui=bold guifg=#de7b28 cterm=bold ctermfg=9 +hi Macro gui=bold guifg=#de7b28 cterm=bold ctermfg=9 +hi Include guifg=#de7b28 ctermfg=9 +hi Define guifg=#de7b28 ctermfg=9 + +hi Title gui=bold guibg=#202427 guifg=#4fa394 cterm=bold ctermbg=0 ctermfg=6 + +hi Delimeter gui=bold guifg=#d17e80 cterm=bold ctermfg=5 +hi Delimiter gui=bold guifg=#d17e80 cterm=bold ctermfg=5 +hi SpecialComment gui=bold guifg=#d17e80 cterm=bold ctermfg=5 + +hi Debug guifg=#ca77c5 ctermfg=13 + +" Other +" ----- +hi LineNr guibg=#2a2e38 guifg=#91959b term=none ctermbg=8 ctermfg=7 +hi Cursor guibg=#8da3b8 guifg=#202427 ctermbg=15 ctermfg=0 +hi CursorLine gui=none guibg=#2a2e38 term=none cterm=none ctermbg=8 +hi CursorColumn gui=none guibg=#2a2e38 term=none cterm=none ctermbg=8 +hi CursorLineNr gui=bold guibg=#91959b guifg=#202427 cterm=bold ctermbg=7 ctermfg=0 +hi ColorColumn guibg=#2a2e38 guifg=#8da3b8 term=none ctermbg=8 ctermfg=15 +hi SignColumn guibg=#2a2e38 guifg=#91959b term=none ctermbg=8 ctermfg=7 + +hi Folded guibg=#2a2e38 guifg=#91959b ctermbg=8 ctermfg=7 +hi FoldColumn guibg=#2a2e38 guifg=#91959b ctermbg=8 ctermfg=7 + +hi Special gui=bold guifg=#af9155 term=none cterm=bold ctermfg=11 +hi SpecialKey gui=none guibg=#2a2e38 guifg=#91959b cterm=none ctermbg=8 ctermfg=7 +hi SpecialChar gui=bold guifg=#af9155 cterm=bold ctermfg=11 +hi NonText gui=none guibg=#2a2e38 guifg=#91959b cterm=none ctermbg=8 ctermfg=7 +hi EndOfBuffer gui=bold guifg=#91959b cterm=bold ctermfg=7 + +hi Directory gui=none guifg=#4aa920 term=none cterm=none ctermfg=2 +hi Question gui=bold guifg=#af9155 cterm=bold ctermfg=11 +hi MoreMsg guifg=#00ab5f ctermfg=10 +hi ModeMsg gui=bold guifg=#4aa920 cterm=bold ctermfg=2 + +hi VimOption guifg=#d17e80 ctermfg=5 +hi VimGroup guifg=#d17e80 ctermfg=5 + +hi Underlined gui=underline guifg=#8da3b8 cterm=underline ctermfg=15 +hi Ignore guibg=#2a2e38 guifg=#91959b ctermbg=8 ctermfg=7 +hi Conceal guibg=#91959b guifg=#2a2e38 ctermbg=7 ctermfg=8 + +hi SpellBad guibg=#ed6e5a guifg=#202427 ctermbg=1 ctermfg=0 +hi SpellCap guibg=#9a9921 guifg=#202427 ctermbg=3 ctermfg=0 +hi SpellRare guibg=#ca77c5 guifg=#202427 ctermbg=13 ctermfg=0 +hi SpellLocal guibg=#1ba6a4 guifg=#202427 ctermbg=14 ctermfg=0 + +hi Pmenu gui=italic guibg=#2a2e38 guifg=#8da3b8 cterm=none ctermbg=8 ctermfg=15 +hi PmenuSel gui=none,bold guibg=#91959b guifg=#202427 cterm=none,bold ctermbg=7 ctermfg=0 +hi PmenuSbar guibg=#2a2e38 ctermbg=8 +hi PmenuThumb guibg=#91959b ctermbg=7 + +" Terminal +" -------- + +if exists('*term_setansicolors') + let g:terminal_ansi_colors = [ + \ "#202427", + \ "#ed6e5a", + \ "#4aa920", + \ "#9a9921", + \ "#7b91df", + \ "#d17e80", + \ "#4fa394", + \ "#91959b", + \ "#2a2e38", + \ "#de7b28", + \ "#00ab5f", + \ "#af9155", + \ "#329fcb", + \ "#ca77c5", + \ "#1ba6a4", + \ "#8da3b8" + \ ] +endif +if has('nvim') + let g:terminal_color_0 = "#202427" + let g:terminal_color_1 = "#ed6e5a" + let g:terminal_color_2 = "#4aa920" + let g:terminal_color_3 = "#9a9921" + let g:terminal_color_4 = "#7b91df" + let g:terminal_color_5 = "#d17e80" + let g:terminal_color_6 = "#4fa394" + let g:terminal_color_7 = "#91959b" + let g:terminal_color_8 = "#2a2e38" + let g:terminal_color_9 = "#de7b28" + let g:terminal_color_10 = "#00ab5f" + let g:terminal_color_11 = "#af9155" + let g:terminal_color_12 = "#329fcb" + let g:terminal_color_13 = "#ca77c5" + let g:terminal_color_14 = "#1ba6a4" + let g:terminal_color_15 = "#8da3b8" +endif + +" Diffs +" ----- +hi DiffAdd gui=bold guibg=#4aa920 guifg=#202427 cterm=bold ctermbg=10 ctermfg=0 +hi DiffDelete gui=none guibg=#ed6e5a guifg=#202427 cterm=none ctermbg=9 ctermfg=0 +hi DiffChange gui=bold guibg=#2a2e38 guifg=#91959b cterm=bold ctermbg=8 ctermfg=7 +hi DiffText gui=bold guibg=#2a2e38 guifg=#de7b28 cterm=bold ctermbg=8 ctermfg=1 + +hi diffAdded guifg=#4aa920 ctermfg=2 +hi diffRemoved guifg=#ed6e5a ctermfg=1 +hi diffNewFile gui=none guifg=#7b91df ctermfg=4 +hi diffFile gui=none guifg=#9a9921 cterm=none ctermfg=3 + +hi GitGutterAdd guibg=#2a2e38 guifg=#4aa920 ctermbg=8 ctermfg=2 +hi GitGutterChange gui=bold guibg=#2a2e38 guifg=#91959b cterm=bold ctermbg=8 ctermfg=7 +hi GitGutterDelete guibg=#2a2e38 guifg=#ed6e5a ctermbg=8 ctermfg=1 +hi GitGutterChangeDelete gui=bold guibg=#2a2e38 guifg=#ed6e5a cterm=bold ctermbg=8 ctermfg=1 + +" Neomake +" ------- +hi NeomakeError gui=none guibg=#ed6e5a guifg=#202427 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeInfo gui=none guibg=#4fa394 guifg=#202427 cterm=none ctermbg=6 ctermfg=0 +hi NeomakeWarning gui=none guibg=#9a9921 guifg=#202427 cterm=none ctermbg=3 ctermfg=0 +hi NeomakeMessage gui=none guibg=#af9155 guifg=#202427 cterm=none ctermbg=11 ctermfg=0 + +hi NeomakeVirtualtextInfoDefault guifg=#1ba6a4 ctermfg=14 +hi NeomakeVirtualtextMessageDefault guifg=#af9155 ctermfg=11 +hi NeomakeVirtualtextWarningDefault guifg=#9a9921 ctermfg=3 +hi NeomakeVirtualtextErrorDefault guifg=#ed6e5a ctermfg=1 + +hi NeomakeStatusGood gui=none guibg=#4aa920 guifg=#202427 cterm=none ctermbg=2 ctermfg=0 +hi NeomakeStatusGoodNC gui=none guibg=#2a2e38 guifg=#4aa920 cterm=none ctermbg=8 ctermfg=2 + +hi NeomakeStatColorDefault gui=none guibg=#7b91df guifg=#202427 cterm=none ctermbg=4 ctermfg=0 +hi NeomakeStatColorTypeE gui=none guibg=#ed6e5a guifg=#202427 cterm=none ctermbg=1 ctermfg=0 +hi NeomakeStatColorTypeW gui=none guibg=#9a9921 guifg=#202427 cterm=none ctermbg=3 ctermfg=0 + +" Markdown +" -------- +hi MarkdownRule gui=bold guibg=#2a2e38 guifg=#00ab5f cterm=bold ctermbg=8 ctermfg=10 + +hi MarkdownHeading gui=bold guifg=#8da3b8 cterm=bold ctermfg=15 +hi default link MarkdownH1 MarkdownHeading +hi default link MarkdownH2 MarkdownHeading +hi default link MarkdownH3 MarkdownHeading +hi default link MarkdownH4 MarkdownHeading +hi default link MarkdownH5 MarkdownHeading +hi default link MarkdownH6 MarkdownHeading +hi default link MarkdownHeadingDelimiter MarkdownHeading +hi default link MarkdownHeadingRule MarkdownHeading + +hi MarkdownBold gui=bold guifg=#de7b28 cterm=bold ctermfg=9 +hi default link MarkdownBoldDelimiter MarkdownBold + +hi MarkdownItalic gui=italic guifg=#9a9921 cterm=none ctermfg=3 +hi default link MarkdownItalicDelimiter MarkdownItalic + +hi MarkdownUrl gui=underline guifg=#7b91df cterm=underline ctermfg=4 +hi MarkdownLinkText gui=none guifg=#329fcb cterm=none ctermfg=12 +hi MarkdownLinkDelimiter gui=bold guifg=#8da3b8 cterm=bold ctermfg=15 +hi default link MarkdownLinkTextDelimiter MarkdownLinkDelimiter + +hi MarkdownCode guifg=#d17e80 ctermfg=5 +hi default link MarkdownCodeDelimiter MarkdownCode + +hi MarkdownCodeBlock guifg=#8da3b8 ctermfg=15 + +hi MarkdownListMarker gui=none guifg=#4aa920 cterm=none ctermfg=2 +hi default link MarkdownOrderedListMarker MarkdownListMarker + +" Linting +" ------- +hi YcmErrorSection gui=undercurl guisp=#ed6e5a cterm=underline +hi YcmWarningSection gui=undercurl guisp=#9a9921 cterm=underline +hi SyntasticError gui=undercurl guisp=#ed6e5a cterm=underline +hi SyntasticWarning gui=undercurl guisp=#9a9921 cterm=underline +hi SyntasticErrorSing guifg=#202427 guibg=#ed6e5a ctermfg=0 ctermbg=1 +hi SyntasticWarningSign guifg=#202427 guibg=#9a9921 ctermfg=0 ctermbg=3 diff --git a/modules/mixins/dotfiles/home/vimrc b/modules/mixins/dotfiles/home/vimrc @@ -0,0 +1,158 @@ +exe "set runtimepath=~/.vim," . $VIMRUNTIME + +filetype plugin on +syntax on + +silent! colorscheme tempus_rift + +set autoindent +set backspace=indent,eol,start +set backupcopy=yes +set cursorline +set formatoptions=qrn +set hlsearch +set ignorecase +set incsearch +set linebreak +set nofoldenable +set nojoinspaces +set nowrap +set number +set relativenumber +set scrolloff=15 +set shiftround +set shiftwidth=4 +set shortmess=aoOtI +set smartcase +set synmaxcol=1000 +set viminfo='20,<1000,s1000 +set ruler +set mouse="" + +let mapleader = "\<Space>" +nnoremap <Leader>w :w<CR> +nnoremap <silent> <leader>n :setlocal paste<CR> +nnoremap <silent> <leader>q :%s/\s\+$//e<CR><C-o> +nnoremap <silent> / :let @/ = ""<CR>:set hlsearch<CR>/ +nnoremap <silent> H :set hlsearch!<CR> + +highlight TrailingWhitespace ctermbg=black +call matchadd('TrailingWhitespace', '\s\+$') + +highlight Normal ctermbg=none +highlight MatchParen ctermbg=darkmagenta ctermfg=black + +command FixFile :set fileencoding=utf-8 fileformat=unix nobomb | %s/\r$// + +" Do not enter ex mode when I fat finger q with shift pressed +nnoremap Q <nop> + +" Do not show me man pages when I'm bad at pressing k +nnoremap K <nop> + +" I'm very bad at pressing things +" nmap <F1> <nop> +nmap <F1> :echo<CR> +imap <F1> <C-o>:echo<CR> + +" Do not show command history window when :q gets entered in the wrong order +map q: :q + +" When joining, do the right thing to join up function definitions +vnoremap J J:s/( /(/g<CR>:s/,)/)/g<CR> + +" Quickly move around (and into) command mode +" imap jk <Esc> +" imap kj <Esc>: +for keymode in ['n', 'v'] + exec keymode . 'noremap ; :' + exec keymode . 'noremap : ;' +endfor + +" Do not copy to default register on delete/change, use <Leader> prefixed +" version to use regular delete/change +for key in ['d', 'D', 'c', 'C'] + for keymode in ['n', 'v'] + exe keymode . 'noremap <Leader>' . key . ' ' . key + exe keymode . 'noremap ' . key . ' "_' . key + endfor +endfor + +" gV to highlight previously inserted text +nnoremap gV `[v`] + +" Automatically move to end of paste +vnoremap <silent> y y`] +vnoremap <silent> p p`] +nnoremap <silent> p p`] + +" I only really use a single mark, so M to set it, m to retrieve it +nnoremap M mA +nnoremap m 'A + +augroup filetype_settings + " Clear this autocmd group so that the settings won't get loaded over and + " over again + autocmd! + + autocmd BufNewFile,BufReadPost *.cconf,*.cinc,TARGETS setlocal filetype=python + autocmd BufNewFile,BufReadPost *.lalrpop setlocal filetype=rust + autocmd BufNewFile,BufReadPost *.def setlocal filetype=c + autocmd BufNewFile,BufReadPost *.bb setlocal filetype=clojure + + for filetype in ['yaml', 'sql', 'ruby', 'html', 'css', 'xml', 'vim'] + exe 'autocmd FileType ' . filetype . ' setlocal sw=2 sts=2 ts=2' + endfor + + for filetype in ['gitcommit'] + exe 'autocmd FileType ' . filetype . ' setlocal joinspaces' + endfor + + for filetype in ['gitcommit'] + exe 'autocmd FileType ' . filetype . ' setlocal tw=72' + endfor + + autocmd BufRead,BufNewFile */linux-mmots/*.c,*/linux-mmots/*.h setlocal textwidth=80 + autocmd BufRead,BufNewFile */systemd/*.c,*/systemd/*.h setlocal textwidth=109 + +augroup END + +nnoremap <C-l> <C-l>zz + +augroup modechange_settings + autocmd! + + " Clear search context when entering insert mode, which implicitly stops the + " highlighting of whatever was searched for with hlsearch on. It should also + " not be persisted between sessions. + autocmd InsertEnter * let @/ = '' + autocmd BufReadPre,FileReadPre * let @/ = '' + + autocmd InsertLeave * setlocal nopaste + + " Jump to last position in file + autocmd BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g'\"" | endif + + " Balance splits on window resize + autocmd VimResized * wincmd = +augroup END + + +" Do not overwrite default register when pasting in visual mode +function! RestoreRegister() + let @" = s:restore_reg + return '' +endfunction +function! s:Repl() + let s:restore_reg = @" + return "p@=RestoreRegister()\<cr>" +endfunction +vmap <silent> <expr> p <sid>Repl() + +" Stuff to make working with unwrapped text easier +for key in ['k', 'j'] + exe 'noremap <buffer> <silent> <expr> ' . key . ' v:count ? ''' . key . ''' : ''g' . key . '''' + exe 'onoremap <silent> <expr> ' . key . ' v:count ? ''' . key . ''' : ''g' . key . '''' +endfor +nnoremap <silent> <Leader>E :set wrap<CR>:setlocal formatoptions-=t<CR>:set textwidth=0<CR> +nnoremap <silent> <Leader>e :set nowrap<CR>:setlocal formatoptions+=t<CR>:set textwidth=79<CR> diff --git a/modules/mixins/dotfiles/home/xinitrc b/modules/mixins/dotfiles/home/xinitrc @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +to_export=(DISPLAY XAUTHORITY PATH GTK_IM_MODULE QT_IM_MODULE XMODIFIERS) + +systemctl --user import-environment "${to_export[@]}" +dbus-update-activation-environment "${to_export[@]}" + +exec spectrwm >> "/tmp/spectrwm-$USER.log" 2>&1 diff --git a/modules/mixins/dotfiles/home/zprofile b/modules/mixins/dotfiles/home/zprofile @@ -0,0 +1,13 @@ +#!/bin/zsh + +[[ "$-" == *i* ]] || return + +config_home="$HOME" + +. "$config_home"/.config/shell/early-funcs + +for file in "$config_home"/.config/{shell,zsh}/profile/*(N); do + . "$file" +done + +[[ -r "$config_home"/.zshrc ]] && . "$config_home"/.zshrc diff --git a/modules/mixins/dotfiles/home/zshrc b/modules/mixins/dotfiles/home/zshrc @@ -0,0 +1,13 @@ +#!/bin/zsh + +[[ "$-" == *i* ]] || return + +config_home="$HOME" + +. "$config_home"/.config/shell/early-funcs + +for file in "$config_home"/.config/{shell,zsh}/rc/*(N); do + . "$file" +done + +PS1='$(_get_ps1)' diff --git a/modules/mixins/secrets.nix b/modules/mixins/secrets.nix Binary files differ. diff --git a/modules/nixos/base.nix b/modules/nixos/base.nix @@ -0,0 +1,68 @@ +{ + inputs, + pkgs, + username, + configData, + ... +}: { + nix = { + settings = { + experimental-features = ["nix-command" "flakes"]; + auto-optimise-store = true; + trusted-users = ["root" "@wheel"]; + substituters = [ + "https://cache.nixos.org" + "https://nix-community.cachix.org" + ]; + trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; + }; + # Pin nixpkgs to the flake version for consistency + registry.nixpkgs.flake = inputs.nixpkgs; + }; + + services.openssh = { + enable = true; + openFirewall = true; + settings = { + PermitRootLogin = "prohibit-password"; + PasswordAuthentication = false; + }; + }; + + users.groups.storage-users = { + gid = 2000; + }; + + users.users.${username} = { + isNormalUser = true; + shell = pkgs.zsh; + extraGroups = ["wheel" "networkmanager"]; + openssh.authorizedKeys.keys = configData.users.${username}.authorizedKeys or []; + }; + + programs.zsh.enable = true; + + security.sudo.wheelNeedsPassword = false; + + time.timeZone = "UTC"; + i18n.defaultLocale = "en_US.UTF-8"; + + environment.systemPackages = with pkgs; [ + vim + curl + wget + htop + git + ]; + + virtualisation.podman.enable = true; + networking.firewall.trustedInterfaces = ["podman0"]; +} diff --git a/modules/services/bandeno.nix b/modules/services/bandeno.nix @@ -0,0 +1,77 @@ +{ + config, + lib, + pkgs, + inputs, + ... +}: let + cfg = config.services.haravara.bandeno; + + bandeno-src = pkgs.stdenv.mkDerivation { + pname = "bandeno-src"; + version = "0.0.1"; + src = "${inputs.tools}/bandeno"; + installPhase = '' + mkdir -p $out + cp -r . $out/ + ''; + }; +in { + options.services.haravara.bandeno = { + enable = lib.mkEnableOption "Bandeno - Deno application"; + + port = lib.mkOption { + type = lib.types.port; + default = 9231; + }; + + host = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + }; + + domain = lib.mkOption { + type = lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.bandeno = { + description = "Bandeno Service"; + wantedBy = ["multi-user.target"]; + after = ["network.target"]; + + environment = { + PORT = toString cfg.port; + HOST = cfg.host; + DENO_DIR = "/var/lib/bandeno/.cache"; + HOME = "/var/lib/bandeno"; + }; + + serviceConfig = { + ExecStart = "${pkgs.deno}/bin/deno run --allow-net --allow-read --allow-env --config ${bandeno-src}/deno.json ${bandeno-src}/main.ts"; + Restart = "always"; + User = "bandeno"; + Group = "bandeno"; + StateDirectory = "bandeno"; + WorkingDirectory = "/var/lib/bandeno"; + }; + }; + + users.users.bandeno = { + isSystemUser = true; + group = "bandeno"; + }; + users.groups.bandeno = {}; + + services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' + @bandeno_rss expression {query}.matches("(artist|fan)") + handle @bandeno_rss { + reverse_proxy 127.0.0.1:${toString cfg.port} + } + handle { + redir https://${lib.concatStringsSep "." (lib.drop 1 (lib.splitString "." cfg.domain))} + } + ''; + }; +} diff --git a/modules/services/bazel-cache.nix b/modules/services/bazel-cache.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.bazel-cache; +in { + options.services.haravara.bazel-cache = { + enable = lib.mkEnableOption "Bazel Remote Cache"; + + listenAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 9820; + }; + + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/bazel-cache"; + }; + + domain = lib.mkOption { + type = lib.types.str; + }; + basicAuthUser = lib.mkOption { + type = lib.types.str; + }; + basicAuthHash = lib.mkOption { + type = lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.bazel-remote = { + description = "Bazel Remote Cache"; + wantedBy = ["multi-user.target"]; + after = ["network.target"]; + serviceConfig = { + ExecStart = '' + ${pkgs.bazel-remote}/bin/bazel-remote \ + --host ${cfg.listenAddress} \ + --port ${toString cfg.port} \ + --dir ${cfg.dataDir} \ + --max_size 1024 + ''; + User = "bazel-remote"; + Group = "bazel-remote"; + StateDirectory = "bazel-cache"; + Restart = "on-failure"; + }; + }; + + users.users.bazel-remote = { + isSystemUser = true; + group = "bazel-remote"; + }; + users.groups.bazel-remote = {}; + + services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' + reverse_proxy ${cfg.listenAddress}:${toString cfg.port} + handle { + basic_auth { + ${cfg.basicAuthUser} ${cfg.basicAuthHash} + } + } + ''; + }; +} diff --git a/modules/services/caddy.nix b/modules/services/caddy.nix @@ -0,0 +1,75 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.caddy; + + mkAuthSnippet = name: authDomain: '' + (${name}) { + forward_auth 127.0.0.1:4180 { + uri /oauth2/auth + copy_headers X-Auth-Request-User X-Auth-Request-Email + + @error status 401 + handle_response @error { + redir * https://${authDomain}/oauth2/start?rd=https://{host}{uri} + } + } + } + ''; +in { + options.services.haravara.caddy = { + enable = lib.mkEnableOption "Caddy reverse proxy and static site server"; + email = lib.mkOption { + type = lib.types.str; + }; + authDomains = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + description = "Attribute set of auth snippets to domain names. Key 'auth' is special and used as is, others prefixed with auth_"; + }; + }; + + config = lib.mkIf cfg.enable { + services.caddy = { + enable = true; + inherit (cfg) email; + + globalConfig = '' + servers { + metrics + } + ''; + + extraConfig = + (lib.concatStringsSep "\n" (lib.mapAttrsToList (name: domain: + mkAuthSnippet ( + if name == "default" + then "auth" + else "auth_${name}" + ) + domain) + cfg.authDomains)) + + '' + (remote_auth) { + forward_auth https://${cfg.authDomains.default} { + uri /oauth2/auth + copy_headers X-Auth-Request-User X-Auth-Request-Email + header_up Host ${cfg.authDomains.default} + + @error status 401 + handle_response @error { + redir * https://${cfg.authDomains.default}/oauth2/start?rd=https://{host}{uri} + } + } + } + ''; + virtualHosts = {}; + }; + + networking.firewall.allowedTCPPorts = [80 443]; + systemd.tmpfiles.rules = [ + "d /var/lib/haravara/static 0755 caddy caddy -" + ]; + }; +} diff --git a/modules/services/cinny.nix b/modules/services/cinny.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.cinny; +in { + options.services.haravara.cinny = { + enable = lib.mkEnableOption "Cinny Matrix client (Configuration only, served via Caddy)"; + domain = lib.mkOption { + type = lib.types.str; + }; + authLabel = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "The auth snippet to import"; + }; + }; + + config = lib.mkIf cfg.enable { + services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' + ${lib.optionalString (cfg.authLabel != null) "import ${ + if cfg.authLabel == "default" + then "auth" + else "auth_${cfg.authLabel}" + }"} + root * ${pkgs.cinny} + file_server + ''; + }; +} diff --git a/modules/services/couchdb.nix b/modules/services/couchdb.nix @@ -0,0 +1,67 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.couchdb; +in { + options.services.haravara.couchdb = { + enable = lib.mkEnableOption "CouchDB database server"; + adminUser = lib.mkOption { + type = lib.types.str; + }; + adminPassFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + }; + publicDomain = lib.mkOption { + type = lib.types.str; + }; + authLabel = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "The auth snippet to import"; + }; + }; + + config = lib.mkIf cfg.enable { + age.secrets.couchdb-admin-pass.file = ../../secrets/couchdb-admin-pass.age; + + services = { + couchdb = { + enable = true; + bindAddress = "127.0.0.1"; + inherit (cfg) adminUser; + adminPass = null; + }; + + couchdb.extraConfig = { + chttpd.bind_address = "127.0.0.1"; + httpd.bind_address = "127.0.0.1"; + httpd.enable_cors = true; + cors = { + origins = "*"; + credentials = true; + methods = "GET, POST, PUT, DELETE, HEAD, OPTIONS"; + headers = "accept, authorization, content-type, origin, referer"; + }; + }; + + caddy.virtualHosts = lib.mkIf (cfg.publicDomain != null) { + "${cfg.publicDomain}".extraConfig = '' + handle /_utils* { + ${lib.optionalString (cfg.authLabel != null) "import ${ + if cfg.authLabel == "default" + then "auth" + else "auth_${cfg.authLabel}" + }"} + reverse_proxy localhost:5984 + } + handle { + reverse_proxy localhost:5984 + } + ''; + }; + }; + }; +} diff --git a/modules/services/dex.nix b/modules/services/dex.nix @@ -0,0 +1,86 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.dex; +in { + options.services.haravara.dex = { + enable = lib.mkEnableOption "Dex - Identity Provider"; + domain = lib.mkOption { + type = lib.types.str; + }; + adminEmail = lib.mkOption { + type = lib.types.str; + }; + adminPasswordHash = lib.mkOption { + type = lib.types.str; + }; + adminUsername = lib.mkOption { + type = lib.types.str; + default = "admin"; + }; + adminUserID = lib.mkOption { + type = lib.types.str; + }; + redirectURIs = lib.mkOption { + type = lib.types.listOf lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + age.secrets.dex-client-secret.file = ../../secrets/dex-client-secret.age; + + services.dex = { + enable = true; + settings = { + issuer = "https://${cfg.domain}"; + logger.level = "warn"; + + storage = { + type = "sqlite3"; + config.file = "/var/lib/dex/dex.db"; + }; + + web.http = "127.0.0.1:5556"; + telemetry.http = "127.0.0.1:5558"; + + staticClients = [ + { + id = "caddy-proxy"; + inherit (cfg) redirectURIs; + name = "Caddy Auth Proxy"; + secretFile = config.age.secrets.dex-client-secret.path; + } + ]; + + enablePasswordDB = true; + + expiry = { + signingKeys = "24h"; + idTokens = "24h"; + }; + + staticPasswords = [ + { + email = cfg.adminEmail; + hash = cfg.adminPasswordHash; + username = cfg.adminUsername; + userID = cfg.adminUserID; + } + ]; + }; + }; + + systemd.services.dex.serviceConfig = { + KillSignal = "SIGINT"; + SuccessExitStatus = 2; + StateDirectory = "dex"; + StateDirectoryMode = "0700"; + }; + + services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' + reverse_proxy 127.0.0.1:5556 + ''; + }; +} diff --git a/modules/services/filestash.nix b/modules/services/filestash.nix Binary files differ. diff --git a/modules/services/forgejo.nix b/modules/services/forgejo.nix @@ -0,0 +1,119 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.forgejo; +in { + options.services.haravara.forgejo = { + enable = lib.mkEnableOption "Forgejo git service"; + httpPort = lib.mkOption { + type = lib.types.port; + default = 3482; + description = "Internal HTTP port for Forgejo"; + }; + sshPort = lib.mkOption { + type = lib.types.port; + default = 22; + description = "SSH port for Forgejo"; + }; + + domain = lib.mkOption { + type = lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + users.users.forgejo = { + isSystemUser = true; + group = lib.mkForce "storage-users"; + }; + + services = { + forgejo = { + enable = true; + package = pkgs.forgejo; + stateDir = "/var/lib/forgejo"; + database.type = "sqlite3"; + lfs.enable = true; + + secrets = { + "FORGEJO__SECURITY__SECRET_KEY".path = "/var/lib/forgejo/custom/conf/secret_key"; + "FORGEJO__SECURITY__INTERNAL_TOKEN".path = "/var/lib/forgejo/custom/conf/internal_token"; + "FORGEJO__OAUTH2__JWT_SECRET".path = "/var/lib/forgejo/custom/conf/oauth2_jwt_secret"; + "FORGEJO__SERVER__LFS_JWT_SECRET".path = "/var/lib/forgejo/custom/conf/lfs_jwt_secret"; + }; + + settings = { + DEFAULT = { + APP_NAME = cfg.domain; + }; + server = { + DOMAIN = cfg.domain; + SSH_DOMAIN = lib.concatStringsSep "." (lib.drop 1 (lib.splitString "." cfg.domain)); + ROOT_URL = "https://${cfg.domain}/"; + HTTP_PORT = cfg.httpPort; + HTTP_ADDR = "127.0.0.1"; + SSH_PORT = cfg.sshPort; + SSH_LISTEN_PORT = cfg.sshPort; + }; + other = { + SHOW_FOOTER_VERSION = false; + }; + repository = { + FORCE_CHMOD_OFF = true; + MAX_CREATION_LIMIT = 0; + }; + service = { + DISABLE_REGISTRATION = true; + }; + "repository.signing" = { + TRUST_MODEL = "committer"; + }; + "git.timeout" = { + DEFAULT = 3600; + EVENT = 3600; + PULL = 3600; + }; + mailer = { + ENABLED = false; + }; + }; + }; + + openssh.ports = [cfg.sshPort]; + + caddy.virtualHosts."${cfg.domain}".extraConfig = '' + # Bypass auth for Docker Registry and Git CLI + @cli_paths { + path /v2/* + path */info/refs* + path */git-upload-pack* + path */git-receive-pack* + } + + handle @cli_paths { + reverse_proxy 127.0.0.1:3482 + } + + handle { + import remote_auth + reverse_proxy 127.0.0.1:3482 + } + ''; + }; + + systemd.services.forgejo = { + serviceConfig.TimeoutSec = 3600; + }; + + networking.firewall.allowedTCPPorts = [cfg.sshPort]; + + systemd.tmpfiles.rules = [ + "d /var/lib/forgejo 0700 forgejo storage-users -" + "d /var/lib/forgejo/custom 0700 forgejo storage-users -" + "d /var/lib/forgejo/custom/conf 0700 forgejo storage-users -" + ]; + }; +} diff --git a/modules/services/headscale.nix b/modules/services/headscale.nix @@ -0,0 +1,62 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.headscale; +in { + options.services.haravara.headscale = { + enable = lib.mkEnableOption "Headscale service"; + initUser = lib.mkOption { + type = lib.types.str; + }; + domain = lib.mkOption { + type = lib.types.str; + description = "The domain for the Headscale instance"; + }; + magicDnsDomain = lib.mkOption { + type = lib.types.str; + description = "The domain for the Magic DNS feature"; + }; + address = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + description = "The address for Headscale to listen on"; + }; + port = lib.mkOption { + type = lib.types.port; + default = 8085; + description = "The port for the Headscale instance"; + }; + }; + + config = lib.mkIf cfg.enable { + services.headscale = { + enable = true; + inherit (cfg) address port; + settings = { + server_url = "https://${cfg.domain}"; + grpc_listen_addr = "127.0.0.1:50443"; + grpc_allow_insecure = true; + dns = { + magic_dns = true; + base_domain = "$(cfg.magicDnsDomain)"; + nameservers.global = [ + "1.1.1.1" + "8.8.8.8" + ]; + }; + ip_prefixes = [ + "100.64.0.0/10" + "fd7a:115c:a1e0::/48" + ]; + }; + }; + + services.caddy.virtualHosts."${cfg.domain}" = { + extraConfig = '' + reverse_proxy ${cfg.address}:${toString cfg.port} + ''; + }; + }; +} diff --git a/modules/services/heisenbridge.nix b/modules/services/heisenbridge.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.heisenbridge; +in { + options.services.haravara.heisenbridge = { + enable = lib.mkEnableOption "Heisenbridge Matrix-IRC bridge"; + owner = lib.mkOption { + type = lib.types.str; + description = "The Matrix ID of the bridge owner"; + }; + }; + + config = lib.mkIf cfg.enable { + services.heisenbridge = { + enable = true; + address = "127.0.0.1"; + homeserver = "http://localhost:6167"; + inherit (cfg) owner; + }; + }; +} diff --git a/modules/services/matrix.nix b/modules/services/matrix.nix @@ -0,0 +1,68 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.matrix; +in { + options.services.haravara.matrix = { + enable = lib.mkEnableOption "Matrix Conduit server"; + port = lib.mkOption { + type = lib.types.port; + default = 6167; + description = "Internal port for Conduit"; + }; + serverName = lib.mkOption { + type = lib.types.str; + description = "The server name for Matrix"; + }; + redirTarget = lib.mkOption { + type = lib.types.str; + description = "The target domain for the root redirect"; + }; + registrationTokenFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = "Path to a file containing the registration token"; + }; + }; + + config = lib.mkIf cfg.enable { + services.matrix-conduit = { + enable = true; + settings.global = + { + server_name = cfg.serverName; + database_backend = "rocksdb"; + inherit (cfg) port; + max_request_size = 20000000; + allow_registration = true; + allow_federation = true; + trusted_servers = ["matrix.org"]; + address = "127.0.0.1"; + } + // lib.optionalAttrs (cfg.registrationTokenFile != null) { + registration_token = {_secret = cfg.registrationTokenFile;}; + }; + }; + + # Basic directory setup for Conduit + systemd.tmpfiles.rules = [ + "d /var/lib/matrix-conduit/appservices 0700 conduit conduit -" + ]; + + services.caddy.virtualHosts."${cfg.serverName}" = { + extraConfig = '' + reverse_proxy /_matrix/* 127.0.0.1:${toString cfg.port} + + redir / https://${cfg.redirTarget} + + header /.well-known/matrix/* Content-Type application/json + header /.well-known/matrix/* Access-Control-Allow-Origin * + + respond /.well-known/matrix/server `{"m.server": "${cfg.serverName}:443"}` + respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://${cfg.serverName}"},"m.identity_server":{"base_url":"https://${cfg.serverName}"}}` + ''; + }; + }; +} diff --git a/modules/services/monitord-exporter.lock b/modules/services/monitord-exporter.lock @@ -0,0 +1,2218 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "chunked_transfer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" + +[[package]] +name = "clap" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "configparser" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57e3272f0190c3f1584272d613719ba5fc7df7f4942fe542e63d949cf3a649b" +dependencies = [ + "indexmap", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "int-enum" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366a1634cccc76b4cfd3e7580de9b605e4d93f1edac48d786c1f867c0def495" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "monitord" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f96683d462cb43b9060c23532b0506f9fa483058ed7583502a1c10accf9ffd5" +dependencies = [ + "anyhow", + "clap", + "configparser", + "futures-util", + "indexmap", + "int-enum", + "procfs", + "serde", + "serde_json", + "serde_repr", + "serde_tuple", + "struct-field-names-as-array", + "strum", + "strum_macros", + "thiserror 2.0.18", + "tokio", + "tracing", + "tracing-core", + "tracing-glog", + "tracing-subscriber", + "uzers", + "zbus", + "zlink", + "zvariant", + "zvariant_derive", +] + +[[package]] +name = "monitord-exporter" +version = "0.19.0" +dependencies = [ + "anyhow", + "clap", + "configparser", + "monitord", + "prometheus_exporter", + "signal-hook", + "tempfile", + "tokio", + "tracing", + "tracing-core", + "tracing-glog", + "tracing-subscriber", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "procfs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" +dependencies = [ + "bitflags", + "chrono", + "flate2", + "procfs-core", + "rustix", +] + +[[package]] +name = "procfs-core" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" +dependencies = [ + "bitflags", + "chrono", + "hex", +] + +[[package]] +name = "prometheus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot", + "thiserror 1.0.69", +] + +[[package]] +name = "prometheus_exporter" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf17cbebe0bfdf4f279ef84eeefe0d50468b0b7116f078acf41d456e48fe81a" +dependencies = [ + "ascii", + "lazy_static", + "log", + "prometheus", + "thiserror 1.0.69", + "tiny_http", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_tuple" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af196b9c06f0aa5555ab980c01a2527b0f67517da8d68b1731b9d4764846a6f" +dependencies = [ + "serde", + "serde_tuple_macros", +] + +[[package]] +name = "serde_tuple_macros" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3a1e7d2eadec84deabd46ae061bf480a91a6bce74d25dad375bd656f2e19d8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b57709da74f9ff9f4a27dce9526eec25ca8407c45a7887243b031a58935fb8e" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "struct-field-names-as-array" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ba4bae771f9cc992c4f403636c54d2ef13acde6367583e99d06bb336674dd9" +dependencies = [ + "struct-field-names-as-array-derive", +] + +[[package]] +name = "struct-field-names-as-array-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2dbf8b57f3ce20e4bb171a11822b283bdfab6c4bb0fe64fa729f045f23a0938" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny_http" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f8734c6d6943ad6df6b588d228a87b4af184998bcffa268ceddf05c2055a8c" +dependencies = [ + "ascii", + "chunked_transfer", + "log", + "time", + "url", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.9+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-glog" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c45ab066a087486d062874889d4b551add3a33890969475d606f175c5ce7b68" +dependencies = [ + "chrono", + "nu-ansi-term 0.46.0", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "chrono", + "nu-ansi-term 0.50.3", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "uzers" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8275fb1afee25b4111d2dc8b5c505dbbc4afd0b990cb96deb2d88bff8be18d" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" +dependencies = [ + "async-broadcast", + "async-recursion", + "async-trait", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", + "serde", + "serde_repr", + "tokio", + "tracing", + "uds_windows", + "uuid", + "windows-sys", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" +dependencies = [ + "serde", + "winnow", + "zvariant", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zlink" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5ad065e2697e98764f2738793904ff0aaa672707d0ee1592dfb4c47800962a" +dependencies = [ + "zlink-smol", + "zlink-tokio", +] + +[[package]] +name = "zlink-core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae6561573e9996c2c26bf1c723b137a99c2d571a3276bd8f4ac52bfa44b3f2c" +dependencies = [ + "futures-util", + "itoa", + "libc", + "pin-project-lite", + "rustix", + "ryu", + "serde", + "serde_json", + "tracing", + "zlink-macros", +] + +[[package]] +name = "zlink-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4219a5aadc4844073d134e27fd52228933a462fbd07fe51ac5df8393f08168a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zlink-smol" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "befa02505904ee15f6721fdae1b6473d59649049c1f1810175fb7205a4dca82a" +dependencies = [ + "async-broadcast", + "async-channel", + "async-io", + "futures-lite", + "futures-util", + "pin-project-lite", + "zlink-core", +] + +[[package]] +name = "zlink-tokio" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378110fc4fad5fa9359251eb830d87993efcca44245f538a552cf26001649378" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", + "tokio-stream", + "zlink-core", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zvariant" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", + "winnow", +] diff --git a/modules/services/monitord.lock b/modules/services/monitord.lock @@ -0,0 +1,1664 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "clap" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_derive" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "configparser" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57e3272f0190c3f1584272d613719ba5fc7df7f4942fe542e63d949cf3a649b" +dependencies = [ + "indexmap", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "int-enum" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366a1634cccc76b4cfd3e7580de9b605e4d93f1edac48d786c1f867c0def495" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "monitord" +version = "0.20.0" +dependencies = [ + "anyhow", + "clap", + "configparser", + "futures-util", + "indexmap", + "int-enum", + "procfs", + "serde", + "serde_json", + "serde_repr", + "serde_tuple", + "struct-field-names-as-array", + "strum", + "strum_macros", + "tempfile", + "thiserror", + "tokio", + "tracing", + "tracing-core", + "tracing-glog", + "tracing-subscriber", + "uzers", + "zbus", + "zlink", + "zvariant", + "zvariant_derive", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "procfs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" +dependencies = [ + "bitflags", + "chrono", + "flate2", + "procfs-core", + "rustix", +] + +[[package]] +name = "procfs-core" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" +dependencies = [ + "bitflags", + "chrono", + "hex", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_tuple" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af196b9c06f0aa5555ab980c01a2527b0f67517da8d68b1731b9d4764846a6f" +dependencies = [ + "serde", + "serde_tuple_macros", +] + +[[package]] +name = "serde_tuple_macros" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3a1e7d2eadec84deabd46ae061bf480a91a6bce74d25dad375bd656f2e19d8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "struct-field-names-as-array" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ba4bae771f9cc992c4f403636c54d2ef13acde6367583e99d06bb336674dd9" +dependencies = [ + "struct-field-names-as-array-derive", +] + +[[package]] +name = "struct-field-names-as-array-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2dbf8b57f3ce20e4bb171a11822b283bdfab6c4bb0fe64fa729f045f23a0938" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tokio" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.9+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-glog" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c45ab066a087486d062874889d4b551add3a33890969475d606f175c5ce7b68" +dependencies = [ + "chrono", + "nu-ansi-term 0.46.0", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "chrono", + "nu-ansi-term 0.50.3", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "uzers" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8275fb1afee25b4111d2dc8b5c505dbbc4afd0b990cb96deb2d88bff8be18d" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zbus" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" +dependencies = [ + "async-broadcast", + "async-recursion", + "async-trait", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", + "serde", + "serde_repr", + "tokio", + "tracing", + "uds_windows", + "uuid", + "windows-sys", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" +dependencies = [ + "serde", + "winnow", + "zvariant", +] + +[[package]] +name = "zlink" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5ad065e2697e98764f2738793904ff0aaa672707d0ee1592dfb4c47800962a" +dependencies = [ + "zlink-smol", + "zlink-tokio", +] + +[[package]] +name = "zlink-core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cae6561573e9996c2c26bf1c723b137a99c2d571a3276bd8f4ac52bfa44b3f2c" +dependencies = [ + "futures-util", + "itoa", + "libc", + "pin-project-lite", + "rustix", + "ryu", + "serde", + "serde_json", + "tracing", + "zlink-macros", +] + +[[package]] +name = "zlink-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4219a5aadc4844073d134e27fd52228933a462fbd07fe51ac5df8393f08168a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zlink-smol" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "befa02505904ee15f6721fdae1b6473d59649049c1f1810175fb7205a4dca82a" +dependencies = [ + "async-broadcast", + "async-channel", + "async-io", + "futures-lite", + "futures-util", + "pin-project-lite", + "zlink-core", +] + +[[package]] +name = "zlink-tokio" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378110fc4fad5fa9359251eb830d87993efcca44245f538a552cf26001649378" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", + "tokio-stream", + "zlink-core", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zvariant" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", + "winnow", +] diff --git a/modules/services/monitoring.nix b/modules/services/monitoring.nix @@ -0,0 +1,430 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.monitoring; + + fetchDashboard = { + name, + sha256, + url, + }: { + inherit name; + path = pkgs.runCommand name {} '' + sed 's/''${DS_PROMETHEUS}/VictoriaMetrics/g; s/''${DS_LOKI}/Loki/g' ${pkgs.fetchurl {inherit url sha256;}} > $out + ''; + }; + + dashboards = pkgs.linkFarm "grafana-dashboards" (map fetchDashboard [ + { + name = "node_exporter.json"; + url = "https://grafana.com/api/dashboards/1860/revisions/42/download"; + sha256 = "a4d827eb1819044bba2d6d257347175f6811910f2583fadeaf7e123c4df2125e"; + } + { + name = "systemd_exporter.json"; + url = "https://grafana.com/api/dashboards/22872/revisions/1/download"; + sha256 = "665bc3e86b79749b2fdae7787f4b7502e00830898bf48f73c68134471f72bf33"; + } + { + name = "monitord.json"; + url = "https://grafana.com/api/dashboards/21855/revisions/1/download"; + sha256 = "JJdkgnlctjofhaLFmwZrPe37oL7kmlK4srCUVH/2cJw="; + } + { + name = "seaweedfs.json"; + url = "https://raw.githubusercontent.com/chrislusf/seaweedfs/c9100a7213e27963f58a0ba783c9598a177384b6/other/metrics/grafana_seaweedfs.json"; + sha256 = "e364d113fed54127cbda10c4c2809d99a90dcc38bcd949b91846d0831e1a68e4"; + } + ] + ++ [ + { + name = "caddy.json"; + path = let + src = pkgs.fetchFromGitHub { + owner = "grafana"; + repo = "jsonnet-libs"; + rev = "2e9c7f4a276f6f6a9bc3f994f2b8804555f31bb9"; + sha256 = "12ikl9p9s6sv1qy5377dk95naz7ckwd767wgq4503xbaq0nq3k11"; + }; + in + pkgs.runCommand "caddy.json" { + nativeBuildInputs = [pkgs.go-jsonnet]; + } '' + jsonnet -J ${src} ${src}/caddy-mixin/dashboards/caddy-overview.jsonnet > $out + ''; + } + ]); + + monitord = pkgs.rustPlatform.buildRustPackage rec { + pname = "monitord"; + version = "0.20.0"; + src = pkgs.fetchFromGitHub { + owner = "cooperlees"; + repo = "monitord"; + rev = version; + hash = "sha256-+mqGt79e8sdfClc+066d5T7V4atl3DJRs65elyGpNcE="; + }; + cargoLock.lockFile = ./monitord.lock; + postUnpack = '' + cp ${./monitord.lock} source/Cargo.lock + ''; + nativeBuildInputs = [pkgs.pkg-config]; + buildInputs = [pkgs.dbus]; + doCheck = false; + }; + + monitord-exporter = pkgs.rustPlatform.buildRustPackage rec { + pname = "monitord-exporter"; + version = "0.19.0"; + src = pkgs.fetchFromGitHub { + owner = "cooperlees"; + repo = "monitord-exporter"; + rev = version; + hash = "sha256-z1a20SXtEuVGDcxuJ7HWd1GzzaSZT30biYX89fS5AZM="; + }; + cargoLock.lockFile = ./monitord-exporter.lock; + postUnpack = '' + cp ${./monitord-exporter.lock} source/Cargo.lock + ''; + nativeBuildInputs = [pkgs.pkg-config]; + buildInputs = [pkgs.dbus]; + doCheck = false; + }; +in { + options.services.haravara.monitoring = { + enable = lib.mkEnableOption "Monitoring stack (VictoriaMetrics + Grafana)"; + grafanaDomain = lib.mkOption { + type = lib.types.str; + }; + victoriaDomain = lib.mkOption { + type = lib.types.str; + }; + authLabel = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "The auth snippet to import"; + }; + }; + + config = lib.mkIf cfg.enable { + users.groups.victoriametrics = {}; + users.users.victoriametrics = { + isSystemUser = true; + group = "victoriametrics"; + extraGroups = ["storage-users"]; + }; + + age.secrets.grafana-secret-key = { + file = ../../secrets/grafana-secret-key.age; + owner = "grafana"; + }; + + systemd = { + services = { + victoriametrics = { + serviceConfig = { + User = "victoriametrics"; + Group = "victoriametrics"; + StateDirectory = lib.mkForce ""; + DynamicUser = lib.mkForce false; + ReadWritePaths = ["/var/lib/victoriametrics"]; + }; + }; + + prometheus-node-exporter.serviceConfig = { + # Relaxing sandboxing and running as root as it fails to collect metrics reliably + # due to dbus connection resets and pending reply limits. + RestrictNamespaces = lib.mkForce false; + RestrictAddressFamilies = lib.mkForce ["AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK"]; + DynamicUser = lib.mkForce false; + User = lib.mkForce "root"; + Group = lib.mkForce "root"; + }; + + prometheus-systemd-exporter.serviceConfig = { + # Relaxing sandboxing and running as root as it fails to collect metrics reliably + # due to dbus connection resets and pending reply limits. + RestrictNamespaces = lib.mkForce false; + RestrictAddressFamilies = lib.mkForce ["AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK"]; + DynamicUser = lib.mkForce false; + User = lib.mkForce "root"; + Group = lib.mkForce "root"; + }; + + monitord-exporter = { + description = "monitord-exporter"; + after = ["network-online.target"]; + requires = ["network-online.target"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + ExecStart = "${monitord-exporter}/bin/monitord-exporter --port 9091"; + Restart = "on-failure"; + User = "root"; + Group = "root"; + IPAddressAllow = ["127.0.0.1" "::1"]; + IPAddressDeny = "any"; + }; + }; + + monitord = { + description = "monitord - systemd health metrics collector"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${monitord}/bin/monitord -c /etc/monitord.conf"; + User = "root"; + Group = "root"; + }; + }; + }; + + timers = { + monitord = { + description = "Run monitord periodically"; + wantedBy = ["timers.target"]; + timerConfig = { + OnBootSec = "1min"; + OnUnitActiveSec = "5min"; + }; + }; + }; + }; + + environment.etc."monitord.conf".text = '' + [monitord] + daemon = false + output_format = json + daemon_stats_refresh_secs = 300 + + [units] + enabled = true + + [pid1] + enabled = true + + [networkd] + enabled = true + + [dbus] + enabled = false + + [varlink] + enabled = false + ''; + + environment.systemPackages = [ + monitord + monitord-exporter + ]; + + services = { + victoriametrics = { + enable = true; + listenAddress = "127.0.0.1:8428"; + prometheusConfig = { + global.scrape_interval = "30s"; + scrape_configs = [ + { + job_name = "bobor_status"; + static_configs = [{targets = ["https://status.saunabobor.sk"];}]; + metrics_path = "/metrics"; + } + { + job_name = "node_exporter"; + static_configs = [{targets = ["127.0.0.1:${toString config.services.prometheus.exporters.node.port}"];}]; + } + { + job_name = "systemd_exporter"; + static_configs = [{targets = ["127.0.0.1:${toString config.services.prometheus.exporters.systemd.port}"];}]; + metrics_path = "/metrics"; + } + { + job_name = "cadvisor"; + static_configs = [{targets = ["127.0.0.1:${toString config.services.cadvisor.port}"];}]; + metrics_path = "/metrics"; + } + { + job_name = "monitord"; + static_configs = [{targets = ["127.0.0.1:9091"];}]; + metrics_path = "/metrics"; + } + { + job_name = "seaweedfs"; + static_configs = [ + { + targets = [ + "127.0.0.1:9324" + "127.0.0.1:9325" + "127.0.0.1:9326" + "127.0.0.1:9327" + ]; + } + ]; + } + { + job_name = "caddy"; + static_configs = [{targets = ["127.0.0.1:2019"];}]; + } + ]; + }; + }; + + prometheus.exporters.node = { + enable = true; + listenAddress = "127.0.0.1"; + enabledCollectors = ["systemd"]; + port = 9100; + }; + + prometheus.exporters.systemd = { + enable = true; + listenAddress = "127.0.0.1"; + port = 9558; + extraFlags = [ + "--systemd.collector.unit-exclude=.*\\\\.(mount|slice|scope|target|device|path|timer|automount|socket|swap)" + ]; + }; + + cadvisor = { + enable = true; + listenAddress = "127.0.0.1"; + port = 8182; + }; + + loki = { + enable = true; + configuration = { + server.http_listen_address = "127.0.0.1"; + server.http_listen_port = 3100; + server.grpc_listen_address = "127.0.0.1"; + auth_enabled = false; + + common = { + instance_addr = "127.0.0.1"; + path_prefix = "/var/lib/loki"; + replication_factor = 1; + ring.kvstore.store = "inmemory"; + }; + + schema_config.configs = [ + { + from = "2020-10-24"; + store = "tsdb"; + object_store = "filesystem"; + schema = "v13"; + index.prefix = "index_"; + index.period = "24h"; + } + ]; + + storage_config.filesystem.directory = "/var/lib/loki/chunks"; + }; + }; + + promtail = { + enable = true; + configuration = { + server = { + http_listen_address = "127.0.0.1"; + http_listen_port = 9080; + grpc_listen_address = "127.0.0.1"; + grpc_listen_port = 0; + }; + clients = [ + { + url = "http://127.0.0.1:3100/loki/api/v1/push"; + } + ]; + scrape_configs = [ + { + job_name = "journal"; + journal = { + max_age = "12h"; + labels = { + job = "systemd-journal"; + host = config.networking.hostName; + }; + }; + relabel_configs = [ + { + source_labels = ["__journal__systemd_unit"]; + target_label = "unit"; + } + ]; + } + ]; + }; + }; + + grafana = { + enable = true; + settings = { + server = { + http_addr = "127.0.0.1"; + http_port = 3001; + }; + security = { + secret_key = "$__file{${config.age.secrets.grafana-secret-key.path}}"; + }; + }; + provision = { + enable = true; + datasources.settings = { + apiVersion = 1; + deleteDatasources = [ + { + name = "VictoriaMetrics"; + orgId = 1; + } + { + name = "Loki"; + orgId = 1; + } + ]; + datasources = [ + { + name = "VictoriaMetrics"; + type = "prometheus"; + url = "http://127.0.0.1:8428"; + uid = "DS_PROMETHEUS"; + isDefault = true; + } + { + name = "Loki"; + type = "loki"; + url = "http://127.0.0.1:3100"; + } + ]; + }; + dashboards.settings.providers = [ + { + name = "Default"; + options.path = dashboards; + } + ]; + }; + }; + + caddy.virtualHosts = { + "${cfg.grafanaDomain}".extraConfig = '' + ${lib.optionalString (cfg.authLabel != null) "import ${ + if cfg.authLabel == "default" + then "auth" + else "auth_${cfg.authLabel}" + }"} + reverse_proxy 127.0.0.1:3001 + ''; + "${cfg.victoriaDomain}".extraConfig = '' + ${lib.optionalString (cfg.authLabel != null) "import ${ + if cfg.authLabel == "default" + then "auth" + else "auth_${cfg.authLabel}" + }"} + reverse_proxy 127.0.0.1:8428 + ''; + }; + }; + }; +} diff --git a/modules/services/mtmn.nix b/modules/services/mtmn.nix Binary files differ. diff --git a/modules/services/oauth2-proxy.nix b/modules/services/oauth2-proxy.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.oauth2-proxy; +in { + options.services.haravara.oauth2-proxy = { + enable = lib.mkEnableOption "OAuth2 Proxy for OIDC authentication"; + domains = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "List of domains to serve the OAuth2 proxy on"; + }; + cookieDomains = lib.mkOption { + type = lib.types.listOf lib.types.str; + }; + oidcIssuer = lib.mkOption { + type = lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + age.secrets.oauth2-proxy-client-secret.file = ../../secrets/oauth2-proxy-client-secret.age; + age.secrets.oauth2-proxy-cookie-secret.file = ../../secrets/oauth2-proxy-cookie-secret.age; + + services.oauth2-proxy = { + enable = true; + provider = "oidc"; + clientID = "caddy-proxy"; + clientSecretFile = config.age.secrets.oauth2-proxy-client-secret.path; + cookie = { + name = "_oauth2_proxy"; + secretFile = config.age.secrets.oauth2-proxy-cookie-secret.path; + domain = lib.concatStringsSep "," cfg.cookieDomains; + expire = "24h"; + refresh = "0h"; + }; + + scope = "openid email profile"; + email.domains = ["*"]; + extraConfig = { + oidc-issuer-url = cfg.oidcIssuer; + insecure-oidc-skip-issuer-verification = "true"; + code-challenge-method = "S256"; + whitelist-domain = lib.concatStringsSep "," cfg.cookieDomains; + http-address = "127.0.0.1:4180"; + reverse-proxy = "true"; + set-xauthrequest = "true"; + pass-user-headers = "true"; + insecure-oidc-allow-unverified-email = "true"; + skip-provider-button = "true"; + cookie-samesite = "lax"; + cookie-secure = "true"; + cookie-expire = "24h"; + cookie-refresh = "0h"; + }; + }; + + services.caddy.virtualHosts = lib.genAttrs cfg.domains (_: { + extraConfig = '' + reverse_proxy 127.0.0.1:4180 + ''; + }); + + # Ensure dex is ready before starting oauth2-proxy + systemd.services.oauth2-proxy = { + after = ["dex.service"]; + requires = ["dex.service"]; + serviceConfig.ExecStartPre = "${pkgs.bash}/bin/bash -c 'while ! ${pkgs.netcat}/bin/nc -z 127.0.0.1 5556; do sleep 1; done'"; + }; + }; +} diff --git a/modules/services/redlib.nix b/modules/services/redlib.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.haravara.redlib; +in { + options.services.haravara.redlib = { + enable = lib.mkEnableOption "Redlib Reddit Frontend"; + domain = lib.mkOption { + type = lib.types.str; + }; + authLabel = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "The auth snippet to import"; + }; + }; + + config = lib.mkIf cfg.enable { + services.redlib = { + enable = true; + port = 7828; + address = "127.0.0.1"; + }; + + services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' + ${lib.optionalString (cfg.authLabel != null) "import ${ + if cfg.authLabel == "default" + then "auth" + else "auth_${cfg.authLabel}" + }"} + reverse_proxy 127.0.0.1:7828 + ''; + }; +} diff --git a/modules/services/searxng.nix b/modules/services/searxng.nix @@ -0,0 +1,56 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.searxng; +in { + options.services.haravara.searxng = { + enable = lib.mkEnableOption "SearXNG search engine"; + domain = lib.mkOption { + type = lib.types.str; + }; + authLabel = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "The auth snippet to import"; + }; + secretKeyFile = lib.mkOption { + type = lib.types.path; + default = config.age.secrets.searx-secret-key.path; + description = "Path to file containing SEARX_SECRET_KEY"; + }; + }; + + config = lib.mkIf cfg.enable { + age.secrets.searx-secret-key.file = ../../secrets/searx-secret-key.age; + + services.searx = { + enable = true; + package = pkgs.searxng; + redisCreateLocally = true; + environmentFile = cfg.secretKeyFile; + settings = { + server = { + port = 8899; + bind_address = "127.0.0.1"; + secret_key = "@SEARX_SECRET_KEY@"; + }; + ui = { + static_use_hash = true; + default_theme = "simple"; + }; + }; + }; + + services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' + ${lib.optionalString (cfg.authLabel != null) "import ${ + if cfg.authLabel == "default" + then "auth" + else "auth_${cfg.authLabel}" + }"} + reverse_proxy 127.0.0.1:8899 + ''; + }; +} diff --git a/modules/services/seaweedfs.nix b/modules/services/seaweedfs.nix @@ -0,0 +1,111 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.services.haravara.seaweedfs; +in { + options.services.haravara.seaweedfs = { + enable = lib.mkEnableOption "SeaweedFS"; + estriDomain = lib.mkOption { + type = lib.types.str; + description = "Domain for the S3 gateway"; + }; + dataDir = lib.mkOption { + type = lib.types.str; + description = "Base directory for SeaweedFS data"; + }; + }; + + config = lib.mkIf cfg.enable { + users.users.seaweedfs = { + isSystemUser = true; + group = "storage-users"; + }; + + systemd = { + services = { + seaweedfs-master = { + description = "SeaweedFS Master"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + User = "seaweedfs"; + Group = "storage-users"; + ExecStart = "${pkgs.seaweedfs}/bin/weed master -mdir=${cfg.dataDir}/master -port=9333 -ip=127.0.0.1 -ip.bind=127.0.0.1 -metricsPort=9324"; + Restart = "always"; + }; + }; + + seaweedfs-volume = { + description = "SeaweedFS Volume"; + after = ["seaweedfs-master.service"]; + requires = ["seaweedfs-master.service"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + User = "seaweedfs"; + Group = "storage-users"; + ExecStart = "${pkgs.seaweedfs}/bin/weed volume -dir=${cfg.dataDir}/volume -max=100 -port=8080 -ip=127.0.0.1 -ip.bind=127.0.0.1 -master=127.0.0.1:9333 -index=leveldb -metricsPort=9325"; + Restart = "always"; + }; + }; + + seaweedfs-filer = { + description = "SeaweedFS Filer"; + after = ["seaweedfs-master.service" "seaweedfs-volume.service"]; + requires = ["seaweedfs-master.service"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + User = "seaweedfs"; + Group = "storage-users"; + ExecStart = "${pkgs.seaweedfs}/bin/weed filer -port=8888 -ip=127.0.0.1 -ip.bind=127.0.0.1 -master=127.0.0.1:9333 -defaultStoreDir=${cfg.dataDir}/filer -metricsPort=9326"; + Restart = "always"; + }; + }; + + seaweedfs-s3 = { + description = "SeaweedFS S3 Gateway"; + after = ["seaweedfs-filer.service"]; + requires = ["seaweedfs-filer.service"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + User = "seaweedfs"; + Group = "storage-users"; + ExecStart = "${pkgs.seaweedfs}/bin/weed s3 -port=8333 -ip.bind=0.0.0.0 -filer=127.0.0.1:8888 -metricsPort=9327"; + Restart = "always"; + IPAddressAllow = ["127.0.0.1" "::1" "10.88.0.0/16"]; + IPAddressDeny = "any"; + }; + }; + + seaweedfs-admin = { + description = "SeaweedFS Admin Interface"; + after = ["seaweedfs-master.service"]; + requires = ["seaweedfs-master.service"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + User = "seaweedfs"; + Group = "storage-users"; + ExecStart = "${pkgs.seaweedfs}/bin/weed admin -port=23646 -master=127.0.0.1:9333"; + Restart = "always"; + IPAddressAllow = ["127.0.0.1" "::1"]; + IPAddressDeny = "any"; + }; + }; + }; + }; + + services.caddy.virtualHosts = { + "${cfg.estriDomain}".extraConfig = '' + reverse_proxy 127.0.0.1:8333 + redir / https://${lib.concatStringsSep "." (lib.drop 1 (lib.splitString "." cfg.estriDomain))} + ''; + }; + }; +} diff --git a/modules/services/shirt-linkener.nix b/modules/services/shirt-linkener.nix @@ -0,0 +1,104 @@ +{ + config, + lib, + pkgs, + inputs, + ... +}: let + cfg = config.services.haravara.shirt-linkener; + + shirt-linkener = pkgs.beamPackages.mixRelease { + pname = "shortener"; + version = "0.0.1"; + src = "${inputs.tools}/shirt_linkener"; + + nativeBuildInputs = [pkgs.beamPackages.elixir_1_18]; + + MIX_HOME = "nix-mix"; + HEX_HOME = "nix-hex"; + ELIXIR_MAKE_CACHE_DIR = "nix-elixir-make"; + + mixFodDeps = pkgs.beamPackages.fetchMixDeps { + pname = "shortener-deps"; + version = "0.0.1"; + src = "${inputs.tools}/shirt_linkener"; + sha256 = "sha256-U/tNP3s7b4bBUrQx5l4VtDHpV9DsWj6zBYj8jsM4Acw="; + }; + }; +in { + options.services.haravara.shirt-linkener = { + enable = lib.mkEnableOption "link shortener that beams up"; + + port = lib.mkOption { + type = lib.types.port; + default = 8721; + }; + + host = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + }; + + baseUrl = lib.mkOption { + type = lib.types.str; + }; + + authToken = lib.mkOption { + type = lib.types.str; + }; + + domain = lib.mkOption { + type = lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.shirt-linkener = { + description = "Shirt Linkener URL Shortener"; + wantedBy = ["multi-user.target"]; + after = ["network.target"]; + + environment = { + PORT = toString cfg.port; + HOST = cfg.host; + ERL_EPMD_ADDRESS = "127.0.0.1"; + BASE_URL = cfg.baseUrl; + AUTH_TOKEN = cfg.authToken; + DB_PATH = "/var/lib/shirt-linkener/shortener.db"; + RELEASE_COOKIE = "shirt-linkener-cookie"; + RELEASE_NODE = "shirt-linkener@localhost"; + RELEASE_TMP = "/var/lib/shirt-linkener/tmp"; + ERL_AFLAGS = "-kernel inet_dist_use_interface '{127,0,0,1}'"; + }; + + serviceConfig = { + Type = "simple"; + ExecStart = "${shirt-linkener}/bin/shortener start"; + ExecStop = "${shirt-linkener}/bin/shortener stop"; + Restart = "always"; + RestartSec = "5s"; + User = "shirt-linkener"; + Group = "shirt-linkener"; + StateDirectory = "shirt-linkener"; + WorkingDirectory = "/var/lib/shirt-linkener"; + RuntimeDirectory = "shirt-linkener"; + SuccessExitStatus = [0 143]; + KillMode = "mixed"; + LimitNOFILE = 65535; + }; + }; + + users.users.shirt-linkener = { + isSystemUser = true; + group = "shirt-linkener"; + }; + users.groups.shirt-linkener = {}; + + services.caddy.virtualHosts = { + "${cfg.domain}".extraConfig = '' + reverse_proxy 127.0.0.1:${toString cfg.port} + redir / https://${lib.concatStringsSep "." (lib.drop 1 (lib.splitString "." cfg.domain))} + ''; + }; + }; +} diff --git a/modules/services/storage-box.nix b/modules/services/storage-box.nix Binary files differ. diff --git a/secrets.nix b/secrets.nix @@ -0,0 +1,15 @@ +let + amen = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEShZSmhIjIXf0DbFG8fZQFBy6CgDU2tFMMTAvCF5/ca"; + nixaran = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILR1AXTb/mETWJgd1b1F4xvwa/MOeeElCUZ9/nklcZuX"; + + allKeys = [amen nixaran]; +in { + "secrets/storage-box-pass.age".publicKeys = allKeys; + "secrets/grafana-secret-key.age".publicKeys = allKeys; + "secrets/oauth2-proxy-client-secret.age".publicKeys = allKeys; + "secrets/oauth2-proxy-cookie-secret.age".publicKeys = allKeys; + "secrets/dex-client-secret.age".publicKeys = allKeys; + "secrets/couchdb-admin-pass.age".publicKeys = allKeys; + "secrets/searx-secret-key.age".publicKeys = allKeys; + "secrets/headscale-api-key.age".publicKeys = allKeys; +} diff --git a/secrets/couchdb-admin-pass.age b/secrets/couchdb-admin-pass.age Binary files differ. diff --git a/secrets/dex-client-secret.age b/secrets/dex-client-secret.age Binary files differ. diff --git a/secrets/grafana-secret-key.age b/secrets/grafana-secret-key.age Binary files differ. diff --git a/secrets/headscale-api-key.age b/secrets/headscale-api-key.age Binary files differ. diff --git a/secrets/oauth2-proxy-client-secret.age b/secrets/oauth2-proxy-client-secret.age Binary files differ. diff --git a/secrets/oauth2-proxy-cookie-secret.age b/secrets/oauth2-proxy-cookie-secret.age Binary files differ. diff --git a/secrets/searx-secret-key.age b/secrets/searx-secret-key.age Binary files differ. diff --git a/secrets/storage-box-pass.age b/secrets/storage-box-pass.age Binary files differ.