├── .gitignore ├── nvim ├── after │ ├── ftplugin │ │ ├── json.vim │ │ ├── vim.vim │ │ ├── cmake.vim │ │ ├── git.vim │ │ ├── fugitive.vim │ │ ├── lspinfo.vim │ │ ├── rust.vim │ │ ├── dap-float.vim │ │ ├── tsplayground.vim │ │ ├── xml.vim │ │ ├── markdown.vim │ │ ├── c.vim │ │ ├── alpha.vim │ │ ├── gnuplot.vim │ │ ├── lisp.vim │ │ ├── qml.vim │ │ ├── zig.lua │ │ ├── python.lua │ │ ├── lua.vim │ │ ├── asm.vim │ │ ├── cpp.vim │ │ └── java.vim │ ├── indent │ │ └── tex.vim │ └── syntax │ │ ├── cpp.vim │ │ ├── tex.vim │ │ └── nftables.vim ├── lua │ ├── plugins │ │ ├── lspsig.lua │ │ ├── dbee.lua │ │ ├── toggleterm.lua │ │ ├── tele_bibtex.lua │ │ ├── friendly_snippets.lua │ │ ├── hydra.lua │ │ ├── ls_latex_snips.lua │ │ ├── semantic_tokens.lua │ │ ├── ssr.lua │ │ ├── vim_snippets.lua │ │ ├── neogen.lua │ │ ├── oil.lua │ │ ├── jupytext.lua │ │ ├── hop.lua │ │ ├── catppuccin.lua │ │ ├── dap_py.lua │ │ ├── dap_ui.lua │ │ ├── illuminate.lua │ │ ├── telescope.lua │ │ ├── togglecomment.lua │ │ ├── iron.lua │ │ ├── lualine.lua │ │ ├── flatten.lua │ │ ├── da_lua.lua │ │ ├── comment.lua │ │ ├── luasnip │ │ │ ├── repeat_integration.lua │ │ │ ├── ft_edit.lua │ │ │ └── helpers.lua │ │ ├── matchconfig.lua │ │ ├── treesitter.lua │ │ ├── cmp.lua │ │ ├── blink.lua │ │ ├── dap.lua │ │ └── gruvbox.lua │ ├── ts-format │ │ ├── init.lua │ │ └── providers.lua │ ├── modes │ │ ├── init.lua │ │ └── upcase.lua │ ├── snippet-utils.lua │ ├── vksnippets │ │ ├── init.lua │ │ └── source.lua │ ├── session.lua │ ├── sighelp │ │ ├── snippet.lua │ │ └── util.lua │ ├── bash-scratch.lua │ ├── scripts │ │ └── co_pe-1_conv.lua │ ├── symbols.lua │ ├── auto_table.lua │ ├── vkinfo.lua │ ├── vkdoc.lua │ ├── write.lua │ └── filejump │ │ └── init.lua ├── queries │ ├── cuda │ │ └── folds.scm │ ├── glsl │ │ └── folds.scm │ ├── bash │ │ └── injections.scm │ ├── latex │ │ ├── togglecomment.scm │ │ └── folds.scm │ ├── xml │ │ ├── highlights.scm │ │ └── injections.scm │ ├── css │ │ └── folds.scm │ ├── zig │ │ └── folds.scm │ ├── luap │ │ └── highlights.scm │ ├── markdown │ │ └── folds.scm │ ├── python │ │ └── folds.scm │ ├── lua │ │ └── folds.scm │ ├── julia │ │ └── folds.scm │ ├── make │ │ └── highlights.scm │ └── c │ │ └── folds.scm ├── ftplugin │ └── zig.lua ├── luasnippets │ ├── css.lua │ ├── html.lua │ ├── zsh │ │ └── a.lua │ ├── yuck.lua │ ├── __symbols.lua │ ├── ipynb.lua │ ├── bash.lua │ ├── editorconfig.lua │ ├── sh.lua │ ├── rust.lua │ ├── matchconfig_lua.lua │ ├── nix.lua │ ├── glsl.lua │ ├── help.lua │ ├── PKGBUILD.lua │ ├── julia.lua │ ├── cpp_mitsuba.lua │ ├── python.lua │ ├── cpp.lua │ ├── c.lua │ ├── all.lua │ ├── zig.lua │ ├── lua.lua │ └── java.lua ├── compiler │ └── grep.vim ├── generated │ └── rtp_base.lua ├── parsers │ └── xml │ │ └── libtree-sitter-xml.so ├── filetype.lua ├── meta │ └── luasnippets │ │ └── defs.lua └── functions.vim ├── nixos ├── overlays │ └── l3mon.nix ├── data │ ├── ordering.nix │ ├── default.nix │ ├── ids.nix │ ├── pubkeys.nix │ ├── ports.nix │ └── gruvbox.nix ├── profiles │ ├── cachefilesd.nix │ ├── history.nix │ ├── sway │ │ ├── zathura.nix │ │ ├── copypaste │ │ │ ├── default.nix │ │ │ └── sway-copypaste.lua │ │ └── decoration.nix │ ├── bash-alias-completion.nix │ ├── unibonn.nix │ ├── nfs.nix │ ├── wakeonlan.nix │ ├── no_sub_langs.patch │ ├── opus-fs.nix │ ├── kodi.nix │ ├── radicale.nix │ ├── firefox.nix │ ├── mxmaster3s.nix │ ├── flake-preserve.nix │ ├── mealie.nix │ ├── pinchflat.nix │ ├── readeck.nix │ ├── webdav.nix │ ├── karakeep.nix │ ├── ncps.nix │ ├── kimmify.nix │ ├── localnet.nix │ ├── paperless.nix │ ├── ddns-updater.nix │ ├── forgejo.nix │ ├── immich.nix │ ├── linkding.nix │ ├── mobile-net.nix │ ├── samba.nix │ └── errormail.nix ├── machines │ ├── indigo │ │ ├── home │ │ │ └── default.nix │ │ ├── profiles │ │ │ └── nvidia.nix │ │ └── hardware-configuration.nix │ ├── carmine │ │ ├── profiles │ │ │ ├── ollama.nix │ │ │ ├── cachefilesd.nix │ │ │ ├── mympd.nix │ │ │ └── remarkable.nix │ │ ├── home │ │ │ ├── profiles │ │ │ │ ├── jellyfin-conf.nix │ │ │ │ └── sway-io.nix │ │ │ └── default.nix │ │ └── hardware-configuration.nix │ └── cobalt │ │ ├── home │ │ ├── profiles │ │ │ ├── jellyfin-mpv-cred.nix │ │ │ └── sway-io.nix │ │ └── default.nix │ │ └── hardware-configuration.nix ├── home │ ├── modules │ │ ├── sway.nix │ │ └── sway-workrooms │ │ │ └── sway-workrooms.lua │ └── profiles │ │ ├── mpv.nix │ │ ├── pass.nix │ │ ├── tev.patch │ │ ├── remote-gpg-agent.nix │ │ ├── mime.nix │ │ ├── qutebrowser │ │ └── config.py │ │ ├── neovim │ │ ├── julia-lsp.nix │ │ └── default.nix │ │ └── julia.nix ├── packages │ ├── default.nix │ ├── iosevka.nix │ ├── k-stream.nix │ ├── struct.nix │ └── k-sway.nix ├── lib.nix ├── modules │ ├── secgen.nix │ ├── automount.nix │ ├── peercache.nix │ ├── sway-netns.nix │ └── qb_control.py └── README.md ├── solaar ├── rules.yaml └── config.yaml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /nvim/info* 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/json.vim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/vim.vim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nvim/lua/plugins/lspsig.lua: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nvim/lua/ts-format/init.lua: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/cmake.vim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/git.vim: -------------------------------------------------------------------------------- 1 | fugitive.vim -------------------------------------------------------------------------------- /nvim/queries/cuda/folds.scm: -------------------------------------------------------------------------------- 1 | ; inherits: cpp 2 | -------------------------------------------------------------------------------- /nvim/queries/glsl/folds.scm: -------------------------------------------------------------------------------- 1 | ; inherits: c 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/fugitive.vim: -------------------------------------------------------------------------------- 1 | set nofoldenable 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/lspinfo.vim: -------------------------------------------------------------------------------- 1 | set foldlevel=99 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/rust.vim: -------------------------------------------------------------------------------- 1 | setlocal expandtab 2 | -------------------------------------------------------------------------------- /nvim/ftplugin/zig.lua: -------------------------------------------------------------------------------- 1 | vim.g.zig_fmt_autosave = 0 2 | -------------------------------------------------------------------------------- /nvim/lua/modes/init.lua: -------------------------------------------------------------------------------- 1 | require("modes.upcase") 2 | -------------------------------------------------------------------------------- /nvim/lua/plugins/dbee.lua: -------------------------------------------------------------------------------- 1 | require("dbee").setup() 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/dap-float.vim: -------------------------------------------------------------------------------- 1 | set nofoldenable 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/tsplayground.vim: -------------------------------------------------------------------------------- 1 | set nofoldenable 2 | -------------------------------------------------------------------------------- /nvim/lua/snippet-utils.lua: -------------------------------------------------------------------------------- 1 | return "bbcccccccccccccccc" 2 | -------------------------------------------------------------------------------- /nvim/luasnippets/css.lua: -------------------------------------------------------------------------------- 1 | parse_add("adf", "css!!!") 2 | -------------------------------------------------------------------------------- /nvim/luasnippets/html.lua: -------------------------------------------------------------------------------- 1 | parse_add("html", "asdf") 2 | -------------------------------------------------------------------------------- /nvim/luasnippets/zsh/a.lua: -------------------------------------------------------------------------------- 1 | parse_add("zsh", "asd") 2 | -------------------------------------------------------------------------------- /nvim/queries/bash/injections.scm: -------------------------------------------------------------------------------- 1 | (heredoc_body) @bash 2 | -------------------------------------------------------------------------------- /nixos/overlays/l3mon.nix: -------------------------------------------------------------------------------- 1 | import ../packages/default.nix 2 | -------------------------------------------------------------------------------- /nvim/after/indent/tex.vim: -------------------------------------------------------------------------------- 1 | set indentexpr= 2 | set indentkeys= 3 | -------------------------------------------------------------------------------- /nvim/lua/plugins/toggleterm.lua: -------------------------------------------------------------------------------- 1 | -- require("toggleterm").setup{} 2 | -------------------------------------------------------------------------------- /nvim/queries/latex/togglecomment.scm: -------------------------------------------------------------------------------- 1 | (section) @togglecomment 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/xml.vim: -------------------------------------------------------------------------------- 1 | setlocal ai nosi 2 | setlocal indentexpr= 3 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/markdown.vim: -------------------------------------------------------------------------------- 1 | set textwidth=80 2 | set conceallevel=0 3 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/c.vim: -------------------------------------------------------------------------------- 1 | so /home/simon/.config/nvim/after/ftplugin/cpp.vim 2 | -------------------------------------------------------------------------------- /nvim/lua/plugins/tele_bibtex.lua: -------------------------------------------------------------------------------- 1 | require"telescope".load_extension("bibtex") 2 | -------------------------------------------------------------------------------- /nvim/after/syntax/cpp.vim: -------------------------------------------------------------------------------- 1 | "load doxygen sntax highlight. 2 | setl syntax=cpp.doxygen 3 | -------------------------------------------------------------------------------- /nvim/luasnippets/yuck.lua: -------------------------------------------------------------------------------- 1 | s_add_auto({trig="(", priority=1001}, {t"(", i(1), t")"}) 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/alpha.vim: -------------------------------------------------------------------------------- 1 | autocmd BufWrite *.alpha :call setreg('*', expand('%:p')) 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/gnuplot.vim: -------------------------------------------------------------------------------- 1 | nnoremap r :Dispatch gnuplot % 2 | -------------------------------------------------------------------------------- /nvim/lua/plugins/friendly_snippets.lua: -------------------------------------------------------------------------------- 1 | require("luasnip.loaders.from_vscode").lazy_load() 2 | -------------------------------------------------------------------------------- /nvim/luasnippets/__symbols.lua: -------------------------------------------------------------------------------- 1 | return { 2 | s({ trig = "", regTrig = true}, t("")) 3 | } 4 | -------------------------------------------------------------------------------- /nixos/data/ordering.nix: -------------------------------------------------------------------------------- 1 | { 2 | # default mkBefore. 3 | peercache-substituters = 500; 4 | } 5 | -------------------------------------------------------------------------------- /nvim/compiler/grep.vim: -------------------------------------------------------------------------------- 1 | CompilerSet makeprg=&grepprg 2 | CompilerSet errorformat=&grepformat 3 | -------------------------------------------------------------------------------- /nvim/lua/vksnippets/init.lua: -------------------------------------------------------------------------------- 1 | -- registers source with cmp. 2 | require("vksnippets.source") 3 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/lisp.vim: -------------------------------------------------------------------------------- 1 | " remove / 2 | set isk=@,48-57,_,192-255,+,-,*,%,<,=,>,:,$,?,!,@-@,94 3 | -------------------------------------------------------------------------------- /nvim/lua/plugins/hydra.lua: -------------------------------------------------------------------------------- 1 | local hydra = require("hydra") 2 | 3 | hydra({ 4 | name = "dap" 5 | }) 6 | -------------------------------------------------------------------------------- /nvim/luasnippets/ipynb.lua: -------------------------------------------------------------------------------- 1 | parse_add({trig="ccc", snippetType="autosnippet"}, "# ---\n# $1\n# ---") 2 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/qml.vim: -------------------------------------------------------------------------------- 1 | setlocal foldmethod=indent 2 | setl ai nocindent nosi 3 | setl indentexpr="" 4 | -------------------------------------------------------------------------------- /nvim/lua/plugins/ls_latex_snips.lua: -------------------------------------------------------------------------------- 1 | require("luasnip-latex-snippets").setup({use_treesitter = true}) 2 | -------------------------------------------------------------------------------- /nvim/lua/session.lua: -------------------------------------------------------------------------------- 1 | -- stores snippets modified by lsp. 2 | return { 3 | lsp_override_snips = {} 4 | } 5 | -------------------------------------------------------------------------------- /nvim/luasnippets/bash.lua: -------------------------------------------------------------------------------- 1 | parse_add("for", [[ 2 | for $1 in $2 3 | do 4 | $3 5 | done$0 6 | ]]) 7 | -------------------------------------------------------------------------------- /nvim/lua/plugins/semantic_tokens.lua: -------------------------------------------------------------------------------- 1 | require'nvim-semantic-tokens'.setup({ 2 | preset = "default" 3 | }) 4 | -------------------------------------------------------------------------------- /nvim/lua/plugins/ssr.lua: -------------------------------------------------------------------------------- 1 | vim.keymap.set({ "n", "x" }, "sr", function() require("ssr").open() end) 2 | -------------------------------------------------------------------------------- /nvim/lua/plugins/vim_snippets.lua: -------------------------------------------------------------------------------- 1 | require("luasnip.loaders.from_snipmate").lazy_load({exclude = {"markdown"}}) 2 | -------------------------------------------------------------------------------- /nvim/lua/plugins/neogen.lua: -------------------------------------------------------------------------------- 1 | require('neogen').setup({snippet_engine = "luasnip"}) 2 | 3 | vim.cmd("command NG Neogen") 4 | -------------------------------------------------------------------------------- /nvim/lua/plugins/oil.lua: -------------------------------------------------------------------------------- 1 | require("oil").setup({ 2 | default_file_explorer= false, 3 | silence_scp_warning = true 4 | }) 5 | -------------------------------------------------------------------------------- /nvim/generated/rtp_base.lua: -------------------------------------------------------------------------------- 1 | return {"/nix/store/hnn6c4svf9fwriji1sl0maslhhkn71b3-neovim-unwrapped-nightly/share/nvim/runtime"} 2 | -------------------------------------------------------------------------------- /nvim/lua/plugins/jupytext.lua: -------------------------------------------------------------------------------- 1 | vim.g.jupytext_fmt = "py" 2 | -- vim.g.jupytext_filetype_map = { 3 | -- py = "python" 4 | -- } 5 | -------------------------------------------------------------------------------- /nvim/parsers/xml/libtree-sitter-xml.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/L3MON4D3/Dotfiles/HEAD/nvim/parsers/xml/libtree-sitter-xml.so -------------------------------------------------------------------------------- /nvim/queries/xml/highlights.scm: -------------------------------------------------------------------------------- 1 | ; extends 2 | 3 | ((PI (PITarget) @name) @comment (#eq? @name "comment") (#set! "priority" 105)) 4 | -------------------------------------------------------------------------------- /nixos/profiles/cachefilesd.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | services.cachefilesd.enable = true; 5 | } 6 | -------------------------------------------------------------------------------- /nvim/luasnippets/editorconfig.lua: -------------------------------------------------------------------------------- 1 | parse_add("root", [[ 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | indent_size = 4 7 | ]]) 8 | -------------------------------------------------------------------------------- /nvim/queries/xml/injections.scm: -------------------------------------------------------------------------------- 1 | ; extends 2 | 3 | ((PI (PITarget) @target) @injection.content (#eq? @target "comment") (#set! injection.language "comment")) 4 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/zig.lua: -------------------------------------------------------------------------------- 1 | local repl = require("repl") 2 | 3 | vim.keymap.set("n", ",i", function() 4 | repl.toggle("bash", "below 15 split", false) 5 | end) 6 | 7 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/python.lua: -------------------------------------------------------------------------------- 1 | local repl = require("repl") 2 | local get_visual = require("util").get_visual 3 | 4 | vim.o.formatoptions="cqjr" 5 | -- vim.o.textwidth=80 6 | -------------------------------------------------------------------------------- /nixos/machines/indigo/home/default.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | imports = [ 5 | ../../../home/profiles/remote-gpg-agent.nix 6 | ]; 7 | } 8 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/lua.vim: -------------------------------------------------------------------------------- 1 | iab pdt print(debug.traceback()) 2 | iab ssu screen:snapshot_util() 3 | set path+=/home/simon/.config/nvim/lua 4 | set includeexpr=substitute(v:fname,'\\.','/','g') 5 | -------------------------------------------------------------------------------- /nvim/lua/plugins/hop.lua: -------------------------------------------------------------------------------- 1 | hop = require("hop") 2 | hop.setup() 3 | 4 | vim.cmd[[ 5 | nnoremap \ lua hop.hint_words() 6 | nnoremap \| lua hop.hint_char1() 7 | ]] 8 | -------------------------------------------------------------------------------- /nvim/luasnippets/sh.lua: -------------------------------------------------------------------------------- 1 | s_add("for", fmt([[ 2 | for {} in {}; do 3 | {} 4 | done 5 | ]], ins_generate())) 6 | s_add("if", fmt([[ 7 | if [ {} ]; then 8 | {} 9 | fi 10 | ]], ins_generate())) 11 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/asm.vim: -------------------------------------------------------------------------------- 1 | nnoremap :Break 2 | nnoremap :Clear 3 | nnoremap :Over 4 | nnoremap :Step 5 | nnoremap :Continue 6 | -------------------------------------------------------------------------------- /nvim/queries/css/folds.scm: -------------------------------------------------------------------------------- 1 | ( 2 | (block) @fold 3 | (#set! foldtext_start "{") 4 | (#set! foldtext_start_hl "@punctuation.bracket") 5 | (#set! foldtext_end "}") 6 | (#set! foldtext_end_hl "@punctuation.bracket") 7 | ) 8 | -------------------------------------------------------------------------------- /nvim/lua/plugins/catppuccin.lua: -------------------------------------------------------------------------------- 1 | -- Maybe work on this when I have time. 2 | 3 | -- local catppuccin = require("catppuccin") 4 | -- catppuccin.setup() 5 | -- 6 | -- vim.g.catppuccin_flavour = "frappe" 7 | -- vim.cmd[[colorscheme catppuccin]] 8 | -------------------------------------------------------------------------------- /solaar/rules.yaml: -------------------------------------------------------------------------------- 1 | %YAML 1.3 2 | --- 3 | - Key: [Back Button, pressed] 4 | - Set: 5 | - null 6 | - dpi 7 | - 600 8 | ... 9 | --- 10 | - Key: [Back Button, released] 11 | - Set: 12 | - null 13 | - dpi 14 | - 2800 15 | ... 16 | -------------------------------------------------------------------------------- /nixos/data/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pubkeys = import ./pubkeys.nix; 3 | network = import ./network.nix; 4 | ids = import ./ids.nix; 5 | ports = import ./ports.nix; 6 | gruvbox = import ./gruvbox.nix; 7 | ordering = import ./ordering.nix; 8 | } 9 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/cpp.vim: -------------------------------------------------------------------------------- 1 | setl ai cindent nosi 2 | " never indent on key-press!! 3 | setl cinkeys= 4 | setl indentexpr="" 5 | nnoremap i :ClangdSwitchSourceHeader 6 | set formatoptions+=c 7 | set formatoptions-=t 8 | set textwidth=80 9 | -------------------------------------------------------------------------------- /nvim/lua/plugins/dap_py.lua: -------------------------------------------------------------------------------- 1 | require('dap-python').setup('python') 2 | 3 | table.insert(require('dap').configurations.python, { 4 | type = 'python', 5 | request = 'launch', 6 | name = 'debug_libs', 7 | program = '${file}', 8 | justMyCode=false 9 | }) 10 | -------------------------------------------------------------------------------- /nixos/profiles/history.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | environment.variables = { 5 | HISTCONTROL="erasedups"; 6 | HISTSIZE=100000; 7 | SAVEHIST=100000; 8 | # hehe 9 | PROMPT_COMMAND="history -a;$PROMPT_COMMAND"; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /nixos/profiles/sway/zathura.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | home.shellAliases = { 5 | za = "zathura --fork"; 6 | }; 7 | programs.zathura = { 8 | enable = true; 9 | package = (pkgs.zathura.override { useMupdf = true; }); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /nixos/machines/carmine/profiles/ollama.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, data, ... }: 2 | 3 | { 4 | services.ollama = { 5 | enable = true; 6 | acceleration = "rocm"; 7 | package = pkgs-unstable.ollama-rocm; 8 | rocmOverrideGfx = "10.3.0"; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /nvim/luasnippets/rust.lua: -------------------------------------------------------------------------------- 1 | parse_add({trig = "fn"}, [[ 2 | /// $1 3 | fn $2($3) ${4:-> ${5:i32}} \{ 4 | $0 5 | \} 6 | ]]) 7 | ts_px_add({ 8 | trig = ".testing", 9 | matchTSNode = { 10 | query = [[(call_expression) @prefix]], 11 | query_lang = "rust", 12 | }, 13 | }, { t"hello" }) 14 | -------------------------------------------------------------------------------- /nvim/lua/plugins/dap_ui.lua: -------------------------------------------------------------------------------- 1 | require("dapui").setup({ 2 | layouts = { 3 | { 4 | elements = { 5 | "stacks", 6 | "scopes", 7 | "watches" 8 | }, 9 | size = 40, 10 | position = "tray" 11 | } 12 | }, 13 | }) 14 | 15 | vim.cmd([[command! DapUI :lua require("dapui").toggle()]]) 16 | -------------------------------------------------------------------------------- /nvim/lua/plugins/illuminate.lua: -------------------------------------------------------------------------------- 1 | vim.cmd("hi! link IlluminatedWordText CursorLine") 2 | vim.cmd("hi! link IlluminatedWordRead CursorLine") 3 | vim.cmd("hi! link IlluminatedWordWrite CursorLine") 4 | 5 | require("illuminate").configure({ 6 | providers = {"lsp", "treesitter"}, 7 | modes_allowlist = {"n"} 8 | }) 9 | -------------------------------------------------------------------------------- /nvim/luasnippets/matchconfig_lua.lua: -------------------------------------------------------------------------------- 1 | parse_add_auto("MC", "Matchconfig.") 2 | s_add("lvi", fmt([[ 3 | require("matchconfig.util.log").new("temp").error({}) 4 | ]], { 5 | c(1, { 6 | parse(nil, [["$1"]]), 7 | parse(nil, [["$1" .. vim.inspect({$1})]]), 8 | t"debug.traceback()", 9 | }) 10 | })) 11 | -------------------------------------------------------------------------------- /nvim/lua/ts-format/providers.lua: -------------------------------------------------------------------------------- 1 | -- collect functions for identifying structures in code. 2 | -- These may use manual parsing, or treesitter, but must return a common format: 3 | -- { 4 | -- type = [string], 5 | -- range = {from, to}, 6 | -- data = [type-specific] 7 | -- } 8 | 9 | return { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /nvim/lua/plugins/telescope.lua: -------------------------------------------------------------------------------- 1 | local builtin_pickers = require("telescope.builtin") 2 | 3 | vim.api.nvim_create_user_command("SP", builtin_pickers.lsp_document_symbols, {}) 4 | vim.api.nvim_set_keymap("n", "gb", "", { 5 | callback = function() 6 | builtin_pickers.buffers() 7 | end, 8 | silent = true 9 | }) 10 | -------------------------------------------------------------------------------- /nvim/lua/plugins/togglecomment.lua: -------------------------------------------------------------------------------- 1 | local tc = require("togglecomment") 2 | vim.keymap.set({"n","v"}, "d", tc.comment, {noremap = true, silent = true}) 3 | 4 | tc.log.set_loglevel("debug") 5 | require("togglecomment.dev") 6 | 7 | -- ---@type Togglecomment.Config 8 | -- local conf = {} 9 | 10 | -- tc.setup(conf) 11 | -------------------------------------------------------------------------------- /nixos/home/modules/sway.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | with lib; 4 | { 5 | options.l3mon.sway = { 6 | outputs = mkOption { 7 | type = lib.types.listOf (lib.types.str); 8 | default = []; 9 | description = '' 10 | Identifiers for all outputs. 11 | ''; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /nixos/packages/default.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | # special scope for my own packages. 3 | l3mon = { 4 | iosevka = prev.callPackage ./iosevka.nix { }; 5 | k-sway = prev.luajitPackages.callPackage ./k-sway.nix { }; 6 | k-stream = prev.luajitPackages.callPackage ./k-stream.nix { }; 7 | struct = prev.luajitPackages.callPackage ./struct.nix { }; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /nixos/profiles/bash-alias-completion.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, data, ... }: 2 | 3 | { 4 | # insert statements for complete-aliasing immediately after the aliases are 5 | # set up. 6 | programs.bash.interactiveShellInit = lib.mkOrder 1001 '' 7 | source ${pkgs.complete-alias}/bin/complete_alias 8 | complete -F _complete_alias "''${!BASH_ALIASES[@]}" 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /nixos/home/profiles/mpv.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | xdg.configFile."mpv/mpv.conf".text = '' 5 | vo=gpu-next 6 | gpu-api=vulkan 7 | hwdec=yes 8 | video-sync=display-resample 9 | ''; 10 | 11 | home.packages = with pkgs; [ 12 | mpv 13 | ]; 14 | 15 | wayland.windowManager.sway.extraConfig = '' 16 | bindsym XF86AudioPlay exec ${pkgs.mpc}/bin/mpc toggle 17 | ''; 18 | } 19 | -------------------------------------------------------------------------------- /nixos/machines/carmine/profiles/cachefilesd.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | services.cachefilesd = { 5 | enable = true; 6 | extraConfig = '' 7 | tag nvme 8 | brun 15% 9 | bcull 5% 10 | bstop 2% 11 | frun 10% 12 | fcull 5% 13 | fstop 2% 14 | ''; 15 | }; 16 | 17 | fileSystems.${config.services.cachefilesd.cacheDir} = { 18 | label = "CACHE"; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /nvim/lua/plugins/iron.lua: -------------------------------------------------------------------------------- 1 | local iron = require("iron") 2 | 3 | iron.core.add_repl_definitions{ 4 | julia = { 5 | my_julia = { 6 | command = {"julia", "-q", "-J/home/simon/.julia/sysimages/GLMakieImage.so"} 7 | } 8 | } 9 | } 10 | 11 | iron.core.set_config{ 12 | preferred = { 13 | julia = "my_julia" 14 | }, 15 | repl_open_cmd = "below 15 split" 16 | } 17 | 18 | vim.keymap.set("n", ",i", function() 19 | iron.core.repl_for(vim.bo.ft) 20 | end) 21 | -------------------------------------------------------------------------------- /nixos/data/ids.nix: -------------------------------------------------------------------------------- 1 | # store uid and gid for known users. 2 | { 3 | simon = 1000; 4 | christel = 1001; 5 | private = 1002; 6 | 7 | qbittorrent = 10001; 8 | media = 10002; 9 | rmfakecloud = 10003; 10 | samba = 10004; 11 | karakeep = 10005; 12 | readeck = 10006; 13 | mealie = 10007; 14 | pinchflat = 10008; 15 | kiwix = 10009; 16 | linkding = 10010; 17 | msmtp-user = 10011; 18 | zotero = 10012; 19 | } 20 | -------------------------------------------------------------------------------- /nixos/profiles/sway/copypaste/default.nix: -------------------------------------------------------------------------------- 1 | { config, l3lib, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | sway-copypaste = l3lib.writeLuajit "/bin/sway-copypaste" { 5 | libraries = [ 6 | pkgs.l3mon.k-sway 7 | ]; } (builtins.readFile ./sway-copypaste.lua); 8 | in { 9 | wayland.windowManager.sway.extraConfig = '' 10 | bindsym $mod+Shift+C exec ${sway-copypaste}/bin/sway-copypaste cut 11 | bindsym $mod+Shift+V exec ${sway-copypaste}/bin/sway-copypaste paste 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /nvim/queries/zig/folds.scm: -------------------------------------------------------------------------------- 1 | ; ([ 2 | ; (Block) 3 | ; (ContainerDecl) 4 | ; (SwitchExpr) 5 | ; (InitList) 6 | ; (AsmExpr) 7 | ; (ErrorSetDecl) 8 | ; (LINESTRING) 9 | ; ( 10 | ; [ 11 | ; (IfPrefix) 12 | ; (WhilePrefix) 13 | ; (ForPrefix) 14 | ; ] 15 | ; ) 16 | ; ] @fold 17 | ; 18 | ; (#set! foldtext_start "{") 19 | ; (#set! foldtext_start_hl "@punctuation.bracket") 20 | ; (#set! foldtext_end "}") 21 | ; (#set! foldtext_end_hl "@punctuation.bracket") 22 | ; ) 23 | -------------------------------------------------------------------------------- /nixos/home/profiles/pass.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | home.activation.myPass = lib.hm.dag.entryAfter ["writeBoundary"] '' 5 | if [ ! -d "${config.home.homeDirectory}/.password-store" ]; then 6 | run ${pkgs.systemd}/lib/systemd/systemd-networkd-wait-online 7 | run ${pkgs.git}/bin/git clone http://git.internal/simon/pass.git ${config.home.homeDirectory}/.password-store 8 | fi 9 | ''; 10 | 11 | home.packages = with pkgs; [ 12 | gnupg 13 | ]; 14 | } 15 | -------------------------------------------------------------------------------- /nvim/after/syntax/tex.vim: -------------------------------------------------------------------------------- 1 | if has('conceal') 2 | syn match texMathSymbol '\\{' contained conceal cchar={ 3 | syn match texMathSymbol '\\}' contained conceal cchar=} 4 | syn match texMathSymbol '\\setminus' contained conceal cchar=\ 5 | syn match texMathSymbol '\\mathcal{P}' contained conceal cchar=P 6 | syn match texMathSymbol '\\limits' contained conceal 7 | syn match texMathSymbol '\\cdot' contained conceal cchar=⋅ 8 | syn match texMathSymbol '\\displaystyle' contained conceal 9 | endif 10 | -------------------------------------------------------------------------------- /nvim/queries/luap/highlights.scm: -------------------------------------------------------------------------------- 1 | (character) @character 2 | (".") @punctuation.delimiter 3 | 4 | [ 5 | (anchor_end) 6 | "^" 7 | ] @punctuation.special 8 | 9 | [ 10 | "[" 11 | "]" 12 | "(" 13 | ")" 14 | ] @punctuation.bracket 15 | 16 | [ 17 | (zero_or_more) 18 | (shortest_zero_or_more) 19 | (one_or_more) 20 | (zero_or_one) 21 | ] @operator 22 | 23 | (class) @keyword 24 | 25 | (balanced_match 26 | first: (character) @parameter 27 | last: (character) @parameter 28 | ) 29 | -------------------------------------------------------------------------------- /nvim/lua/plugins/lualine.lua: -------------------------------------------------------------------------------- 1 | require('lualine').setup { 2 | options = { 3 | icons_enabled = false, 4 | theme = 'gruvbox', 5 | always_divide_middle = true, 6 | globalstatus = false, 7 | }, 8 | sections = { 9 | lualine_a = {'filename'}, 10 | lualine_z = {'location'} 11 | }, 12 | inactive_sections = { 13 | lualine_a = {"filename"}, 14 | lualine_b = {}, 15 | lualine_c = {'filename'}, 16 | lualine_x = {'location'}, 17 | lualine_y = {}, 18 | lualine_z = {} 19 | }, 20 | tabline = {}, 21 | extensions = {} 22 | } 23 | -------------------------------------------------------------------------------- /nixos/machines/carmine/profiles/mympd.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | machine_lan_address = data.network.lan.peers.${machine}.address; 5 | port = data.ports.mympd; 6 | in { 7 | services.mympd = { 8 | enable = true; 9 | settings = { 10 | http_port = lib.strings.toInt port; 11 | }; 12 | }; 13 | 14 | services.caddy.extraConfig = '' 15 | http://mympd, http://mympd.internal, http://mympd.${machine} { 16 | reverse_proxy http://${machine_lan_address}:${port} 17 | } 18 | ''; 19 | } 20 | -------------------------------------------------------------------------------- /nvim/lua/plugins/flatten.lua: -------------------------------------------------------------------------------- 1 | require("flatten").setup{ 2 | window = { 3 | -- open = function() 4 | -- -- vim.schedule(function() 5 | -- -- print("lvfdw ", last_valid_file_display_window) 6 | -- -- end) 7 | -- return vim.api.nvim_win_get_buf(last_valid_file_display_window), last_valid_file_display_window 8 | -- end 9 | -- open = "alternate" 10 | open = "smart" 11 | }, 12 | block_for = { 13 | conf = true 14 | }, 15 | -- fix for lua-dap/osv. 16 | -- https://github.com/willothy/flatten.nvim/issues/41 17 | nest_if_no_args = true 18 | } 19 | -------------------------------------------------------------------------------- /nvim/lua/plugins/da_lua.lua: -------------------------------------------------------------------------------- 1 | local dap = require("dap") 2 | dap.configurations.lua = { 3 | { 4 | type = 'nlua', 5 | request = 'attach', 6 | name = "Attach to running Neovim instance", 7 | host = "127.0.0.1", 8 | port = function() 9 | local val = tonumber(vim.fn.input('Port: ')) 10 | assert(val, "Please provide a port number") 11 | return val 12 | end, 13 | } 14 | } 15 | 16 | dap.adapters.nlua = function(callback, config) 17 | callback({ type = 'server', host = config.host, port = config.port }) 18 | end 19 | 20 | vim.cmd [[command! DLL :lua require"osv".launch()]] 21 | -------------------------------------------------------------------------------- /nixos/machines/cobalt/home/profiles/jellyfin-mpv-cred.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | xdg.configFile."jellyfin-mpv-shim/cred.json".text = '' 5 | [{"address": "http://jellyfin.internal:80", "Name": "indigo", "Id": "19115077000e43dca1172812a4f96c59", "Version": "10.10.7", "DateLastAccessed": "2025-05-25T17:26:04Z", "UserId":"db65cdf9d37b4d7cb0fdfe39058c5657", "AccessToken": "c04fbd73e5514e698fa95b30fc1ded11", "Users": [{"Id": "db65cdf9d37b4d7cb0fdfe39058c5657", "IsSignedInOffline": true}], "uuid": "a364a772-5157-4c40-9b9f-642e78724c94", "username": "simon", "connected": true}] 6 | ''; 7 | } 8 | -------------------------------------------------------------------------------- /nvim/luasnippets/nix.lua: -------------------------------------------------------------------------------- 1 | parse_add("$", "\\${$1}") 2 | parse_add("prof", [[ 3 | { config, lib, pkgs, machine, data, ... }: 4 | 5 | { 6 | $1 7 | } 8 | ]]) 9 | s_add("wsa", fmta([[ 10 | .writeShellApplication { 11 | name = ""; 12 | text = '' 13 | 14 | ''; 15 | } 16 | ]], { 17 | pkgs = i(1, "pkgs", {key = "pkgs"}), 18 | name = i(2, "name"), 19 | rti = c(3, { 20 | t"", 21 | fmta("\n\truntimeInputs = with ; [];", { 22 | pkgsrep = l(l._1, {k"pkgs"}), 23 | pkgs = i(1) 24 | }, {trim_empty = false, dedent = false}), 25 | }), 26 | txt = i(4) 27 | })) 28 | -------------------------------------------------------------------------------- /nixos/profiles/unibonn.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | services.openvpn.servers = { 5 | unibonn = {config = "config /var/secrets/unibonn.conf";}; 6 | }; 7 | # log in once with root! 8 | fileSystems."/mnt/wildhorn" = { 9 | device = "katz@wildhorn.cs.uni-bonn.de:/"; 10 | fsType = "sshfs"; 11 | # only mount on-demand. 12 | options = [ "noauto" "nodev" "noatime" "allow_other" "ro" "IdentityFile=/var/secrets/id_rsa" "uid=1000" "gid=1000" "x-systemd-requires=openvpn-unibonn.service" ]; 13 | }; 14 | 15 | systemd.tmpfiles.rules = [ 16 | "d /mnt/wildhorn" 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /nixos/machines/carmine/home/profiles/jellyfin-conf.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | # maybe have to update this? 5 | xdg.configFile."jellyfin-mpv-shim/cred.json".text = '' 6 | [{"address": "http://jellyfin.internal", "Name": "indigo", "Id": "19115077000e43dca1172812a4f96c59", "Version": "10.10.7", "DateLastAccessed": "2025-05-31T23:00:28Z", "UserId": "db65cdf9d37b4d7cb0fdfe39058c5657", "AccessToken": "6f98461806084700b59e58475c2cd698", "Users": [{"Id": "db65cdf9d37b4d7cb0fdfe39058c5657", "IsSignedInOffline": true}], "uuid": "ef4258af-90d9-4f29-9219-f604c9ab6ba7", "username": "simon", "connected": true}] 7 | ''; 8 | } 9 | -------------------------------------------------------------------------------- /nixos/profiles/nfs.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | services.nfs.server.enable = true; 5 | services.nfs.settings.nfsd = { 6 | rdma = true; 7 | vers3 = false; 8 | vers4 = true; 9 | "vers4.0" = false; 10 | "vers4.1" = false; 11 | "vers4.2" = true; 12 | }; 13 | 14 | # mkBefore not strictly necessary, but seems nice to put the root at the top 15 | # :) 16 | services.nfs.server.exports = lib.mkBefore ( 17 | "/srv/nfs " + 18 | "192.168.178.0/24(rw,fsid=0,no_subtree_check,no_root_squash) " + 19 | "10.0.0.0/24(rw,fsid=0,no_subtree_check,no_root_squash) " 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /nixos/home/profiles/tev.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/ImageViewer.cpp b/src/ImageViewer.cpp 2 | index e208d0e..0c419cf 100644 3 | --- a/src/ImageViewer.cpp 4 | +++ b/src/ImageViewer.cpp 5 | @@ -1225,9 +1225,9 @@ void ImageViewer::insertImage(shared_ptr image, size_t index, bool shallS 6 | // First image got added, let's select it. 7 | if ((index == 0 && mImages.size() == 1) || shallSelect) { 8 | selectImage(image); 9 | - if (!isMaximized()) { 10 | - resizeToFit(sizeToFitImage(image)); 11 | - } 12 | + // if (!isMaximized()) { 13 | + // resizeToFit(sizeToFitImage(image)); 14 | + // } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nixos/profiles/wakeonlan.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | lan = data.network.lan; 5 | in { 6 | environment.systemPackages = [ 7 | (pkgs.writeShellApplication { 8 | name = "wake"; 9 | runtimeInputs = [ pkgs.wakeonlan ]; 10 | text = '' 11 | case "$1" in 12 | '' + (lib.attrsets.foldlAttrs (acc: k: v: acc + (if v ? "phys_mac" then '' 13 | ${k}) 14 | wakeonlan ${v.phys_mac} 15 | ;; 16 | '' else "") ) "" lan.peers) + '' 17 | *) 18 | printf "Pass a valid machine-name!" 19 | esac 20 | ''; 21 | }) 22 | ]; 23 | } 24 | -------------------------------------------------------------------------------- /nixos/home/profiles/remote-gpg-agent.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | gpgdir = "/run/user/1000/gnupg"; 5 | in { 6 | home.sessionVariables = { 7 | GNUPGHOME = gpgdir; 8 | }; 9 | 10 | home.activation.myGPG = lib.hm.dag.entryAfter ["writeBoundary"] '' 11 | run mkdir -p -m 700 ${gpgdir}/ 12 | run mkdir -p -m 700 ${gpgdir}/d.cpwgsr1yrynbs7nu683b3gty 13 | run echo 'no-autostart' > ${gpgdir}/gpg.conf 14 | GNUPGHOME=${gpgdir} run ${pkgs.gnupg}/bin/gpg --import ${l3lib.secret "gpg-simon@l3mon4.de.pub"} 15 | GNUPGHOME=${gpgdir} run ${pkgs.gnupg}/bin/gpg --import ${l3lib.secret "gpg-simljk@outlook.de.pub"} 16 | ''; 17 | } 18 | -------------------------------------------------------------------------------- /nvim/lua/plugins/comment.lua: -------------------------------------------------------------------------------- 1 | require("Comment").setup{ 2 | toggler = { 3 | block = 'bb', 4 | line = 'cc' 5 | }, 6 | opleader = { 7 | line = 'c', 8 | block = 'b' 9 | }, 10 | } 11 | 12 | 13 | local config = require("Comment.config"):get() 14 | 15 | vim.keymap.set("n", "o", function() 16 | require("Comment.api").insert.linewise.below(config) 17 | end, {noremap = true}) 18 | vim.keymap.set("n", "O", function() 19 | require("Comment.api").insert.linewise.above(config) 20 | end, {noremap = true}) 21 | vim.keymap.set("n", "A", function() 22 | require("Comment.api").insert.linewise.eol(config) 23 | end, {noremap = true}) 24 | -------------------------------------------------------------------------------- /nixos/packages/iosevka.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | iosevka, 4 | fetchFromGithub, 5 | buildNpmPackage, 6 | writeTextFile 7 | }: 8 | 9 | iosevka.override { 10 | privateBuildPlan = '' 11 | [buildPlans.Iosevka-l3mon] 12 | family = "iosevka" 13 | spacing = "term" 14 | serifs = "sans" 15 | noCvSs = true 16 | 17 | [buildPlans.Iosevka-l3mon.weights.Regular] 18 | shape = 400 19 | menu = 400 20 | css = 400 21 | 22 | [buildPlans.Iosevka-l3mon.variants.design] 23 | asterisk = "hex-low" 24 | dollar = "open" 25 | cent = "open" 26 | percent = "rings-continuous-slash" 27 | number-sign = "slanted" 28 | ''; 29 | set = "-l3mon"; 30 | } 31 | -------------------------------------------------------------------------------- /nvim/luasnippets/glsl.lua: -------------------------------------------------------------------------------- 1 | local function capture_insert(_, snip, _, capture_indx, pre_text, post_text) 2 | return sn(nil, {i(1, {(pre_text or "") .. snip.captures[capture_indx] .. (post_text or "")})}) 3 | end 4 | 5 | s_add({trig = "for(%w+)", wordTrig = true, regTrig = true}, { 6 | t({"for ("}), d(1, capture_insert, {}, { user_args = {1, "int ", " = 0"}}), t({"; "}), 7 | f(function(_, snip) return {snip.captures[1]} end, {}), c(2, {sn(nil, {t({" != "}), i(1)}), i(nil)}), t({"; "}), 8 | d(3, capture_insert, {}, {user_args = {1, "++"}}), t({")", "\t"}), i(0) 9 | }) 10 | parse_add("hguard", [[ 11 | #ifndef $1 12 | #define $1 13 | 14 | ${2:$SELECT_DEDENT} 15 | 16 | #endif 17 | ]]) 18 | -------------------------------------------------------------------------------- /nvim/lua/modes/upcase.lua: -------------------------------------------------------------------------------- 1 | local libmodal = require("libmodal") 2 | 3 | local alphabet = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"} 4 | 5 | local keymaps = {} 6 | 7 | -- replace lowercase-letters with uppercase-variants. 8 | for _, char in ipairs(alphabet) do 9 | keymaps[char] = { rhs = char:upper()} 10 | end 11 | -- replace space with underscore. 12 | keymaps[""] = {rhs = "_"} 13 | 14 | local layer 15 | 16 | keymaps[""] = {rhs = function() 17 | layer:exit() 18 | end} 19 | layer = libmodal.layer.new({ i = keymaps }) 20 | 21 | vim.keymap.set("i", "", function() 22 | layer:enter() 23 | end) 24 | -------------------------------------------------------------------------------- /nvim/luasnippets/help.lua: -------------------------------------------------------------------------------- 1 | local function neg(fn, ...) 2 | return not fn(...) 3 | end 4 | 5 | local function even_count(c) 6 | local line = vim.api.nvim_get_current_line() 7 | local _, ct = string.gsub(line, c, '') 8 | return ct % 2 == 0 9 | end 10 | 11 | local function part(func, ...) 12 | local args = {...} 13 | return function() return func(unpack(args)) end 14 | end 15 | 16 | s_add({trig="con", wordTrig=true}, { 17 | i(1), 18 | f(function(args) return {" "..string.rep(".", 80-(#args[1][1]+#args[2][1]+2+2)).." "} end, {1, 2}), 19 | t({"|"}), 20 | i(2), 21 | t({"|"}), 22 | i(0) 23 | }) 24 | s_add({trig="*", wordTrig=true}, { 25 | t({"*"}), 26 | i(1), 27 | t({"*"}), 28 | i(0) 29 | }, { cond = part(neg, even_count, '%*') }) 30 | -------------------------------------------------------------------------------- /nixos/machines/cobalt/home/default.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, nur, ... }: 2 | 3 | { 4 | imports = [ 5 | ./profiles/sway-io.nix 6 | ./profiles/jellyfin-mpv-cred.nix 7 | ]; 8 | 9 | l3mon.sway = { 10 | workrooms.enable = false; 11 | outputs = [ "eDP-1" ]; 12 | }; 13 | l3mon.sway-netns.wg_rec_de = { 14 | enable = true; 15 | openPrivateWindow = true; 16 | netnsKey = "d"; 17 | landingPage = "https://mullvad.net/en/check"; 18 | firefoxProfileSettings = { 19 | id = 1; 20 | extensions.packages = with nur.repos.rycee.firefox-addons; [ 21 | ublock-origin 22 | passff 23 | ]; 24 | }; 25 | }; 26 | 27 | home.packages = with pkgs; [ 28 | brightnessctl 29 | ]; 30 | } 31 | -------------------------------------------------------------------------------- /nvim/queries/markdown/folds.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (indented_code_block) 3 | ] @fold 4 | 5 | ((fenced_code_block 6 | . 7 | (fenced_code_block_delimiter) @from . 8 | (info_string)? @from 9 | (fenced_code_block_delimiter) @to . 10 | ) 11 | ; make sure to cover the entire line. 12 | (#make-range-extended! "fold" @from "end" 0 1 @to "end" 0 0) 13 | (#set! foldtext_start "") 14 | (#set! foldtext_start_hl "") 15 | (#set! foldtext_end "```") 16 | (#set! foldtext_end_hl "@punctuation.delimiter") 17 | ) 18 | 19 | ( (section 20 | (atx_heading heading_content: (_) @heading ) ) @section 21 | ; end of section is one line to high, I think.. just move endpoint to end of previous line 22 | (#make-range-extended! "fold" @heading "end" 0 0 @section "end" -1 1000) 23 | ) 24 | -------------------------------------------------------------------------------- /nvim/luasnippets/PKGBUILD.lua: -------------------------------------------------------------------------------- 1 | parse_add("skeleton", [[ 2 | pkgname=${1:name, or array (in parens) of names} 3 | pkgver=1 4 | pkgrel=1 5 | pkgdesc='${2:succinct description}' 6 | arch=('any') 7 | source=('local-file') 8 | sha256sums=('SKIP') 9 | install=local-file 10 | 11 | package() { 12 | install='install-server' 13 | depends=('l3mon-nfs-server' 'l3mon-nginx') 14 | 15 | cd \$srcdir 16 | install -dm644 "\${pkgdir}"/some/dir/ 17 | install -Dm644 local-file "\${pkgdir}"/path/to/some/file 18 | 19 | install -Dm644 backup.sh "\$pkgdir"/home/simon/.local/share/l3mon-backup/backup-hooks/hooktype/pkgname.sh 20 | install -Dm644 forget.sh "\$pkgdir"/home/simon/.local/share/l3mon-backup/forget-hooks/pkgname.sh 21 | 22 | chown -R simon:simon "\$pkgdir"/home/simon 23 | } 24 | ]]) 25 | -------------------------------------------------------------------------------- /nixos/machines/indigo/profiles/nvidia.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | # https://nixos.wiki/wiki/Nvidia 5 | hardware.nvidia = { 6 | modesetting.enable = true; 7 | powerManagement.enable = false; 8 | # load even if no graphical session. 9 | nvidiaPersistenced = true; 10 | # newer open driver only supports <= turing(20xx) 11 | open = false; 12 | package = config.boot.kernelPackages.nvidiaPackages.stable; 13 | }; 14 | # for mesa, which provides hardware acceleration for video encoding (I think). 15 | hardware.graphics.enable = true; 16 | # also necessary for transcoding. 17 | services.xserver.videoDrivers = [ "nvidia" ]; 18 | 19 | environment.systemPackages = with pkgs; [ 20 | nvtopPackages.nvidia 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /nixos/packages/k-stream.nix: -------------------------------------------------------------------------------- 1 | { buildLuarocksPackage, fetchFromGitHub, fetchurl, luaAtLeast, luaOlder }: 2 | buildLuarocksPackage { 3 | pname = "k-stream"; 4 | version = "0.1-2"; 5 | knownRockspec = (fetchurl { 6 | url = "https://luarocks.org/k-stream-0.1-2.rockspec"; 7 | sha256 = "1b060m01438ybgdm2r1csxpxjmmrsp9blby94rlfg90shjlqi3qq"; 8 | }).outPath; 9 | src = fetchFromGitHub { 10 | owner = "norcalli"; 11 | repo = "lua-stream"; 12 | rev = "k-stream-v0.1-2"; 13 | hash = "sha256-xC8cfxEy3wfJNKLRiLqsOmYn8ReeBSX7/Ju1oR/mjgs="; 14 | }; 15 | 16 | disabled = luaOlder "5.1" || luaAtLeast "5.4"; 17 | 18 | meta = { 19 | homepage = "https://github.com/norcalli/lua-stream.git"; 20 | description = "No summary"; 21 | license.fullName = "MIT"; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /nixos/profiles/no_sub_langs.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/pinchflat/downloading/download_option_builder.ex b/lib/pinchflat/downloading/download_option_builder.ex 2 | index ab2b56a..11b1444 100644 3 | --- a/lib/pinchflat/downloading/download_option_builder.ex 4 | +++ b/lib/pinchflat/downloading/download_option_builder.ex 5 | @@ -97,12 +97,6 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do 6 | {{:embed_subs, true}, %{preferred_resolution: pr}} when pr != :audio -> 7 | acc ++ [:embed_subs] 8 | 9 | - {{:sub_langs, sub_langs}, %{download_subs: true}} -> 10 | - acc ++ [sub_langs: sub_langs] 11 | - 12 | - {{:sub_langs, sub_langs}, %{embed_subs: true}} -> 13 | - acc ++ [sub_langs: sub_langs] 14 | - 15 | _ -> 16 | acc 17 | end 18 | -------------------------------------------------------------------------------- /nvim/luasnippets/julia.lua: -------------------------------------------------------------------------------- 1 | s_add("fn", fmt([[ 2 | function{}({}) 3 | {} 4 | end 5 | ]], ins_generate())) 6 | s_add("f", fmt([[{}({}) = {}]], ins_generate())) 7 | parse_add("if", "if $1\n\t$2\nend") 8 | s_add("for", fmt([[ 9 | for {} 10 | {} 11 | end 12 | ]], ins_generate())) 13 | parse_add("d", "display(${1:$LS_SELECT_DEDENT})") 14 | -- parse_add_auto("theta", "θ") 15 | -- parse_add_auto("phi", "φ") 16 | -- parse_add_auto("alpha", "α") 17 | -- parse_add_auto("pi", "π") 18 | -- parse_add_auto("eta", "η") 19 | parse_add("xor", "⊻") 20 | parse_add("struct", [[ 21 | struct $1 22 | $2 23 | end 24 | ]]) 25 | 26 | -- parse_add("p", "println(\"$1\", $2)") 27 | s_add("p", fmt([[println("{}", {})]], {i(1, "", {key="i1"}), dl(2, l._1:gsub(" $", ""), {k("i1")})})) 28 | 29 | parse_add("lus", [[ 30 | include("$1.jl") 31 | using .$1 32 | ]]) 33 | -------------------------------------------------------------------------------- /nixos/machines/carmine/profiles/remarkable.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, data, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; [ 5 | pkgs-unstable.rmapi 6 | ]; 7 | environment.variables = { 8 | RMAPI_HOST = "http://rmfakecloud.internal"; 9 | }; 10 | 11 | # home-manager.sharedModules = [ 12 | # ( 13 | # { config, lib, pkgs, machine, data, ... }: { 14 | # home.packages = with pkgs; [ 15 | # (pkgs-unstable.rmapi.overrideAttrs (old: { 16 | # src = fetchFromGitHub { 17 | # owner = "ddvk"; 18 | # repo = "rmapi"; 19 | # rev = "4988805"; 20 | # sha256 = "sha256-xB/xQcXU5Nja6YAG5a2NrYFflt1dQVT40doVQDCcFOs="; 21 | # }; 22 | # })) 23 | # ]; 24 | # } 25 | # ) 26 | # ]; 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dotfiles 2 | 3 | Contains configurations for various programs, split up into subdirectories. 4 | Generally, these are symlinked into place by nixOS home-manager (or are 5 | maintained in home-manager itself). 6 | 7 | # TODO 8 | * neovim: all packages needed for nvim-internal stuff (eg. zig for compiling 9 | ts-grammars) is also accessible in any shell spawneed by it. I don't really 10 | like that, I should only be able to access compilers etc. when in a devShell 11 | or when it's pulled in temporarily via `nix-shell -p ...`. 12 | A possible solution for binaries I invoke manually is to put their paths into 13 | some file, like 14 | ```lua 15 | return { 16 | zig = "/nix/store/...zig-x.y.z", 17 | ... 18 | } 19 | ``` 20 | and then don't rely on PATH being correct, but that does not work for plugins 21 | that need some binary :/ 22 | -------------------------------------------------------------------------------- /nvim/lua/plugins/luasnip/repeat_integration.lua: -------------------------------------------------------------------------------- 1 | _G.expand_func = ls.snip_expand 2 | 3 | ls.snip_expand = function(snip, expand_params) 4 | _G.expand_snip = snip 5 | _G.expand_opts = expand_params 6 | vim.fn.feedkeys(vim.api.nvim_replace_termcodes('repeatable-snip-expand', true, true, true), '') 7 | end 8 | 9 | _G.repeatable_expand = function() 10 | print("here!!!") 11 | -- actually expands the snippet. 12 | _G.expand_func(_G.expand_snip, _G.expand_opts) 13 | 14 | -- prevent clearing text on repeated calls. 15 | _G.expand_opts.clear_region = nil 16 | _G.expand_opts.pos = nil 17 | 18 | vim.cmd[[silent! call repeat#set("\repeatable-snip-expand", -1)]] 19 | end 20 | 21 | vim.cmd[[ 22 | noremap repeatable-snip-expand lua _G.repeatable_expand() 23 | noremap! repeatable-snip-expand lua _G.repeatable_expand() 24 | ]] 25 | -------------------------------------------------------------------------------- /nixos/profiles/opus-fs.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, inputs, system, ... }: 2 | 3 | let 4 | target_dir = "/srv/media/audio/lossy"; 5 | in { 6 | # for opus-fs. 7 | programs.fuse.userAllowOther = true; 8 | 9 | systemd.services.opus-fs = { 10 | enable = true; 11 | unitConfig.RequiresMountsFor = [ target_dir ]; 12 | serviceConfig = { 13 | Type = "exec"; 14 | User = "simon"; 15 | Group = "simon"; 16 | }; 17 | path = [ inputs.dirmap.packages.${system}.default ]; 18 | script = '' 19 | mkdir -p ${target_dir} 20 | chown simon:media ${target_dir} 21 | # run in foreground, need direct_io due to unknown/incorrect st_size. 22 | opus-fs /srv/media/audio/original ${target_dir} -f -o direct_io,ro,allow_other 23 | ''; 24 | preStop = '' 25 | ${config.security.wrapperDir}/fusermount -u ${target_dir} 26 | ''; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /nvim/queries/python/folds.scm: -------------------------------------------------------------------------------- 1 | ; [ 2 | ; (function_definition) 3 | ; (class_definition) 4 | ; (while_statement) 5 | ; (for_statement) 6 | ; (if_statement) 7 | ; (with_statement) 8 | ; (try_statement) 9 | ; (match_statement) 10 | ; (import_from_statement) 11 | ; (parameters) 12 | ; (argument_list) 13 | ; (parenthesized_expression) 14 | ; (generator_expression) 15 | ; (list_comprehension) 16 | ; (set_comprehension) 17 | ; (dictionary_comprehension) 18 | ; (tuple) 19 | ; (list) 20 | ; (set) 21 | ; (dictionary) 22 | ; (string) 23 | ; ] @fold 24 | 25 | ( 26 | (class_definition) @class 27 | (#make-range-extended! "fold" @class "start" 0 300 @class "end" 0 0) 28 | ) 29 | 30 | ( 31 | (function_definition (parameters) @parms) @fn 32 | (#make-range-extended! "fold" @parms "end" 0 300 @fn "end" 0 0) 33 | ) 34 | 35 | [ 36 | (import_statement) 37 | (import_from_statement) 38 | ]+ @fold 39 | -------------------------------------------------------------------------------- /nvim/filetype.lua: -------------------------------------------------------------------------------- 1 | vim.filetype.add({ 2 | extension = { 3 | alpha = "alpha", 4 | comp = "glsl", 5 | frag = "glsl", 6 | gs = "glsl", 7 | plt = "gnuplot", 8 | sc = "cpp", 9 | tpp = "cpp", 10 | ["code-snippets"] = "json", 11 | zon = "zig", 12 | ush = "c", 13 | usf = "c", 14 | nftables = "nftables" 15 | }, 16 | filename = { 17 | PKGBUILD = "PKGBUILD", 18 | ["/home/simon/.config/waybar/config"] = "json" 19 | }, 20 | pattern = { 21 | [".git/hooks/.*"] = "bash", 22 | ["/home/simon/.config/sway/.*"] = "swayconfig", 23 | -- from opening current line in editor, via bash. 24 | ["/tmp/bash%-fc%..*"] = "bash", 25 | ['.*'] = { 26 | -- priority less than all other rules, but higher than defaults. 27 | priority = -math.huge, 28 | function(_, bufnr) 29 | local content = vim.api.nvim_buf_get_lines(bufnr, 1, 2, false)[1] 30 | if content == "[Unit]" then 31 | return "systemd" 32 | end 33 | end 34 | } 35 | }, 36 | }) 37 | -------------------------------------------------------------------------------- /nvim/luasnippets/cpp_mitsuba.lua: -------------------------------------------------------------------------------- 1 | parse_add_auto("v3", "Vector3f") 2 | parse_add_auto("unus", "UNUSED($1)") 3 | parse_add_auto("ttf", "template") 4 | parse_add_auto("tts", "template") 5 | parse_add("mv", "MI_VARIANT") 6 | parse_add({trig=".fs", wordTrig=false}, "") 7 | parse_add("isnan", [[dr::any_or(dr::isnan($1))]]) 8 | parse_add("ifj", [[ 9 | if constexpr (${1|!,|}dr::is_jit_v) 10 | $2 11 | ]]) 12 | parse_add("ifp", [[ 13 | if constexpr (${1|!,|}is_polarized_v) 14 | $2 15 | ]]) 16 | parse_add("drif", [[ 17 | if (dr::any_or($1)) 18 | $2 19 | ]]) 20 | ts_px_add({ 21 | trig = ".a", 22 | matchTSNode = { 23 | query = [[ 24 | [ 25 | (call_expression) 26 | (identifier) 27 | ] 28 | @prefix ]], 29 | query_lang = "cpp", 30 | select = "longest" 31 | }, 32 | reparseBuffer = "live" 33 | }, { 34 | l("dr::abs(" .. l.LS_TSMATCH .. ")") 35 | }) 36 | -------------------------------------------------------------------------------- /nixos/lib.nix: -------------------------------------------------------------------------------- 1 | {pkgs}: rec { 2 | assertSecret = sname: '' 3 | if [ ! -f /var/secrets/${sname} ]; then 4 | echo ASSERT FAILED: Secret ${sname} is missing! 5 | exit 1 6 | fi 7 | ''; 8 | secret = (sname: "/var/secrets/${sname}"); 9 | 10 | # 11 | # lua-write from nixpkgs does not respect `libraries`. 12 | # 13 | makeLuaWriter = 14 | lua: luaPackages: buildLuaPackages: name: 15 | { 16 | libraries ? [ ], 17 | ... 18 | }@args: 19 | pkgs.writers.makeScriptWriter ( 20 | (builtins.removeAttrs args [ "libraries" ]) 21 | // { 22 | interpreter = (if libraries == [] then lua.interpreter else (lua.withPackages (ps: libraries)).interpreter); 23 | check = ( 24 | pkgs.writers.writeDash "luacheck.sh" '' 25 | exec ${buildLuaPackages.luacheck}/bin/luacheck "$1" 26 | '' 27 | ); 28 | } 29 | ) name; 30 | 31 | writeLuajit = makeLuaWriter pkgs.luajit pkgs.luajitPackages pkgs.buildPackages.luajitPackages; 32 | } 33 | -------------------------------------------------------------------------------- /nixos/data/pubkeys.nix: -------------------------------------------------------------------------------- 1 | rec { 2 | simon-ssh = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC+bbq8R77Io4jzi5O0nTWHok6AwOM9MboGerFyxVyzxSXzGWY4ODwzgKjdLgEAYX7CbG9pFSnvqwhlKOWcy7Rg7ocV9R9t1zh140GDKzJpf/ZwlwWrCp0JkPDyQzps154cZon0GL+Qp/PjVUIyiaFhI8bLnUR4QVV/Z7iuYniPVWjMdJMDU2C4DDoW9LcSjjJssjJiHxyizFkUWo9YOKqGfoVmwd+eQoVxCDfYbBwv+h/g5K33Kq904dovEU5dU6LrpdvEw4oM9fGl8PwCNcJp7mHuv/FBEPJPDKs+MA4ORoCwWGYLctlzktrBJ9bAUTWbgnXN7pJz7th9y0G1HSLzAlWpMjp7NAQDa3DKK5sKCsEyqlh4La+lbKNsB/vHGixHIeD9JSD2nmZVx0bk2UTJwnGPZSGtQv1ZGuhw1mQkRXsNCmQvWagU/1YS8/SsnWko3GWXOpeC6alieFZlltV8AMaJiY1Tm5xOWm27p6U5M326vdhoDV06e/X+BJTWGi8= simon@ArchPC"; 3 | peercache-raw = "dmRV8DJW4a9BBGtzXO2bYAfZAU5l7utBg4n4fTkfSRE="; 4 | peercache-carmine = "cache.carmine.internal:${peercache-raw}"; 5 | peercache-indigo = "cache.indigo.internal:${peercache-raw}"; 6 | cachix-community = "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="; 7 | nixos-org = "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="; 8 | ncps = "ncps.internal:qgVbbSb3MWw/LPQopde7q8WmU+luM5wSC0hOWiQSp/0="; 9 | } 10 | -------------------------------------------------------------------------------- /nvim/lua/sighelp/snippet.lua: -------------------------------------------------------------------------------- 1 | local util = require("sighelp.util") 2 | 3 | local ls = require("luasnip") 4 | ls.setup_snip_env() 5 | 6 | local function sig_snipnodes(signature) 7 | local nodes = {} 8 | local indx = 1 9 | for _, param in ipairs(signature.parameters) do 10 | if param:match("pNext") then 11 | goto continue 12 | end 13 | vim.list_extend(nodes, { 14 | t"\t", i(indx, param), t{",", ""} 15 | }) 16 | indx = indx + 1 17 | ::continue:: 18 | end 19 | nodes[#nodes] = t{"", ""} 20 | 21 | return sn(nil, nodes) 22 | end 23 | 24 | local function handler(err, res, _, _) 25 | local sig_res = util.normalize(err, res) 26 | if not sig_res then 27 | vim.notify("no sighelp here", vim.log.levels.WARN) 28 | end 29 | 30 | local choices = {} 31 | for i, sig in ipairs(sig_res.signatures) do 32 | choices[i] = sig_snipnodes(sig) 33 | end 34 | ls.snip_expand(s("", { 35 | t{"", ""}, c(1, choices), t")" 36 | })) 37 | end 38 | 39 | local function trigger() 40 | util.request_sighelp(handler) 41 | end 42 | 43 | vim.keymap.set("i", "", trigger) 44 | -------------------------------------------------------------------------------- /nixos/machines/cobalt/home/profiles/sway-io.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | wayland.windowManager.sway.extraConfig = '' 5 | input 1133:50504:Logitech_USB_Receiver_Mouse { 6 | pointer_accel -1 7 | } 8 | 9 | input 1240:60205:liliums_Lily58_Mouse { 10 | pointer_accel 1 11 | scroll_factor 0.06 12 | } 13 | 14 | input 1240:60205:liliums_Lily58 { 15 | repeat_delay 120 16 | repeat_rate 100 17 | xkb_layout "us" 18 | xkb_variant "altgr-intl" 19 | } 20 | 21 | input 1:1:AT_Translated_Set_2_keyboard { 22 | repeat_delay 120 23 | repeat_rate 100 24 | xkb_layout "de" 25 | # xkb_variant "altgr-intl" 26 | } 27 | 28 | output "AU Optronics 0x38ED Unknown" transform 0 mode 1920x1080@60.096Hz position 0,0 29 | 30 | mode "power" { 31 | bindsym --no-repeat d output DP-1 dpms toggle; mode "default" 32 | bindsym --no-repeat h output HDMI-A-1 dpms toggle; mode "default" 33 | 34 | bindsym --no-repeat b output DP-1 dpms toggle; output HDMI-A-1 dpms toggle; mode "default" 35 | } 36 | ''; 37 | } 38 | -------------------------------------------------------------------------------- /nixos/packages/struct.nix: -------------------------------------------------------------------------------- 1 | { buildLuarocksPackage, fetchurl, luaAtLeast, luaOlder }: 2 | buildLuarocksPackage { 3 | pname = "struct"; 4 | version = "1.4-1"; 5 | knownRockspec = (fetchurl { 6 | url = "mirror://luarocks/struct-1.4-1.rockspec"; 7 | sha256 = "142zbyzqcqmhq10xwnv6h4h5f46gbkbvdfsg9avi8gc3l70y235h"; 8 | }).outPath; 9 | src = fetchurl { 10 | url = "http://www.inf.puc-rio.br/~roberto/struct/struct-0.2.tar.gz"; 11 | sha256 = "19d72xlflyxs4dpk3d6wafphs82iaql62ngpfflp9b3lkygiy7f7"; 12 | }; 13 | # nix complains if unpacking does not produce a directory => just unpack into 14 | # some directory and adjust all paths. 15 | unpackPhase = '' 16 | echo $out 17 | mkdir struct 18 | tar -xvf $src -C struct 19 | ''; 20 | postConfigure = '' 21 | substituteInPlace ''${rockspecFilename} --replace-warn '"struct.c"' '"struct/struct.c"' 22 | ''; 23 | 24 | disabled = luaOlder "5.1" || luaAtLeast "5.3"; 25 | 26 | meta = { 27 | homepage = "http://www.inf.puc-rio.br/~roberto/struct/"; 28 | description = "A library to convert Lua values to and from C structs"; 29 | license.fullName = "MIT/X"; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /nixos/packages/k-sway.nix: -------------------------------------------------------------------------------- 1 | { buildLuarocksPackage, fetchFromGitHub, fetchurl, l3mon, luaAtLeast, luaOlder, luaposix, lua-cjson }: 2 | 3 | buildLuarocksPackage { 4 | pname = "k-sway"; 5 | version = "0.1-2"; 6 | knownRockspec = (fetchurl { 7 | url = "mirror://luarocks/k-sway-0.1-2.rockspec"; 8 | sha256 = "123lw97s45zl6mfldk9d32j4x5nmv0d2rs6n7scjas7b3r015jm1"; 9 | }).outPath; 10 | src = fetchFromGitHub { 11 | owner = "norcalli"; 12 | repo = "lua-sway"; 13 | rev = "k-sway-v0.1-2"; 14 | hash = "sha256-7uhFNUzp1MDUULJXWK6coW/H3bEqxp4AooIMcALab8o="; 15 | }; 16 | 17 | postConfigure = '' 18 | substituteInPlace ''${rockspecFilename} --replace-warn "luaposix ~> 34.0" "luaposix >= 34.0" 19 | substituteInPlace ''${rockspecFilename} --replace-warn '-- "struct ~> 1.4"; -- Optional' '"struct ~> 1.4"' 20 | echo $(cat rockspecs/k-sway-0.1-2.rockspec) 21 | ''; 22 | 23 | disabled = luaOlder "5.1" || luaAtLeast "5.4"; 24 | propagatedBuildInputs = [ l3mon.k-stream l3mon.struct lua-cjson luaposix ]; 25 | 26 | meta = { 27 | homepage = "https://github.com/norcalli/lua-sway"; 28 | description = "No summary"; 29 | license.fullName = "MIT"; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /nvim/lua/bash-scratch.lua: -------------------------------------------------------------------------------- 1 | local repl = require("repl") 2 | 3 | local function nnoremapsilent_buflocal(lhs, rhs) 4 | local callback = nil 5 | if type(rhs) == "function" then 6 | callback = rhs 7 | rhs = "" 8 | end 9 | vim.api.nvim_buf_set_keymap(0, "n", lhs, rhs, {noremap = true, silent = true, callback = callback}) 10 | end 11 | 12 | local function bash_scratch() 13 | vim.cmd[[ 14 | :silent e `mktemp /tmp/XXXX.sh` 15 | :set ft=bash 16 | :silent !chmod +x % 17 | ]] 18 | local tmpfile_name = vim.api.nvim_buf_get_name(0) 19 | 20 | nnoremapsilent_buflocal(",i", function() 21 | repl.toggle("bash", "below 15 split", false) 22 | end) 23 | nnoremapsilent_buflocal(",,f", function() 24 | vim.cmd([[:write]]) 25 | repl.send("bash", tmpfile_name) 26 | end) 27 | 28 | -- actually, don't remove the file, it might be nice to get back to it. 29 | -- + I don't think I'll use this excessively, so not too bad to clutter /tmp. 30 | ---- remove file once buffer unloaded (happens on exit I hope). 31 | --vim.api.nvim_create_autocmd("BufUnload", function() os.execute("rm " .. tmpfile_name) end, {buffer=true}) 32 | end 33 | 34 | vim.api.nvim_create_user_command("BashScratch", bash_scratch, {}) 35 | -------------------------------------------------------------------------------- /nixos/data/ports.nix: -------------------------------------------------------------------------------- 1 | { 2 | ssh = 22; 3 | dns = 53; 4 | http = 80; 5 | rpcbind = 111; 6 | nbt-ns = 137; 7 | nbd = 138; 8 | 9 | smb_old = 139; 10 | 11 | https = 443; 12 | 13 | smb = 445; 14 | 15 | dnstls = 853; 16 | 17 | caddy_admin = 2019; 18 | 19 | nfsv4 = 2049; 20 | 21 | mysql = 3306; 22 | 23 | nix-serve = 5000; 24 | radicale = 5232; 25 | 26 | mpd = 6600; 27 | 28 | qbittorrent = 7000; 29 | radarr = 7001; 30 | sonarr = 7002; 31 | jackett = 7003; 32 | forgejo = 7004; 33 | immich = 7005; 34 | paperless = 7006; 35 | rmfakecloud = 7007; 36 | restic-rest-server = 7008; 37 | mympd = 7009; 38 | wireguard_rec_de = 7010; 39 | wireguard_home = 7011; 40 | statd = 7012; 41 | mountd = 7013; 42 | karakeep = 7014; 43 | meilisearch = 7015; 44 | readeck = 7016; 45 | mealie = 7017; 46 | pinchflat = 7018; 47 | kiwix-serve = 7019; 48 | zimit = 7020; 49 | linkding = 7021; 50 | ddns-updater = 7022; 51 | pds = 7023; 52 | zotero-serve = 7024; 53 | ncps = 7025; 54 | harmonia = 7026; 55 | 56 | jellyfin_web = 8096; 57 | jellyfin_discovery = 7359; 58 | } 59 | -------------------------------------------------------------------------------- /nixos/profiles/kodi.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | with lib; 4 | { 5 | services.mysql = { 6 | ensureUsers = [ 7 | { 8 | name = "kodi"; 9 | # plaintext password, but mysql is not exposed to the internet, so no worries :) 10 | remotePassword = "kodi"; 11 | ensurePermissions = { 12 | # https://kodi.wiki/view/MySQL/Setting_up_MySQL#tab=Restricting_MySQL_access_rights 13 | "*.*" = "ALL PRIVILEGES"; 14 | }; 15 | } 16 | { 17 | # for backup 18 | name = "restic"; 19 | ensurePermissions = { 20 | "*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES"; 21 | }; 22 | } 23 | ]; 24 | }; 25 | 26 | l3mon.restic.dailyRequiredServices = [ "mysql.service" ]; 27 | l3mon.restic.specs.kodi = { 28 | backupDaily = { 29 | runtimeInputs = [ config.services.mysql.package ]; 30 | text = '' 31 | mysqldump MyVideos131 | restic backup --tag=kodi --stdin --stdin-filename=MyVideos131 --skip-if-unchanged=true 32 | ''; 33 | }; 34 | forget = { 35 | text = '' 36 | restic forget --tag=kodi --group-by=tag --keep-monthly=2 37 | ''; 38 | }; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /nixos/machines/carmine/home/default.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, nur, inputs, ... }: 2 | 3 | { 4 | imports = [ 5 | ./profiles/sway-io.nix 6 | ./profiles/jellyfin-conf.nix 7 | ./profiles/store-secrets.nix 8 | ]; 9 | l3mon.sway = { 10 | workrooms.enable = true; 11 | outputs = [ "DP-1" "HDMI-A-1" ]; 12 | }; 13 | l3mon.sway-netns.wg_home2 = { 14 | enable = true; 15 | openPrivateWindow = false; 16 | netnsKey = "h"; 17 | landingPage = "http://git.internal"; 18 | firefoxProfileSettings = { 19 | id = 1; 20 | extensions.packages = with nur.repos.rycee.firefox-addons; [ 21 | ublock-origin 22 | passff 23 | ]; 24 | }; 25 | }; 26 | 27 | l3mon.sway-netns.wg_rec_de = { 28 | enable = true; 29 | openPrivateWindow = true; 30 | netnsKey = "d"; 31 | landingPage = "https://mullvad.net/en/check"; 32 | firefoxProfileSettings = { 33 | id = 2; 34 | extensions.packages = with nur.repos.rycee.firefox-addons; [ 35 | ublock-origin 36 | passff 37 | inputs.aa-torrent-dl.packages.${pkgs.system}.extension 38 | inputs.nvim-browseredit.packages.${pkgs.system}.extension 39 | ]; 40 | }; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /nixos/profiles/radicale.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | port = data.ports.radicale; 5 | machine_lan_address = data.network.lan.peers.${machine}.address; 6 | in { 7 | services.radicale = { 8 | enable = true; 9 | settings = { 10 | storage.filesystem_folder = "/var/lib/radicale/collections"; 11 | server = { 12 | hosts = "0.0.0.0:${toString port}"; 13 | max_connections = 20; 14 | max_content_length = 1000000000; 15 | timeout = 30; 16 | }; 17 | auth.type = "none"; 18 | }; 19 | }; 20 | 21 | services.caddy.extraConfig = '' 22 | http://radicale, http://radicale.internal, http://radicale.${machine} { 23 | reverse_proxy http://${machine_lan_address}:5232 24 | } 25 | ''; 26 | 27 | l3mon.restic.extraGroups = [ "radicale" ]; 28 | l3mon.restic = { 29 | specs.radicale = { 30 | backupStopResumeServices = [ "radicale.service" ]; 31 | backupDaily = { 32 | text = '' 33 | cd /var/lib/radicale 34 | restic backup --tag=radicale --skip-if-unchanged=true -- * 35 | ''; 36 | }; 37 | forget = { 38 | text = '' 39 | restic forget --tag=radicale --group-by=tag --keep-last=10 40 | ''; 41 | }; 42 | }; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /nvim/luasnippets/python.lua: -------------------------------------------------------------------------------- 1 | s_add("def", fmt([[ 2 | def {}({}) : 3 | {} 4 | ]], ins_generate())) 5 | 6 | s_add("if", fmt([[ 7 | if {} : 8 | {} 9 | ]], ins_generate())) 10 | s_add("for", fmt([[ 11 | for {} : 12 | {} 13 | ]], ins_generate({ 14 | [1] = c(1, { 15 | { i(1, "i"), t" in ", c(2, { 16 | {i(1)}, 17 | {i(1), t"range(", c(2, { 18 | {r(1, "high", i(1))}, 19 | {r(1, "low", i(1)), t", ", r(2, "high", i(1))}, 20 | {r(1, "high", i(1)), t", ", r(2, "low", i(1)), t", ", i(3, "-1")}, 21 | }), t")"} 22 | }) }, 23 | {i(1, "key"), t", ", i(2, "val"), t" in enumerate(", i(3), t")"}, 24 | {i(1, "key"), t", ", i(2, "val"), t" in enumerate(", i(3), t")"} 25 | }) 26 | }))) 27 | parse_add("class", [[ 28 | class $1 : 29 | 30 | ]]) 31 | parse_add("init", [[ 32 | def __init__(self) : 33 | $1 34 | ]]) 35 | parse_add("meth", [[ 36 | def $1(self$2) : 37 | $3 38 | ]]) 39 | 40 | px_add({trig=".p", match_pattern = "^%s+(.*)"}, parse(nil, [[print($POSTFIX_MATCH)]])) 41 | 42 | local function import(shorthand, importname) 43 | parse_add(shorthand, ("import %s as %s"):format(importname, shorthand)) 44 | end 45 | 46 | import("pd", "pandas") 47 | import("px", "plotly.express") 48 | import("np", "numpy") 49 | import("sns", "seaborn") 50 | import("plt", "matplotlib.pyplot") 51 | import("sk", "sklearn") 52 | -------------------------------------------------------------------------------- /nixos/home/profiles/mime.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | qutebrowser = ["org.qutebrowser.qutebrowser.desktop"]; 5 | firefox = ["firefox.desktop"]; 6 | zathura = ["org.pwmt.zathura-pdf-mupdf.desktop"]; 7 | thunderbird = ["userapp-Thunderbird-D15E22.desktop"]; 8 | 9 | associations = { 10 | # "inode/directory" = [ "foot.desktop" ]; 11 | "text/html" = firefox; 12 | 13 | "x-scheme-handler/http" = firefox; 14 | "x-scheme-handler/https" = firefox; 15 | "x-scheme-handler/about" = firefox; 16 | "x-scheme-handler/unknown" = firefox; 17 | "x-scheme-handler/ftp" = firefox; 18 | "x-scheme-handler/chrome" = firefox; 19 | 20 | "application/x-extension-htm" = firefox; 21 | "application/x-extension-html" = firefox; 22 | "application/x-extension-shtml" = firefox; 23 | "application/xhtml+xml" = firefox; 24 | "application/x-extension-xhtml" = firefox; 25 | "application/x-extension-xht" = firefox; 26 | 27 | "application/pdf" = zathura; 28 | 29 | "x-scheme-handler/mailto" = thunderbird; 30 | "message/rfc822" = thunderbird; 31 | "x-scheme-handler/mid" = thunderbird; 32 | }; 33 | in { 34 | xdg.mime.enable = true; 35 | xdg.mimeApps = { 36 | enable = true; 37 | associations.added = associations; 38 | defaultApplications = associations; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /nixos/profiles/firefox.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | programs.firefox = { 5 | enable = true; 6 | policies = { 7 | DisableTelemetry = true; 8 | DisableFirefoxStudies = true; 9 | EnableTrackingProtection = { 10 | Value= true; 11 | Locked = true; 12 | Cryptomining = true; 13 | Fingerprinting = true; 14 | }; 15 | DisablePocket = true; 16 | DisableFirefoxAccounts = true; 17 | DisableAccounts = true; 18 | DisableFirefoxScreenshots = true; 19 | OverrideFirstRunPage = ""; 20 | OverridePostUpdatePage = ""; 21 | DontCheckDefaultBrowser = true; 22 | FirefoxHome = { 23 | TopSites = false; 24 | SponsoredTopSites = false; 25 | SponsoredPocket = false; 26 | }; 27 | # maybe override for home-network? OTOH, pass is as fast. 28 | OfferToSaveLoginsDefault = false; 29 | 30 | # always block. 31 | Permissions.Notifications.BlockNewRequests = true; 32 | 33 | DefaultDownloadDirectory = ''''${home}/downloads''; 34 | 35 | DisplayBookmarksToolbar = "never"; # alternatives: "always" or "newtab" 36 | DisplayMenuBar = "default-off"; # alternatives: "always", "never" or "default-on" 37 | SearchBar = "unified"; # alternative: "separate" 38 | }; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /nixos/profiles/mxmaster3s.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, inputs, system, ... }: 2 | 3 | { 4 | # gives special udev-rules needed by solaar. 5 | hardware.logitech.wireless.enable = true; 6 | hardware.logitech.wireless.enableGraphical = true; 7 | 8 | # use up-to-date solaar from flake. 9 | nixpkgs.overlays = [ 10 | (final: prev: { 11 | solaar = inputs.solaar.outputs.packages.${system}.solaar; 12 | }) 13 | ]; 14 | 15 | home-manager.sharedModules = [ 16 | ( 17 | { config, lib, pkgs, machine, data, ... }: 18 | 19 | { 20 | systemd.user.services.solaar = { 21 | Unit = { 22 | Description = "solaar"; 23 | Wants = [ "graphical-session.target" ]; 24 | PartOf = [ "graphical-session.target" ]; 25 | }; 26 | Service = { 27 | Type = "simple"; 28 | ExecStart = "${pkgs.solaar}/bin/solaar --window=hide"; 29 | Restart = "on-failure"; 30 | RestartSec = 1; 31 | TimeoutStopSec = 10; 32 | }; 33 | Install = { 34 | WantedBy = ["graphical-session.target"]; 35 | }; 36 | }; 37 | 38 | xdg.configFile."solaar".source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/projects/dotfiles/solaar"; 39 | } 40 | ) 41 | ]; 42 | } 43 | -------------------------------------------------------------------------------- /nixos/data/gruvbox.nix: -------------------------------------------------------------------------------- 1 | # https://github.com/morhetz/gruvbox 2 | # use bg0_h, I like it :) 3 | rec { 4 | # 5 | # default first 15 ansi-colors. 6 | # 7 | bg0 = "282828"; 8 | # use custom color for red, default is a bit too bright imo. 9 | # regular_red = "#cc241d"; 10 | regular_red = "d75151"; 11 | regular_green = "98971a"; 12 | regular_yellow = "d79921"; 13 | regular_blue = "458588"; 14 | regular_purple = "b16286"; 15 | regular_aqua = "689d6a"; 16 | regular_fg4 = "a89984"; 17 | 18 | gray = "928374"; 19 | bright_red = "fb4934"; 20 | bright_green = "b8bb26"; 21 | bright_yellow = "fabd2f"; 22 | bright_blue = "83a598"; 23 | bright_purple = "d3869b"; 24 | bright_aqua = "8ec07c"; 25 | fg = "ebdbb2"; 26 | 27 | # 28 | # alternative colors. 29 | # 30 | bg0_h = "1d2021"; 31 | bg1 = "3c3836"; 32 | bg2 = "504945"; 33 | bg3 = "665c54"; 34 | bg4 = "7c6f64"; 35 | gray_alt = "928374"; 36 | orange = "d65d0e"; 37 | bg0_s = "32302f"; 38 | fg4 = "a89984"; 39 | fg3 = "bdae93"; 40 | fg2 = "d5c4a1"; 41 | fg1 = "ebdbb2"; 42 | fg0 = "fbf1c7"; 43 | bright_orange = "fe8019"; 44 | } 45 | -------------------------------------------------------------------------------- /nvim/lua/scripts/co_pe-1_conv.lua: -------------------------------------------------------------------------------- 1 | local uv = vim.loop 2 | local posix = require("posix.unistd") 3 | 4 | local function svg_name(dot_file) 5 | return dot_file:gsub(".dot", ".svg") 6 | end 7 | local function dot_name(svg_file) 8 | return svg_file:gsub(".svg", ".dot") 9 | end 10 | 11 | return function() 12 | local scan_handle = uv.fs_scandir("captures") 13 | local function captures_iter() 14 | return uv.fs_scandir_next(scan_handle) 15 | end 16 | 17 | -- collect .dot-files for which no svg-file is present 18 | local dot_files = {} 19 | 20 | local svg_files = {} 21 | for name, _ in captures_iter do 22 | if name:match(".dot$") and svg_files[svg_name(name)] == nil then 23 | -- might be removed later! 24 | dot_files[name] = true 25 | end 26 | if name:match(".svg$") then 27 | if dot_files[dot_name(name)] then 28 | -- doesn't have to handled! 29 | dot_files[dot_name(name)] = nil 30 | else 31 | -- store svg-file, we will encounter a dot-file, which doesn't have to be handled. 32 | svg_files[name] = true 33 | end 34 | end 35 | end 36 | 37 | 38 | local child_pid = posix.fork() 39 | if child_pid == 0 then 40 | -- we are in child, convert .dot-files and exit. 41 | for fname, _ in pairs(dot_files) do 42 | os.execute(("dot -Tsvg %s -o %s"):format("captures/"..fname, "captures/"..svg_name(fname))) 43 | end 44 | 45 | posix._exit(0) 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /nvim/queries/latex/folds.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (chapter) 3 | (part) 4 | (paragraph) 5 | (subparagraph) 6 | (comment_environment) 7 | (block_comment) 8 | (displayed_equation) 9 | ] @fold 10 | 11 | ((brack_group_key_value) @group 12 | (#make-range-extended! fold @group "start" 0 1 @group "end" 0 -1) ) 13 | 14 | (generic_environment 15 | (begin) @beg 16 | end: (end) @end 17 | (#make-range-extended! "fold" @beg "end" 0 1 @end "start" 0 1) ) 18 | 19 | (generic_environment 20 | (begin name: (_ text: (_) @name)) @beg 21 | (generic_command command: (_) @cname arg: (_ (text) @carg)) 22 | end: (end) @end 23 | (#eq? @name "frame") 24 | (#eq? @cname "\\frametitle") 25 | 26 | (#make-range-extended! "fold" @beg "end" 0 1 @end "start" 0 1) 27 | 28 | (#set-from-nodetext-gsub! foldtext_start @carg "^" " [" "$" "]") 29 | (#set! foldtext_start_hl "@markup.heading.latex") 30 | 31 | (#set! priority 1001) ) 32 | 33 | (math_environment 34 | (begin) @beg 35 | end: (end) @end 36 | (#make-range-extended! "fold" @beg "end" 0 1 @end "start" 0 1) ) 37 | 38 | ( 39 | (section 40 | text: (_) @label) @sec 41 | (#make-range-extended! "fold" @label "end" 0 1 @sec "end" 0 1) ) 42 | ( 43 | (subsection 44 | text: (_) @label) @sec 45 | (#make-range-extended! "fold" @label "end" 0 1 @sec "end" 0 1) ) 46 | ( 47 | (subsubsection 48 | text: (_) @label) @sec 49 | (#make-range-extended! "fold" @label "end" 0 1 @sec "end" 0 1) ) 50 | -------------------------------------------------------------------------------- /nvim/lua/symbols.lua: -------------------------------------------------------------------------------- 1 | local superscripts = { 2 | ["0"] = "⁰", 3 | ["1"] = "¹", 4 | ["2"] = "²", 5 | ["3"] = "³", 6 | ["4"] = "⁴", 7 | ["5"] = "⁵", 8 | ["6"] = "⁶", 9 | ["7"] = "⁷", 10 | ["8"] = "⁸", 11 | ["9"] = "⁹", 12 | ["-"] = "⁻", 13 | ["+"] = "⁺", 14 | ["n"] = "ⁿ", 15 | } 16 | 17 | local subscripts = { 18 | ["0"] = "₀", 19 | ["1"] = "₁", 20 | ["2"] = "₂", 21 | ["3"] = "₃", 22 | ["4"] = "₄", 23 | ["5"] = "₅", 24 | ["6"] = "₆", 25 | ["7"] = "₇", 26 | ["8"] = "₈", 27 | ["9"] = "₉", 28 | ["a"] = "ₐ", 29 | ["e"] = "ₑ", 30 | ["o"] = "ₒ", 31 | ["x"] = "ₓ", 32 | ["y"] = "ᵧ", 33 | ["h"] = "ₕ", 34 | ["k"] = "ₖ", 35 | ["l"] = "ₗ", 36 | ["m"] = "ₘ", 37 | ["n"] = "ₙ", 38 | ["p"] = "ₚ", 39 | ["s"] = "ₛ", 40 | ["t"] = "ₜ", 41 | ["-"] = "₋", 42 | ["+"] = "₊", 43 | } 44 | 45 | local greeks = { 46 | ["a"] = "α", 47 | ["ps"] = "ψ", 48 | ["b"] = "β", 49 | ["t"] = "θ", 50 | ["l"] = "λ", 51 | ["L"] = "Λ", 52 | ["ph"] = "φ", 53 | ["pi"] = "π", 54 | ["o"] = "ω", 55 | ["D"] = "Δ", 56 | ["d"] = "δ", 57 | ["ga"] = "γ", 58 | ["e"] = "η", 59 | ["gr"] = "∇", 60 | ["S"] = "Σ", 61 | ["s"] = "σ", 62 | ["m"] = "μ", 63 | } 64 | 65 | local function table_to_mapping(prefix, table) 66 | for lhs, rhs in pairs(table) do 67 | vim.keymap.set({"i", "c", "t"}, prefix..lhs, rhs, { buffer = true }) 68 | end 69 | end 70 | 71 | table_to_mapping("", superscripts) 72 | table_to_mapping("", subscripts) 73 | table_to_mapping("", greeks) 74 | -------------------------------------------------------------------------------- /solaar/config.yaml: -------------------------------------------------------------------------------- 1 | - 1.1.14 2 | - _NAME: MX Master 3S 3 | _absent: [hi-res-scroll, lowres-scroll-mode, onboard_profiles, report_rate, report_rate_extended, pointer_speed, dpi_extended, speed-change, backlight, 4 | backlight_level, backlight_duration_hands_out, backlight_duration_hands_in, backlight_duration_powered, backlight-timed, led_control, led_zone_, rgb_control, 5 | rgb_zone_, brightness_control, per-key-lighting, fn-swap, persistent-remappable-keys, disable-keyboard-keys, crown-smooth, divert-crown, divert-gkeys, 6 | m-key-leds, mr-key-led, multiplatform, gesture2-gestures, gesture2-divert, gesture2-params, sidetone, equalizer, adc_power_management] 7 | _battery: 4100 8 | _dpi-sliding: 63 9 | _modelId: B03400000000 10 | _sensitive: {change-host: false, divert-keys: false, dpi: true, hires-scroll-mode: false, hires-smooth-invert: false, hires-smooth-resolution: false, 11 | reprogrammable-keys: false, scroll-ratchet: false, smart-shift: false, thumb-scroll-invert: false} 12 | _serial: 0D684A4B 13 | _unitId: 0D684A4B 14 | _wpid: B034 15 | change-host: null 16 | divert-keys: {82: 0, 83: 1, 86: 1, 195: 0, 196: 0} 17 | dpi: 2800 18 | hires-scroll-mode: false 19 | hires-smooth-invert: false 20 | hires-smooth-resolution: false 21 | reprogrammable-keys: {80: 80, 81: 81, 82: 82, 83: 196, 86: 86, 195: 195, 196: 196} 22 | scroll-ratchet: 2 23 | smart-shift: 25 24 | thumb-scroll-invert: true 25 | thumb-scroll-mode: false 26 | -------------------------------------------------------------------------------- /nvim/luasnippets/cpp.lua: -------------------------------------------------------------------------------- 1 | parse_add({trig = "if", wordTrig = true}, "if ($1)\n\t$0") 2 | parse_add({trig = "for", wordTrig = true}, "for ($1 : $2)\n\t$0") 3 | s_add("iferr", fmt("if ({})\n\tthrow std::runtime_error(\"failed to {}\")", {i(1), i(2)})) 4 | parse_add("vapp", "$1.insert($1.end(), $2.begin(), $2.end())") 5 | parse_add("allof", "$1.begin(), $1.end()") 6 | parse_add("prag", "#pragma once") 7 | parse_add("ns", "namespace $1 {\n\n$2\n\n}") 8 | s_add("co", fmt([[std::cout << {} << std::endl;]], { 9 | c(1, { 10 | i(1), 11 | {t"glm::to_string(", i(1), t")"} 12 | }) 13 | })) 14 | parse_add("hg", [[ 15 | #ifndef $1 16 | #define $1 17 | 18 | ${2:$SELECT_DEDENT} 19 | 20 | #endif 21 | ]]) 22 | parse_add("class", [[ 23 | class $1 { 24 | public: 25 | $2 26 | private: 27 | $3 28 | }; 29 | ]]) 30 | ts_px_add({ 31 | trig = ".up", 32 | matchTSNode = { 33 | query = [[ 34 | [ 35 | (type_identifier) 36 | (template_type) 37 | (qualified_identifier) 38 | ] 39 | @prefix ]], 40 | query_lang = "cpp", 41 | select = "longest" 42 | }, 43 | reparseBuffer = "live" 44 | }, { 45 | l("std::unique_ptr<" .. l.LS_TSMATCH .. ">") 46 | }) 47 | ts_px_add({ 48 | trig = ".opt", 49 | matchTSNode = { 50 | query = [[ 51 | [ 52 | (type_identifier) 53 | (template_type) 54 | (qualified_identifier) 55 | ] 56 | @prefix ]], 57 | query_lang = "cpp", 58 | select = "longest" 59 | }, 60 | reparseBuffer = "live" 61 | }, { 62 | l("std::optional<" .. l.LS_TSMATCH .. ">") 63 | }) 64 | -------------------------------------------------------------------------------- /nvim/lua/plugins/matchconfig.lua: -------------------------------------------------------------------------------- 1 | local mc = require("matchconfig") 2 | mc.setup({ 3 | path = "configs.lua", 4 | options = { 5 | require("my_mc.options.repl"), 6 | { 7 | new = function(conf) 8 | return require("matchconfig.options.run_buf").new(conf, {raw_key = "run_buf_prio", respect_barrier = false}) 9 | end, 10 | reset = function() end 11 | }, 12 | require("matchconfig.options.bufvar"), 13 | require("matchconfig.extras.options.dap"), 14 | require("matchconfig.extras.options.luasnip_ft_extend"), 15 | require("matchconfig.options.run_buf"), 16 | require("matchconfig.options.run_buf_named"), 17 | require("matchconfig.options.run_session"), 18 | require("matchconfig.options.bufopt"), 19 | require("matchconfig.options.lsp"), 20 | } 21 | }) 22 | require("matchconfig.util.log").set_loglevel("debug") 23 | vim.api.nvim_create_user_command("C", mc.pick_current, {}) 24 | vim.api.nvim_create_user_command("CO", ":e " .. vim.uv.fs_realpath(require("matchconfig").get_configfile()), {}) 25 | vim.api.nvim_create_user_command("MC", function() 26 | print(vim.inspect(mc.get_config())) 27 | end, {}) 28 | 29 | vim.api.nvim_create_user_command("LspRestart", function() 30 | local servers = require("matchconfig.options.lsp").lsp_client_pool.clients 31 | local servercommands = vim.tbl_map(function(server) 32 | return table.concat(server.cmd, " ") 33 | end, servers) 34 | vim.ui.select( 35 | servercommands, 36 | { kind = "matchconfig_lsp_restart" }, 37 | function(_, idx) 38 | servers[idx]:restart() 39 | end 40 | ) 41 | end, {}) 42 | -------------------------------------------------------------------------------- /nvim/after/syntax/nftables.vim: -------------------------------------------------------------------------------- 1 | if exists('b:current_syntax') 2 | finish 3 | endif 4 | 5 | syn match nftablesSet /{.*}/ contains=nftablesSetEntry 6 | syn match nftablesSetEntry /[a-zA-Z0-9]\+/ contained 7 | hi def link nftablesSet Keyword 8 | hi def link nftablesSetEntry Operator 9 | 10 | syn match nftablesNumber "\<[0-9A-Fa-f./:]\+\>" contains=nftablesMask,nftablesDelimiter 11 | syn match nftablesHex "\<0x[0-9A-Fa-f]\+\>" 12 | syn match nftablesDelimiter "[./:]" contained 13 | syn match nftablesMask "/[0-9.]\+" contained contains=nftablesDelimiter 14 | hi def link nftablesNumber Number 15 | hi def link nftablesHex Number 16 | hi def link nftablesDelimiter Operator 17 | hi def link nftablesMask Operator 18 | 19 | syn region Comment start=/#/ end=/$/ 20 | syn region String start=/"/ end=/"/ 21 | syn keyword Function flush 22 | syn keyword Function table chain map 23 | syn keyword Statement type hook 24 | syn keyword Type ip ip6 inet arp bridge 25 | syn keyword Type filter nat route 26 | syn keyword Type ether vlan arp ip icmp igmp ip6 icmpv6 tcp udp udplite sctp dccp ah esp comp icmpx 27 | syn keyword Type ct 28 | syn keyword Type length protocol priority mark iif iifname iiftype oif oifname oiftype skuid skgid rtclassid 29 | syn keyword Constant prerouting input forward output postrouting 30 | 31 | syn keyword Special snat dnat masquerade redirect 32 | syn keyword Special accept drop reject queue 33 | syn keyword Keyword continue return jump goto 34 | syn keyword Keyword counter log limit 35 | syn keyword Keyword define 36 | 37 | let b:current_syntax = 'nftables' 38 | -------------------------------------------------------------------------------- /nixos/machines/indigo/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-intel" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/" = 17 | { device = "/dev/disk/by-label/NIXROOT"; 18 | fsType = "btrfs"; 19 | }; 20 | 21 | fileSystems."/boot" = 22 | { device = "/dev/disk/by-label/NIXBOOT"; 23 | fsType = "vfat"; 24 | options = [ "fmask=0077" "dmask=0077" ]; 25 | }; 26 | 27 | swapDevices = [ ]; 28 | 29 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 30 | # (the default) this is the recommended approach. When using systemd-networkd it's 31 | # still possible to use this option, but it's recommended to use it in conjunction 32 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 33 | networking.useDHCP = lib.mkDefault true; 34 | # networking.interfaces.ens3.useDHCP = lib.mkDefault true; 35 | 36 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 37 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 38 | } 39 | -------------------------------------------------------------------------------- /nixos/machines/carmine/home/profiles/sway-io.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | primary = "DP-1"; 5 | secondary = "HDMI-A-1"; 6 | in { 7 | wayland.windowManager.sway.extraConfig = '' 8 | input 1133:50504:Logitech_USB_Receiver_Mouse { 9 | pointer_accel -1 10 | } 11 | 12 | input 1240:60205:liliums_Lily58_Mouse { 13 | pointer_accel 1 14 | scroll_factor 0.06 15 | } 16 | 17 | input 1240:60205:liliums_Lily58 { 18 | repeat_delay 120 19 | repeat_rate 100 20 | xkb_layout "us" 21 | xkb_variant "altgr-intl" 22 | } 23 | 24 | # qemu? 25 | input 1:1:AT_Translated_Set_2_keyboard { 26 | repeat_delay 120 27 | repeat_rate 100 28 | xkb_layout "us" 29 | xkb_variant "altgr-intl" 30 | } 31 | 32 | output "${secondary}" transform 90 resolution 1920x1080@60.000Hz position 2560,0 33 | output "${secondary}" subpixel vbgr 34 | 35 | output "${primary}" transform 0 mode 2560x1440@120.066Hz position 0,0 36 | output "${primary}" subpixel rgb 37 | 38 | output "Red Hat, Inc. QEMU Monitor Unknown" transform 0 mode 1280x800@74.994Hz position 0,0 39 | 40 | output "Unknown Unknown Unknown" transform 0 mode 1600x1200@60.000Hz position 0,0 41 | 42 | mode "power" { 43 | bindsym --no-repeat d output "${primary}" dpms toggle; mode "default" 44 | bindsym --no-repeat h output "${secondary}" dpms toggle; mode "default" 45 | 46 | bindsym --no-repeat b output "${primary}" dpms toggle; output "${secondary}" dpms toggle; mode "default" 47 | } 48 | ''; 49 | } 50 | -------------------------------------------------------------------------------- /nixos/machines/carmine/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "nvme" "usbhid" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-amd" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/" = 17 | { device = "/dev/disk/by-label/NIXROOT"; 18 | fsType = "btrfs"; 19 | }; 20 | 21 | fileSystems."/boot" = 22 | { device = "/dev/disk/by-label/NIXBOOT"; 23 | fsType = "vfat"; 24 | options = [ "fmask=0022" "dmask=0022" ]; 25 | }; 26 | 27 | swapDevices = [ 28 | { 29 | device = "/dev/disk/by-label/SWAP"; 30 | } 31 | ]; 32 | 33 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 34 | # (the default) this is the recommended approach. When using systemd-networkd it's 35 | # still possible to use this option, but it's recommended to use it in conjunction 36 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 37 | # networking.useDHCP = lib.mkDefault true; 38 | # networking.interfaces.ens3.useDHCP = lib.mkDefault true; 39 | 40 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 41 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 42 | } 43 | -------------------------------------------------------------------------------- /nixos/profiles/flake-preserve.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; [ 5 | (pkgs.writeShellApplication { 6 | name = "devshell-preserve"; 7 | runtimeInputs = with pkgs; [ nix jq ]; 8 | text = (let 9 | preserve-flake-srcs = pkgs.writeText "preserve-flake-srcs" 10 | # nix 11 | '' 12 | flake: shell_drv_path: let 13 | pkgs = import ${pkgs.path} {}; 14 | collectFlakeInputs = input: 15 | ([ input ] ++ pkgs.lib.concatMap collectFlakeInputs (builtins.attrValues (input.inputs or {}))); 16 | shell_drv = import shell_drv_path; 17 | in (flake.outputs.devShells.x86_64-linux.default.overrideAttrs (old: { 18 | inputSrcs = (if old ? "inputSrcs" then old.inputSrcs else []) ++ (builtins.tail (collectFlakeInputs flake)); 19 | inputDrvs = (if old ? "inputDrvs" then old.inputDrvs else []) ++ [ shell_drv.man shell_drv.out ]; 20 | })) 21 | ''; 22 | in 23 | # bash 24 | '' 25 | # get pid of devshell -> get path to bashInteractive from /proc -> get derivation -> get path to out/man. 26 | # shellcheck disable=2016 27 | shellpath=$(echo 'readlink /proc/$$/exe' | nix develop) 28 | shell_drvpath="$(nix-store --query --deriver "$shellpath")" 29 | # pipe into devshells prevents interactive session. 30 | echo exit 0 | nix develop --expr 'import ${preserve-flake-srcs} (builtins.getFlake "git+file://'"$(pwd)"'") '"$shell_drvpath" --impure --profile ./profile 31 | ''); 32 | }) 33 | ]; 34 | } 35 | -------------------------------------------------------------------------------- /nixos/profiles/mealie.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, data, ... }: 2 | 3 | { 4 | services.mealie = { 5 | enable = true; 6 | package = pkgs.mealie.overrideAttrs (old: rec { 7 | version = "3.1.2"; 8 | src = pkgs.fetchFromGitHub { 9 | owner = "mealie-recipes"; 10 | repo = "mealie"; 11 | tag = "v3.1.2"; 12 | hash = "sha256-8ZLXXA4NKR7GaCdgk8XDMjAssQsKP1wZpEZPYWpglwk="; 13 | # hash = "sha256-txkHCQ/xTakPXXFki161jNOKwAH9p9z1hCNEEkbqQtM="; 14 | }; 15 | patches = []; 16 | }); 17 | port = data.ports.mealie; 18 | }; 19 | 20 | users.users.mealie = { 21 | isSystemUser = true; 22 | uid = data.ids.mealie; 23 | group = "mealie"; 24 | }; 25 | users.groups.mealie.gid = data.ids.mealie; 26 | 27 | systemd.services.mealie.serviceConfig = { 28 | User = "mealie"; 29 | Group = "mealie"; 30 | DynamicUser = lib.mkForce false; 31 | }; 32 | 33 | services.caddy.extraConfig = '' 34 | http://mealie, http://mealie.internal, http://mealie.${machine} { 35 | reverse_proxy http://127.0.0.1:${toString data.ports.mealie} 36 | } 37 | ''; 38 | 39 | l3mon.restic.extraGroups = [ "mealie" ]; 40 | l3mon.restic.specs.mealie = { 41 | backupStopResumeServices = ["mealie.service"]; 42 | backupDaily = { 43 | text = '' 44 | cd /var/lib/mealie/ 45 | restic backup --tag=mealie --skip-if-unchanged=true -- ./recipes ./templates ./users 46 | ''; 47 | }; 48 | forget = { 49 | text = '' 50 | restic forget --tag=mealie --group-by=tag --keep-daily=7 --keep-monthly=12 51 | ''; 52 | }; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /nvim/luasnippets/c.lua: -------------------------------------------------------------------------------- 1 | -- parse_add({trig = "if", wordTrig = true}, "if ($1)\n\t${LS_SELECT_DEDENT}$0") 2 | s_add({trig = "for(%w+)", wordTrig = true, regTrig = true}, fmt([[ 3 | for ({}; {}; {}) 4 | {} 5 | ]], { 6 | dl(1, "int " .. l.CAPTURE1 .. " = 0", {}), 7 | c(2, {sn(nil, {l(l.CAPTURE1), t({" != "}), i(1)}), i(nil)}), 8 | dl(3, "++" .. l.CAPTURE1, {}), 9 | i(0) 10 | })) 11 | 12 | 13 | s_add("if", fmt([[ 14 | if ({}) {brackets_open} 15 | {content} 16 | {brackets_close} 17 | ]], { 18 | [1] = i(1), 19 | content = d(2, function(_, parent) 20 | if #parent.snippet.env.LS_SELECT_DEDENT ~= 0 then 21 | return isn(nil, { 22 | t(parent.snippet.env.LS_SELECT_DEDENT), i(1) 23 | }, "$PARENT_INDENT\t") 24 | else 25 | return sn(nil, { i(1) }) 26 | end 27 | end), 28 | brackets_open = f(function(args) 29 | if #args[1] > 1 then 30 | return "{" 31 | end 32 | end, 2), 33 | brackets_close = f(function(args) 34 | if #args[1] > 1 then 35 | return "}" 36 | end 37 | end, 2) 38 | })) 39 | 40 | ts_px_add({ 41 | trig = ".ei", 42 | matchTSNode = { 43 | query = "(if_statement) @prefix", 44 | query_lang = "c", 45 | select = "longest" 46 | }, 47 | reparseBuffer = "live" }, { 48 | d(1, function(_, parent) 49 | if parent.env.LS_TSMATCH == nil then 50 | return s(nil, t"") 51 | end 52 | -- tricky: remove indent on lines containing LS_TSMATCH. The 53 | -- indentation is provided by the captured `if`. 54 | return sn(nil, { 55 | isn(1, fmt([[ 56 | {} else if ({}) {{]], {t(parent.env.LS_TSMATCH), i(1)}), ""), 57 | t{"",""}, 58 | sn(2, fmt([[ 59 | {} 60 | }} 61 | ]], {i(1)})) }) 62 | end)}) 63 | -------------------------------------------------------------------------------- /nixos/profiles/pinchflat.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, data, l3lib, ... }: 2 | 3 | let 4 | yt_dlp_config = pkgs.writeText "yt-dlp-conf" '' 5 | # youtube seems to heavily rate-limit auto-translated subtitle downloads => 6 | # ignore errors and just download the subtitles youtube doesn't 429. 7 | # --extractor-args 'youtube:skip=translated_subs' 8 | -i 9 | # generated via procedure described [here](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies) 10 | --cookies ${l3lib.secret "youtube-cookies.txt"} 11 | ''; 12 | in { 13 | services.pinchflat = { 14 | enable = true; 15 | package = pkgs-unstable.pinchflat; 16 | port = data.ports.pinchflat; 17 | mediaDir = "/srv/media/video/youtube"; 18 | selfhosted = true; 19 | secretsFile = l3lib.secret "pinchflat_env"; 20 | }; 21 | 22 | system.activationScripts.pinchflat = { 23 | text = '' 24 | install -D -o pinchflat -g pinchflat ${yt_dlp_config} "/var/lib/pinchflat/extras/yt-dlp-configs/base-config.txt" 25 | ''; 26 | }; 27 | 28 | users.users.pinchflat = { 29 | isSystemUser = true; 30 | uid = data.ids.pinchflat; 31 | extraGroups = ["media"]; 32 | group = "pinchflat"; 33 | }; 34 | users.groups.pinchflat.gid = data.ids.pinchflat; 35 | 36 | systemd.services.pinchflat.serviceConfig = { 37 | User = "pinchflat"; 38 | Group = "pinchflat"; 39 | DynamicUser = lib.mkForce false; 40 | }; 41 | 42 | services.caddy.extraConfig = '' 43 | http://pinchflat, http://pinchflat.internal, http://pinchflat.${machine} { 44 | reverse_proxy http://127.0.0.1:${toString data.ports.pinchflat} 45 | } 46 | ''; 47 | } 48 | -------------------------------------------------------------------------------- /nvim/lua/auto_table.lua: -------------------------------------------------------------------------------- 1 | -- depth specifies how many levels under this table should be allowed to index 2 | -- throug this metamethod 3 | -- set depth to 0 to disable checking 4 | -- Acknowledgment: This is (maybe more than) inspired by 5 | -- https://lua-users.org/wiki/AutomagicTables so special thanks to 6 | -- Thomas Wrensch and Rici Lake for sharing their ideas on this topic. 7 | local function auto_creating_tables_warn_depth(self, key, depth) 8 | local t = {} 9 | assert(depth ~= 1, "don't index at that level") 10 | setmetatable(t, { 11 | -- creating a new function on each time (could be shared) isn't that 12 | -- nice. Nonetheless this shouldn't be too bad, as these are only 13 | -- created twice (auto+snippet) per ft and twice for each prio,ft 14 | -- combination 15 | __index = function(s, k) 16 | return auto_creating_tables_warn_depth(s, k, depth - 1) 17 | end, 18 | }) 19 | self[key] = t 20 | return t 21 | end 22 | 23 | local function auto_creating_tables(self, key, depth) 24 | local t = {} 25 | if depth ~= 1 then 26 | setmetatable(t, { 27 | __index = function(s, k) 28 | return auto_creating_tables(s, k, depth - 1) 29 | end, 30 | }) 31 | end 32 | self[key] = t 33 | return t 34 | end 35 | 36 | local M = {} 37 | 38 | function M.autotable(max_depth, opts) 39 | opts = opts or {} 40 | local warn = vim.F.if_nil(opts.warn, false) 41 | 42 | local auto_table_func = warn and auto_creating_tables_warn_depth 43 | or auto_creating_tables 44 | 45 | return setmetatable({}, { 46 | __index = function(s, k) 47 | return auto_table_func(s, k, max_depth - 1) 48 | end, 49 | }) 50 | end 51 | 52 | M.warn_depth_autotable = auto_creating_tables_warn_depth 53 | 54 | return M 55 | -------------------------------------------------------------------------------- /nixos/machines/cobalt/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" "sr_mod" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/" = 17 | { device = "/dev/disk/by-label/NIXROOT"; 18 | fsType = "btrfs"; 19 | }; 20 | 21 | fileSystems."/boot" = 22 | { device = "/dev/disk/by-label/NIXBOOT"; 23 | fsType = "vfat"; 24 | options = [ "fmask=0022" "dmask=0022" ]; 25 | }; 26 | 27 | swapDevices = [ 28 | { 29 | device = "/dev/disk/by-label/SWAP"; 30 | } 31 | ]; 32 | 33 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 34 | # (the default) this is the recommended approach. When using systemd-networkd it's 35 | # still possible to use this option, but it's recommended to use it in conjunction 36 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 37 | networking.useDHCP = lib.mkDefault true; 38 | # networking.interfaces.eno1.useDHCP = lib.mkDefault true; 39 | # networking.interfaces.wlo1.useDHCP = lib.mkDefault true; 40 | 41 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 42 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 43 | } 44 | -------------------------------------------------------------------------------- /nvim/lua/plugins/luasnip/ft_edit.lua: -------------------------------------------------------------------------------- 1 | -- asssumes both of these are loaded. 2 | local snippet_collections = { 3 | -- lua-snippets 4 | { 5 | dir = "/home/simon/.config/nvim/luasnippets", 6 | extension = "lua" 7 | }, 8 | { 9 | dir = vim.fn.getcwd() .. "/.luasnippets", 10 | extension = "lua" 11 | }, 12 | -- snipmate-snippets 13 | -- this would edit snippets provided by vim-snippets. 14 | { 15 | dir = "/home/simon/.local/share/nvim/site/pack/packer/start/vim-snippets/snippets/", 16 | extension = "snippets" 17 | } 18 | -- vscode would be more involved 19 | } 20 | 21 | return function() 22 | require("luasnip.loaders").edit_snippet_files({ 23 | extend = function(ft, files) 24 | local extend_items = {} 25 | 26 | for _, collection in ipairs(snippet_collections) do 27 | for _, file in ipairs(files) do 28 | if file:match(collection.dir) then 29 | -- a file is in personal_dir, no need to create a new file there. 30 | goto continue 31 | end 32 | end 33 | -- not continued, we need to append a new file for personal_dir 34 | table.insert(extend_items, { 35 | "New file in " .. collection.dir, 36 | ("%s/%s.%s"):format(collection.dir, ft, collection.extension)}) 37 | 38 | :: continue :: 39 | end 40 | 41 | return extend_items 42 | end, 43 | format = function(path, _) 44 | path = path:gsub( 45 | vim.pesc(vim.fn.stdpath("data") .. "/lazy"), 46 | "$PLUGINS" 47 | ) 48 | if vim.env.HOME then 49 | path = path:gsub(vim.pesc(vim.env.HOME .. "/.config/nvim"), "$CONFIG") 50 | end 51 | path = path:gsub(vim.pesc(vim.fn.getcwd()), "$CWD") 52 | return path 53 | end, 54 | edit = function(file) 55 | vim.cmd("tabnew " .. file) 56 | end 57 | }) 58 | end 59 | -------------------------------------------------------------------------------- /nvim/lua/sighelp/util.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local function to_paramstring(param_label, label) 4 | if type(param_label) == "table" then 5 | -- 0-based index in table from lsp. 6 | -- this will fail for some UTF16-chars. 7 | -- exclude end. 8 | return label:sub(param_label[1] + 1, param_label[2]) 9 | else 10 | return param_label 11 | end 12 | end 13 | 14 | ---Extract labels from sighelp-response. 15 | ---@param res response 16 | ---@return table: 17 | --- -active_parameter 18 | --- -active_signature 19 | --- -signatures: list of tables with 20 | --- -funcname: string 21 | --- -parameters: string[] or nil. 22 | function M.normalize(err, res) 23 | if err or not res then 24 | return nil 25 | end 26 | local clean = {} 27 | -- both 0-based to 1-based. 28 | -- default is 0. 29 | clean.active_parameter = (res.activeParameter or 0)+1 30 | clean.active_signature = (res.activeSignature or 0)+1 31 | 32 | -- no signatures returned. 33 | if #res.signatures == 0 then 34 | return nil 35 | end 36 | 37 | clean.signatures = {} 38 | for _, res_sig in ipairs(res.signatures) do 39 | local sig = {} 40 | sig.funcname = res_sig.label:match("^([^(]+)%(") 41 | 42 | local params = {} 43 | for _, param in ipairs(res_sig.parameters) do 44 | table.insert(params, to_paramstring(param.label, res_sig.label)) 45 | end 46 | sig.parameters = #params > 0 and params or nil 47 | table.insert(clean.signatures, sig) 48 | end 49 | 50 | return clean 51 | end 52 | 53 | function M.request_sighelp(handler) 54 | vim.lsp.buf_request(0, 55 | "textDocument/signatureHelp", 56 | vim.tbl_extend("error", 57 | vim.lsp.util.make_position_params(0), 58 | { context = { triggerKind=1 } } ), handler) 59 | end 60 | 61 | 62 | return M 63 | -------------------------------------------------------------------------------- /nvim/lua/vkinfo.lua: -------------------------------------------------------------------------------- 1 | ---Call cb for _all_ tables in t. 2 | ---Stop recursing further into a table if cb returns true for it. 3 | ---@param t table 4 | ---@param cb function, does some stuff. Returns whether further recursion should be aborted. 5 | local function recursive_walk(t, cb) 6 | -- only inspect tables. 7 | if type(t) ~= "table" or cb(t) then 8 | return 9 | end 10 | for _, v in pairs(t) do 11 | recursive_walk(v, cb) 12 | end 13 | end 14 | 15 | local function find_structs(xml) 16 | local structs = {} 17 | recursive_walk(xml, function(t) 18 | if t[0] == "type" and t.category == "struct" then 19 | table.insert(structs, t) 20 | return true 21 | end 22 | -- keep recursing on no match. 23 | return false 24 | end) 25 | 26 | return structs 27 | end 28 | 29 | local function find_category(xml, category_name) 30 | local items = {} 31 | recursive_walk(xml, function(t) 32 | if t.category == category_name then 33 | items[t.name] = true 34 | end 35 | -- keep recursing on no match. 36 | return false 37 | end) 38 | 39 | return items 40 | end 41 | 42 | local function find_functions(xml) 43 | local items = {} 44 | recursive_walk(xml, function(t) 45 | if t[0] == "command" then 46 | if t[1] == nil and not t.alias then 47 | items[t.name] = true 48 | end 49 | end 50 | return false 51 | end) 52 | 53 | return items 54 | end 55 | 56 | local lxp = require("lxp.totable") 57 | local vk_xml = io.open("/usr/share/vulkan/registry/vk.xml", "r") 58 | p = lxp.parse(vk_xml) 59 | lxp.clean(p) 60 | lxp.torecord(p) 61 | 62 | return { 63 | structs = find_structs(p), 64 | structnames = find_category(p, "struct"), 65 | enumnames = find_category(p, "enum"), 66 | handlenames = find_category(p, "handle"), 67 | functions = find_functions(p) 68 | } 69 | -------------------------------------------------------------------------------- /nixos/home/profiles/qutebrowser/config.py: -------------------------------------------------------------------------------- 1 | c.fonts.tabs.selected = '13pt Inter' 2 | c.fonts.tabs.unselected = '13pt Inter' 3 | c.fonts.hints = '13pt Inter' 4 | c.fonts.keyhint = '13pt Inter' 5 | c.fonts.prompts = '13pt Inter' 6 | c.fonts.downloads = '13pt Inter' 7 | c.fonts.statusbar = '13pt Inter' 8 | c.fonts.contextmenu = '13pt Inter' 9 | c.fonts.messages.info = '13pt Inter' 10 | c.fonts.debug_console = '13pt Inter' 11 | c.fonts.completion.entry = '13pt Inter' 12 | c.fonts.completion.category = '13pt Inter' 13 | 14 | c.content.javascript.clipboard = 'access-paste' 15 | 16 | c.tabs.title.format = '{current_title}' 17 | c.tabs.favicons.show = 'never' 18 | c.tabs.indicator.width = 0 19 | c.tabs.show = 'switching' 20 | 21 | c.url.default_page = 'http://google.com' 22 | c.url.start_pages = 'http://google.com' 23 | c.downloads.prevent_mixed_content = False 24 | 25 | c.statusbar.show = 'never' 26 | 27 | c.editor.command = ['foot', 'nvim', '{}'] 28 | 29 | config.load_autoconfig(False) 30 | c.url.searchengines = { 31 | 'DEFAULT': 'https://google.com/search?q={}', 32 | '!k': 'https://kagi.com/search?q={}', 33 | '!d': 'https://duckduckgo.com/?ia=web&q={}', 34 | '!a': 'https://annas-archive.org/search?q={}', 35 | '!np': 'https://search.nixos.org/packages?channel=25.05&type=packages&query={}', 36 | '!no': 'https://search.nixos.org/options?channel=25.05&query={}', 37 | } 38 | 39 | c.content.pdfjs = True 40 | 41 | config.bind("pf", "spawn --userscript qute-pass --username-target=secret --username-pattern=\"[\\w]+: ?(.*)\"") 42 | config.bind("pp", "spawn --userscript qute-pass --username-target=secret --username-pattern=\"[\\w]+: ?(.*)\" --password-only ") 43 | config.bind("pu", "spawn --userscript qute-pass --username-target=secret --username-pattern=\"[\\w]+: ?(.*)\" --username-only ") 44 | config.bind("e", "edit-url") 45 | -------------------------------------------------------------------------------- /nixos/profiles/readeck.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, l3lib, ... }: 2 | 3 | let 4 | machine_lan_address = data.network.lan.peers.${machine}.address; 5 | in { 6 | services.readeck = { 7 | enable = true; 8 | settings = { 9 | server = { 10 | port = data.ports.readeck; 11 | host = "127.0.0.1"; 12 | trusted_proxies = ["127.0.0.1"]; 13 | allowed_hosts = ["readeck.internal"]; 14 | }; 15 | }; 16 | }; 17 | 18 | users.users.readeck = { 19 | isSystemUser = true; 20 | uid = data.ids.readeck; 21 | group = "readeck"; 22 | }; 23 | users.groups.readeck.gid = data.ids.readeck; 24 | 25 | systemd.services.readeck.serviceConfig = { 26 | LoadCredential = "secret_key:${l3lib.secret "readeck_secret_key"}"; 27 | Environment = "READECK_SECRET_KEY=%d/secret_key"; 28 | User = "readeck"; 29 | Group = "readeck"; 30 | DynamicUser = lib.mkForce false; 31 | }; 32 | 33 | services.caddy.extraConfig = '' 34 | http://readeck, http://readeck.internal, http://readeck.${machine} { 35 | reverse_proxy http://127.0.0.1:${toString data.ports.readeck} 36 | } 37 | ''; 38 | 39 | l3mon.restic.extraGroups = [ "readeck" ]; 40 | l3mon.restic.specs.readeck = { 41 | backupStopResumeServices = ["readeck.service"]; 42 | backupDaily = { 43 | text = '' 44 | cd /var/lib/readeck/ 45 | restic backup --tag=readeck --skip-if-unchanged=true -- ./data 46 | ''; 47 | }; 48 | forget = { 49 | text = '' 50 | # For each known file (torrent), keep last snapshot where it existed. 51 | # This makes sure every torrent-file still exists somewhere in the restic-repository. 52 | restic forget --tag=readeck --group-by=tag --keep-daily=7 --keep-monthly=12 53 | ''; 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /nvim/after/ftplugin/java.vim: -------------------------------------------------------------------------------- 1 | let g:crtFuncIndent = 4 2 | 3 | setlocal nocindent nosmartindent indentexpr="" autoindent 4 | setlocal foldmethod=indent 5 | setlocal foldlevel=1 6 | setlocal foldtext=MyFoldText() 7 | setlocal fillchars=fold:\ ,vert:\| 8 | setlocal foldnestmax=2 9 | 10 | set suffixesadd=.java 11 | set path+=** 12 | 13 | nnoremap sc :so ~/.vim/java.vim 14 | nnoremap ec :tabe ~/.vim/java.vim :tc 15 | 16 | command! -nargs=0 JDoc :call JDoc() 17 | 18 | function! MoveClass() 19 | let l:newClassname = py3eval("get_classname(vim.current.buffer)") 20 | let l:oldClassname = expand("%:t:s/.java//") 21 | if l:newClassname == l:oldClassname 22 | return 23 | endif 24 | let l:bufname = expand("%") 25 | let l:dir = expand("%:h") 26 | let l:newname = l:dir."/".l:newClassname.".java" 27 | call rename(l:bufname, l:newname) 28 | execute "edit ".l:newname 29 | execute "bdelete ".l:bufname 30 | execute "%s/".l:oldClassname."/".l:newClassname."/g" 31 | write 32 | endfunction 33 | 34 | function! JDoc() 35 | python3 << EOF 36 | import vim 37 | import re 38 | line = vim.current.line 39 | regObj = re.match("^(\s)*(?:\w+ )*(\w+) \w+\((.*?)\) {$", line) 40 | indentstr = regObj.group(1) 41 | reType = regObj.group(2) 42 | params = regObj.group(3) 43 | paramLs = params.split(', ') 44 | docstr = ( 45 | indentstr+'/**\n' + 46 | indentstr+' * \n' + 47 | (('\n'.join([ 48 | indentstr+' *' + ' @param ' + paramLs[i].split(' ')[1] 49 | for i in range(0, len(paramLs)) 50 | ]) + '\n') if params != '' else '') + 51 | (indentstr+' * @return ' + '\n' if reType != 'void' else '') + 52 | indentstr+' */' 53 | ) 54 | vim.current.buffer.append(docstr.split("\n"), int(vim.eval('line(\'.\')'))-1) 55 | EOF 56 | endfunction 57 | -------------------------------------------------------------------------------- /nvim/luasnippets/all.lua: -------------------------------------------------------------------------------- 1 | local function neg(fn, ...) 2 | return not fn(...) 3 | end 4 | 5 | local function even_count(c) 6 | local line = vim.api.nvim_get_current_line() 7 | local _, ct = string.gsub(line, c, '') 8 | return ct % 2 == 0 9 | end 10 | 11 | local function part(func, ...) 12 | local args = {...} 13 | return function() return func(unpack(args)) end 14 | end 15 | 16 | local function char_count_same(c1, c2) 17 | local line = vim.api.nvim_get_current_line() 18 | local _, ct1 = string.gsub(line, '%'..c1, '') 19 | local _, ct2 = string.gsub(line, '%'..c2, '') 20 | return ct1 == ct2 21 | end 22 | 23 | local function pair(pair_begin, pair_end, expand_func, ...) 24 | s_add({trig = pair_begin, wordTrig=false}, {t({pair_begin}), i(1), t({pair_end})}, {condition = part(expand_func, part(..., pair_begin, pair_end))}) 25 | end 26 | 27 | pair("(", ")", neg, char_count_same) 28 | pair("{", "}", neg, char_count_same) 29 | pair("[", "]", neg, char_count_same) 30 | pair("<", ">", neg, char_count_same) 31 | pair("'", "'", neg, even_count) 32 | pair('"', '"', neg, even_count) 33 | pair("`", "`", neg, even_count) 34 | s_add({trig="{,", wordTrig=false, hidden=true, priority=1001}, { t({"{","\t"}), i(1, "", {key = "asdf"}), t({"", "}"}) }) 35 | 36 | parse_add("lel", "lo") 37 | parse_add("lal", "la") 38 | 39 | -- local k = require("luasnip.nodes.key_indexer").new_key 40 | -- s_add("aaa", { 41 | -- rep(k("a")), 42 | -- t" ", 43 | -- i(1, "etest", {key = "a"}) 44 | -- }) 45 | 46 | s_add('map1', 47 | fmt( 48 | [[ 49 | vim.keaeeeeeee.set('{}', '{}', function() 50 | {} 51 | end, {{ silent = true, desc = '{}' }}) 52 | ]], 53 | { 54 | i(1, 'mode'), 55 | i(2, 'lhs'), 56 | i(3, 'vim.opt.textwidth = 100'), 57 | i(4, 'My awesome mapping'), 58 | } 59 | )) 60 | 61 | parse_add("xx", "(${1:asdf})") 62 | -------------------------------------------------------------------------------- /nixos/home/profiles/neovim/julia-lsp.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | pkgs.writeShellApplication (let 3 | lsp_script = pkgs.writeTextFile { 4 | name = "lsp"; 5 | text = 6 | # julia 7 | '' 8 | # Load LanguageServer.jl: attempt to load from ~/.julia/environments/nvim-lspconfig 9 | # with the regular load path as a fallback 10 | ls_install_path = joinpath( 11 | get(DEPOT_PATH, 1, joinpath(homedir(), ".julia")), 12 | "environments", "nvim-lspconfig" 13 | ) 14 | pushfirst!(LOAD_PATH, ls_install_path) 15 | using LanguageServer 16 | popfirst!(LOAD_PATH) 17 | depot_path = get(ENV, "JULIA_DEPOT_PATH", "") 18 | project_path = let 19 | dirname(something( 20 | ## 1. Finds an explicitly set project (JULIA_PROJECT) 21 | Base.load_path_expand(( 22 | p = get(ENV, "JULIA_PROJECT", nothing); 23 | p === nothing ? nothing : isempty(p) ? nothing : p 24 | )), 25 | ## 2. Look for a Project.toml file in the current working directory, 26 | ## or parent directories, with $HOME as an upper boundary 27 | Base.current_project(), 28 | ## 3. First entry in the load path 29 | get(Base.load_path(), 1, nothing), 30 | ## 4. Fallback to default global environment, 31 | ## this is more or less unreachable 32 | Base.load_path_expand("@v#.#"), 33 | )) 34 | end 35 | @info "Running language server" VERSION pwd() project_path depot_path 36 | server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path) 37 | run(server) 38 | ''; 39 | }; 40 | in { 41 | name = "julia-lsp"; 42 | text = '' 43 | ${pkgs.julia-bin}/bin/julia --startup-file=no --history-file=no ${lsp_script} 44 | ''; 45 | }) 46 | -------------------------------------------------------------------------------- /nvim/lua/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | vim.treesitter.language.register("bash", "PKGBUILD") 2 | 3 | require'nvim-treesitter.configs'.setup { 4 | ensure_installed = { 5 | "rust", 6 | "hlsl", 7 | "bibtex", 8 | "c", 9 | "gitignore", 10 | "gitattributes", 11 | "bash", 12 | "zig", 13 | "make", 14 | "python", 15 | "mermaid", 16 | -- "jsonc", 17 | "json", 18 | "markdown", 19 | "dot", 20 | "java", 21 | -- "vimdoc", 22 | "regex", 23 | "luap", 24 | "vim", 25 | "toml", 26 | "css", 27 | "html", 28 | "julia", 29 | "latex", 30 | "nix", 31 | "llvm", 32 | "lua", 33 | "cpp", 34 | "proto", 35 | "just" 36 | }, 37 | playground = { 38 | enable = true 39 | }, 40 | textobjects = { 41 | select = { 42 | enable = true, 43 | 44 | -- Automatically jump forward to textobj, similar to targets.vim 45 | lookahead = true, 46 | 47 | keymaps = { 48 | -- You can use the capture groups defined in textobjects.scm 49 | ["af"] = "@function.outer", 50 | ["if"] = "@function.inner", 51 | ["ac"] = "@call.outer", 52 | ["ic"] = "@call.inner", 53 | }, 54 | }, 55 | swap = { 56 | enable = true, 57 | swap_next = { 58 | [">"] = "@parameter.inner", 59 | }, 60 | swap_previous = { 61 | ["<"] = "@parameter.inner", 62 | }, 63 | }, 64 | move = { 65 | enable = true, 66 | set_jumps = true, -- whether to set jumps in the jumplist 67 | goto_next_start = { 68 | ["]m"] = "@function.outer", 69 | }, 70 | goto_next_end = { 71 | ["]M"] = "@function.outer", 72 | }, 73 | goto_previous_start = { 74 | ["[m"] = "@function.outer", 75 | }, 76 | goto_previous_end = { 77 | ["[M"] = "@function.outer", 78 | }, 79 | }, 80 | }, 81 | highlight = { 82 | enable = true, 83 | additional_vim_regex_highlighting = false, 84 | }, 85 | indent = { 86 | enable = false 87 | }, 88 | } 89 | -------------------------------------------------------------------------------- /nixos/profiles/webdav.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, data, ... }: 2 | 3 | let 4 | dav_root = "/srv/http/dav"; 5 | in { 6 | # downside: can only do this once, for other plugins I'll have to make a personal caddy module or something. 7 | services.caddy.package = pkgs.caddy.withPlugins { 8 | plugins = ["github.com/mholt/caddy-webdav@v0.0.0-20241008162340-42168ba04c9d"]; 9 | # May have to update this whenever a new nixpkgs is used! 10 | hash = "sha256-rrkUDnTPKehdKMBDaZdFbaEL2QOsHb3tn6dst2UclE8="; 11 | }; 12 | 13 | services.caddy.globalConfig = '' 14 | order webdav before file_server 15 | ''; 16 | 17 | services.caddy.extraConfig = '' 18 | http://webdav, http://webdav.internal, http://webdav.${machine} { 19 | webdav * { 20 | root ${dav_root} 21 | prefix / 22 | } 23 | file_server 24 | } 25 | ''; 26 | 27 | systemd.tmpfiles.rules = [ 28 | "d ${dav_root} 0750 caddy caddy" 29 | "d ${dav_root}/android-backup 0750 caddy caddy" 30 | "d ${dav_root}/media 0755" 31 | ]; 32 | # for clients: nfs-mount these shares. 33 | fileSystems."${dav_root}/media" = { 34 | device = "/srv/media/"; 35 | options = [ "bind" ]; 36 | }; 37 | 38 | l3mon.restic.extraGroups = [ "caddy" ]; 39 | l3mon.restic.specs.webdav = { 40 | backupDaily = { 41 | text = '' 42 | cd ${dav_root} 43 | if ls ./* &> /dev/null; then 44 | restic backup --tag=webdav --skip-if-unchanged=true -- ./android-backup/ 45 | fi 46 | ''; 47 | }; 48 | forget = { 49 | text = '' 50 | # Primarily stores seedvault-files, which can get rather big :| 51 | # They are not plain text, but encrypted, so no good incremental sync 52 | # => only keep one up-to-date backup. 53 | restic forget --tag=webdav --group-by=tag --keep-last=1 54 | ''; 55 | }; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /nixos/profiles/karakeep.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, data, ... }: 2 | 3 | let 4 | machine_lan_address = data.network.lan.peers.${machine}.address; 5 | in { 6 | users.users.karakeep.uid = data.ids.karakeep; 7 | users.groups.karakeep.gid = data.ids.karakeep; 8 | 9 | services.karakeep = { 10 | enable = true; 11 | package = pkgs-unstable.karakeep.overrideAttrs (old: { 12 | # from https://github.com/NixOS/nixpkgs/pull/416531 13 | postInstall = '' 14 | # provide a environment variable to override the cache directory 15 | # https://github.com/vercel/next.js/discussions/58864 16 | # solution copied from nextjs-ollama-llm-ui 17 | substituteInPlace $out/lib/karakeep/apps/web/.next/standalone/node_modules/next/dist/server/image-optimizer.js \ 18 | --replace '_path.join)(distDir,' '_path.join)(process.env["NEXT_CACHE_DIR"] || distDir,' 19 | ''; 20 | }); 21 | # environmentFile = "/var/secrets/karakeep-envfile"; 22 | extraEnvironment = { 23 | PORT = toString data.ports.karakeep; 24 | DISABLE_SIGNUPS = "false"; 25 | DISABLE_NEW_RELEASE_CHECK = "true"; 26 | CRAWLER_VIDEO_DOWNLOAD = "true"; 27 | # 100 hrs. 28 | CRAWLER_VIDEO_DOWNLOAD_TIMEOUT_SEC = "360000"; 29 | CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE = "-1"; 30 | 31 | # from https://github.com/NixOS/nixpkgs/pull/416531 32 | # uses systemd unit CacheDirectory instead of in nix store 33 | NEXT_CACHE_DIR = "$CACHE_DIRECTORY"; 34 | }; 35 | }; 36 | 37 | services.meilisearch = { 38 | package = pkgs-unstable.meilisearch; 39 | enable = true; 40 | listenPort = data.ports.meilisearch; 41 | }; 42 | 43 | services.caddy.extraConfig = '' 44 | http://kk, http://kk.internal, http://kk.${machine} { 45 | reverse_proxy http://${machine_lan_address}:${toString data.ports.karakeep} 46 | } 47 | ''; 48 | } 49 | -------------------------------------------------------------------------------- /nvim/lua/vkdoc.lua: -------------------------------------------------------------------------------- 1 | local p = require("dbus_proxy") 2 | local vkinfo = require("vkinfo") 3 | 4 | local function find_zathura_dbus() 5 | local fd = io.popen("pidof zathura") 6 | -- skip linebreak. 7 | local pidofstring = fd:read("*all"):sub(1, -2) 8 | 9 | if #pidofstring == 0 then 10 | return nil 11 | end 12 | for _, pidstr in ipairs(vim.split(pidofstring, " ")) do 13 | local proxy = p.Proxy:new({ 14 | bus = p.Bus.SESSION, 15 | name = "org.pwmt.zathura.PID-" .. pidstr, 16 | interface = "org.pwmt.zathura", 17 | path = "/org/pwmt/zathura" 18 | }) 19 | if proxy.filename:match("vkspec.pdf$") then 20 | return proxy 21 | end 22 | end 23 | 24 | return nil 25 | end 26 | 27 | local function to_search_name(word) 28 | -- does not begin with any of vk, Vk 29 | if word:sub(1,2):lower() ~= "vk" then 30 | word = "Vk"..word 31 | end 32 | if vkinfo.structnames[word] then 33 | return "typedef struct " .. word 34 | end 35 | if vkinfo.handlenames[word] then 36 | return "HANDLE(" .. word .. ")" 37 | end 38 | if vkinfo.enumnames[word] then 39 | return "typedef enum " .. word 40 | 41 | end 42 | if vkinfo.functions[word] then 43 | return word .. "(\n" 44 | end 45 | 46 | -- not found -> just search for word. 47 | return word 48 | end 49 | 50 | local dbus 51 | vim.keymap.set("n", "", function() 52 | local word = to_search_name(vim.fn.expand("")) 53 | if not word then 54 | vim.notify("Invalid query: " .. word) 55 | return 56 | end 57 | -- dbus has to be initialized. 58 | if not dbus then 59 | dbus = find_zathura_dbus() 60 | -- vkspec might not have been opened yet! 61 | if not dbus then 62 | vim.defer_fn(function() 63 | io.popen("bash -c 'zathura --fork ~/Documents/vkspec.pdf -f \"" .. word .. "\" > /dev/null 2>/dev/null'") 64 | end, 0) 65 | return 66 | end 67 | end 68 | dbus:Search(word) 69 | vim.notify("Couldn't find vkspec in any zathura session.") 70 | end) 71 | -------------------------------------------------------------------------------- /nixos/profiles/ncps.nix: -------------------------------------------------------------------------------- 1 | { self, config, lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | services.ncps = { 5 | enable = true; 6 | cache = { 7 | hostName = "ncps.internal"; 8 | allowPutVerb = true; 9 | allowDeleteVerb = true; 10 | secretKeyPath = config.l3mon.secgen.secrets.ncps.key; 11 | }; 12 | server.addr = "127.0.0.1:${toString data.ports.ncps}"; 13 | upstream = { 14 | # if possible, pull from local caches. 15 | caches = (lib.attrsets.foldlAttrs (acc: name: os: 16 | if os.config.l3mon.peercache.push && {"carmine"=null; "indigo"=null;} ? ${name} then 17 | acc ++ ["http://cache.${name}.internal"] 18 | else acc) [] self.outputs.nixosConfigurations) 19 | ++ [ 20 | "https://cache.nixos.org" 21 | "https://nix-community.cachix.org" 22 | ]; 23 | publicKeys = with data.pubkeys; [ 24 | cachix-community 25 | nixos-org 26 | peercache-carmine 27 | peercache-indigo 28 | ]; 29 | }; 30 | }; 31 | 32 | systemd.services.ncps = { 33 | after = [ "blocky_lan.service" ]; 34 | serviceConfig.RestartSec = "30s"; 35 | }; 36 | 37 | services.caddy.extraConfig = '' 38 | http://ncps, http://ncps.internal, http://ncps.${machine} { 39 | reverse_proxy http://127.0.0.1:${toString data.ports.ncps} 40 | } 41 | ''; 42 | 43 | l3mon.secgen.secrets.ncps = rec { 44 | key = "${config.l3mon.secgen.secret_dir}/nix-cache-ncps"; 45 | backup_files = [ key ]; 46 | gen = pkgs.writeShellApplication { 47 | name = "gen"; 48 | text = 49 | # bash 50 | '' 51 | tmppubkey=$(mktemp) 52 | nix-store --generate-binary-cache-key "ncps.internal" "${key}" "$tmppubkey" 53 | 54 | PUBKEY=$(cat "$tmppubkey") 55 | echo "Update 'ncps' to \"$PUBKEY\" in data/pubkeys.nix" 56 | 57 | rm "$tmppubkey" 58 | ''; 59 | }; 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /nvim/queries/lua/folds.scm: -------------------------------------------------------------------------------- 1 | ( 2 | (for_statement 3 | clause: (_) @clause 4 | (_) 5 | ) @for_stmt 6 | (#make-range-extended! "fold" @clause "end" 0 1 @for_stmt "end" 0 0) 7 | (#set! foldtext_start "do") 8 | (#set! foldtext_start_hl "@conditional") 9 | (#set! foldtext_end "end") 10 | (#set! foldtext_end_hl "@conditional") 11 | ) 12 | 13 | ( 14 | (if_statement 15 | condition: (_) @cond 16 | (_) 17 | ) @if_stmt 18 | (#make-range-extended! "fold" @cond "end" 0 1 @if_stmt "end" 0 0) 19 | (#set! foldtext_start "then") 20 | (#set! foldtext_start_hl "@conditional") 21 | (#set! foldtext_end "end") 22 | (#set! foldtext_end_hl "@conditional") 23 | ) 24 | 25 | ( 26 | [ 27 | (function_declaration 28 | parameters: (_) @params) 29 | (function_definition 30 | parameters: (_) @params) 31 | ] @fn 32 | (#make-range-extended! "fold" @params "end" 0 1 @fn "end" 0 0) 33 | (#set! foldtext_start "") 34 | (#set! foldtext_start_hl "") 35 | (#set! foldtext_end "end") 36 | (#set! foldtext_end_hl "@keyword.function") 37 | ) 38 | 39 | ( 40 | (table_constructor) @tc 41 | (#make-range-extended! "fold" @tc "start" 0 1 @tc "end" 0 -1) 42 | ) 43 | 44 | 45 | ; ( 46 | ; (function_call 47 | ; name: (_) @name 48 | ; (arguments) @fold) 49 | ; (#set! foldtext_start "(") 50 | ; (#set! foldtext_start_hl "@punctuation.bracket") 51 | ; (#set! foldtext_end ")") 52 | ; (#set! foldtext_end_hl "@punctuation.bracket") 53 | ; (#not-any-of? @name "it" "describe") 54 | ; ) 55 | 56 | ; fold both a single and multiple arguments. 57 | ( 58 | (function_call 59 | name: (_) @name 60 | [(arguments 61 | (_) @first . 62 | (_)* 63 | (_) @last 64 | ) 65 | (arguments 66 | . (_) @first @last .) 67 | ] 68 | ) 69 | 70 | (#make-range-extended! "fold" @first "start" 0 0 @last "end" 0 0) 71 | (#set! foldtext_start "") 72 | (#set! foldtext_start_hl "") 73 | (#set! foldtext_end "") 74 | (#set! foldtext_end_hl "") 75 | ) 76 | -------------------------------------------------------------------------------- /nvim/lua/plugins/cmp.lua: -------------------------------------------------------------------------------- 1 | local cmp = require'cmp' 2 | local types = require("cmp.types") 3 | local session = require("session") 4 | 5 | cmp.setup { 6 | completion = { 7 | autocomplete = false,-- {cmp.TriggerEvent.TextChanged}, 8 | completeopt = "menu,menuone,select" 9 | }, 10 | snippet = { 11 | expand = function(args) 12 | local override_snip = session.lsp_override_snips[args.body] 13 | if override_snip then 14 | require("luasnip").snip_expand(override_snip) 15 | else 16 | require("luasnip").lsp_expand(args.body) 17 | end 18 | end, 19 | }, 20 | mapping = { 21 | [''] = cmp.mapping.scroll_docs(-4), 22 | -- [''] = cmp.mapping.scroll_docs(4), 23 | [''] = cmp.mapping.confirm(), 24 | [''] = cmp.mapping.select_next_item({ behavior = types.cmp.SelectBehavior.Insert }), 25 | [''] = cmp.mapping.select_prev_item({ behavior = types.cmp.SelectBehavior.Insert }), 26 | }, 27 | sources = cmp.config.sources({ 28 | {name = "path"}, 29 | {name = "luasnip"} 30 | }), 31 | window = { 32 | documentation = false, 33 | }, 34 | experimental = { 35 | ghost_text = true 36 | }, 37 | } 38 | 39 | vim.keymap.set("i", "", function() 40 | cmp.complete({ 41 | config = { 42 | sources = { 43 | {name = "nvim_lsp"}, 44 | {name = "luasnip"}, 45 | } 46 | } 47 | }) 48 | end) 49 | 50 | vim.keymap.set("i", "", function() 51 | cmp.complete({ 52 | config = { 53 | sources = { 54 | {name = "emoji"}, 55 | } 56 | } 57 | }) 58 | end) 59 | 60 | vim.keymap.set("i", "", function() 61 | cmp.complete({ 62 | config = { 63 | sources = { 64 | { 65 | name = "path", 66 | option = { 67 | get_cwd = function(params) 68 | local path = { 69 | vim.fn.expand(('#%d:p:h'):format(params.context.bufnr)), -- default value 70 | vim.fn.getcwd(), 71 | } 72 | return path 73 | end 74 | }, 75 | } 76 | } 77 | } 78 | }) 79 | end) 80 | -------------------------------------------------------------------------------- /nixos/profiles/sway/decoration.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | wayland.windowManager.sway.extraConfig = let 5 | fg = data.gruvbox.bg0_h; 6 | bg = data.gruvbox.regular_aqua; 7 | focused = data.gruvbox.bright_green; 8 | unfocused = data.gruvbox.bright_blue; 9 | in '' 10 | titlebar_border_thickness 0 11 | titlebar_padding 3 12 | 13 | default_border none 14 | default_floating_border normal 1 15 | 16 | font pango:monospace 0.001 17 | 18 | client.focused #${focused} #${focused} #${focused} 19 | client.unfocused #${unfocused} #${unfocused} #${unfocused} 20 | client.focused_inactive #${unfocused} #${unfocused} #${unfocused} 21 | 22 | output * bg #${bg} solid_color 23 | ''; 24 | 25 | systemd.user.services.sway_top_bar = let 26 | sway_top_bar = l3lib.writeLuajit "/bin/sway_top_bar" { libraries = [ pkgs.l3mon.k-sway ]; } '' 27 | local Sway = require("sway") 28 | local sway = Sway.connect() 29 | 30 | for event in sway:subscribe({"window"}, 0) do 31 | -- have to apply border to new windows, and windows whose floating is toggled. 32 | if event.change == "floating" or event.change == "new" then 33 | -- os.execute("${pkgs.coreutils}/bin/sleep .001") 34 | local command = event.container.type == "floating_con" and 35 | "border pixel 1, border normal" or "border pixel 0, border normal" 36 | sway:msg(("[con_id=%s] %s"):format(event.container.id, command)) 37 | end 38 | end 39 | ''; 40 | in { 41 | Unit = { 42 | Description = "Adjust top-bar for floating/tiling windows."; 43 | PartOf = [ "sway-session.target" ]; 44 | After = [ "sway-session.target" ]; 45 | ConditionEnvironment = "WAYLAND_DISPLAY"; 46 | }; 47 | Service = { 48 | ExecStart = "${sway_top_bar}/bin/sway_top_bar"; 49 | }; 50 | Install = { 51 | WantedBy = [ "sway-session.target" ]; 52 | }; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /nixos/home/profiles/julia.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, scientific-fhs, ... }: 2 | 3 | { 4 | home.file.".julia/config/startup.jl".text = '' 5 | using Revise 6 | 7 | using Images 8 | 9 | global imv_proc 10 | global imv_pid = -1 11 | fname_png = "/tmp/julia_image.png" 12 | function Base.display(i::AbstractArray{RGBA{N0f8}, 2}) 13 | save(fname_png, i) 14 | if imv_pid == -1 15 | global imv_proc = run(`imv $fname_png`, wait = false) 16 | global imv_pid = getpid(imv_proc) 17 | atexit() do 18 | kill(imv_proc) 19 | end 20 | end 21 | end 22 | function Base.display(i::AbstractArray{RGB{N0f8}, 2}) 23 | save(fname_png, i) 24 | if imv_pid == -1 25 | global imv_proc = run(`imv $fname_png`, wait = false) 26 | global imv_pid = getpid(imv_proc) 27 | atexit() do 28 | kill(imv_proc) 29 | end 30 | end 31 | end 32 | 33 | global tev_proc 34 | global tev_pid = -1 35 | fname_exr = "/tmp/julia_image.exr" 36 | function Base.display(i::AbstractArray{RGB{Float16}, 2}) 37 | save(fname_exr, i) 38 | run(`tev $fname_exr`, wait = false) 39 | end 40 | ''; 41 | 42 | home.packages = with pkgs; [ 43 | (pkgs.writeShellApplication (let 44 | # the unsafe is okay here because we want nixos-rebuild to only build the derivation, and then `nix develop ...` will actually build the derivation. 45 | fhs_path = (builtins.unsafeDiscardOutputDependency (scientific-fhs.override{ enableQuarto=true; enableJulia=true; juliaVersion = "1.11.6"; commandScript = "julia"; }).env.drvPath); 46 | in { 47 | name = "julia"; 48 | text = '' 49 | nix develop "${fhs_path}" 50 | ''; 51 | })) 52 | imv 53 | (tev.overrideAttrs (final: prev: { 54 | patches = (if prev ? patches then prev.patches else []) ++ [ 55 | ./tev.patch 56 | ]; 57 | })) 58 | ]; 59 | home.shellAliases = { 60 | jl = "julia"; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /nvim/lua/plugins/blink.lua: -------------------------------------------------------------------------------- 1 | local cmp = require("blink.cmp") 2 | cmp.setup{ 3 | -- default-keybindings do weird stuff on . 4 | keymap = { 5 | preset = 'none', 6 | [""] = {'accept'} 7 | }, 8 | cmdline = { 9 | enabled = false, 10 | sources = {} 11 | }, 12 | sources = { 13 | default = function() 14 | return {"lsp", "snippets"} 15 | end, 16 | }, 17 | completion = { 18 | trigger = { 19 | prefetch_on_insert = false, 20 | show_on_keyword = false, 21 | show_on_trigger_character = false, 22 | show_on_insert_on_trigger_character = false, 23 | show_on_accept_on_trigger_character = false, 24 | }, 25 | list = { 26 | selection = {auto_insert = true} 27 | } 28 | }, 29 | snippets = { 30 | preset = "luasnip", 31 | expand = function(snip) 32 | local override_snip = require("session").lsp_override_snips[snip] 33 | if override_snip then 34 | require("luasnip").snip_expand(override_snip) 35 | else 36 | require("luasnip").lsp_expand(snip) 37 | end 38 | end, 39 | } 40 | } 41 | 42 | local function show_and_select(opts) 43 | cmp.show(opts) 44 | -- run cmp.select_next as soon as the window is open. 45 | local select_immediately_cb 46 | select_immediately_cb = function() 47 | cmp.select_next() 48 | require("blink.cmp.completion.windows.menu").open_emitter:off(select_immediately_cb) 49 | end 50 | require("blink.cmp.completion.windows.menu").open_emitter:on(select_immediately_cb) 51 | end 52 | 53 | vim.keymap.set("i", "", function() 54 | cmp.show({providers = {"lsp", "snippets"}}) 55 | end) 56 | 57 | vim.keymap.set("i", "", function() 58 | if not require('blink.cmp.completion.windows.menu').win:is_open() then 59 | return "" 60 | -- show_and_select({providers = {"buffer"}}) 61 | else 62 | cmp.select_next() 63 | end 64 | end, {expr=true}) 65 | 66 | vim.keymap.set("i", "", function() 67 | if not require('blink.cmp.completion.windows.menu').win:is_open() then 68 | return "" 69 | -- show_and_select({providers = {"buffer"}}) 70 | else 71 | cmp.select_prev() 72 | end 73 | end, {expr=true}) 74 | -------------------------------------------------------------------------------- /nvim/queries/julia/folds.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (macro_definition) 3 | 4 | (if_statement) 5 | (try_statement) 6 | (while_statement) 7 | (let_statement) 8 | (quote_statement) 9 | 10 | (compound_statement) 11 | ] @fold 12 | 13 | ((vector_expression) @expr 14 | (#make-range-extended! "fold" @expr "start" 0 0 @expr "end" 0 0) 15 | (#set! foldtext_start "[") 16 | (#set! foldtext_start_hl "@punctuation.bracket.julia") 17 | (#set! foldtext_end "]") 18 | (#set! foldtext_end_hl "@punctuation.bracket.julia") 19 | ) 20 | 21 | ((if_statement 22 | condition: (_) @cond) @if 23 | ; ends with a `end`, have the folded region end just before that. 24 | (#make-range-extended! "fold" @cond "end" 0 1 @if "end" 0 -3) 25 | ) 26 | 27 | ((for_statement 28 | (for_binding) @bind) @if 29 | ; ends with a `end`, have the folded region end just before that. 30 | (#make-range-extended! "fold" @bind "end" 0 1 @if "end" 0 -3) 31 | ) 32 | 33 | ; ( 34 | ; [ 35 | ; (for_statement 36 | ; (for_binding) @from 37 | ; ) @to 38 | ; (function_definition 39 | ; parameters: (parameter_list) @from) @to 40 | ; (module_definition 41 | ; name: (identifier) @from) @to 42 | ; ] 43 | ; (#make-range-extended! "fold" @from "end" 0 1 @to "end" 0 0) 44 | ; (#set! foldtext_start "") 45 | ; (#set! foldtext_start_hl "") 46 | ; (#set! foldtext_end "end") 47 | ; (#set! foldtext_end_hl "@keyword") 48 | ; ) 49 | 50 | ( 51 | (do_clause) @fold 52 | (#set! foldtext_start "do") 53 | (#set! foldtext_start_hl "@keyword") 54 | (#set! foldtext_end "end") 55 | (#set! foldtext_end_hl "@keyword") 56 | ) 57 | 58 | ( 59 | (function_definition 60 | (signature) @sig) @fn 61 | (#make-range-extended! "fold" @sig "end" 0 1 @fn "end" 0 -3) 62 | ) 63 | 64 | ( 65 | (struct_definition) @struct 66 | (#make-range-extended! "fold" @struct "start" 0 1000 @struct "end" 0 -3) 67 | ) 68 | 69 | ( 70 | (matrix_expression) @mx 71 | (#make-range-extended! "fold" @mx "start" 0 1 @mx "end" 0 -1) 72 | (#set! "priority" 101) 73 | ) 74 | ( 75 | (argument_list) @ls 76 | (#make-range-extended! "fold" @ls "start" 0 1 @ls "end" 0 -1) 77 | ) 78 | -------------------------------------------------------------------------------- /nvim/meta/luasnippets/defs.lua: -------------------------------------------------------------------------------- 1 | ---@meta 2 | 3 | ms = require("luasnip").multi_snippet 4 | ms_add = require("luasnip").multi_snippet 5 | s_add = require("luasnip").s 6 | s_add_auto = require("luasnip").s 7 | ts_px_add = require("luasnip.extras.treesitter_postfix").treesitter_postfix 8 | px_add = require("luasnip.extras.postfix").postfix 9 | s = require("luasnip").s 10 | sn = require("luasnip").sn 11 | t = require("luasnip").t 12 | i = require("luasnip").i 13 | f = require("luasnip").f 14 | -- override to enable restore_cursor. 15 | c = require("luasnip").c 16 | d = require("luasnip").d 17 | isn = require("luasnip.nodes.snippet").ISN 18 | l = require'luasnip.extras'.lambda 19 | dl = require'luasnip.extras'.dynamic_lambda 20 | rep = require'luasnip.extras'.rep 21 | r = require("luasnip").restore_node 22 | p = require("luasnip.extras").partial 23 | types = require("luasnip.util.types") 24 | events = require("luasnip.util.events") 25 | util = require("luasnip.util.util") 26 | fmt = require("luasnip.extras.fmt").fmt 27 | fmta = require("luasnip.extras.fmt").fmta 28 | ls = require("luasnip") 29 | ins_generate = function(nodes) 30 | return setmetatable(nodes or {}, { 31 | __index = function(table, key) 32 | local indx = tonumber(key) 33 | if indx then 34 | local val = require("luasnip").i(indx) 35 | rawset(table, key, val) 36 | return val 37 | end 38 | end}) 39 | end 40 | parse_add = require("luasnip").parser.parse_snippet 41 | parse_add_auto = require("luasnip").parser.parse_snippet 42 | parse = require("luasnip").parser.parse_snippet 43 | n = require("luasnip.extras").nonempty 44 | m = require("luasnip.extras").match 45 | ai = require("luasnip.nodes.absolute_indexer") 46 | postfix = require("luasnip.extras.postfix").postfix 47 | ts_postfix = require("luasnip.extras.treesitter_postfix").treesitter_postfix 48 | conds = require("luasnip.extras.expand_conditions") 49 | k = require("luasnip.nodes.key_indexer").new_key 50 | opt = (function() 51 | if pcall(require, "luasnip.nodes.optional_arg") then 52 | return require("luasnip.nodes.optional_arg").new_opt 53 | else 54 | return nil 55 | end 56 | end)() 57 | -------------------------------------------------------------------------------- /nixos/profiles/kimmify.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | kimmify = pkgs.writeShellApplication { 5 | name = "kimmify"; 6 | runtimeInputs = with pkgs; [ (ffmpeg.override {withPlacebo=true;}) util-linux ripgrep coreutils ]; 7 | text = '' 8 | TARGET_DIR=/srv/media/video/kim 9 | 10 | for FILE_PATH in "$@" 11 | do 12 | FNAME=$(basename -- "$FILE_PATH") 13 | 14 | # map video, audio, and subtitle-streams. 15 | # copy subtitles, transcode video to h264 1080p, transcode audio to aac. 16 | # use crf19 for a good bitrate. 17 | # use veryslow so the files are as small as possible (transcoding happens overnight anyway, so that should be fine :D) 18 | # profile high and level 4.1 are recommended [here](https://developers.google.com/cast/docs/media) 19 | # 20 | # Apply tonemapping via libplacebo, and crop video so width|height % 2 == 0 (for yuv420p). 21 | # The resulting video is not profile high but profile constrained baseline, but that seems fine :) 22 | # 23 | # 0:V to exclude cover art. 24 | 25 | # confine ffmpeg to all but the first core. 26 | # for nvenc: -hwaccel -vcodec h264_nvenc -preset p7 (for example). 27 | taskset -c 1-"$(lscpu | rg ^CPU.s.: | rg -o -e '\d+')" ffmpeg -y -init_hw_device vulkan=vk -filter_hw_device vk -i "''${FILE_PATH}" \ 28 | -map 0:V \ 29 | -vf "libplacebo=w=1920:h=1080:force_original_aspect_ratio=decrease:normalize_sar=true:upscaler=ewa_lanczos:downscaler=ewa_lanczos:colorspace=bt709:color_primaries=bt709:color_trc=bt709:range=tv:format=yuv420p,crop=trunc(iw/2)*2:trunc(ih/2)*2" \ 30 | -vcodec libx265 \ 31 | -crf 19 \ 32 | -preset slow \ 33 | -map 0:a \ 34 | -acodec aac \ 35 | -map 0:s? \ 36 | -c:s copy \ 37 | "$TARGET_DIR/$FNAME" 38 | done 39 | ''; 40 | }; 41 | in { 42 | environment.systemPackages = [ 43 | kimmify 44 | ]; 45 | systemd.tmpfiles.rules = [ 46 | "d /srv/media/video/kim 750 simon simon" 47 | ]; 48 | } 49 | -------------------------------------------------------------------------------- /nixos/profiles/localnet.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, data, machine, ... }: 2 | 3 | let 4 | lan = data.network.lan; 5 | lan_machine = lan.peers.${machine}; 6 | in 7 | { 8 | networking.hostName = machine; 9 | networking.useDHCP = false; 10 | networking.firewall.enable = false; 11 | 12 | networking.interfaces.${lan_machine.phys_interface} = { 13 | macAddress = lan_machine.phys_mac; 14 | wakeOnLan.enable = true; 15 | }; 16 | 17 | systemd.network.enable = true; 18 | systemd.network.networks = { 19 | "10-lan" = { 20 | matchConfig.Name = lan.peers."${machine}".phys_interface; 21 | # prevent systemd-wait-online for waiting on an ip for this interface. 22 | linkConfig.RequiredForOnline = "carrier"; 23 | # don't wait for ip-assignment via DHCP. 24 | networkConfig.DHCP = false; 25 | networkConfig.IPv6AcceptRA = false; 26 | networkConfig.LinkLocalAddressing = false; 27 | networkConfig.MACVLAN = "${lan.peers."${machine}".interface}"; 28 | }; 29 | "20-vlan" = { 30 | matchConfig.Name = "${lan.peers.${machine}.interface}"; 31 | linkConfig.RequiredForOnline = "routable"; 32 | networkConfig.Address = lan.peers."${machine}".address + lan.subnet_mask; 33 | networkConfig.Gateway = lan.gateway_peer.address; 34 | networkConfig.DHCP = false; 35 | networkConfig.IPv6AcceptRA = false; 36 | networkConfig.LinkLocalAddressing = false; 37 | networkConfig.DNS = lan.dns; 38 | networkConfig.DNSOverTLS = false; 39 | networkConfig.DNSSEC = false; 40 | networkConfig.BindCarrier = "${lan.peers.${machine}.phys_interface}"; 41 | }; 42 | }; 43 | 44 | systemd.network.netdevs."10-macvlan" = { 45 | netdevConfig = { 46 | Name = "${lan.peers."${machine}".interface}"; 47 | Kind = "macvlan"; 48 | MACAddress = "${lan.peers."${machine}".mac}"; 49 | }; 50 | macvlanConfig.Mode = "bridge"; 51 | }; 52 | 53 | services.resolved = { 54 | enable = true; 55 | dnssec = "true"; 56 | dnsovertls = "true"; 57 | llmnr = "false"; 58 | extraConfig = '' 59 | ResolveUnicastSingleLabel=true 60 | ''; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /nvim/functions.vim: -------------------------------------------------------------------------------- 1 | function! MyTabLine() 2 | let s = '' 3 | for i in range(tabpagenr('$')) 4 | if i + 1 == tabpagenr() 5 | let s .= '%#TabLineSel#' 6 | else 7 | let s .= '%#TabLine#' 8 | endif 9 | 10 | let s .= ' %{MyTabLabel('.(i+1).')}%{g:branches['.(i).']} ' 11 | endfor 12 | 13 | "let s .= '%#Statusbg#%T' 14 | let s .= '%=%{pathshorten(fnamemodify(expand("%"), ":~:.:s?\.*/\\ze.*/.git/??"))}' 15 | 16 | return s 17 | endfunction 18 | 19 | function! MyTabLabel(n) 20 | return fnamemodify(getcwd(-1, a:n), ":t")."/" 21 | endfunction 22 | 23 | function! AddSpacesNonempty(string) 24 | if a:string != "" 25 | return "\ ".a:string."\ " 26 | endif 27 | return "" 28 | endfunction 29 | 30 | function! FilenameClean() 31 | let l:fn=expand('%:t') 32 | if &buftype == "terminal" 33 | let l:fn = substitute(l:fn, "\\d\\+:", "", "") 34 | endif 35 | return l:fn 36 | endfunction 37 | 38 | function! FilepathClean() 39 | if mode()=='t' 40 | return '' 41 | endif 42 | let l:fp=expand('%:.:h') 43 | if l:fp=='' 44 | return '' 45 | endif 46 | return l:fp 47 | endfunction 48 | 49 | function! FiletypeClean() 50 | if mode()=='t' 51 | return ' Terminal ' 52 | endif 53 | let l:ft=&filetype 54 | if l:ft=='' 55 | return '' 56 | endif 57 | return ' '.l:ft.' ' 58 | endfunction 59 | 60 | function! BranchClean() 61 | let l:branches=[] 62 | for i in range(tabpagenr('$')) 63 | let l:branch = [system("cd ". fnameescape(getcwd(-1,i+1)) ." && git branch --show-current")[:-2]] 64 | if match(l:branch[0], "^fatal:") == 0 65 | let l:branch = [""] 66 | else 67 | let l:branch[0]=": ".l:branch[0] 68 | endif 69 | let l:branches+=l:branch 70 | endfor 71 | return l:branches 72 | endfunction 73 | 74 | function! Statusline() 75 | let l:var = "%#Status1#"."%( %{w:stFn}%m %)" 76 | let l:var .= "%#Status2#"."%{w:stFt}" 77 | let l:var .= "%1*" 78 | let l:var .= "%=" 79 | let l:var .= "%#Status3#\ %03l/%L:%02v\ " 80 | return l:var 81 | endfunction 82 | -------------------------------------------------------------------------------- /nixos/profiles/paperless.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | machine_lan_address = data.network.lan.peers.${machine}.address; 5 | port = data.ports.paperless; 6 | in { 7 | services.paperless = { 8 | enable = true; 9 | 10 | address = machine_lan_address; 11 | port = port; 12 | 13 | passwordFile = l3lib.secret "paperless_password"; 14 | settings = { 15 | PAPERLESS_OCR_LANGUAGE = "deu+eng"; 16 | PAPERLESS_OCR_USER_ARGS = { 17 | optimize = 1; 18 | pdfa_image_compression = "lossless"; 19 | }; 20 | }; 21 | }; 22 | 23 | fileSystems."/srv/nfs/paperless-consume" = { 24 | device = "/var/lib/paperless/consume"; 25 | options = [ "bind" ]; 26 | }; 27 | 28 | # 315 is id of paperless. 29 | # make sure client has id 315 for paperless as well, and user belongs to paperless-group. 30 | services.nfs.server.exports = '' 31 | /srv/nfs/paperless-consume 192.168.178.0/24(rw,all_squash,anonuid=${toString config.ids.uids.paperless},anongid=${toString config.ids.gids.paperless}) 32 | ''; 33 | 34 | systemd.tmpfiles.rules = lib.mkAfter [ 35 | "A /var/lib/paperless - - - - g:paperless:rX" 36 | "Z /var/lib/paperless/index 0750 paperless paperless" 37 | ]; 38 | l3mon.restic.extraGroups = [ "paperless" ]; 39 | 40 | l3mon.restic.specs.paperless = { 41 | backupStopResumeServices = [ 42 | "paperless-task-queue.service" 43 | "paperless-consumer.service" 44 | "paperless-scheduler.service" 45 | "paperless-web.service" 46 | ]; 47 | backupDaily = { 48 | text = '' 49 | cd /var/lib/paperless 50 | restic backup --tag=paperless --skip-if-unchanged=true -- media/documents/archive media/documents/originals db.sqlite3 index src-version 51 | ''; 52 | }; 53 | forget = { 54 | text = '' 55 | restic forget --tag=paperless --group-by=tag --keep-daily=7 --keep-monthly=12 56 | ''; 57 | }; 58 | }; 59 | 60 | services.caddy.extraConfig = '' 61 | http://paperless, http://paperless.internal, http://paperless.${machine} { 62 | reverse_proxy http://${machine_lan_address}:${toString port} 63 | } 64 | ''; 65 | } 66 | -------------------------------------------------------------------------------- /nixos/profiles/ddns-updater.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, pkgs-unstable, pkgs-ddns-updater-2-7, machine, data, ... }: 2 | 3 | let 4 | conf = pkgs.writeTextFile { 5 | name = "conf"; 6 | text = builtins.toJSON { 7 | settings = [ 8 | { 9 | provider = "porkbun"; 10 | domain = "l3mon4.de,wireguard.l3mon4.de,nix-cache.l3mon4.de,nix-tarballs.l3mon4.de"; 11 | api_key = "$PORKBUN_API_KEY"; 12 | secret_api_key = "$PORKBUN_SECRET_API_KEY"; 13 | ip_version = "ipv4"; 14 | ipv6_suffix = ""; 15 | ttl = 60; 16 | } 17 | # { 18 | # provider = "cloudflare"; 19 | # zone_identifier = "b17b3bd2466d8a209be5bc5e3c88585d"; 20 | # domain = "l3mon4.de"; 21 | # host = "@,wireguard"; 22 | # ip_version = "ipv4"; 23 | # ipv6_suffix = ""; 24 | # ttl = 60; 25 | # token = "$CF_TOKEN"; 26 | # } 27 | ]; 28 | }; 29 | }; 30 | runtime_conf_file = "/run/ddns-updater.conf"; 31 | in { 32 | system.activationScripts = { 33 | ddns-updater = { 34 | text = 35 | (l3lib.assertSecret "porkbun_api_key") + 36 | (l3lib.assertSecret "porkbun_secret_api_key") + 37 | '' 38 | (umask 0077 && \ 39 | PORKBUN_API_KEY=$(cat ${l3lib.secret "porkbun_api_key"}) \ 40 | PORKBUN_SECRET_API_KEY=$(cat ${l3lib.secret "porkbun_secret_api_key"}) \ 41 | ${pkgs.envsubst}/bin/envsubst -i ${conf} -o ${runtime_conf_file}) 42 | ''; 43 | }; 44 | }; 45 | 46 | services.ddns-updater = { 47 | enable = true; 48 | package = pkgs.ddns-updater; 49 | environment = { 50 | SERVER_ENABLED="yes"; 51 | CONFIG_FILEPATH = "%d/conf"; 52 | LISTENING_ADDRESS=":${toString data.ports.ddns-updater}"; 53 | RESOLVER_ADDRESS="1.1.1.1:53"; 54 | }; 55 | }; 56 | systemd.services.ddns-updater.serviceConfig.LoadCredential = "conf:${runtime_conf_file}"; 57 | 58 | services.caddy.extraConfig = '' 59 | http://ddns-updater, http://ddns-updater.internal, http://ddns-updater.${machine} { 60 | reverse_proxy http://localhost:${toString data.ports.ddns-updater} 61 | } 62 | ''; 63 | } 64 | -------------------------------------------------------------------------------- /nvim/lua/plugins/luasnip/helpers.lua: -------------------------------------------------------------------------------- 1 | local ls = require("luasnip") 2 | 3 | local snip_defs = { 4 | s = ls.s, 5 | sn = ls.sn, 6 | t = ls.t, 7 | i = ls.i, 8 | f = function(func, argnodes, ...) 9 | return ls.f(function(args, imm_parent, user_args) 10 | return func(args, imm_parent.snippet, user_args) 11 | end, argnodes, ...) 12 | end, 13 | -- override to enable restore_cursor. 14 | c = function(pos, nodes, opts) 15 | opts = opts or {} 16 | opts.restore_cursor = true 17 | return ls.c(pos, nodes, opts) 18 | end, 19 | d = function(pos, func, argnodes, ...) 20 | return ls.d(pos, function(args, imm_parent, old_state, ...) 21 | return func(args, imm_parent.snippet, old_state, ...) 22 | end, argnodes, ...) 23 | end, 24 | isn = require("luasnip.nodes.snippet").ISN, 25 | l = require'luasnip.extras'.lambda, 26 | dl = require'luasnip.extras'.dynamic_lambda, 27 | rep = require'luasnip.extras'.rep, 28 | r = ls.restore_node, 29 | p = require("luasnip.extras").partial, 30 | types = require("luasnip.util.types"), 31 | events = require("luasnip.util.events"), 32 | util = require("luasnip.util.util"), 33 | fmt = require("luasnip.extras.fmt").fmt, 34 | fmta = require("luasnip.extras.fmt").fmta, 35 | ls = ls, 36 | ins_generate = function(nodes) 37 | return setmetatable(nodes or {}, { 38 | __index = function(table, key) 39 | local indx = tonumber(key) 40 | if indx then 41 | local val = ls.i(indx) 42 | rawset(table, key, val) 43 | return val 44 | end 45 | end}) 46 | end, 47 | parse = ls.parser.parse_snippet, 48 | n = require("luasnip.extras").nonempty, 49 | m = require("luasnip.extras").match, 50 | ai = require("luasnip.nodes.absolute_indexer") 51 | } 52 | 53 | local function setup_snip_env() 54 | setfenv(2, vim.tbl_extend("force", _G, snip_defs)) 55 | end 56 | 57 | local function edit_ft() 58 | local fts = require("luasnip.util.util").get_snippet_filetypes() 59 | vim.ui.select(fts, { 60 | prompt = "Select which filetype to edit:" 61 | }, function(item, idx) 62 | if idx then 63 | vim.cmd("edit /home/simon/.config/nvim/lua/snippets/"..item..".lua") 64 | end 65 | end) 66 | end 67 | 68 | return { 69 | setup_snip_env = setup_snip_env, 70 | edit_ft = edit_ft 71 | } 72 | -------------------------------------------------------------------------------- /nvim/lua/write.lua: -------------------------------------------------------------------------------- 1 | -- stolen from @wincent 2 | 3 | local cache_time = 5 * 60 * 1000 -- 5 minutes 4 | local password = nil 5 | local timer = nil 6 | 7 | local expect = function(expected, fn, description) 8 | local result = fn() 9 | if result ~= expected then 10 | error( 11 | 'error: wincent.sudo.write got result ' .. result .. ' for ' .. description .. '(expected ' .. expected .. ')' 12 | ) 13 | end 14 | end 15 | 16 | local reject = function(rejected, fn, description) 17 | local result = fn() 18 | if result == rejected then 19 | error( 20 | 'error: wincent.sudo.write got result ' .. result .. ' for ' .. description .. '(expected non-' .. rejected .. ')' 21 | ) 22 | end 23 | end 24 | 25 | local write = function(args) 26 | local bang = args.bang 27 | if bang or password == nil then 28 | password = vim.fn.inputsecret('Password:') 29 | if timer ~= nil then 30 | timer:stop() 31 | end 32 | timer = vim.defer_fn(function() 33 | password = nil 34 | end, cache_time) 35 | end 36 | 37 | local askpass = vim.fn.tempname() 38 | 39 | expect(0, function() 40 | return vim.fn.writefile({ '' }, askpass, 's') 41 | end, 'writefile (touch)') 42 | reject(0, function() 43 | return vim.fn.setfperm(askpass, 'rwx------') 44 | end, 'setfperm') 45 | expect(0, function() 46 | return vim.fn.writefile({ '#!/usr/bin/env bash', 'builtin echo -n ' .. vim.fn.shellescape(password) }, askpass, 's') 47 | end, 'writefile (fill)') 48 | 49 | local buftype = vim.o.buftype 50 | if buftype == '' then 51 | -- Avoid `:help W12` warning. 52 | vim.opt_local.buftype = 'nowrite' 53 | end 54 | 55 | vim.api.nvim_create_autocmd("BufEnter", {command = "set noro", buffer = 0}) 56 | 57 | pcall(function() 58 | vim.cmd('silent write !env SUDO_ASKPASS=' .. vim.fn.shellescape(askpass) .. ' sudo -A tee % > /dev/null') 59 | end) 60 | 61 | if vim.v.shell_error ~= 0 then 62 | -- Common cause of this is wrong password, so invalidate the cache. 63 | password = nil 64 | if timer ~= nil then 65 | timer:stop() 66 | end 67 | 68 | if buftype == '' then 69 | vim.opt_local.buftype = buftype 70 | end 71 | else 72 | if buftype == '' then 73 | vim.cmd('edit') 74 | vim.opt_local.buftype = buftype 75 | end 76 | end 77 | 78 | expect(0, function() 79 | return vim.fn.delete(askpass) 80 | end, 'delete') 81 | end 82 | 83 | vim.api.nvim_create_user_command("W", write, {bang = true}) 84 | -------------------------------------------------------------------------------- /nixos/profiles/forgejo.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | cfg = config.services.forgejo; 5 | srv = cfg.settings.server; 6 | machine_lan_address = data.network.lan.peers.${machine}.address; 7 | port = data.ports.forgejo; 8 | in { 9 | services.forgejo = { 10 | enable = true; 11 | database.type = "mysql"; 12 | 13 | settings = { 14 | server = { 15 | DOMAIN = "git.internal"; 16 | ROOT_URL = "http://${srv.DOMAIN}"; 17 | HTTP_PORT = port; 18 | }; 19 | service.DISABLE_REGISTRATION = true; 20 | }; 21 | }; 22 | 23 | 24 | systemd.services.forgejo.preStart = let 25 | adminCmd = "${lib.getExe cfg.package} admin user"; 26 | user = "simon"; # Note, Forgejo doesn't allow creation of an account named "admin" 27 | in '' 28 | ${adminCmd} create --admin --email "simon@l3mon4.de" --username ${user} --password "bbbbbbbb" || true 29 | ''; 30 | 31 | services.caddy.extraConfig = '' 32 | http://git, http://git.internal, http://git.${machine} { 33 | reverse_proxy http://${machine_lan_address}:${toString port} 34 | } 35 | ''; 36 | 37 | # override module-level rules for forgejo (specifically for .ssh). 38 | systemd.tmpfiles.rules = lib.mkAfter [ 39 | "A ${cfg.stateDir} - - - - g:forgejo:rX" 40 | "z '${cfg.stateDir}/.ssh' 0750 forgejo forgejo" 41 | ]; 42 | 43 | l3mon.restic.extraGroups = [ "forgejo" ]; 44 | l3mon.restic.dailyRequiredServices = [ "mysql.service" ]; 45 | l3mon.restic.specs.forgejo = { 46 | backupStopResumeServices = ["forgejo.service"]; 47 | # create two tags, one for files and one for the database-backup. 48 | # I don't think both can be put into one snapshot easily if I want to use 49 | # the `--stdin`-option. 50 | # This is fine though :) 51 | backupDaily = { 52 | text = '' 53 | cd ${cfg.stateDir} 54 | restic backup --tag=forgejo-data --skip-if-unchanged=true -- repositories data .ssh 55 | mysqldump forgejo | restic backup --tag=forgejo-db --skip-if-unchanged=true --stdin --stdin-filename=forgejo.mysql 56 | ''; 57 | runtimeInputs = [ config.services.mysql.package ]; 58 | }; 59 | forget = { 60 | text = '' 61 | restic forget --tag=forgejo-data --group-by=tag --keep-daily=7 --keep-monthly=12 62 | restic forget --tag=forgejo-db --group-by=tag --keep-daily=7 --keep-monthly=12 63 | ''; 64 | }; 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /nvim/luasnippets/zig.lua: -------------------------------------------------------------------------------- 1 | parse_add("imp", [[const $1 = @import("$2")$0;]]) 2 | parse_add("if", [[ 3 | if ($1) { 4 | $2 5 | } 6 | ]]) 7 | parse_add("for", [[ 8 | for ($1) |$2| { 9 | $3 10 | } 11 | ]]) 12 | parse_add({trig = "for(%w+)", wordTrig = true, regTrig = true}, [[ 13 | for (0..$1) |${LS_CAPTURE_1}| { 14 | $0 15 | } 16 | ]]) 17 | 18 | ts_px_add({ 19 | trig = ".map", 20 | matchTSNode = { 21 | query = [[ (identifier) @prefix ]], 22 | query_lang = "zig", 23 | select = "longest" 24 | }, 25 | reparseBuffer = "live" 26 | }, fmt([[ 27 | for {} {{ 28 | {} 29 | }} 30 | ]], { 31 | c(1, { 32 | parse(nil, "($LS_TSMATCH) |$1|"), 33 | parse(nil, "($LS_TSMATCH, ${1:0..}) |$2, ${3:i}|"), 34 | }), 35 | i(0) 36 | })) 37 | ts_px_add({ 38 | trig = ".c", 39 | matchTSNode = { 40 | query = [[ (call_expression) @prefix ]], 41 | query_lang = "zig", 42 | select = "longest" 43 | }, 44 | reparseBuffer = "live" 45 | }, parse(nil, "$LS_TSMATCH catch ${1:unreachable}")) 46 | ts_px_add({ 47 | trig = ".cu", 48 | matchTSNode = { 49 | query = [[ (call_expression) @prefix ]], 50 | query_lang = "zig", 51 | select = "longest" 52 | }, 53 | reparseBuffer = "live" 54 | }, parse(nil, "$LS_TSMATCH catch unreachable")) 55 | ts_px_add({ 56 | trig = ".t", 57 | matchTSNode = { 58 | query = [[ (call_expression) @prefix ]], 59 | query_lang = "zig", 60 | select = "longest" 61 | }, 62 | reparseBuffer = "live" 63 | }, parse(nil, "try $LS_TSMATCH")) 64 | 65 | ts_px_add({ 66 | trig = ".f32", 67 | matchTSNode = { 68 | query = [[ (identifier) @prefix ]], 69 | query_lang = "zig", 70 | select = "shortest" 71 | }, 72 | reparseBuffer = "live" 73 | }, parse(nil, "@as(f32, @floatFromInt($LS_TSMATCH))")) 74 | 75 | s_add("struct", { 76 | c(1, { 77 | t"pub ", 78 | t"" 79 | }), 80 | c(2, { 81 | fmt([[ 82 | const {} = struct {{ 83 | const Self = @This(); 84 | {} 85 | }}; 86 | ]], {r(1, "name", i(1)), r(2, "body", i(1)) }), 87 | fmt([[ 88 | fn {}({}) type {{ 89 | return struct {{ 90 | const Self = @This(); 91 | {} 92 | }}; 93 | }} 94 | ]], {r(1, "name", i(1)), i(2), r(3, "body", i(1)) }) 95 | }) 96 | }) 97 | 98 | s_add("while", fmt([[ 99 | while ({}) {}{{ 100 | {} 101 | }} 102 | ]], {i(1), c(2, {t"", {t"|",i(1),t"| "} }), i(3) })) 103 | -------------------------------------------------------------------------------- /nixos/profiles/immich.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | machine_lan_address = data.network.lan.peers.${machine}.address; 5 | port = data.ports.immich; 6 | in { 7 | services.immich = { 8 | enable = true; 9 | port = port; 10 | host = machine_lan_address; 11 | }; 12 | 13 | services.caddy.extraConfig = '' 14 | http://immich, http://immich.internal, http://immich.${machine} { 15 | reverse_proxy http://${machine_lan_address}:${toString port} 16 | } 17 | ''; 18 | 19 | services.postgresql = { 20 | ensureUsers = [ { 21 | name = "restic"; 22 | }]; 23 | authentication = '' 24 | local immich restic peer 25 | ''; 26 | }; 27 | # run after immich sets up its database. 28 | systemd.services.postgresql.postStart = lib.mkAfter '' 29 | $PSQL immich -tAc 'GRANT CONNECT ON DATABASE immich TO restic' || true 30 | $PSQL immich -tAc 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO restic' || true 31 | $PSQL immich -tAc 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO restic' || true 32 | ''; 33 | 34 | # override settings from service-file. 35 | systemd.tmpfiles.settings.immich = lib.mkForce { 36 | ${config.services.immich.mediaLocation} = { 37 | e = { 38 | user = "immich"; 39 | group = "immich"; 40 | mode = "0750"; 41 | }; 42 | }; 43 | }; 44 | systemd.services.immich-server.serviceConfig.UMask = lib.mkForce 0027; 45 | systemd.services.immich-machine-learning.serviceConfig.UMask = lib.mkForce 0027; 46 | 47 | l3mon.restic.extraGroups = [ "immich" ]; 48 | l3mon.restic = { 49 | dailyRequiredServices = [ "postgresql.service" ]; 50 | specs.immich = { 51 | backupStopResumeServices = ["immich-server.service"]; 52 | backupDaily = { 53 | runtimeInputs = [ config.services.postgresql.package ]; 54 | text = '' 55 | cd ${config.services.immich.mediaLocation} 56 | restic backup --tag=immich-data --skip-if-unchanged=true -- library 57 | pg_dump immich | restic backup --tag=immich-db --skip-if-unchanged=true --stdin --stdin-filename=immich.db 58 | ''; 59 | }; 60 | forget = { 61 | text = '' 62 | restic forget --tag=immich-data --group-by=tag --keep-daily=7 --keep-monthly=12 63 | restic forget --tag=immich-db --group-by=tag --keep-daily=7 --keep-monthly=12 64 | ''; 65 | }; 66 | }; 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /nixos/profiles/sway/copypaste/sway-copypaste.lua: -------------------------------------------------------------------------------- 1 | local Sway = require("sway") 2 | local sway = Sway.connect() 3 | 4 | -- helper methods 5 | local function read(fname) 6 | local f = io.open(fname) 7 | if not f then 8 | return nil 9 | end 10 | 11 | local content = f:read("*all") 12 | f:close() 13 | return content 14 | end 15 | local function write(fname, str) 16 | local f = io.open(fname, "w") 17 | 18 | local content = f:write(str) 19 | f:close() 20 | return content 21 | end 22 | 23 | local function find_current_window(tree) 24 | if tree.focused then 25 | local ret = { 26 | id = tree.id, 27 | floating = tree.type == "floating_con" 28 | } 29 | return ret 30 | end 31 | 32 | for _, v in pairs(tree) do 33 | if type(v) == "table" then 34 | local id = find_current_window(v) 35 | if id then 36 | return id 37 | end 38 | end 39 | end 40 | return nil 41 | end 42 | 43 | local cut_con_id_file_path = "/tmp/sway_copypaste" 44 | local function push_cut(spec) 45 | local stack = read(cut_con_id_file_path) 46 | if not stack then 47 | stack = "" 48 | end 49 | stack = stack .. ";" .. tostring(spec.id) .. ":" .. tostring(spec.floating) 50 | write(cut_con_id_file_path, stack) 51 | end 52 | local function pop_cut() 53 | local stack = read(cut_con_id_file_path) 54 | if not stack or stack == "" then 55 | return nil 56 | end 57 | -- there is at least one item on the stack. 58 | 59 | -- sub2: omit leading ';' 60 | local spec = stack:match(";[^;]+$"):sub(2) 61 | stack = stack:sub(1, -#spec-2) 62 | write(cut_con_id_file_path, stack) 63 | 64 | local cut_id = spec:match("(%d+):") 65 | local cut_floating = spec:match(":(%w+)") == "true" 66 | 67 | return { 68 | id = cut_id, 69 | floating = cut_floating 70 | } 71 | end 72 | 73 | if arg[1] == "cut" then 74 | local sway_tree = sway:getTree() 75 | local current_window = find_current_window(sway_tree) 76 | if not current_window then 77 | print("No active window!") 78 | return 79 | end 80 | 81 | push_cut(current_window) 82 | sway:msg("move window to scratchpad") 83 | elseif arg[1] == "paste" then 84 | local cut_spec = pop_cut() 85 | if not cut_spec then 86 | print("no window-id saved in ", cut_con_id_file_path) 87 | return 88 | end 89 | local cut_id = cut_spec.id 90 | local cut_floating = cut_spec.floating 91 | 92 | sway:msg(("[con_id=%s] move window workspace current,, %sfocus"):format( 93 | cut_id, 94 | cut_floating and "" or "floating disable,, ")) 95 | end 96 | 97 | -------------------------------------------------------------------------------- /nixos/modules/secgen.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | with lib; { 4 | options.l3mon.secgen = { 5 | secrets = mkOption { 6 | type = types.attrsOf types.attrs; 7 | description = mdDoc '' 8 | Map secret-names to an attrset which has to have a key `gen`, which is a 9 | derivation that can generate a new secret, and a key `backup_relfiles`, 10 | which is a list of relative filepaths, and these will be backed up 11 | before a new secreet is generated. 12 | The attrset may have other keys which can help accessing the secret. 13 | ''; 14 | default = {}; 15 | }; 16 | secret_dir = mkOption { 17 | type = types.str; 18 | description = mdDoc '' 19 | Location of secrets. 20 | ''; 21 | default = "/var/secrets"; 22 | }; 23 | }; 24 | config = let 25 | format = pkgs.formats.yaml {}; 26 | completely_spec = format.generate "completion.yaml" { 27 | secgen = attrsets.foldlAttrs (acc: k: v: acc ++ [k]) [] config.l3mon.secgen.secrets; 28 | }; 29 | secgen_completion = pkgs.runCommand "secgen_completion" {} '' 30 | mkdir -p "$out/share/bash-completion/completions" 31 | ${pkgs.completely}/bin/completely generate ${completely_spec} "$out/share/bash-completion/completions/secgen" 32 | ''; 33 | in { 34 | environment.systemPackages = with pkgs; [ 35 | (writeShellApplication (let 36 | secbackup = secpath: 37 | # bash 38 | '' 39 | if [[ -f "${secpath}" ]]; then 40 | mkdir -p "$(dirname /var/secrets/.old/${secpath})" 41 | BACKUP_PATH="/var/secrets/.old/${secpath}-$(date +%s)" 42 | install -D -o root -g root -m 400 "${secpath}" "$BACKUP_PATH" 43 | fi 44 | ''; 45 | in { 46 | name = "secgen"; 47 | text = '' 48 | if [[ $EUID -ne 0 ]]; then 49 | printf "secgen needs root to manipulate permissions on secrets." 50 | exit 1 51 | fi 52 | 53 | case "$1" in 54 | '' + (attrsets.foldlAttrs (acc: k: v: acc + '' 55 | ${k}) 56 | ${builtins.concatStringsSep "\n" (builtins.map (secpath: secbackup secpath) v.backup_files)} 57 | ${v.gen}/bin/gen 58 | ;; 59 | '') "" config.l3mon.secgen.secrets) + 60 | '' 61 | *) 62 | echo "$1 is not a valid secret-identifier!" 63 | esac 64 | ''; 65 | })) 66 | secgen_completion 67 | ]; 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /nixos/modules/automount.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | with lib; let 4 | cfg = config.l3mon.automount; 5 | in { 6 | options.l3mon.automount = { 7 | enable = mkEnableOption (lib.mdDoc "Enable automounting."); 8 | spec = mkOption { 9 | type = types.attrsOf types.attrs; 10 | description = lib.mdDoc "Maps partition-labels to options for mounting it."; 11 | }; 12 | }; 13 | config = mkIf cfg.enable (let 14 | umount_command = partlabel: "${config.security.wrapperDir}/umount /dev/disk/by-label/${partlabel}"; 15 | in { 16 | services.udev.extraRules = lib.attrsets.foldlAttrs (acc: partlabel: spec: acc + '' 17 | ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem" ENV{ID_FS_LABEL}=="${partlabel}", RUN{program}+="${pkgs.systemd}/bin/systemd-mount --no-block --automount=yes --collect $devnode ${spec.at} -o x-systemd.idle-timeout=600${if spec ? options then ",${spec.options}" else ""}" 18 | '') "" cfg.spec; 19 | 20 | systemd.tmpfiles.rules = lib.attrsets.foldlAttrs (acc: _: spec: acc ++ [ 21 | "d ${spec.at} 0770 simon simon" 22 | ]) [] cfg.spec; 23 | 24 | security.sudo = { 25 | extraRules = [{ 26 | commands = [{ 27 | command = builtins.concatStringsSep "," (lib.attrsets.foldlAttrs (acc: partlabel: spec: acc ++ ["${umount_command partlabel}"]) [] cfg.spec); 28 | options = [ "NOPASSWD" ]; 29 | }]; 30 | groups = [ "simon" ]; 31 | }]; 32 | }; 33 | environment.systemPackages = with pkgs; [ 34 | (writeShellApplication (let 35 | in { 36 | name = "um"; 37 | text = '' 38 | case "$1" in 39 | '' + (attrsets.foldlAttrs (acc: partlabel: _: acc + '' 40 | ${partlabel}) 41 | ${config.security.wrapperDir}/sudo ${umount_command partlabel} 42 | ;; 43 | '') "" cfg.spec) + 44 | '' 45 | *) 46 | echo "$1 is not a registered partition-lable!" 47 | esac 48 | ''; 49 | })) 50 | (pkgs.runCommand "automount_completion" {} (let 51 | format = pkgs.formats.yaml {}; 52 | completely_spec = format.generate "completion.yaml" { 53 | um = attrsets.foldlAttrs (acc: label: _: acc ++ [label]) [] cfg.spec; 54 | }; 55 | in '' 56 | mkdir -p "$out/share/bash-completion/completions" 57 | ${pkgs.completely}/bin/completely generate ${completely_spec} "$out/share/bash-completion/completions/um" 58 | '')) 59 | ]; 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /nvim/lua/vksnippets/source.lua: -------------------------------------------------------------------------------- 1 | local cmp = require("cmp") 2 | local vkinfo = require("vkinfo") 3 | local ls = require("luasnip") 4 | 5 | 6 | local source = {} 7 | 8 | function source.new() 9 | return setmetatable({}, {__index = source}) 10 | end 11 | 12 | function source:is_available() 13 | return true 14 | end 15 | 16 | function source:get_debug_name() 17 | return "vksnippets" 18 | end 19 | 20 | local items = {} 21 | 22 | for i, struct in ipairs(vkinfo.structs) do 23 | items[i] = { 24 | -- omit "Vk". 25 | word = struct.name:sub(3, -1), 26 | -- indent one space so it lines up with lsp-results. 27 | label = " " .. struct.name:sub(3, -1), 28 | kind = cmp.lsp.CompletionItemKind.Snippet, 29 | -- store index in structs, snippets are memoized in a separate table, 30 | -- with the same index. 31 | data = i 32 | } 33 | end 34 | function source:complete(_, callback) 35 | callback(items) 36 | end 37 | 38 | local function to_snippet(struct) 39 | ls.setup_snip_env() 40 | 41 | local nodes = { 42 | -- replace Vk-prefix with vk::. 43 | t("vk::" .. struct.name:sub(3, -1) .. " "), i(1), t{" {", ""} 44 | } 45 | 46 | local in_indx = 2 47 | -- skip sType and pNext (hope they are actually always at [1] and [2]...) 48 | for _, member in ipairs(struct) do 49 | if member.name == "sType" or member.name == "pNext" then 50 | goto continue 51 | end 52 | 53 | vim.list_extend(nodes, { 54 | t("\t." .. member.name .. " = "), 55 | i(in_indx, member.type), 56 | t{",", ""} 57 | }) 58 | 59 | in_indx = in_indx + 1 60 | ::continue:: 61 | end 62 | -- remove last ",": 63 | nodes[#nodes] = t{"", ""} 64 | 65 | table.insert(nodes, t"};") 66 | 67 | return s("", nodes) 68 | end 69 | 70 | local snippets = {} 71 | function source:execute(completion_item, callback) 72 | local indx = completion_item.data 73 | if not snippets[indx] then 74 | snippets[indx] = to_snippet(vkinfo.structs[indx]) 75 | end 76 | 77 | local cursor = vim.api.nvim_win_get_cursor(0) 78 | -- get_cursor returns (1,0)-indexed position, clear_region expects (0,0)-indexed. 79 | cursor[1] = cursor[1] - 1 80 | 81 | -- text cannot be cleared before, as TM_CURRENT_LINE and 82 | -- TM_CURRENT_WORD couldn't be set correctly. 83 | ls.snip_expand(snippets[indx], { 84 | -- clear word inserted into buffer by cmp. 85 | -- cursor is currently behind word. 86 | clear_region = { 87 | from = { 88 | cursor[1], 89 | cursor[2]-#completion_item.word 90 | }, 91 | to = cursor 92 | } 93 | }) 94 | callback(completion_item) 95 | end 96 | 97 | cmp.register_source("vksnippets", source.new()) 98 | -------------------------------------------------------------------------------- /nvim/queries/make/highlights.scm: -------------------------------------------------------------------------------- 1 | (comment) @comment @spell 2 | 3 | (conditional 4 | (_ [ 5 | "ifeq" 6 | "else" 7 | "ifneq" 8 | "ifdef" 9 | "ifndef" 10 | ] @conditional) 11 | "endif" @conditional) 12 | 13 | (rule (targets 14 | (word) @function.builtin 15 | (#any-of? @function.builtin 16 | ".DEFAULT" 17 | ".SUFFIXES" 18 | ".DEFAULT" 19 | ".DELETE_ON_ERROR" 20 | ".EXPORT_ALL_VARIABLES" 21 | ".IGNORE" 22 | ".INTERMEDIATE" 23 | ".LOW_RESOLUTION_TIME" 24 | ".NOTPARALLEL" 25 | ".ONESHELL" 26 | ".PHONY" 27 | ".POSIX" 28 | ".PRECIOUS" 29 | ".SECONDARY" 30 | ".SECONDEXPANSION" 31 | ".SILENT" 32 | ".SUFFIXES"))) 33 | 34 | (rule ["&:" ":" "::"] @operator) 35 | 36 | (export_directive "export" @keyword) 37 | (override_directive "override" @keyword) 38 | (include_directive ["include" "-include"] @include) 39 | 40 | (variable_assignment 41 | (word) @constant) 42 | (variable_assignment [ 43 | "?=" 44 | ":=" 45 | "+=" 46 | "=" 47 | ] @operator) 48 | 49 | (rule (targets) @rule ) 50 | ; highlight other targets blue as well. (not sure if this really looks good). 51 | (prerequisites (word) @rule) 52 | 53 | (variable_assignment 54 | (word) @variable.builtin 55 | (#any-of? @variable.builtin 56 | ".DEFAULT_GOAL" 57 | ".EXTRA_PREREQS" 58 | ".FEATURES" 59 | ".INCLUDE_DIRS" 60 | ".RECIPEPREFIX" 61 | ".SHELLFLAGS" 62 | ".VARIABLES" 63 | "MAKEARGS" 64 | "MAKEFILE_LIST" 65 | "MAKEFLAGS" 66 | "MAKE_RESTARTS" 67 | "MAKE_TERMERR" 68 | "MAKE_TERMOUT" 69 | "SHELL" 70 | ) 71 | ) 72 | 73 | ; Use string to match bash 74 | (variable_reference (word) @constant ) @operator 75 | 76 | 77 | (shell_function 78 | ["$" "(" ")"] @operator 79 | "shell" @function.builtin 80 | ) 81 | 82 | (function_call ["$" "(" ")"] @operator) 83 | (substitution_reference ["$" "(" ")"] @operator) 84 | 85 | (function_call [ 86 | "subst" 87 | "patsubst" 88 | "strip" 89 | "findstring" 90 | "filter" 91 | "filter-out" 92 | "sort" 93 | "word" 94 | "words" 95 | "wordlist" 96 | "firstword" 97 | "lastword" 98 | "dir" 99 | "notdir" 100 | "suffix" 101 | "basename" 102 | "addsuffix" 103 | "addprefix" 104 | "join" 105 | "wildcard" 106 | "realpath" 107 | "abspath" 108 | "error" 109 | "warning" 110 | "info" 111 | "origin" 112 | "flavor" 113 | "foreach" 114 | "if" 115 | "or" 116 | "and" 117 | "call" 118 | "eval" 119 | "file" 120 | "value" 121 | ] @function.builtin 122 | ) 123 | -------------------------------------------------------------------------------- /nvim/luasnippets/lua.lua: -------------------------------------------------------------------------------- 1 | s_add({trig="if", wordTrig=true}, { 2 | t({"if "}), 3 | i(1), 4 | t({" then", "\t"}), 5 | isn(2, {dl(1, l.LS_SELECT_DEDENT)}, "$PARENT_INDENT\t"), 6 | t({"", "end"}) 7 | }) 8 | s_add({trig="ee", wordTrig=true}, { 9 | t({"else", "\t"}), 10 | i(0), 11 | }) 12 | s_add("for", { 13 | t"for ", c(1, { 14 | sn(nil, {i(1, "k"), t", ", i(2, "v"), t" in ", c(3, {{t"pairs(",i(1),t")"}, {t"ipairs(",i(1),t")"}, i(nil)}) }), 15 | sn(nil, {i(1, "val"), t" in ", i(2) }), 16 | sn(nil, {i(1, "i"), t" = ", i(2), t", ", i(3) }), 17 | fmt([[{} in vim.gsplit({})]], {i(1, "str"), i(2)}) 18 | }), t{" do", "\t"}, isn(2, {dl(1, l.LS_SELECT_DEDENT)}, "$PARENT_INDENT\t"), t{"", "end"} 19 | }) 20 | 21 | s_add("while", fmt([[ 22 | while {} do 23 | {} 24 | end 25 | ]], ins_generate())) 26 | 27 | s_add("fn", { 28 | c(1, { 29 | fmt([[ 30 | function{}({}) 31 | {} 32 | end 33 | ]], { 34 | r(1, "name", i(1)), 35 | r(2, "args", i(1)), 36 | r(3, "body", d(1, function(_, parent) 37 | if #parent.snippet.env.LS_SELECT_DEDENT ~= 0 then 38 | return isn(nil, { 39 | t(parent.snippet.env.LS_SELECT_DEDENT), i(1) 40 | }, "$PARENT_INDENT\t") 41 | else 42 | return sn(nil, { i(1) }) 43 | end 44 | end)) 45 | }), 46 | fmt([[function{}({}) {} end]], { 47 | r(1, "name"), 48 | r(2, "args"), 49 | r(3, "body") 50 | }) 51 | }) 52 | }) 53 | 54 | s_add("str", fmt("[[\n\t{}\n]]", ins_generate())) 55 | s_add("sdt", fmt( 56 | [[ls_helpers.static_docstring_test({}, {}, {})]], 57 | { i(1, "snip"), c(2, {{t"{\"", i(1), t"\"}"}, i(1)}), c(3, {{t"{\"", i(1), t"$0\"}"}, i(1)}) } ) 58 | ) 59 | s_add("lar", fmt( 60 | "${{{}}}", 61 | { i(1) } 62 | )) 63 | s_add({trig = "lar(%d)", regTrig = true, wordTrig = false}, fmt( 64 | "${{{}:{}}}", 65 | { f(function(_, snip) return snip.captures[1] end, {}), i(1) } 66 | )) 67 | s_add({trig = "([%w_]+)%+%+", regTrig = true, wordTrig = false}, fmt( 68 | "{} = {} + 1", 69 | { l(l.CAPTURE1, {}), l(l.CAPTURE1, {}) } 70 | )) 71 | s_add("req", fmt("local {} = require(\"{}\")", { 72 | dl(2, l._1:match("%.?([%w_]+)$"), {1}), 73 | i(1) 74 | })) 75 | parse_add("ti", "table.insert($1, $2)") 76 | 77 | parse_add_auto("tiaa", "table.insertaaa($1, $2)") 78 | 79 | s_add("I", fmt("I({})", {c(1, {parse(nil, "{\"$1\", $2}"), i(1)})})) 80 | 81 | local function uuid() 82 | local id, _ = vim.fn.system('uuidgen'):gsub('\n', '') 83 | return id 84 | end 85 | 86 | s_add("add_k", fmta([[ 87 | ls.add_snippets("all", { 88 | <> 89 | }, { key = "<>" }) 90 | ]], { 91 | i(1), 92 | f(function() return uuid() end) 93 | })) 94 | 95 | parse_add("vi", "vim.inspect($1)") 96 | -------------------------------------------------------------------------------- /nvim/lua/plugins/dap.lua: -------------------------------------------------------------------------------- 1 | local dap = require('dap') 2 | 3 | dap.defaults.fallback.external_terminal = { 4 | command = '/usr/bin/foot'; 5 | -- footclient executes first argument. 6 | args = {'-Tfloatwindow'}; 7 | } 8 | 9 | dap.defaults.fallback.force_external_terminal = true 10 | 11 | dap.adapters.lldb = { 12 | type = 'executable', 13 | command = 'lldb-dap', 14 | name = "lldb", 15 | } 16 | dap.adapters.python = { 17 | type = "executable", 18 | command = "python", 19 | args = {"-m", "debugpy.adapter"}; 20 | options = { 21 | source_filetype = "python" 22 | } 23 | } 24 | dap.adapters.julia = { 25 | type = "server", 26 | port = "${port}", 27 | executable = { 28 | command = "julia", 29 | args = {"-J", "/home/simon/.julia/sysimages/mine1.11-dap2.so", "--startup-file=no", "-e", "using Sockets, DebugAdapter, Logging; function start_debugger(); server_port = parse(Int, ARGS[1]); server = Sockets.listen(server_port); conn = Sockets.accept(server); debugsession = DebugAdapter.DebugSession(conn); run(debugsession); close(conn); end; start_debugger();", "${port}" } 30 | }, 31 | options = { 32 | max_retries = 1000 33 | } 34 | } 35 | 36 | vim.fn.sign_define('DapBreakpoint', {text='〇', texthl='GruvboxRed', linehl='', numhl=''}) 37 | vim.fn.sign_define('DapBreakpointCondition', {text='〇', texthl='GruvboxBlue', linehl='', numhl=''}) 38 | vim.fn.sign_define('DapStopped', {text=' ', texthl='GruvboxYellow', linehl='', numhl=''}) 39 | 40 | local dap_widgets = require("dap.ui.widgets") 41 | 42 | local float 43 | vim.api.nvim_create_user_command("DF", function() 44 | if not float then 45 | float = dap_widgets.centered_float(dap_widgets.frames) 46 | else 47 | float.toggle() 48 | end 49 | end, {}) 50 | 51 | local sidebar 52 | vim.api.nvim_create_user_command("DS", function() 53 | if not sidebar then 54 | sidebar = dap_widgets.sidebar(dap_widgets.scopes) 55 | end 56 | sidebar.toggle() 57 | end, {}) 58 | 59 | vim.api.nvim_create_user_command("DT", function() 60 | dap.terminate(); 61 | end, {}) 62 | 63 | vim.cmd[[ 64 | command! DR :lua require("dap").repl.toggle() 65 | 66 | noremap :lua require"dap".toggle_breakpoint() 67 | " S-F2 68 | noremap :lua require"dap".set_breakpoint(vim.fn.input("Breakpoint condition: ")) 69 | noremap :lua require'dap'.set_breakpoint(nil, nil, vim.fn.input('Log point message: ')) 70 | noremap :lua require"dap".step_over() 71 | noremap :lua require"dap".step_into() 72 | noremap :lua require"dap".step_out() 73 | noremap :lua require"dap".run_last() 74 | noremap :lua require"dap.ui.widgets".hover() 75 | noremap - :lua require"dap".up() 76 | noremap + :lua require"dap".down() 77 | ]] 78 | 79 | 80 | -------------------------------------------------------------------------------- /nixos/profiles/linkding.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | linkding_img = pkgs.dockerTools.pullImage { 5 | imageName = "ghcr.io/sissbruecker/linkding"; 6 | imageDigest = "sha256:12ffd6f3b48c5d46543d2f38030de1f476d8dcff5f486eb75c9c7cb5941e7127"; 7 | hash = "sha256-zoHFMAMAb/OojndFsRqGBFP+Df4BUm6HlIEByRzoIdw="; 8 | finalImageName = "linkding"; 9 | finalImageTag = "system"; 10 | }; 11 | linkding_dir = "/var/lib/linkding"; 12 | in { 13 | users.users.linkding = { 14 | isSystemUser = true; 15 | uid = data.ids.linkding; 16 | group = "linkding"; 17 | subUidRanges = [{count = 100; startUid = 200000;}]; 18 | subGidRanges = [{count = 100; startGid = 200000;}]; 19 | }; 20 | users.groups.linkding.gid = data.ids.linkding; 21 | 22 | systemd.tmpfiles.settings.linkding = { 23 | ${linkding_dir}.d = lib.mkForce { 24 | mode = "770"; 25 | user = "linkding"; 26 | group = "linkding"; 27 | }; 28 | "${linkding_dir}/data".d = lib.mkForce { 29 | mode = "770"; 30 | user = "linkding"; 31 | group = "linkding"; 32 | }; 33 | "${linkding_dir}/podman".d = lib.mkForce { 34 | mode = "770"; 35 | user = "linkding"; 36 | group = "linkding"; 37 | }; 38 | }; 39 | 40 | virtualisation.oci-containers.backend = "podman"; 41 | virtualisation.oci-containers.containers.linkding = { 42 | serviceName = "linkding"; 43 | pull = "never"; 44 | privileged = false; 45 | ports = [ "${toString data.ports.linkding}:9090" ]; 46 | # podman.user = "linkding"; 47 | imageFile = linkding_img; 48 | image = "linkding:system"; 49 | extraOptions = [ "--userns" "keep-id:uid=${toString data.ids.linkding},gid=${toString data.ids.linkding}" "--no-healthcheck"]; 50 | volumes = ["${linkding_dir}/data:/etc/linkding/data"]; 51 | environment = { 52 | LD_SUPERUSER_NAME = "l3mon"; 53 | LD_SUPERUSER_PASSWORD = "l3mon"; 54 | LD_DISABLE_BACKGROUND_TASKS = "True"; 55 | }; 56 | }; 57 | systemd.services.linkding.serviceConfig.Environment=["HOME=${linkding_dir}/podman"]; 58 | 59 | services.caddy.extraConfig = '' 60 | http://linkding, http://linkding.internal, http://linkding.${machine} { 61 | reverse_proxy http://localhost:${toString data.ports.linkding} 62 | } 63 | ''; 64 | 65 | l3mon.restic.extraGroups = [ "linkding" ]; 66 | l3mon.restic.specs.linkding = { 67 | backupStopResumeServices = ["linkding.service"]; 68 | backupDaily = { 69 | text = '' 70 | cd /var/lib/linkding/data 71 | restic backup --tag=linkding --skip-if-unchanged=true -- ./* 72 | ''; 73 | }; 74 | forget = { 75 | text = '' 76 | restic forget --tag=linkding --group-by=tag --keep-daily=7 --keep-monthly=12 77 | ''; 78 | }; 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /nvim/luasnippets/java.lua: -------------------------------------------------------------------------------- 1 | local function jdocsnip(args, _, old_state) 2 | local nodes = { 3 | t({"/**"," * "}), 4 | old_state and i(1, old_state.descr:get_text()) or i(1, {"A short Description"}), 5 | t({"", ""}) 6 | } 7 | 8 | -- These will be merged with the snippet; that way, should the snippet be updated, 9 | -- some user input eg. text can be referred to in the new snippet. 10 | local param_nodes = { 11 | descr = nodes[2] 12 | } 13 | 14 | -- At least one param. 15 | if string.find(args[2][1], " ") then 16 | vim.list_extend(nodes, {t({" * ", ""})}) 17 | end 18 | 19 | local insert = 2 20 | for indx, arg in ipairs(vim.split(args[2][1], ", ", true)) do 21 | -- Get actual name parameter. 22 | arg = vim.split(arg, " ", true)[2] 23 | if arg then 24 | arg = arg:gsub(",", "") 25 | local inode 26 | -- if there was some text in this parameter, use it as static_text for this new snippet. 27 | if old_state and old_state["arg"..arg] then 28 | inode = i(insert, old_state["arg"..arg]:get_text()) 29 | else 30 | inode = i(insert) 31 | end 32 | vim.list_extend(nodes, {t({" * @param "..arg.." "}), inode, t({"", ""})}) 33 | param_nodes["arg"..arg] = inode 34 | 35 | insert = insert + 1 36 | end 37 | end 38 | 39 | if args[1][1] ~= "void" then 40 | local inode 41 | if old_state and old_state.ret then 42 | inode = i(insert, old_state.ret:get_text()) 43 | else 44 | inode = i(insert) 45 | end 46 | 47 | vim.list_extend(nodes, {t({" * ", " * @return "}), inode, t({"", ""})}) 48 | param_nodes.ret = inode 49 | insert = insert + 1 50 | end 51 | 52 | if vim.tbl_count(args[3]) ~= 1 then 53 | local exc = string.gsub(args[3][2], " throws ", "") 54 | local ins 55 | if old_state and old_state.ex then 56 | ins = i(insert, old_state.ex:get_text()) 57 | else 58 | ins = i(insert) 59 | end 60 | vim.list_extend(nodes, {t({" * ", " * @throws "..exc.." "}), ins, t({"", ""})}) 61 | param_nodes.ex = ins 62 | insert = insert + 1 63 | end 64 | 65 | vim.list_extend(nodes, {t({" */"})}) 66 | 67 | local snip = sn(nil, nodes) 68 | -- Error on attempting overwrite. 69 | snip.old_state = param_nodes 70 | return snip 71 | end 72 | s_add({trig="fn"}, { 73 | d(6, jdocsnip, {ai[2], ai[4], ai[5]}), t({"", ""}), 74 | c(1, { 75 | t({"public "}), 76 | t({"private "}) 77 | }), 78 | c(2, { 79 | t({"void"}), 80 | i(nil, {""}), 81 | t({"String"}), 82 | t({"char"}), 83 | t({"int"}), 84 | t({"double"}), 85 | t({"boolean"}), 86 | }), 87 | t({" "}), 88 | i(3, {"myFunc"}), 89 | t({"("}), i(4), t({")"}), 90 | c(5, { 91 | t({""}), 92 | sn(nil, { 93 | t({""," throws "}), 94 | i(1) 95 | }) 96 | }), 97 | t({" {", "\t"}), 98 | i(0), 99 | t({"", "}"}) 100 | }, { 101 | condition = function() return true end 102 | }) 103 | -------------------------------------------------------------------------------- /nixos/modules/peercache.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, self, ... }: 2 | 3 | with lib; 4 | { 5 | options = { 6 | l3mon.peercache = { 7 | pull = mkEnableOption "Pull from other caches."; 8 | push = mkEnableOption "Push to other caches."; 9 | }; 10 | }; 11 | config = let 12 | cfg = config.l3mon.peercache; 13 | machine_lan_address = data.network.lan.peers.${machine}.address; 14 | in mkMerge [ 15 | (mkIf cfg.pull { 16 | # check configs for other machines, only put those that have push enabled. 17 | nix.settings = { 18 | connect-timeout = 5; 19 | substituters = lib.mkOrder data.ordering.peercache-substituters (lib.attrsets.foldlAttrs (acc: name: os: 20 | if os.config.l3mon.peercache.push && name != machine then 21 | acc ++ ["http://cache.${name}.internal"] 22 | else acc) [] self.outputs.nixosConfigurations); 23 | trusted-public-keys = lib.attrsets.foldlAttrs (acc: name: os: 24 | if os.config.l3mon.peercache.push && name != machine then 25 | # we only use this key for signing. 26 | acc ++ ["cache.${name}.internal:dmRV8DJW4a9BBGtzXO2bYAfZAU5l7utBg4n4fTkfSRE="] 27 | else acc) [] self.outputs.nixosConfigurations; 28 | }; 29 | }) 30 | (mkIf cfg.push { 31 | 32 | l3mon.secgen.secrets.peercache = rec { 33 | backup_files = []; 34 | gen = pkgs.writeShellApplication { 35 | name = "gen"; 36 | text = 37 | # bash 38 | '' 39 | tmpkey=$(mktemp) 40 | tmppubkey=$(mktemp) 41 | 42 | nix-store --generate-binary-cache-key "" "$tmpkey" "$tmppubkey" 43 | 44 | KEY=$(cat "$tmpkey") 45 | PUBKEY=$(cat "$tmppubkey") 46 | 47 | echo "Update 'peercache-raw' to $PUBKEY in data/pubkeys.nix" 48 | 49 | rm "$tmpkey" 50 | rm "$tmppubkey" 51 | '' + 52 | lib.attrsets.foldlAttrs (acc: name: _: acc + '' 53 | echo -n "cache.${name}.internal$KEY" > /var/secrets/nix-serve-key-${name} 54 | '') "" self.outputs.nixosConfigurations; 55 | }; 56 | } // lib.attrsets.concatMapAttrs (name: os: {"key-${name}" = "${config.l3mon.secgen.secret_dir}/nix-serve-key-${name}";}) self.outputs.nixosConfigurations; 57 | 58 | services.harmonia = { 59 | enable = true; 60 | signKeyPaths = [config.l3mon.secgen.secrets.peercache."key-${machine}"]; 61 | settings = { 62 | bind = "127.0.0.1:${toString data.ports.harmonia}"; 63 | }; 64 | }; 65 | 66 | services.caddy = { 67 | enable = true; 68 | extraConfig = '' 69 | http://cache.${machine}.internal { 70 | reverse_proxy http://127.0.0.1:${toString data.ports.harmonia} 71 | } 72 | ''; 73 | }; 74 | }) 75 | ]; 76 | } 77 | -------------------------------------------------------------------------------- /nixos/profiles/mobile-net.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, data, machine, ... }: 2 | 3 | let 4 | lan = data.network.lan; 5 | home_wg_net = data.network.wireguard_home2; 6 | home_wg_net_peerconf = data.network.wireguard_home2.peers.${machine}; 7 | blocky_address = "127.0.0.1"; 8 | in { 9 | networking.hostName = machine; 10 | 11 | # can still be per-case enabled via systemd. 12 | networking.useDHCP = false; 13 | networking.firewall.enable = false; 14 | 15 | systemd.network.enable = true; 16 | systemd.network.networks."10-homenet" = { 17 | matchConfig.Name = lan.peers."${machine}".interface; 18 | matchConfig.SSID = "\"${lan.ssid}\""; 19 | networkConfig.Address = lan.peers."${machine}".address + lan.subnet_mask; 20 | networkConfig.Gateway = lan.gateway_peer.address; 21 | networkConfig.DHCP = false; 22 | networkConfig.IPv6AcceptRA = false; 23 | networkConfig.LinkLocalAddressing = false; 24 | networkConfig.DNS = lan.dns; 25 | networkConfig.DNSOverTLS = false; 26 | networkConfig.DNSSEC = false; 27 | }; 28 | 29 | systemd.network.networks."20-nonhomenet" = { 30 | matchConfig.Name = lan.peers."${machine}".interface; 31 | networkConfig.DHCP = true; 32 | dhcpV4Config.UseDNS = false; 33 | dhcpV6Config.UseDNS = false; 34 | # connect to blocky-wg_home2. 35 | networkConfig.DNS = blocky_address; 36 | networkConfig.DNSOverTLS = false; 37 | networkConfig.DNSSEC = false; 38 | }; 39 | 40 | systemd.network.networks."30-${home_wg_net.name}" = { 41 | matchConfig.Name = home_wg_net.name; 42 | networkConfig.Address = home_wg_net_peerconf.address + home_wg_net.subnet_mask; 43 | }; 44 | 45 | systemd.network.netdevs."30-${home_wg_net.name}" = { 46 | netdevConfig = { 47 | Name = home_wg_net.name; 48 | Kind = "wireguard"; 49 | }; 50 | wireguardConfig = { 51 | PrivateKeyFile=home_wg_net_peerconf.privkey_file; 52 | }; 53 | wireguardPeers = [ 54 | { 55 | AllowedIPs = [ 56 | home_wg_net.address_range 57 | ]; 58 | PublicKey = home_wg_net.host.pubkey; 59 | # create all routes. 60 | RouteTable = "main"; 61 | Endpoint = home_wg_net.host.endpoint; 62 | # 0 disables. 63 | PersistentKeepalive = if home_wg_net.keepalive then 60 else 0; 64 | } 65 | ]; 66 | }; 67 | 68 | systemd.services.blocky-wg_home2 = config.l3mon.blocky.mkService { 69 | conf = config.l3mon.blocky.mkConfig { 70 | ports = [ "${blocky_address}:53" ]; 71 | network = data.network.wireguard_home2; 72 | block = false; 73 | upstream = [ "https://one.one.one.one/dns-query" "https://dns0.eu" ]; 74 | }; 75 | }; 76 | 77 | services.resolved = { 78 | enable = true; 79 | dnssec = "true"; 80 | dnsovertls = "true"; 81 | llmnr = "false"; 82 | extraConfig = '' 83 | ResolveUnicastSingleLabel=true 84 | ''; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /nvim/queries/c/folds.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (switch_statement) 3 | (case_statement) 4 | (preproc_if) 5 | (preproc_elif) 6 | (preproc_else) 7 | ] @fold 8 | 9 | (enum_specifier 10 | (enumerator_list) @list 11 | (#make-range-extended! "fold" @list "start" 0 0 @list "end" 0 0) 12 | (#set! foldtext_start "{") 13 | (#set! foldtext_start_hl "@punctuation.bracket") 14 | (#set! foldtext_end "}") 15 | (#set! foldtext_end_hl "@punctuation.bracket")) 16 | 17 | (struct_specifier 18 | (field_declaration_list) @list 19 | (#make-range-extended! "fold" @list "start" 0 0 @list "end" 0 0) 20 | (#set! foldtext_start "{") 21 | (#set! foldtext_start_hl "@punctuation.bracket") 22 | (#set! foldtext_end "}") 23 | (#set! foldtext_end_hl "@punctuation.bracket")) 24 | 25 | ( 26 | [ 27 | ; prevent elseif from becoming its' own fold 28 | ; (might be useful though....) 29 | (compound_statement 30 | (if_statement 31 | condition: (_) 32 | (compound_statement) @comp) @outer 33 | ) 34 | (while_statement 35 | condition: (_) 36 | (compound_statement) @comp 37 | ) @outer 38 | ] 39 | 40 | (#make-range-extended! "fold" @comp "start" 0 0 @outer "end" 0 0) 41 | (#set! foldtext_start "{") 42 | (#set! foldtext_start_hl "@punctuation.bracket") 43 | (#set! foldtext_end "}") 44 | (#set! foldtext_end_hl "@punctuation.bracket") 45 | ) 46 | 47 | ( 48 | (comment) @fold 49 | (#match? @fold "^/*") 50 | (#set! foldtext_start "/*") 51 | (#set! foldtext_start_hl "@comment.cpp") 52 | (#set! foldtext_end "*/") 53 | (#set! foldtext_end_hl "@comment.cpp") 54 | ) 55 | 56 | ( 57 | (for_statement 58 | (compound_statement) @fold) 59 | (#set! foldtext_start "{") 60 | (#set! foldtext_start_hl "@punctuation.bracket") 61 | (#set! foldtext_end "}") 62 | (#set! foldtext_end_hl "@punctuation.bracket") 63 | ) 64 | 65 | ( 66 | (preproc_ifdef 67 | name: (identifier) @ident) @ifd 68 | 69 | (#make-range-extended! "fold" @ident "end" 0 1 @ifd "end" 0 0) 70 | (#set! foldtext_start "") 71 | (#set! foldtext_start_hl "") 72 | (#set! foldtext_end "#endif") 73 | (#set! foldtext_end_hl "@keyword") 74 | ) 75 | 76 | ( 77 | (argument_list) @fold 78 | (#set! foldtext_start "(") 79 | (#set! foldtext_start_hl "@punctuation.bracket") 80 | (#set! foldtext_end ")") 81 | (#set! foldtext_end_hl "@punctuation.bracket") 82 | ) 83 | 84 | ; only match functions without initializer list. 85 | ( 86 | (function_definition . (_)? . (_)? . declarator: (_) . (compound_statement) @fold .) 87 | (#set! foldtext_start "{") 88 | (#set! foldtext_start_hl "@punctuation.bracket") 89 | (#set! foldtext_end "}") 90 | (#set! foldtext_end_hl "@punctuation.bracket") 91 | ) 92 | 93 | ( 94 | (initializer_list) @fold 95 | (#set! foldtext_start "{") 96 | (#set! foldtext_start_hl "@punctuation.bracket") 97 | (#set! foldtext_end "}") 98 | (#set! foldtext_end_hl "@punctuation.bracket") 99 | ) 100 | -------------------------------------------------------------------------------- /nvim/lua/filejump/init.lua: -------------------------------------------------------------------------------- 1 | local util = require("util") 2 | local get_filelocation = require("filejump.filelocation") 3 | local function t(x) return vim.api.nvim_replace_termcodes(x, true, true, true) end 4 | 5 | -- buffers where the binding should be activated. 6 | local function binding_valid_buf(bufnr) 7 | -- only for buffer 8 | local bufname = vim.api.nvim_buf_get_name(bufnr) 9 | return (bufnr == 1 and bufname == "") or bufname:match("^/") or vim.bo[bufnr].filetype == "repl" or vim.bo[bufnr].filetype == "term" 10 | end 11 | 12 | -- whether this window can be used for displaying some file. 13 | local function file_display_window(win) 14 | local win_bufnr = vim.api.nvim_win_get_buf(win) 15 | -- only for buffer 16 | local bufname = vim.api.nvim_buf_get_name(win_bufnr) 17 | return bufname:match("^/") and vim.bo[win_bufnr].filetype ~= "repl" or vim.bo[win_bufnr].filetype ~= "term" 18 | end 19 | 20 | -- value for initial window? is static? 21 | local last_valid_file_display_window = 1000 22 | -- we want to track the window that displayed a valid buffer. 23 | -- This value changes when switching windows and when a buffer becomes valid 24 | -- through editing some other file (maybe?) 25 | -- Although, if a window was valid once, I think in my usage, it should 26 | -- continue being valid... 27 | -- And, if I go with this, I'd need to make last_valid_file_display_window a 28 | -- stack and pop off all invalid windows or something. 29 | vim.api.nvim_create_autocmd({"VimEnter", "WinEnter"}, { 30 | pattern = "*", 31 | callback = function(args) 32 | local win = vim.api.nvim_get_current_win() 33 | if file_display_window(win) then 34 | last_valid_file_display_window = win 35 | end 36 | end 37 | }) 38 | 39 | local function file_jump(filelocation) 40 | vim.api.nvim_tabpage_set_win(0, last_valid_file_display_window) 41 | vim.api.nvim_exec2("edit " .. filelocation.path, {}) 42 | -- lets hope columns are always 1-indexed... 43 | -- maybe we need custom-behaviour 44 | vim.api.nvim_win_set_cursor(last_valid_file_display_window, {filelocation.row or 1, filelocation.col and (filelocation.col-1) or 0}) 45 | end 46 | 47 | vim.keymap.set("n", "", function() 48 | local buf = vim.api.nvim_get_current_buf() 49 | local win = vim.api.nvim_get_current_win() 50 | 51 | local cursor = util.get_cursor_0ind(win) 52 | local cursor_line = vim.api.nvim_buf_get_lines(buf, cursor[1], cursor[1]+1, true)[1] 53 | 54 | -- check paths relative to cwd+root via "", and local to file-directory via buf-directory. 55 | local paths = {util.bufname_to_dir(vim.api.nvim_buf_get_name(buf)), vim.loop.cwd()} 56 | -- +1: 0- to 1-based indexing. 57 | local filelocation_under_cursor = get_filelocation(paths, cursor_line, cursor[2]+1) 58 | if binding_valid_buf(buf) and filelocation_under_cursor ~= nil then 59 | vim.schedule(function() 60 | file_jump(filelocation_under_cursor) 61 | end) 62 | return t"" 63 | else 64 | return t"" 65 | end 66 | end, {noremap=true, expr=true}) 67 | -------------------------------------------------------------------------------- /nixos/home/profiles/neovim/default.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, pkgs-unstable, machine, inputs, data, ... }: 2 | 3 | let 4 | nvim = inputs.neovim-nightly.packages.${pkgs.system}.default; 5 | in { 6 | home.activation.myNvimRepos = lib.hm.dag.entryAfter ["writeBoundary"] '' 7 | run mkdir -p ${config.home.homeDirectory}/projects/dotfiles/nvim 8 | if [ ! -d "${config.home.homeDirectory}/projects/nvim/matchconfig" ]; then 9 | run ${pkgs.systemd}/lib/systemd/systemd-networkd-wait-online 10 | run ${pkgs.git}/bin/git clone http://git.internal/simon/matchconfig.git ${config.home.homeDirectory}/projects/nvim/matchconfig 11 | fi 12 | if [ ! -d "${config.home.homeDirectory}/projects/nvim/luasnip" ]; then 13 | run ${pkgs.systemd}/lib/systemd/systemd-networkd-wait-online 14 | run ${pkgs.git}/bin/git clone http://git.internal/simon/luasnip.git ${config.home.homeDirectory}/projects/nvim/luasnip 15 | fi 16 | if [ ! -d "${config.home.homeDirectory}/projects/nvim/togglecomment" ]; then 17 | run ${pkgs.systemd}/lib/systemd/systemd-networkd-wait-online 18 | run ${pkgs.git}/bin/git clone http://git.internal/simon/togglecomment.git ${config.home.homeDirectory}/projects/nvim/togglecomment 19 | fi 20 | 21 | echo 'return {"${nvim}/share/nvim/runtime"}' > "${config.home.homeDirectory}/projects/dotfiles/nvim/generated/rtp_base.lua" 22 | ''; 23 | 24 | programs.neovim = { 25 | enable = true; 26 | defaultEditor = true; 27 | extraPackages = [ 28 | # add tree-sitter from nvim-nightly package. 29 | # we need tree-sitter for building grammars from nvim-treesitter, and the 30 | # version in pkgs may be wrong. 31 | (builtins.head (builtins.filter (x: x.name == "tree-sitter-bundled") inputs.neovim-nightly.packages.${pkgs.system}.neovim.buildInputs)) 32 | # for building treesitter grammars. 33 | pkgs.zig 34 | pkgs.nodejs 35 | pkgs.luajit 36 | pkgs.luarocks 37 | 38 | pkgs-unstable.lua-language-server 39 | pkgs.pyright 40 | # make sure to install LanguageServer.jl, Images, Revise 41 | # clangd 42 | pkgs.clang-tools 43 | pkgs.python312Packages.ipython 44 | 45 | (import ./julia-lsp.nix { pkgs = pkgs; }) 46 | 47 | # lldb-dap 48 | pkgs.lldb 49 | 50 | # preview markdown. 51 | (pkgs.python312Packages.grip.overrideAttrs (prev: { 52 | src = pkgs.fetchFromGitHub { 53 | owner = "nikolavp"; 54 | repo = "grip"; 55 | rev = "add-mermaid-support"; 56 | hash = "sha256-cRC+vst/W0pZosZXAOey4WtcLNOL8THRJ+5bhcCRdZw="; 57 | }; 58 | patches = []; 59 | # not all checks pass on that branch :/ 60 | checkPhase = ""; 61 | installCheckPhase = ""; 62 | })) 63 | ]; 64 | extraLuaPackages = ps: with ps; [ 65 | luasocket 66 | ]; 67 | package = nvim; 68 | }; 69 | 70 | xdg.configFile."nvim".source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/projects/dotfiles/nvim"; 71 | } 72 | -------------------------------------------------------------------------------- /nixos/README.md: -------------------------------------------------------------------------------- 1 | This directory contains my NixOS configuration. 2 | 3 | The general structure is as follows: 4 | 5 | * `flake.nix` is the root-flake and manages all inputs. 6 | * `data/` contains an attribute set for miscellanious data that applies to all 7 | machines managed by the config. 8 | * `machines/` contains hardware-related settings for all machines, eg. setup of 9 | mountpoints and cleaning of such. 10 | * `modules/` contains reusable modules that manage services etc. 11 | 12 | # Workflows 13 | 14 | ## Wireguard 15 | `/var/secrets` contains all public and private keys, generate 16 | wg-netns-consumable files from them via 17 | 18 | # Cleaning /nix/store 19 | `nix-collect-garbage --delete-old` as regular user for home-manager-, and root 20 | for the system-profiles. 21 | 22 | # Conventions 23 | 24 | ## Wireguard 25 | * netns-name matches name of wg_network. 26 | * service-name is netns-`netns-name`. 27 | 28 | ## Custom packages 29 | * provide via overlay as pkgs.l3mon.*. I think this makes a lot of sense since 30 | packages are included in pkgs-fixpoint-computation and can be overridden (not 31 | possible when maintaining in a separate attrset) and I don't have to worry 32 | about name-conflicts with packages in pkgs. 33 | 34 | ## Secrets 35 | Provide secrets at runtime by referring to files in /var/secret. 36 | Or, and this seems very flexible: use envsubst in an activationScript to 37 | populate secrets via env-var into some template-file! 38 | See `profiles/radarr.nix` for an example. 39 | 40 | All secrets except the following are set up automatically: 41 | * gpg: Set these up via 42 | ``` 43 | gpg --import /var/secrets/gpg-simljk@outlook.de.priv 44 | gpg --import /var/secrets/gpg-simljk@outlook.de.priv-subkey 45 | gpg --import /var/secrets/gpg-simljk@outlook.de.pub 46 | gpg --edit-key 47 | trust 5 48 | ``` 49 | 50 | ## Steam 51 | Log into steam once with steamcmd and HOME=/var/lib/steam/cmd and enter 52 | steamguard-code, then it should run again for a while. 53 | ## GOG 54 | Log into gog via HOME=/var/lib/gog lgogdownloader --login, then update-games can 55 | do its job for gog. 56 | 57 | # TODO 58 | * Use DHCP (Kea, dhcpcd is deprecated) for configuring ips. 59 | Be careful doing this in fritzbox-net, have to disable its dhcp-server. 60 | * Look into using tailscale (or the self-hosted variant), it may be faster 61 | than raw wireguard due to hole-punching (directly connect peers vs route all 62 | traffic over server). 63 | * Use ACL to allow granular access to files and directories for restic. Probably 64 | use systemd.tmpfiles for granular access, and run it after NixOS rebuild via 65 | systemd-tmpfiles-resetup.service in activationScript (After?) to make sure 66 | permissions are correct even when nixOS has different ACL for some directory. 67 | * mount-unit with NetworkNamespacePath in Unit??? 68 | 69 | # Resources 70 | * [noogle](https://noogle.dev/) for searching stdlib functions and pulling the 71 | implementation. 72 | * [nixpkgs](https://github.com/NixOS/nixpkgs) Actually has all implementations 73 | :D 74 | -------------------------------------------------------------------------------- /nvim/lua/plugins/gruvbox.lua: -------------------------------------------------------------------------------- 1 | require("gruvbox").setup({ 2 | contrast = "hard", 3 | transparent_mode = true, 4 | palette_overrides = { 5 | -- bright_red = "#d75151" 6 | }, 7 | overrides = { 8 | TabLine = { 9 | bg = "#1d2021", 10 | fg = "#504945" 11 | }, 12 | TabLineSel = { 13 | bg="#1d2021", 14 | fg="" 15 | }, 16 | Status1 = { 17 | bg = "#fabd2f", 18 | fg = "#1d2021", 19 | bold = true, 20 | }, 21 | Status2 = { 22 | bg = "#fe8019", 23 | fg = "#1d2021", 24 | bold = true, 25 | }, 26 | Status3 = { 27 | bg = "#83a598", 28 | fg = "#1d2021", 29 | bold = true, 30 | }, 31 | 32 | User1 = { 33 | bg = "#3c3836", 34 | fg = "#1d2021" 35 | }, 36 | StatusLine = { 37 | bg="#3c3836", 38 | fg="#1d2021" 39 | }, 40 | StatusLineNC = { 41 | bg="#282828", 42 | fg="#1d2021" 43 | }, 44 | NormalFloat= { 45 | fg="#ebdbb2", 46 | bg="#3c3836", 47 | }, 48 | InlayHint = { 49 | fg="#665c54", 50 | bg="#3c3836", 51 | }, 52 | 53 | -- don't do a palette override, only change for keywords and the like. 54 | GruvboxRed = { fg = "#d75151" }, 55 | 56 | String = { italic = false }, 57 | Operator = { italic = false }, 58 | 59 | GruvboxRedSign = { bg = "#1d2021" }, 60 | GruvboxYellowSign = { bg = "#1d2021" }, 61 | GruvboxBlueSign = { bg = "#1d2021" }, 62 | GruvboxAquaSign = { bg = "#1d2021" }, 63 | 64 | ["@string.escape"] = { bold = true }, 65 | Function = {link = "GruvboxOrangeBold"}, 66 | Identifier = {link = "GruvboxFg1"}, 67 | Field = {link = "GruvboxBlue"}, 68 | Namespace = {link = "GruvboxAquaBold"}, 69 | ["@field"] = {link = "Field"}, 70 | ["@field.lua"] = {link = "Identifier"}, 71 | ["@lsp.type.property"] = {link = "Field"}, 72 | ["@parameter"] = {link = "Identifier"}, 73 | Method = {link = "GruvboxBlueBold"}, 74 | ["@lsp.type.method"] = {link = "Method"}, 75 | ["@lsp.type.function"] = {link = "Function"}, 76 | ["@lsp.type.namespace"] = {link = "Namespace"}, 77 | ["@lsp.type.type"] = {link = "Type"}, 78 | ["@lsp.type.class"] = {link = "Type"}, 79 | ["@lsp.type.variable"] = {link = "Identifier"}, 80 | ["@lsp.type.enumMember"] = {link = "Constant"}, 81 | ["@lsp.type.macro"] = {link = "GruvboxPurple"}, 82 | ["@lsp.type.comment"] = {link = "Comment"}, 83 | 84 | ["@lsp.mod.static"] = {link = "Field"}, 85 | ["@lsp.mod.namespace"] = {link = "Namespace"}, 86 | ["@lsp.mod.global.lua"] = {link = "Namespace"}, 87 | 88 | ["@function.cpp"] = {link = "GruvboxOrange"}, 89 | 90 | Delimiter = {link = "GruvboxOrange"}, 91 | 92 | ["@module.latex"] = {link = "GruvboxAquaBold"}, 93 | }, 94 | }) 95 | 96 | vim.cmd([[ 97 | colorscheme gruvbox 98 | " hi! link @preproc GruvboxRed 99 | 100 | hi! UnderlineTransparent gui=underline 101 | 102 | hi! link LspReferenceText CursorLine 103 | hi! link LspReferenceRead CursorLine 104 | hi! link LspReferenceWrite CursorLine 105 | 106 | " for tsplayground 107 | hi! link NodeType GruvboxBlue 108 | 109 | hi! link @rule GruvboxBlue 110 | 111 | hi Folded guibg= cterm=none gui=none 112 | ]]) 113 | -------------------------------------------------------------------------------- /nixos/modules/sway-netns.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, machine, data, ... }: 2 | 3 | with lib; 4 | let 5 | netns_cfg = config.l3mon.network_namespaces; 6 | in { 7 | home-manager.sharedModules = (map 8 | (wg_network: let 9 | netns_name = "${wg_network.name}"; 10 | in ( 11 | { config, lib, pkgs, machine, data, ... }: { 12 | options.l3mon.sway-netns.${netns_name} = { 13 | enable = mkEnableOption "Enable sway-keybindings for ${netns_name}."; 14 | openPrivateWindow = mkOption { 15 | type = types.bool; 16 | description = "Whether to open firefox in incognito mode."; 17 | default = false; 18 | }; 19 | netnsKey = mkOption { 20 | type = types.str; 21 | description = "bindsym for this network namespace."; 22 | }; 23 | landingPage = mkOption { 24 | type = types.str; 25 | description = "Page to open on startup."; 26 | default = "http://google.com"; 27 | }; 28 | firefoxProfileSettings = mkOption { 29 | type = types.attrs; 30 | description = "Attrs for the netns-specific firefox profile."; 31 | default = {}; 32 | }; 33 | }; 34 | config = let 35 | cfg = config.l3mon.sway-netns.${netns_name}; 36 | ff_profile_name = "netns-${netns_name}"; 37 | in (mkIf cfg.enable { 38 | programs.firefox.profiles = { 39 | ${ff_profile_name} = { 40 | name = ff_profile_name; 41 | isDefault = false; 42 | } // cfg.firefoxProfileSettings; 43 | }; 44 | 45 | 46 | wayland.windowManager.sway.extraConfig = let 47 | # ns_exec = "${config.security.wrapperDir}/netns-exec ${netns_name}"; 48 | ns_exec = "netns-exec"; 49 | in '' 50 | mode "netns" { 51 | bindsym ${cfg.netnsKey} mode "${netns_name}" 52 | } 53 | 54 | mode "${netns_name}" { 55 | bindsym Return exec $term ${ns_exec} ${netns_name} bash; mode "default" 56 | ${lib.optionalString config.programs.firefox.enable "bindsym f exec ${ns_exec} ${netns_name} ${config.programs.firefox.finalPackage}/bin/firefox -no-remote -P ${ff_profile_name} ${lib.optionalString cfg.openPrivateWindow "--private-window"} ${cfg.landingPage}; mode default"} 57 | 58 | bindsym Escape mode "default" 59 | } 60 | ''; 61 | }); 62 | } 63 | )) 64 | config.l3mon.network_namespaces.network_configs) ++ 65 | [ 66 | ({ config, lib, pkgs, machine, data, ... }: { 67 | config = mkIf (any (wg_network: config.l3mon.sway-netns.${wg_network.name}.enable) netns_cfg.network_configs) { 68 | wayland.windowManager.sway.extraConfig = '' 69 | mode "netns" { 70 | bindsym Escape mode "default" 71 | } 72 | bindsym $mod+n mode "netns" 73 | ''; 74 | }; 75 | }) 76 | ]; 77 | } 78 | -------------------------------------------------------------------------------- /nixos/profiles/samba.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, ... }: 2 | 3 | { 4 | services.samba = { 5 | enable = true; 6 | settings = { 7 | global = { 8 | "security" = "user"; 9 | "dns proxy" = "no"; 10 | "server role" = "standalone server"; 11 | "server string" = machine; 12 | "idmap config * : backend" = "tdb"; 13 | "hosts allow" = "192.168.178. 127. 10.0.0."; 14 | "logging" = "systemd"; 15 | "disable netbios" = "yes"; 16 | }; 17 | christel = { 18 | "force directory mode" = "02770"; 19 | "path" = "/srv/samba/christel"; 20 | "read only" = "no"; 21 | "valid users" = "christel"; 22 | }; 23 | simon = { 24 | # make sure group has read-permission. 25 | "force directory mode" = "02770"; 26 | "path" = "/srv/media"; 27 | "read only" = "yes"; 28 | "valid users" = "simon"; 29 | }; 30 | private = { 31 | # make sure group has read-permission. 32 | "force directory mode" = "02770"; 33 | "path" = "/srv/private"; 34 | "read only" = "yes"; 35 | "valid users" = "private"; 36 | }; 37 | }; 38 | }; 39 | 40 | # allow access to /srv/samba, for cd. 41 | systemd.tmpfiles.rules = [ 42 | "d /srv/samba 0755 samba samba" 43 | "d /srv/samba/christel 0750 christel christel" 44 | ]; 45 | 46 | users.users.samba = { 47 | isSystemUser = true; 48 | uid = data.ids.samba; 49 | group = "samba"; 50 | }; 51 | users.groups.samba.gid = data.ids.samba; 52 | 53 | users.users.christel = { 54 | isSystemUser = true; 55 | uid = data.ids.christel; 56 | group = "christel"; 57 | }; 58 | users.groups.christel.gid = data.ids.christel; 59 | 60 | users.users.private = { 61 | isSystemUser = true; 62 | uid = data.ids.private; 63 | group = "private"; 64 | }; 65 | users.groups.private.gid = data.ids.private; 66 | 67 | system.activationScripts = { 68 | samba-users = { 69 | text = (l3lib.assertSecret "smb_passwd_christel") + 70 | (l3lib.assertSecret "smb_passwd_simon") + 71 | (l3lib.assertSecret "smb_passwd_private") + 72 | '' 73 | echo -ne "$(cat ${l3lib.secret "smb_passwd_christel"})\n$(cat ${l3lib.secret "smb_passwd_christel"})\n" | ${pkgs.samba}/bin/smbpasswd -a christel 74 | echo -ne "$(cat ${l3lib.secret "smb_passwd_simon"})\n$(cat ${l3lib.secret "smb_passwd_simon"})\n" | ${pkgs.samba}/bin/smbpasswd -a simon 75 | echo -ne "$(cat ${l3lib.secret "smb_passwd_private"})\n$(cat ${l3lib.secret "smb_passwd_private"})\n" | ${pkgs.samba}/bin/smbpasswd -a private 76 | ''; 77 | }; 78 | }; 79 | 80 | l3mon.restic.extraGroups = [ "christel" "samba" ]; 81 | l3mon.restic.specs.samba = { 82 | backupDaily = { 83 | text = '' 84 | cd /srv/samba 85 | restic backup --tag=samba-christel --skip-if-unchanged=true -- christel 86 | ''; 87 | }; 88 | forget = { 89 | text = '' 90 | restic forget --tag=samba-christel --group-by=tag --keep-monthly 12 --keep-yearly=unlimited --keep-last=20 91 | ''; 92 | }; 93 | }; 94 | } 95 | -------------------------------------------------------------------------------- /nixos/modules/qb_control.py: -------------------------------------------------------------------------------- 1 | import qbittorrentapi 2 | from enum import Enum 3 | from functools import reduce 4 | import time 5 | 6 | client = qbittorrentapi.Client(host="qbittorrent.internal:80") 7 | 8 | 9 | class QBTTorrent: 10 | def __init__(self, hash=None): 11 | assert hash 12 | self.hash = hash 13 | 14 | @classmethod 15 | def from_hash(cls, hash): 16 | return cls(hash=hash) 17 | 18 | def stop(self): 19 | client.torrents_stop(self.hash) 20 | 21 | def info(self): 22 | return client.torrents_info(torrent_hashes=self.hash)[0] 23 | 24 | def limit_download(self): 25 | client.torrents_set_download_limit(torrent_hashes=self.hash, limit=1) 26 | 27 | def unlimit_download(self): 28 | client.torrents_set_download_limit(torrent_hashes=self.hash, limit=-1) 29 | 30 | 31 | class APITorrentState(Enum): 32 | ERROR = "error" 33 | MISSING_FILES = "missingFiles" 34 | UPLOADING = "uploading" 35 | STOPPED_UPLOAD = "stoppedUP" 36 | QUEUED_UPLOAD = "queuedUP" 37 | STALLED_UPLOAD = "stalledUP" 38 | CHECKING_UPLOAD = "checkingUP" 39 | FORCED_UPLOAD = "forcedUP" 40 | ALLOCATING = "allocating" 41 | DOWNLOADING = "downloading" 42 | METADATA_DOWNLOAD = "metaDL" 43 | FORCED_METADATA_DOWNLOAD = "forcedMetaDL" 44 | STOPPED_DOWNLOAD = "stoppedDL" 45 | QUEUED_DOWNLOAD = "queuedDL" 46 | FORCED_DOWNLOAD = "forcedDL" 47 | STALLED_DOWNLOAD = "stalledDL" 48 | CHECKING_DOWNLOAD = "checkingDL" 49 | CHECKING_RESUME_DATA = "checkingResumeData" 50 | MOVING = "moving" 51 | UNKNOWN = "unknown" 52 | 53 | 54 | # not sure about the statuses here.. 55 | def get_torrents(state, category): 56 | return reduce( 57 | lambda list, info: 58 | list + ([QBTTorrent.from_hash(info.hash)] 59 | if info.state in state else []), 60 | client.torrents_info(category=category), []) 61 | 62 | 63 | # only stop if movie is actually downloading! 64 | movie_downloading_states = frozenset({ 65 | APITorrentState.FORCED_DOWNLOAD.value, 66 | APITorrentState.DOWNLOADING.value 67 | }) 68 | 69 | # collect states to stop. 70 | aa_downloading_states = frozenset({ 71 | APITorrentState.FORCED_DOWNLOAD.value, 72 | APITorrentState.STALLED_DOWNLOAD.value, 73 | APITorrentState.DOWNLOADING.value 74 | }) 75 | 76 | 77 | max_tries = 5 78 | tries = 0 79 | retry_timeout_s = 10 80 | while True: 81 | tries += 1 82 | print(f"Try {tries}") 83 | try: 84 | priority_dl_torrents = get_torrents(movie_downloading_states, "radarr") + get_torrents(movie_downloading_states, "tv-sonarr") # noqa: E501. 85 | if len(priority_dl_torrents) > 0: 86 | for t in get_torrents(aa_downloading_states, "aa"): 87 | t.limit_download() 88 | else: 89 | for t in get_torrents(aa_downloading_states, "aa"): 90 | t.unlimit_download() 91 | break 92 | except qbittorrentapi.exceptions.InternalServerError500Error as ex: 93 | if tries >= max_tries: 94 | ex.add_note(f"The exception occured {max_tries} times!") 95 | raise 96 | 97 | print("Got 500-Error, trying again...") 98 | time.sleep(retry_timeout_s) 99 | -------------------------------------------------------------------------------- /nixos/profiles/errormail.nix: -------------------------------------------------------------------------------- 1 | { config, lib, l3lib, pkgs, machine, data, ... }: 2 | 3 | let 4 | target_email = "simon@l3mon4.de"; 5 | notify-generic = pkgs.writeShellApplication { 6 | name = "notify-generic"; 7 | runtimeInputs = with pkgs; [ msmtp ]; 8 | text = '' 9 | sendmail -t < we stay on the active output. 76 | local ordered_output_names = {} 77 | for _, output in ipairs(inactive_output_specs) do 78 | table.insert(ordered_output_names, output.name) 79 | end 80 | table.insert(ordered_output_names, active_output_spec.name) 81 | 82 | for _, output in ipairs(ordered_output_names) do 83 | local workspace = new_workspaces[output] 84 | sway:msg(("focus output %s"):format(output)) 85 | os.execute("sleep 0.001") 86 | sway:msg(("workspace %s"):format(workspace)) 87 | end 88 | write(statefile_path, cjson.encode(self)) 89 | end 90 | 91 | local function get_state() 92 | local state_str = read(statefile_path) 93 | return setmetatable(state_str and cjson.decode(state_str) or default_state, State_mt) 94 | end 95 | 96 | local next_workroom = arg[1] 97 | 98 | assert(#next_workroom == 1) 99 | 100 | local state = get_state() 101 | state:activate_workroom(next_workroom) 102 | --------------------------------------------------------------------------------