From 1c853edcab3261a431315a4b675f9409a3dde82e Mon Sep 17 00:00:00 2001 From: Leon Vatthauer Date: Fri, 16 Feb 2024 13:59:46 +0100 Subject: [PATCH] initial commit after purge --- .gitignore | 1 + .gitmodules | 3 + common/default.nix | 11 + common/direnv.nix | 8 + common/doom.d/config.el | 0 common/doom.d/init.el | 0 common/doom.d/packages.el | 0 common/eww/config/eww.scss | 109 ++++ common/eww/config/eww.yuck | 51 ++ common/eww/config/widgets/resources/eww.yuck | 92 +++ .../eww/config/widgets/resources/network.sh | 9 + .../eww/config/widgets/window-title/eww.yuck | 7 + .../widgets/window-title/get-window-title.sh | 3 + .../workspaces/change-active-workspace.sh | 21 + common/eww/config/widgets/workspaces/eww.yuck | 18 + .../workspaces/get-active-workspace.sh | 6 + .../widgets/workspaces/get-workspaces.sh | 11 + common/eww/default.nix | 8 + common/git.nix | 24 + common/neovim/coc.nix | 185 ++++++ common/neovim/coq.nix | 15 + common/neovim/default.nix | 32 + common/neovim/haskell.nix | 18 + common/neovim/lightline.nix | 30 + common/neovim/nerdtree.nix | 27 + common/neovim/nvimrc.nix | 296 +++++++++ common/neovim/telescope.nix | 38 ++ common/neovim/treesitter.nix | 13 + common/starship.nix | 17 + common/vim.nix | 28 + common/vimrc.nix | 604 ++++++++++++++++++ common/vscode.nix | 103 +++ flake.lock | 361 +++++++++++ flake.nix | 84 +++ gunther/configuration.nix | 248 +++++++ gunther/hardware-configuration.nix | 34 + gunther/hypr/catppuccin-macchiato.rasi | 111 ++++ gunther/hypr/hyprland.nix | 181 ++++++ gunther/hypr/hyprpaper.conf | 5 + gunther/hypr/start.sh | 13 + gunther/hypr/wallpaper.jpg | Bin 0 -> 85902 bytes gunther/leonv.nix | 137 ++++ iso/configuration.nix | 105 +++ shinx/default.nix | 27 + shinx/leonvatthauer.nix | 70 ++ willem/README.md | 20 + willem/configuration.nix | 77 +++ willem/hardware-configuration.nix | 26 + willem/programs/default.nix | 8 + willem/programs/neovim.nix | 14 + willem/programs/ssh.nix | 6 + willem/programs/starship.nix | 8 + willem/programs/zsh.nix | 19 + willem/services/acme.nix | 8 + willem/services/ddns.nix | 16 + willem/services/default.nix | 12 + willem/services/gitea.nix | 23 + willem/services/nginx.nix | 33 + willem/services/printing.nix | 20 + willem/services/restic.nix | 17 + willem/services/ssh.nix | 4 + willem/services/vaultwarden.nix | 19 + 62 files changed, 3494 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100755 common/default.nix create mode 100755 common/direnv.nix create mode 100644 common/doom.d/config.el create mode 100644 common/doom.d/init.el create mode 100644 common/doom.d/packages.el create mode 100644 common/eww/config/eww.scss create mode 100644 common/eww/config/eww.yuck create mode 100644 common/eww/config/widgets/resources/eww.yuck create mode 100755 common/eww/config/widgets/resources/network.sh create mode 100644 common/eww/config/widgets/window-title/eww.yuck create mode 100644 common/eww/config/widgets/window-title/get-window-title.sh create mode 100644 common/eww/config/widgets/workspaces/change-active-workspace.sh create mode 100644 common/eww/config/widgets/workspaces/eww.yuck create mode 100755 common/eww/config/widgets/workspaces/get-active-workspace.sh create mode 100755 common/eww/config/widgets/workspaces/get-workspaces.sh create mode 100644 common/eww/default.nix create mode 100755 common/git.nix create mode 100644 common/neovim/coc.nix create mode 100644 common/neovim/coq.nix create mode 100644 common/neovim/default.nix create mode 100644 common/neovim/haskell.nix create mode 100644 common/neovim/lightline.nix create mode 100644 common/neovim/nerdtree.nix create mode 100644 common/neovim/nvimrc.nix create mode 100644 common/neovim/telescope.nix create mode 100644 common/neovim/treesitter.nix create mode 100755 common/starship.nix create mode 100644 common/vim.nix create mode 100644 common/vimrc.nix create mode 100755 common/vscode.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100755 gunther/configuration.nix create mode 100644 gunther/hardware-configuration.nix create mode 100644 gunther/hypr/catppuccin-macchiato.rasi create mode 100644 gunther/hypr/hyprland.nix create mode 100644 gunther/hypr/hyprpaper.conf create mode 100755 gunther/hypr/start.sh create mode 100644 gunther/hypr/wallpaper.jpg create mode 100755 gunther/leonv.nix create mode 100644 iso/configuration.nix create mode 100755 shinx/default.nix create mode 100755 shinx/leonvatthauer.nix create mode 100644 willem/README.md create mode 100644 willem/configuration.nix create mode 100644 willem/hardware-configuration.nix create mode 100644 willem/programs/default.nix create mode 100644 willem/programs/neovim.nix create mode 100644 willem/programs/ssh.nix create mode 100644 willem/programs/starship.nix create mode 100644 willem/programs/zsh.nix create mode 100644 willem/services/acme.nix create mode 100644 willem/services/ddns.nix create mode 100644 willem/services/default.nix create mode 100644 willem/services/gitea.nix create mode 100644 willem/services/nginx.nix create mode 100644 willem/services/printing.nix create mode 100644 willem/services/restic.nix create mode 100644 willem/services/ssh.nix create mode 100644 willem/services/vaultwarden.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3570931 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "nix-secrets"] + path = nix-secrets + url = gitea@git.vatthauer.xyz:leonv/nix-secrets.git diff --git a/common/default.nix b/common/default.nix new file mode 100755 index 0000000..475408f --- /dev/null +++ b/common/default.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: +{ + imports = [ + ./vscode.nix + ./git.nix + ./direnv.nix + ./starship.nix + ./neovim + #./vim.nix + ]; +} diff --git a/common/direnv.nix b/common/direnv.nix new file mode 100755 index 0000000..d222ccb --- /dev/null +++ b/common/direnv.nix @@ -0,0 +1,8 @@ +{ + programs.direnv = { + enable = true; + nix-direnv = { + enable = true; + }; + }; +} \ No newline at end of file diff --git a/common/doom.d/config.el b/common/doom.d/config.el new file mode 100644 index 0000000..e69de29 diff --git a/common/doom.d/init.el b/common/doom.d/init.el new file mode 100644 index 0000000..e69de29 diff --git a/common/doom.d/packages.el b/common/doom.d/packages.el new file mode 100644 index 0000000..e69de29 diff --git a/common/eww/config/eww.scss b/common/eww/config/eww.scss new file mode 100644 index 0000000..c053b74 --- /dev/null +++ b/common/eww/config/eww.scss @@ -0,0 +1,109 @@ +// catppuccin colors +$rosewater: #f4dbd6; +$flamingo: #f0c6c6; +$pink: #f5bde6; +$mauve: #c6a0f6; +$red: #ed8796; +$maroon: #ee99a0; +$peach: #f5a97f; +$yellow: #eed49f; +$green: #a6da95; +$teal: #8bd5ca; +$sky: #91d7e3; +$sapphire: #7dc4e4; +$blue: #8aadf4; +$lavender: #b7bdf8; +$accent: $flamingo; +$text: #cad3f5; +$subtext1: #b8c0e0; +$subtext0: #a5adcb; +$overlay2: #939ab7; +$overlay1: #8087a2; +$overlay0: #6e738d; +$surface2: #5b6078; +$surface1: #494d64; +$surface0: #363a4f; +$base: #24273a; +$mantle: #1e2030; +$crust: #181926; + +*{ + all: unset; + font-family: "monospace"; +} + +// .bar { +// background-color: $base; +// border-radius: 16px; +// } + +.container { + background-color: $base; + border-radius: 16px; +} + +tooltip.background { + background-color: #0f0f17; + font-size: 18px; + border-radius: 10px; + color: #bfc9db; +} + +tooltip label { + margin: 6px; +} + +.time { + font-size: 18px; + margin: 0px 20px 0px 10px; + color: $teal; + font-weight: bold; +} + +.volume_text { + font-size: 18px; + color: $maroon; + margin: 0px 10px 0px 10px; +} + +.network_icon { + font-size: 18px; + color: $green; + margin: 0px 10px 0px 10px; +} +.bluetooth_icon { + font-size: 18px; + color: $blue; + margin: 0px 10px 0px 10px; +} +.cpu_text { + font-size: 18px; + color: $maroon; + margin: 0px 10px 0px 10px; +} +.mem_text { + font-size: 18px; + color: $yellow; + margin: 0px 10px 0px 10px; +} + +.workspaces-widget { + color: $sky; + font-size: 22px; +} + +.workspaces-widget .empty { + color: rgba($sky, 0.3); +} + +.title { + color: $mauve; + font-size: 16px; + padding: 0px 5px 0px 5px; +} + +.nixos-icon { + font-size: 22px; + color: #7CB5DE; + margin: 0px 10px 0px 10px; +} \ No newline at end of file diff --git a/common/eww/config/eww.yuck b/common/eww/config/eww.yuck new file mode 100644 index 0000000..be74b1d --- /dev/null +++ b/common/eww/config/eww.yuck @@ -0,0 +1,51 @@ +; inspired by https://github.com/saimoomedits/eww-widgets/tree/main + +(include "./widgets/workspaces/eww.yuck") +(include "./widgets/window-title/eww.yuck") +(include "./widgets/resources/eww.yuck") + +(defwindow top-bar + :monitor 0 + :geometry (geometry :x "0%" + :y "10px" + :width "98.8%" + :height "30px" + :anchor "top center") + :stacking "fg" + :exclusive true + (centerbox + :class "bar" + (left) + (center) + (right))) + +(defwidget left [] + (box + :space-evenly false + :halign "start" + :class "container" + (label :text "" :class "nixos-icon") + (workspaces) + )) + +(defwidget center [] + (box + :space-evenly false + :halign "center" + :class "container" + :visible {strlength(window) != 0} + (windowtitle) + )) + +(defwidget right [] + (box + :space-evenly false + :halign "end" + :class "container" + (volume) + (cpu) + (mem) + (network) + (bluetooth) + (datetime) + )) diff --git a/common/eww/config/widgets/resources/eww.yuck b/common/eww/config/widgets/resources/eww.yuck new file mode 100644 index 0000000..b647f2a --- /dev/null +++ b/common/eww/config/widgets/resources/eww.yuck @@ -0,0 +1,92 @@ +; for unicode symbols: https://jrgraphix.net/r/Unicode/E000-F8FF + +; VARIABLES + +(defvar GB 1024000000) +(defvar MB 1024000) + +; DATE + TIME + +(defpoll time :interval "5s" + :initial "" + `date +%H:%M`) +(defpoll date :interval "60s" + :initial "" + `date "+%A | %m-%d-%+4Y"`) + +(defwidget datetime [] + (eventbox + :tooltip date + (label + :class "text time" + :text time) + )) + +; CPU + +(defwidget cpu [] + (box + :active true + :tooltip "${round(EWW_CPU.cores[0].freq/1000,2)} GHz" + (label + :class "cpu_text" + :text " ${round(EWW_CPU.avg,0)}%") + ) +) + +; MEMORY +(defwidget mem [] + (box + :active true + :tooltip {EWW_RAM.used_mem / GB < 1 ? "${round(EWW_RAM.used_mem / MB, 1)} M used" : "${round(EWW_RAM.used_mem / GB, 1)} G used"} + (label + :class "mem_text" + :text " ${round(EWW_RAM.used_mem_perc,0)}%") + ) +) + +; TEMP +; TODO temperature widget (hover to show all times sorted nicely) +;  + +; NETWORK + +(defpoll hostname :interval "1m" :initial "" "hostname") +(defpoll status-icon :interval "5s" :initial "" "./widgets/resources/network.sh") + +(defwidget network [] + (eventbox + :active true + :onclick "/usr/bin/env nm-connection-editor &" + :tooltip hostname + (label + :text status-icon + :class "network_icon"))) + +; BLUETOOTH +(defwidget bluetooth [] + (eventbox + :active true + :onclick "blueman-manager &" + (label + :text "" + :class "bluetooth_icon"))) + +; VOLUME + +(defpoll volume_percent :interval "0.1s" :initial "40" "amixer sget Master | grep 'Left:' | awk -F'[][]' '{ print $2 }' | tr -d '%'") + +(defwidget volume [] + (eventbox + :active true + :onclick "/usr/bin/env pavucontrol &" + :onscroll "if [ {} = 'up' ]; then wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+; else wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%-; fi" ; wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%- + (box + :space-evenly false + :orientation "h" + :spacing "3" + (label + :class "volume_text" + :text "${volume_percent <= 33 ? "" : volume_percent <= 66 ? "" : ""} ${volume_percent}%") + ))) +; TODO add mic widget \ No newline at end of file diff --git a/common/eww/config/widgets/resources/network.sh b/common/eww/config/widgets/resources/network.sh new file mode 100755 index 0000000..a42907f --- /dev/null +++ b/common/eww/config/widgets/resources/network.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +status=$(nmcli g | grep -oE "disconnected") + +if [ $status ] ; then + echo "✘" +else + echo "" +fi diff --git a/common/eww/config/widgets/window-title/eww.yuck b/common/eww/config/widgets/window-title/eww.yuck new file mode 100644 index 0000000..66ff506 --- /dev/null +++ b/common/eww/config/widgets/window-title/eww.yuck @@ -0,0 +1,7 @@ +(deflisten window :initial "" "sh ./widgets/window-title/get-window-title.sh") +(defwidget windowtitle [] + (box :class "title" + (label :text {window == "null" ? "" : window} :class "title" + ) + ) +) \ No newline at end of file diff --git a/common/eww/config/widgets/window-title/get-window-title.sh b/common/eww/config/widgets/window-title/get-window-title.sh new file mode 100644 index 0000000..f5a494a --- /dev/null +++ b/common/eww/config/widgets/window-title/get-window-title.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +hyprctl activewindow -j | jq --raw-output .title +socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | stdbuf -o0 awk -F '>>|,' '/^activewindow>>/{print $3}' \ No newline at end of file diff --git a/common/eww/config/widgets/workspaces/change-active-workspace.sh b/common/eww/config/widgets/workspaces/change-active-workspace.sh new file mode 100644 index 0000000..19b559a --- /dev/null +++ b/common/eww/config/widgets/workspaces/change-active-workspace.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +function clamp { + min=$1 + max=$2 + val=$3 + python -c "print(max($min, min($val, $max)))" +} + +direction=$1 +current=$2 +if test "$direction" = "down" +then + target=$(clamp 1 10 $(($current+1))) + echo "jumping to $target" + hyprctl dispatch workspace $target +elif test "$direction" = "up" +then + target=$(clamp 1 10 $(($current-1))) + echo "jumping to $target" + hyprctl dispatch workspace $target +fi \ No newline at end of file diff --git a/common/eww/config/widgets/workspaces/eww.yuck b/common/eww/config/widgets/workspaces/eww.yuck new file mode 100644 index 0000000..b361931 --- /dev/null +++ b/common/eww/config/widgets/workspaces/eww.yuck @@ -0,0 +1,18 @@ +(deflisten workspaces :initial "[]" "bash ./widgets/workspaces/get-workspaces.sh") +(deflisten current_workspace :initial "1" "bash ./widgets/workspaces/get-active-workspace.sh") + +(defwidget workspaces [] + (eventbox :onscroll "bash ./widgets/workspaces/change-active-workspace.sh {} ${current_workspace}" :class "workspaces-widget" + (box :space-evenly true + (label :text "${workspaces}${current_workspace}" :visible false) + (for workspace in workspaces + (eventbox :onclick "hyprctl dispatch workspace ${workspace.id}" + (box :width "30" :height "30" :class "workspace-entry ${workspace.id == current_workspace ? "current" : ""} ${workspace.windows > 0 ? "occupied" : "empty"}" + (label :text {workspace.id == current_workspace ? "" : workspace.windows > 0 ? "" : ""} + ) + ) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/common/eww/config/widgets/workspaces/get-active-workspace.sh b/common/eww/config/widgets/workspaces/get-active-workspace.sh new file mode 100755 index 0000000..0ebac7b --- /dev/null +++ b/common/eww/config/widgets/workspaces/get-active-workspace.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +hyprctl monitors -j | jq '.[] | select(.focused) | .activeWorkspace.id' + +socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | + stdbuf -o0 awk -F '>>|,' -e '/^workspace>>/ {print $2}' -e '/^focusedmon>>/ {print $3}' \ No newline at end of file diff --git a/common/eww/config/widgets/workspaces/get-workspaces.sh b/common/eww/config/widgets/workspaces/get-workspaces.sh new file mode 100755 index 0000000..fa7d904 --- /dev/null +++ b/common/eww/config/widgets/workspaces/get-workspaces.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +spaces (){ + WORKSPACE_WINDOWS=$(hyprctl workspaces -j | jq 'map({key: .id | tostring, value: .windows}) | from_entries') + seq 1 10 | jq --argjson windows "${WORKSPACE_WINDOWS}" --slurp -Mc 'map(tostring) | map({id: ., windows: ($windows[.]//0)})' +} + +spaces +socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | while read -r line; do + spaces +done \ No newline at end of file diff --git a/common/eww/default.nix b/common/eww/default.nix new file mode 100644 index 0000000..65ec07e --- /dev/null +++ b/common/eww/default.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: +{ + programs.eww = { + enable = true; + package = pkgs.eww-wayland; + configDir = ./config; + }; +} \ No newline at end of file diff --git a/common/git.nix b/common/git.nix new file mode 100755 index 0000000..8b2e56b --- /dev/null +++ b/common/git.nix @@ -0,0 +1,24 @@ +{ + programs.git = { + enable = true; + lfs.enable = true; + extraConfig = { + init = { + defaultBranch = "main"; + }; + }; + includes = [ + { + contents = { + gpg.format = "ssh"; + user = { + name = "Leon Vatthauer"; + email = "leon.vatthauer@fau.de"; + signingkey = "~/.ssh/git"; + }; + commit.gpgsign = true; + }; + } + ]; + }; +} diff --git a/common/neovim/coc.nix b/common/neovim/coc.nix new file mode 100644 index 0000000..2c2f526 --- /dev/null +++ b/common/neovim/coc.nix @@ -0,0 +1,185 @@ +{ pkgs, ...}: +{ + programs.neovim = { + coc = { + enable = true; + settings = { + languageserver = { + haskell = { + command = "haskell-language-server-wrapper"; + args = [ "--lsp" ]; + rootPatterns = [ + "*.cabal" + "cabal.project" + "hie.yaml" + ]; + filetypes = [ "haskell" "lhaskell" ]; + }; + }; + }; + }; + plugins = with pkgs.vimPlugins; [ + { + plugin = coc-nvim; + config = '' + " Having longer updatetime (default is 4000 ms = 4s) leads to noticeable + " delays and poor user experience + set updatetime=300 + + " Always show the signcolumn, otherwise it would shift the text each time + " diagnostics appear/become resolved + set signcolumn=yes + + " Use tab for trigger completion with characters ahead and navigate + " NOTE: There's always complete item selected by default, you may want to enable + " no select by `"suggest.noselect": true` in your configuration file + " NOTE: Use command ':verbose imap ' to make sure tab is not mapped by + " other plugin before putting this into your config + inoremap + \ coc#pum#visible() ? coc#pum#next(1) : + \ CheckBackspace() ? "\" : + \ coc#refresh() + inoremap coc#pum#visible() ? coc#pum#prev(1) : "\" + + " Make to accept selected completion item or notify coc.nvim to format + " u breaks current undo, please make your own choice + inoremap coc#pum#visible() ? coc#pum#confirm() + \: "\u\\=coc#on_enter()\" + + function! CheckBackspace() abort + let col = col('.') - 1 + return !col || getline('.')[col - 1] =~# '\s' + endfunction + + " Use to trigger completion + if has('nvim') + inoremap coc#refresh() + else + inoremap coc#refresh() + endif + + " Use `[g` and `]g` to navigate diagnostics + " Use `:CocDiagnostics` to get all diagnostics of current buffer in location list + nmap [g (coc-diagnostic-prev) + nmap ]g (coc-diagnostic-next) + + " GoTo code navigation + nmap gd (coc-definition) + nmap gy (coc-type-definition) + nmap gi (coc-implementation) + nmap gr (coc-references) + + " Use K to show documentation in preview window + nnoremap K :call ShowDocumentation() + + function! ShowDocumentation() + if CocAction('hasProvider', 'hover') + call CocActionAsync('doHover') + else + call feedkeys('K', 'in') + endif + endfunction + + " Highlight the symbol and its references when holding the cursor + autocmd CursorHold * silent call CocActionAsync('highlight') + + " Symbol renaming + nmap rn (coc-rename) + + " Formatting selected code + xmap f (coc-format-selected) + nmap f (coc-format-selected) + + augroup mygroup + autocmd! + " Setup formatexpr specified filetype(s) + autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected') + " Update signature help on jump placeholder + autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp') + augroup end + + " Applying code actions to the selected code block + " Example: `aap` for current paragraph + xmap a (coc-codeaction-selected) + nmap a (coc-codeaction-selected) + + " Remap keys for applying code actions at the cursor position + nmap ac (coc-codeaction-cursor) + " Remap keys for apply code actions affect whole buffer + nmap as (coc-codeaction-source) + " Apply the most preferred quickfix action to fix diagnostic on the current line + nmap qf (coc-fix-current) + + " Remap keys for applying refactor code actions + nmap re (coc-codeaction-refactor) + xmap r (coc-codeaction-refactor-selected) + nmap r (coc-codeaction-refactor-selected) + + " Run the Code Lens action on the current line + nmap cl (coc-codelens-action) + + " Map function and class text objects + " NOTE: Requires 'textDocument.documentSymbol' support from the language server + xmap if (coc-funcobj-i) + omap if (coc-funcobj-i) + xmap af (coc-funcobj-a) + omap af (coc-funcobj-a) + xmap ic (coc-classobj-i) + omap ic (coc-classobj-i) + xmap ac (coc-classobj-a) + omap ac (coc-classobj-a) + + " Remap and to scroll float windows/popups + if has('nvim-0.4.0') || has('patch-8.2.0750') + nnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\" + nnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\" + inoremap coc#float#has_scroll() ? "\=coc#float#scroll(1)\" : "\" + inoremap coc#float#has_scroll() ? "\=coc#float#scroll(0)\" : "\" + vnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\" + vnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\" + endif + + " Use CTRL-S for selections ranges + " Requires 'textDocument/selectionRange' support of language server + nmap (coc-range-select) + xmap (coc-range-select) + + " Add `:Format` command to format current buffer + command! -nargs=0 Format :call CocActionAsync('format') + " Add `:Fold` command to fold current buffer + command! -nargs=? Fold :call CocAction('fold', ) + + " Add `:OR` command for organize imports of the current buffer + command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport') + + " Add (Neo)Vim's native statusline support + " NOTE: Please see `:h coc-status` for integrations with external plugins that + " provide custom statusline: lightline.vim, vim-airline + + " Mappings for CoCList + " Show all diagnostics + nnoremap a :CocList diagnostics + " Manage extensions + nnoremap e :CocList extensions + " Show commands + nnoremap c :CocList commands + " Find symbol of current document + nnoremap o :CocList outline + " Search workspace symbols + nnoremap s :CocList -I symbols + " Do default action for next item + nnoremap j :CocNext + " Do default action for previous item + nnoremap k :CocPrev + " Resume latest coc list + nnoremap p :CocListResume + ''; + } + coc-git + coc-snippets + vim-snippets + coc-vimtex + vim-lightline-coc + ]; + }; +} diff --git a/common/neovim/coq.nix b/common/neovim/coq.nix new file mode 100644 index 0000000..bcad816 --- /dev/null +++ b/common/neovim/coq.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: +{ + programs.neovim = { + plugins = with pkgs.vimPlugins; [ + { + plugin = Coqtail; + config = '' + nnoremap CoqNextCoqJumpToEnd + nnoremap CoqUndoCoqJumpToEnd + nnoremap CoqToLine + ''; + } + ]; + }; +} diff --git a/common/neovim/default.nix b/common/neovim/default.nix new file mode 100644 index 0000000..6b86429 --- /dev/null +++ b/common/neovim/default.nix @@ -0,0 +1,32 @@ +{ pkgs, ... }: +{ + imports = [ + ./haskell.nix + ./coq.nix + ./telescope.nix + ./coc.nix + ./lightline.nix + ./nerdtree.nix + ./treesitter.nix + ]; + programs.neovim = { + enable = true; + extraConfig = import ./nvimrc.nix; + plugins = with pkgs.vimPlugins; [ + # languages + nvim-dap + nvim-lspconfig + vim-nix + vimtex + + # look and feel + awesome-vim-colorschemes + fugitive + ]; + withPython3 = true; + withNodeJs = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + }; +} diff --git a/common/neovim/haskell.nix b/common/neovim/haskell.nix new file mode 100644 index 0000000..ab79d12 --- /dev/null +++ b/common/neovim/haskell.nix @@ -0,0 +1,18 @@ +# haskell integration, adapted from @srid +# https://github.com/srid/nixos-config/blob/master/home/neovim/haskell.nix + +{ pkgs, ... }: +{ + programs.neovim = { + plugins = with pkgs.vimPlugins; [ + haskell-vim + vim-hoogle + ]; + extraLuaConfig = '' + -- Setup language servers. + local lspconfig = require('lspconfig') + lspconfig.hls.setup {} + ''; + + }; +} \ No newline at end of file diff --git a/common/neovim/lightline.nix b/common/neovim/lightline.nix new file mode 100644 index 0000000..51c8ad8 --- /dev/null +++ b/common/neovim/lightline.nix @@ -0,0 +1,30 @@ +{ pkgs, ...}: +{ + programs.neovim = { + plugins = with pkgs.vimPlugins; [ + { + plugin = lightline-vim; + config = '' + function! CocCurrentFunction() + return get(b:, 'coc_current_function', ''\'') + endfunction + + let g:lightline = { + \ 'colorscheme': 'solarized', + \ 'active': { + \ 'left': [ [ 'mode', 'paste' ], + \ [ 'cocstatus', 'currentfunction', 'readonly', 'filename', 'modified' ], + \ [ 'gitbranch' ] ] + \ }, + \ 'component_function': { + \ 'cocstatus': 'coc#status', + \ 'currentfunction': 'CocCurrentFunction', + \ 'gitbranch': 'FugitiveHead' + \ }, + \ } + + ''; + } + ]; + }; +} diff --git a/common/neovim/nerdtree.nix b/common/neovim/nerdtree.nix new file mode 100644 index 0000000..c8ac46a --- /dev/null +++ b/common/neovim/nerdtree.nix @@ -0,0 +1,27 @@ +{ pkgs, ... }: +{ + programs.neovim = { + plugins = with pkgs.vimPlugins; [ + { + plugin = nerdtree; + config = '' + nnoremap + nnoremap + nnoremap + nnoremap + nnoremap :NERDTreeToggle + nnoremap :NERDTreeFocus + " Exit Vim if NERDTree is the only window remaining in the only tab. + autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif + + " Close the tab if NERDTree is the only window remaining in it. + autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif + " If another buffer tries to replace NERDTree, put it in the other window, and bring back NERDTree. + autocmd BufEnter * if bufname('#') =~ 'NERD_tree_\d\+' && bufname('%') !~ 'NERD_tree_\d\+' && winnr('$') > 1 | + \ let buf=bufnr() | buffer# | execute "normal! \w" | execute 'buffer'.buf | endif + ''; + } + nerdtree-git-plugin + ]; + }; +} diff --git a/common/neovim/nvimrc.nix b/common/neovim/nvimrc.nix new file mode 100644 index 0000000..528358e --- /dev/null +++ b/common/neovim/nvimrc.nix @@ -0,0 +1,296 @@ +'' +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => General +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +set mouse=a +" Sets how many lines of history VIM has to remember +set history=500 + +" Enable filetype plugins +filetype plugin on +filetype indent on + +" Set to auto read when a file is changed from the outside +set autoread +au FocusGained,BufEnter * checktime + +" Fast saving +nmap s :w! + +" :W sudo saves the file +" (useful for handling the permission-denied error) +command! W execute 'w !sudo tee % > /dev/null' edit! + +" clipboard +set clipboard^=unnamed,unnamedplus + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => VIM user interface +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Set 7 lines to the cursor - when moving vertically using j/k +set so=7 + +" Avoid garbled characters in Chinese language windows OS +let $LANG='en' +set langmenu=en +source $VIMRUNTIME/delmenu.vim +source $VIMRUNTIME/menu.vim + +" Turn on the Wild menu +set wildmenu + +set relativenumber + +" Ignore compiled files +set wildignore=*.o,*~,*.pyc +if has("win16") || has("win32") + set wildignore+=.git\*,.hg\*,.svn\* +else + set wildignore+=*/.git/*,*/.hg/*,*/.svn/*,*/.DS_Store +endif + +"Always show current position +set ruler + +" Height of the command bar +set cmdheight=1 + +" A buffer becomes hidden when it is abandoned +set hid + +" Configure backspace so it acts as it should act +set backspace=eol,start,indent +set whichwrap+=<,>,h,l + +" Ignore case when searching +set ignorecase + +" When searching try to be smart about cases +set smartcase + +" Highlight search results +set hlsearch + +" Makes search act like search in modern browsers +set incsearch + +" Don't redraw while executing macros (good performance config) +set lazyredraw + +" For regular expressions turn magic on +set magic + +" Show matching brackets when text indicator is over them +set showmatch +" How many tenths of a second to blink when matching brackets +set mat=2 + +" No annoying sound on errors +set noerrorbells +set novisualbell +set t_vb= +set tm=500 + +" Properly disable sound on errors on MacVim +if has("gui_macvim") + autocmd GUIEnter * set vb t_vb= +endif + + +" Add a bit extra margin to the left +set foldcolumn=1 + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Colors and Fonts +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Enable syntax highlighting +syntax enable + +" Enable 256 colors palette in Gnome Terminal +if $COLORTERM == 'gnome-terminal' + set t_Co=256 +endif + +try + colorscheme solarized8_high +catch +endtry + +set background=dark + +" Set extra options when running in GUI mode +if has("gui_running") + set guioptions-=T + set guioptions-=e + set t_Co=256 + set guitablabel=%M\ %t +endif + +" Set utf8 as standard encoding and en_US as the standard language +set encoding=utf8 + +" Use Unix as the standard file type +set ffs=unix,dos,mac + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Files, backups and undo +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Turn backup off, since most stuff is in SVN, git etc. anyway... +set nobackup +set nowb +set noswapfile + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Text, tab and indent related +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Use spaces instead of tabs +set expandtab + +" Be smart when using tabs ;) +set smarttab + +" 1 tab == 4 spaces +set shiftwidth=4 +set tabstop=4 + +" Linebreak on 500 characters +set lbr +set tw=500 + +set ai "Auto indent +set si "Smart indent +set wrap "Wrap lines + + +"""""""""""""""""""""""""""""" +" => Visual mode related +"""""""""""""""""""""""""""""" +" Visual mode pressing * or # searches for the current selection +" Super useful! From an idea by Michael Naumann +vnoremap * :call VisualSelection(''\'', ''\'')/=@/ +vnoremap # :call VisualSelection(''\'', ''\'')?=@/ + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Moving around, tabs, windows and buffers +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Map to / (search) and Ctrl- to ? (backwards search) +"map / +"map ? + +" Disable highlight when is pressed +"map :noh + +" Smart way to move between windows +"map j +"map k +"map h +"map l + +" Close the current buffer +"map bd :Bclose:tabclosegT + +" Close all the buffers +"map ba :bufdo bd + +"map bl :bnext +"map bh :bprevious + +" Useful mappings for managing tabs +"map tn :tabnew +"map to :tabonly +"map tc :tabclose +"map tm :tabmove +"map t :tabnext + +" Let 'tl' toggle between this and the last accessed tab +"let g:lasttab = 1 +"nmap tl :exe "tabn ".g:lasttab +"au TabLeave * let g:lasttab = tabpagenr() + + +" Opens a new tab with the current buffer's path +" Super useful when editing files in the same directory +"map te :tabedit =expand("%:p:h")/ + +" Switch CWD to the directory of the open buffer +"map cd :cd %:p:h:pwd + +" Specify the behavior when switching between buffers +"try +" set switchbuf=useopen,usetab,newtab +" set stal=2 +"catch +"endtry + +" Return to last edit position when opening files (You want this!) +"au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif + + +"""""""""""""""""""""""""""""" +" => Status line +"""""""""""""""""""""""""""""" +" Always show the status line +"set laststatus=2 + +" Format the status line +"set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{getcwd()}%h\ \ \ Line:\ %l\ \ Column:\ %c + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Editing mappings +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Remap VIM 0 to first non-blank character +"map 0 ^ + +" Move a line of text using ALT+[jk] or Command+[jk] on mac +"nmap mz:m+`z +"nmap mz:m-2`z +"vmap :m'>+`mzgv`yo`z +"vmap :m'<-2`>my` +" nmap +" vmap +" vmap +"endif + +"" Delete trailing white space on save, useful for some filetypes ;) +"fun! CleanExtraSpaces() +" let save_cursor = getpos(".") +" let old_query = getreg('/') +" silent! %s/\s\+$//e +" call setpos('.', save_cursor) +" call setreg('/', old_query) +"endfun + +"if has("autocmd") +" autocmd BufWritePre *.txt,*.js,*.py,*.wiki,*.sh,*.coffee :call CleanExtraSpaces() +"endif + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => EXTRAS BY LEON +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +" Better splitting +set splitbelow +set splitright +" Enable mouse + +set noshowmode + +augroup neovim_terminal + autocmd! + " Enter Terminal-mode (insert) automatically + autocmd TermOpen * startinsert + " Disables number lines on terminal buffers + autocmd TermOpen * :set nonumber norelativenumber + " allows you to use Ctrl-c on terminal window + autocmd TermOpen * nnoremap i +augroup END +'' diff --git a/common/neovim/telescope.nix b/common/neovim/telescope.nix new file mode 100644 index 0000000..71449c5 --- /dev/null +++ b/common/neovim/telescope.nix @@ -0,0 +1,38 @@ +{ pkgs, ... }: +{ + programs.neovim = { + plugins = with pkgs.vimPlugins; [ + { + plugin = telescope-nvim; + type = "lua"; + config = '' + local telescope = require('telescope') + telescope.setup { + extensions = { + coc = { + theme = 'ivy', + prefer_locations = true, -- always use Telescope locations to preview definitions/declarations/implementations etc + } + }, + } + telescope.load_extension('hoogle') + telescope.load_extension('coc') + function map (mode, shortcut, command) + vim.api.nvim_set_keymap(mode, shortcut, command, { noremap = true, silent = true }) + end + map('n', "ff", ":Telescope find_files") + map('n', "fg", ":Telescope live_grep") + map('n', "fb", ":Telescope buffers") + map('n', "fH", ":Telescope help_tags") + map('n', "fd", ":Telescope lsp_definitions") + map('n', "fs", ":Telescope lsp_document_symbols") + map('n', "fS", ":Telescope lsp_workspace_symbols") + map('n', "fh", ":Telescope hoogle") + ''; + } + telescope-coc-nvim + telescope_hoogle + plenary-nvim + ]; + }; +} \ No newline at end of file diff --git a/common/neovim/treesitter.nix b/common/neovim/treesitter.nix new file mode 100644 index 0000000..8a8cb22 --- /dev/null +++ b/common/neovim/treesitter.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: +{ + programs.neovim = { + plugins = with pkgs.vimPlugins; [ + nvim-treesitter + nvim-treesitter-parsers.haskell + nvim-treesitter-parsers.latex + nvim-treesitter-parsers.bibtex + nvim-treesitter-parsers.rust + nvim-treesitter-parsers.agda + ]; + }; +} diff --git a/common/starship.nix b/common/starship.nix new file mode 100755 index 0000000..ede36bc --- /dev/null +++ b/common/starship.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: +{ + programs.starship = { + enable = true; + settings = { + format = "$all"; + palette = "catppuccin_macchiato"; + gradle.symbol = "🐘"; + } // builtins.fromTOML (builtins.readFile + (pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "starship"; + rev = "5629d2356f62a9f2f8efad3ff37476c19969bd4f"; + sha256 = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; + } + /palettes/macchiato.toml)); + }; +} \ No newline at end of file diff --git a/common/vim.nix b/common/vim.nix new file mode 100644 index 0000000..d9e7990 --- /dev/null +++ b/common/vim.nix @@ -0,0 +1,28 @@ +{ pkgs, ...}: +{ + programs.vim = { + enable = true; + extraConfig = import ./vimrc.nix; + plugins = with pkgs.vimPlugins; [ + # specific language support + vim-nix + Coqtail + vimtex + + # general plugins + nerdtree + fugitive + nerdtree-git-plugin + vim-lsp + vim-snippets + lightline-vim + vim-colorschemes + + # CoC + coc-nvim + coc-git + coc-snippets + ]; + defaultEditor = true; + }; +} \ No newline at end of file diff --git a/common/vimrc.nix b/common/vimrc.nix new file mode 100644 index 0000000..fa3ae70 --- /dev/null +++ b/common/vimrc.nix @@ -0,0 +1,604 @@ +'' +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Maintainer: +" Amir Salihefendic - @amix3k +" Forked by: +" Leon Vatthauer - @reijix +" +" Sections: +" -> General +" -> VIM user interface +" -> Colors and Fonts +" -> Files and backups +" -> Text, tab and indent related +" -> Visual mode related +" -> Moving around, tabs and buffers +" -> Status line +" -> Editing mappings +" -> vimgrep searching and cope displaying +" -> Spell checking +" -> Misc +" -> Helper functions +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => General +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Sets how many lines of history VIM has to remember +set history=500 + +" Enable filetype plugins +filetype plugin on +filetype indent on + +" Set to auto read when a file is changed from the outside +set autoread +au FocusGained,BufEnter * checktime + +" With a map leader it's possible to do extra key combinations +" like w saves the current file +let mapleader = "," + +" Fast saving +nmap w :w! + +" :W sudo saves the file +" (useful for handling the permission-denied error) +command! W execute 'w !sudo tee % > /dev/null' edit! + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => VIM user interface +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Set 7 lines to the cursor - when moving vertically using j/k +set so=7 + +" Avoid garbled characters in Chinese language windows OS +let $LANG='en' +set langmenu=en +source $VIMRUNTIME/delmenu.vim +source $VIMRUNTIME/menu.vim + +" Turn on the Wild menu +set wildmenu + +" Ignore compiled files +set wildignore=*.o,*~,*.pyc +if has("win16") || has("win32") + set wildignore+=.git\*,.hg\*,.svn\* +else + set wildignore+=*/.git/*,*/.hg/*,*/.svn/*,*/.DS_Store +endif + +" Always show current position +set ruler +set relativenumber + +" Height of the command bar +set cmdheight=1 + +" A buffer becomes hidden when it is abandoned +set hid + +" Configure backspace so it acts as it should act +set backspace=eol,start,indent +set whichwrap+=<,>,h,l + +" Ignore case when searching +set ignorecase + +" When searching try to be smart about cases +set smartcase + +" Highlight search results +set hlsearch + +" Makes search act like search in modern browsers +set incsearch + +" Don't redraw while executing macros (good performance config) +set lazyredraw + +" For regular expressions turn magic on +set magic + +" Show matching brackets when text indicator is over them +set showmatch + +" How many tenths of a second to blink when matching brackets +set mat=2 + +" No annoying sound on errors +set noerrorbells +set novisualbell +set t_vb= +set tm=500 + +" Properly disable sound on errors on MacVim +if has("gui_macvim") + autocmd GUIEnter * set vb t_vb= +endif + +" Add a bit extra margin to the left +set foldcolumn=1 + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Colors and Fonts +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Enable syntax highlighting +syntax enable + +" Set regular expression engine automatically +set regexpengine=0 + +" Enable 256 colors palette in Gnome Terminal +"if $COLORTERM == 'gnome-terminal' +" set t_Co=256 +"endif + +" termcolors for theme +set termguicolors + +try + colorscheme molokai +catch +endtry + +set background=dark + +" Set extra options when running in GUI mode +if has("gui_running") + set guioptions-=T + set guioptions-=e + set t_Co=256 + set guitablabel=%M\ %t +endif + +" Set utf8 as standard encoding and en_US as the standard language +set encoding=utf8 + +" Use Unix as the standard file type +set ffs=unix,dos,mac + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Files, backups and undo +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Turn backup off, since most stuff is in SVN, git etc. anyway... +set nobackup +set nowb +set noswapfile + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Text, tab and indent related +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Use spaces instead of tabs +set expandtab + +" Be smart when using tabs ;) +set smarttab + +" 1 tab == 4 spaces +set shiftwidth=4 +set tabstop=4 + +" Linebreak on 500 characters +set lbr +set tw=500 + +set ai "Auto indent +set si "Smart indent +set wrap "Wrap lines + + +"""""""""""""""""""""""""""""" +" => Visual mode related +"""""""""""""""""""""""""""""" +" Visual mode pressing * or # searches for the current selection +" Super useful! From an idea by Michael Naumann +vnoremap * :call VisualSelection(''\'', ''\'')/=@/ +vnoremap # :call VisualSelection(''\'', ''\'')?=@/ + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Moving around, tabs, windows and buffers +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Map to / (search) and Ctrl- to ? (backwards search) +map / +map ? + +" Disable highlight when is pressed +map :noh + +" Smart way to move between windows +map j +map k +map h +map l + +" Close the current buffer +map bd :Bclose:tabclosegT + +" Close all the buffers +map ba :bufdo bd + +map l :bnext +map h :bprevious + +" Useful mappings for managing tabs +map tn :tabnew +map to :tabonly +map tc :tabclose +map tm :tabmove +map t :tabnext + +" Let 'tl' toggle between this and the last accessed tab +let g:lasttab = 1 +nmap tl :exe "tabn ".g:lasttab +au TabLeave * let g:lasttab = tabpagenr() + + +" Opens a new tab with the current buffer's path +" Super useful when editing files in the same directory +map te :tabedit =escape(expand("%:p:h"), " ")/ + +" Switch CWD to the directory of the open buffer +map cd :cd %:p:h:pwd + +" Specify the behavior when switching between buffers +try + set switchbuf=useopen,usetab,newtab + set stal=2 +catch +endtry + +" Return to last edit position when opening files (You want this!) +au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif + + +"""""""""""""""""""""""""""""" +" => Status line +"""""""""""""""""""""""""""""" +" Always show the status line +set laststatus=2 + +" Format the status line +set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{getcwd()}%h\ \ \ Line:\ %l\ \ Column:\ %c + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Editing mappings +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Remap VIM 0 to first non-blank character +map 0 ^ + +" Move a line of text using ALT+[jk] or Command+[jk] on mac +nmap mz:m+`z +nmap mz:m-2`z +vmap :m'>+`mzgv`yo`z +vmap :m'<-2`>my` + nmap + vmap + vmap +endif + +" Delete trailing white space on save, useful for some filetypes ;) +fun! CleanExtraSpaces() + let save_cursor = getpos(".") + let old_query = getreg('/') + silent! %s/\s\+$//e + call setpos('.', save_cursor) + call setreg('/', old_query) +endfun + +if has("autocmd") + autocmd BufWritePre *.txt,*.js,*.py,*.wiki,*.sh,*.coffee :call CleanExtraSpaces() +endif + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Spell checking +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Pressing ,ss will toggle and untoggle spell checking +map ss :setlocal spell! + +" Shortcuts using +map sn ]s +map sp [s +map sa zg +map s? z= + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Misc +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Remove the Windows ^M - when the encodings gets messed up +noremap m mmHmt:%s///ge'tzt'm + +" Quickly open a buffer for scribble +map q :e ~/buffer + +" Quickly open a markdown buffer for scribble +map x :e ~/buffer.md + +" Toggle paste mode on and off +map pp :setlocal paste! + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Helper functions +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Returns true if paste mode is enabled +function! HasPaste() + if &paste + return 'PASTE MODE ' + endif + return ''\'' +endfunction + +" Don't close window, when deleting a buffer +command! Bclose call BufcloseCloseIt() +function! BufcloseCloseIt() + let l:currentBufNum = bufnr("%") + let l:alternateBufNum = bufnr("#") + + if buflisted(l:alternateBufNum) + buffer # + else + bnext + endif + + if bufnr("%") == l:currentBufNum + new + endif + + if buflisted(l:currentBufNum) + execute("bdelete! ".l:currentBufNum) + endif +endfunction + +function! CmdLine(str) + call feedkeys(":" . a:str) +endfunction + +function! VisualSelection(direction, extra_filter) range + let l:saved_reg = @" + execute "normal! vgvy" + + let l:pattern = escape(@", "\\/.*'$^~[]") + let l:pattern = substitute(l:pattern, "\n$", "", "") + + if a:direction == 'gv' + call CmdLine("Ack '" . l:pattern . "' " ) + elseif a:direction == 'replace' + call CmdLine("%s" . '/'. l:pattern . '/') + endif + + let @/ = l:pattern + let @" = l:saved_reg +endfunction + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => EXTRAS BY LEON +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +" Better splitting +set splitbelow +set splitright +" Enable mouse +set mouse=a + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => COQ +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +nnoremap CoqNextCoqJumpToEnd +nnoremap CoqUndoCoqJumpToEnd +nnoremap CoqToLine + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => NERDTree +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +nnoremap +nnoremap +nnoremap :NERDTreeToggle +" Exit Vim if NERDTree is the only window remaining in the only tab. +autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif + +" Close the tab if NERDTree is the only window remaining in it. +autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif +" If another buffer tries to replace NERDTree, put it in the other window, and bring back NERDTree. +autocmd BufEnter * if bufname('#') =~ 'NERD_tree_\d\+' && bufname('%') !~ 'NERD_tree_\d\+' && winnr('$') > 1 | + \ let buf=bufnr() | buffer# | execute "normal! \w" | execute 'buffer'.buf | endif + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => CoC +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +" Having longer updatetime (default is 4000 ms = 4s) leads to noticeable +" delays and poor user experience +set updatetime=300 + +" Always show the signcolumn, otherwise it would shift the text each time +" diagnostics appear/become resolved +set signcolumn=yes + +" Use tab for trigger completion with characters ahead and navigate +" NOTE: There's always complete item selected by default, you may want to enable +" no select by `"suggest.noselect": true` in your configuration file +" NOTE: Use command ':verbose imap ' to make sure tab is not mapped by +" other plugin before putting this into your config +inoremap + \ coc#pum#visible() ? coc#pum#next(1) : + \ CheckBackspace() ? "\" : + \ coc#refresh() +inoremap coc#pum#visible() ? coc#pum#prev(1) : "\" + +" Make to accept selected completion item or notify coc.nvim to format +" u breaks current undo, please make your own choice +inoremap coc#pum#visible() ? coc#pum#confirm() + \: "\u\\=coc#on_enter()\" + +function! CheckBackspace() abort +let col = col('.') - 1 +return !col || getline('.')[col - 1] =~# '\s' +endfunction + +" Use to trigger completion +if has('nvim') +inoremap coc#refresh() +else +inoremap coc#refresh() +endif + +" Use `[g` and `]g` to navigate diagnostics +" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list +nmap [g (coc-diagnostic-prev) +nmap ]g (coc-diagnostic-next) + +" GoTo code navigation +nmap gd (coc-definition) +nmap gy (coc-type-definition) +nmap gi (coc-implementation) +nmap gr (coc-references) + +" Use K to show documentation in preview window +nnoremap K :call ShowDocumentation() + +function! ShowDocumentation() +if CocAction('hasProvider', 'hover') + call CocActionAsync('doHover') +else + call feedkeys('K', 'in') +endif +endfunction + +" Highlight the symbol and its references when holding the cursor +autocmd CursorHold * silent call CocActionAsync('highlight') + +" Symbol renaming +nmap rn (coc-rename) + +" Formatting selected code +xmap f (coc-format-selected) +nmap f (coc-format-selected) + +augroup mygroup +autocmd! +" Setup formatexpr specified filetype(s) +autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected') +" Update signature help on jump placeholder +autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp') +augroup end + +" Applying code actions to the selected code block +" Example: `aap` for current paragraph +xmap a (coc-codeaction-selected) +nmap a (coc-codeaction-selected) + +" Remap keys for applying code actions at the cursor position +nmap ac (coc-codeaction-cursor) +" Remap keys for apply code actions affect whole buffer +nmap as (coc-codeaction-source) +" Apply the most preferred quickfix action to fix diagnostic on the current line +nmap qf (coc-fix-current) + +" Remap keys for applying refactor code actions +nmap re (coc-codeaction-refactor) +xmap r (coc-codeaction-refactor-selected) +nmap r (coc-codeaction-refactor-selected) + +" Run the Code Lens action on the current line +nmap cl (coc-codelens-action) + +" Map function and class text objects +" NOTE: Requires 'textDocument.documentSymbol' support from the language server +xmap if (coc-funcobj-i) +omap if (coc-funcobj-i) +xmap af (coc-funcobj-a) +omap af (coc-funcobj-a) +xmap ic (coc-classobj-i) +omap ic (coc-classobj-i) +xmap ac (coc-classobj-a) +omap ac (coc-classobj-a) + +" Remap and to scroll float windows/popups +if has('nvim-0.4.0') || has('patch-8.2.0750') +nnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\" +nnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\" +inoremap coc#float#has_scroll() ? "\=coc#float#scroll(1)\" : "\" +inoremap coc#float#has_scroll() ? "\=coc#float#scroll(0)\" : "\" +vnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\" +vnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\" +endif + +" Use CTRL-S for selections ranges +" Requires 'textDocument/selectionRange' support of language server +nmap (coc-range-select) +xmap (coc-range-select) + +" Add `:Format` command to format current buffer +command! -nargs=0 Format :call CocActionAsync('format') + +" Add `:Fold` command to fold current buffer +command! -nargs=? Fold :call CocAction('fold', ) + +" Add `:OR` command for organize imports of the current buffer +command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport') + +" Add (Neo)Vim's native statusline support +" NOTE: Please see `:h coc-status` for integrations with external plugins that +" provide custom statusline: lightline.vim, vim-airline + +" Mappings for CoCList +" Show all diagnostics +nnoremap a :CocList diagnostics +" Manage extensions +nnoremap e :CocList extensions +" Show commands +nnoremap c :CocList commands +" Find symbol of current document +nnoremap o :CocList outline +" Search workspace symbols +nnoremap s :CocList -I symbols +" Do default action for next item +nnoremap j :CocNext +" Do default action for previous item +nnoremap k :CocPrev +" Resume latest coc list +nnoremap p :CocListResume + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Lightline +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +function! CocCurrentFunction() + return get(b:, 'coc_current_function', ''\'') +endfunction + +let g:lightline = { + \ 'colorscheme': 'molokai', + \ 'active': { + \ 'left': [ [ 'mode', 'paste' ], + \ [ 'cocstatus', 'currentfunction', 'readonly', 'filename', 'modified' ], + \ [ 'gitbranch' ] ] + \ }, + \ 'component_function': { + \ 'cocstatus': 'coc#status', + \ 'currentfunction': 'CocCurrentFunction', + \ 'gitbranch': 'FugitiveHead' + \ }, + \ } + +set noshowmode + +'' diff --git a/common/vscode.nix b/common/vscode.nix new file mode 100755 index 0000000..8c0ef6b --- /dev/null +++ b/common/vscode.nix @@ -0,0 +1,103 @@ +{ pkgs, ... }: +{ + programs.vscode = { + enable = true; + extensions = with pkgs.vscode-extensions; [ + jdinhlife.gruvbox + vscodevim.vim + yzhang.markdown-all-in-one + haskell.haskell + justusadam.language-haskell + maximedenes.vscoq + james-yu.latex-workshop + bbenoist.nix + mkhl.direnv + catppuccin.catppuccin-vsc + ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ + { + name = "theme-panda"; + publisher = "tinkertrain"; + version = "1.3.0"; + sha256 = "sha256-ijOXoby3FHgDhF2sibXnGpkldKNPCoEXCY0Iw0ndUtw="; + } + { + name = "agda-mode"; + publisher = "banacorn"; + version = "0.4.1"; + sha256 = "sha256-Zt2OifhS5BI0HcMZkKOa1gqV9Vpj0lIUR6VcHvX5M9o="; + } + { + name = "yuck"; + publisher = "eww-yuck"; + version = "0.0.3"; + sha256 = "sha256-DITgLedaO0Ifrttu+ZXkiaVA7Ua5RXc4jXQHPYLqrcM="; + } + ]; + userSettings = { + "agdaMode.connection.agdaLanguageServer" = false; + "agdaMode.highlighting.getHighlightWithThemeColors" = false; + "editor.unicodeHighlight.ambiguousCharacters" = false; + "editor.semanticHighlighting.enabled" = true; + "workbench.colorTheme" = "Catppuccin Mocha"; + # "workbench.iconTheme" = "catppuccin-mocha"; + "haskell.manageHLS" = "PATH"; + "editor.fontFamily" = "Berkeley Mono, DejaVu Sans Mono, monospace, Unifont"; + "terminal.integrated.minimumContrastRatio" = 1; + "terminal.integrated.shellIntegration.enabled" = false; + "terminal.integrated.profiles.linux" = { + bash = null; + zsh = { + path = "/run/current-system/sw/bin/zsh"; + icon = "terminal-linux"; + }; + }; + "terminal.integrated.defaultProfile.linux" = "zsh"; + "vim.handleKeys" = { + "" = false; + "" = false; + "" = false; + "" = false; + "" = false; + "" = false; + }; + "vim.overrideCopy" = false; + "window.titleBarStyle" = "custom"; + "window.customMenuBarAltFocus" = false; + "window.enableMenuBarMnemonics" = false; + #"ltex.additionalRules.motherTongue" = "de-DE"; + #"ltex.language" = "de-DE"; + #"ltex.ltex-ls.path" = "/etc/profiles/per-user/leonv/"; + "ltex.java.path" = "/etc/profiles/per-user/leonv/"; + #"ltex.sentenceCacheSize" = 50000; + #"ltex.java.maximumHeapSize" = 8192; + "editor.tabSize" = 2; + "explorer.excludeGitIgnore" = true; + "files.exclude" = { + "**/*.agdai" = true; + }; + # try to fix agda suggestions: + "editor.acceptSuggestionOnCommitCharacter" = false; + "editor.minimap.enabled" = false; + "editor.autoClosingOvertype" = "never"; + "editor.autoClosingBrackets" = "never"; + "editor.accessibilitySupport" = "off"; + }; + keybindings = [ + { + key = "ctrl+shift+v"; + command = "extension.vim_ctrl+v"; + when = "editorTextFocus && vim.active && !inDebugRepl"; + } + { + key = "ctrl+shift+="; + command = "editor.action.fontZoomIn"; + when = ""; + } + { + key = "ctrl+shift+-"; + command = "editor.action.fontZoomOut"; + when = ""; + } + ]; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..800065f --- /dev/null +++ b/flake.lock @@ -0,0 +1,361 @@ +{ + "nodes": { + "brew-src": { + "flake": false, + "locked": { + "lastModified": 1705326576, + "narHash": "sha256-9PvMgHgdbpb5vBO8fHCRufodR731ynzGMF9+68vKWck=", + "owner": "Homebrew", + "repo": "brew", + "rev": "1c612baa096c69f2fcb221c74e6f5b9979efdcee", + "type": "github" + }, + "original": { + "owner": "Homebrew", + "ref": "4.2.4", + "repo": "brew", + "type": "github" + } + }, + "cask-fonts": { + "flake": false, + "locked": { + "lastModified": 1707957157, + "narHash": "sha256-RjcJgrLJ9Zed6XsRTYuq/yXOBm+K5AMGycOWWW8QIUI=", + "owner": "homebrew", + "repo": "homebrew-cask-fonts", + "rev": "3c9d137956343e190e0feb319613de9ab50cd8c0", + "type": "github" + }, + "original": { + "owner": "homebrew", + "repo": "homebrew-cask-fonts", + "type": "github" + } + }, + "cl-nix-lite": { + "locked": { + "lastModified": 1698901928, + "narHash": "sha256-gMHZybEVA3uMOBu1483gXfvUqpv4Qn7GJs3ZfCQYxpc=", + "owner": "hraban", + "repo": "cl-nix-lite", + "rev": "9ad861b45bda7f59eba5ad1b43565a03c7c58553", + "type": "github" + }, + "original": { + "owner": "hraban", + "repo": "cl-nix-lite", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "unstable" + ] + }, + "locked": { + "lastModified": 1707707289, + "narHash": "sha256-YuDt/eSTXMEHv8jS8BEZJgqCcG8Tr3cyqaZjJFXZHsw=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "44f50a5ecaab72a61d5fd8e5c5717bc4bf9c25dd", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1697816753, + "narHash": "sha256-40to80AEIyKCQI0xMKCeF5ePoIKTYgjVVCZeu4CnTxM=", + "owner": "hraban", + "repo": "flake-compat", + "rev": "6025bade1336a36014639bc3f67eacc853dab78f", + "type": "github" + }, + "original": { + "owner": "hraban", + "ref": "fixed-output", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1687709756, + "narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "unstable" + ] + }, + "locked": { + "lastModified": 1708031129, + "narHash": "sha256-EH20hJfNnc1/ODdDVat9B7aKm0B95L3YtkIRwKLvQG8=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3d6791b3897b526c82920a2ab5f61d71985b3cf8", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "homebrew-cask": { + "flake": false, + "locked": { + "lastModified": 1708086358, + "narHash": "sha256-h+afCxxV/FdfipQ/HpHhgkvbXgu9UfEgyrmfxr32ogA=", + "owner": "homebrew", + "repo": "homebrew-cask", + "rev": "75f6b30c1d7b23c7984a93b53fc86b97df233157", + "type": "github" + }, + "original": { + "owner": "homebrew", + "repo": "homebrew-cask", + "type": "github" + } + }, + "homebrew-core": { + "flake": false, + "locked": { + "lastModified": 1708085757, + "narHash": "sha256-u/rE6MjReC+34dT83BmRRSbtqWubg0hf/gRQoZ2Uh2E=", + "owner": "homebrew", + "repo": "homebrew-core", + "rev": "a008a7f04d026bb35b9aded0a427c6ee38aa8eb7", + "type": "github" + }, + "original": { + "owner": "homebrew", + "repo": "homebrew-core", + "type": "github" + } + }, + "hyprland-contrib": { + "inputs": { + "nixpkgs": [ + "unstable" + ] + }, + "locked": { + "lastModified": 1706198673, + "narHash": "sha256-bHlxFd+3QHy6eXtTzzhwVNcyxBSOxTvBuJGNUzI4C4M=", + "owner": "hyprwm", + "repo": "contrib", + "rev": "16884001b26e6955ff4b88b4dfe4c8986e20f153", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "contrib", + "type": "github" + } + }, + "mac-app-util": { + "inputs": { + "cl-nix-lite": "cl-nix-lite", + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1707183497, + "narHash": "sha256-K6LVwmM32uUEYXpDFCnwNqOyi863FRXR6KFq87X3iHg=", + "owner": "hraban", + "repo": "mac-app-util", + "rev": "95d9c38d6dec0296d73929f63a7de130f435437b", + "type": "github" + }, + "original": { + "owner": "hraban", + "repo": "mac-app-util", + "type": "github" + } + }, + "nix-darwin": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1688307440, + "narHash": "sha256-7PTjbN+/+b799YN7Tk2SS5Vh8A0L3gBo8hmB7Y0VXug=", + "owner": "LnL7", + "repo": "nix-darwin", + "rev": "b06bab83bdf285ea0ae3c8e145a081eb95959047", + "type": "github" + }, + "original": { + "owner": "LnL7", + "repo": "nix-darwin", + "type": "github" + } + }, + "nix-homebrew": { + "inputs": { + "brew-src": "brew-src", + "flake-utils": "flake-utils_2", + "nix-darwin": "nix-darwin", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1705952034, + "narHash": "sha256-H0nk8Gk8kPw4yi2WwOTsSHgPrzSwyNgWEYHk10IJwfc=", + "owner": "zhaofengli-wip", + "repo": "nix-homebrew", + "rev": "40f5ee46b58e7c5f1927e2c5a583dc3d7e571ed9", + "type": "github" + }, + "original": { + "owner": "zhaofengli-wip", + "repo": "nix-homebrew", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1698553279, + "narHash": "sha256-T/9P8yBSLcqo/v+FTOBK+0rjzjPMctVymZydbvR/Fak=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "90e85bc7c1a6fc0760a94ace129d3a1c61c3d035", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1687274257, + "narHash": "sha256-TutzPriQcZ8FghDhEolnHcYU2oHIG5XWF+/SUBNnAOE=", + "path": "/nix/store/22qgs3skscd9bmrxv9xv4q5d4wwm5ppx-source", + "rev": "2c9ecd1f0400076a4d6b2193ad468ff0a7e7fdc5", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1688049487, + "narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "cask-fonts": "cask-fonts", + "darwin": "darwin", + "home-manager": "home-manager", + "homebrew-cask": "homebrew-cask", + "homebrew-core": "homebrew-core", + "hyprland-contrib": "hyprland-contrib", + "mac-app-util": "mac-app-util", + "nix-homebrew": "nix-homebrew", + "unstable": "unstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "unstable": { + "locked": { + "lastModified": 1707956935, + "narHash": "sha256-ZL2TrjVsiFNKOYwYQozpbvQSwvtV/3Me7Zwhmdsfyu4=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a4d4fe8c5002202493e87ec8dbc91335ff55552c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..09bc8c6 --- /dev/null +++ b/flake.nix @@ -0,0 +1,84 @@ +{ + description = "Master flake for all my setups"; + + inputs = { + unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + + darwin.url = "github:lnl7/nix-darwin/master"; + darwin.inputs.nixpkgs.follows = "unstable"; + + nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew"; + + homebrew-core.url = "github:homebrew/homebrew-core"; + homebrew-core.flake = false; + + homebrew-cask.url = "github:homebrew/homebrew-cask"; + homebrew-cask.flake = false; + + cask-fonts.url = "github:homebrew/homebrew-cask-fonts"; + cask-fonts.flake = false; + + home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "unstable"; + + hyprland-contrib.url = "github:hyprwm/contrib"; + hyprland-contrib.inputs.nixpkgs.follows = "unstable"; + + # fix for app links on macos + mac-app-util.url = "github:hraban/mac-app-util"; + }; + + outputs = { unstable, home-manager, darwin, hyprland-contrib, nix-homebrew, homebrew-core, homebrew-cask, cask-fonts, ...}@inputs: { + nixosConfigurations = { + gunther = unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { inherit inputs; }; + modules = [ + ./gunther/configuration.nix + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.users.leonv = import ./gunther/leonv.nix; + home-manager.extraSpecialArgs = { inherit inputs; }; + } + ]; + }; + iso = unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { inherit inputs; }; + modules = [ + "${unstable}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + ./iso/configuration.nix + ]; + }; + willem = unstable.lib.nixosSystem { + system = "aarch64-linux"; + modules = [ ./willem/configuration.nix ]; + }; + }; + darwinConfigurations = { + shinx = darwin.lib.darwinSystem { + system = "aarch64-darwin"; + specialArgs = { inherit inputs; }; + modules = [ + ./shinx/default.nix + home-manager.darwinModules.home-manager + nix-homebrew.darwinModules.nix-homebrew + { + nix-homebrew = { + enable = true; + enableRosetta = true; + user = "leonvatthauer"; + taps = { + "homebrew/homebrew-core" = homebrew-core; + "homebrew/homebrew-cask" = homebrew-cask; + "homebrew/homebrew-cask-fonts" = cask-fonts; + }; + }; + } + ]; + }; + }; + }; +} diff --git a/gunther/configuration.nix b/gunther/configuration.nix new file mode 100755 index 0000000..10a5d4f --- /dev/null +++ b/gunther/configuration.nix @@ -0,0 +1,248 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, lib, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + # VM + virtualisation.vmVariant = { + # following configuration is added only when building VM with build-vm + virtualisation = { + memorySize = 2048; # Use 2048MiB memory. + cores = 3; + }; + }; + + # optimize storage + nix.optimise.automatic = true; + + # Bootloader. + boot.loader.efi.canTouchEfiVariables = true; + boot.loader.efi.efiSysMountPoint = "/boot"; + boot.loader.systemd-boot.enable = true; + + networking.hostName = "gunther"; + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "Europe/Berlin"; + + i18n.supportedLocales = [ + "en_US.UTF-8/UTF-8" + "de_DE.UTF-8/UTF-8" + ]; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LANG = "en_US.UTF-8"; + LC_ALL = "en_US.UTF-8"; + LANGUAGE = "en_US.UTF-8"; + LC_ADDRESS = "de_DE.UTF-8"; + LC_IDENTIFICATION = "de_DE.UTF-8"; + LC_MEASUREMENT = "de_DE.UTF-8"; + LC_MONETARY = "de_DE.UTF-8"; + LC_NAME = "de_DE.UTF-8"; + LC_NUMERIC = "de_DE.UTF-8"; + LC_PAPER = "de_DE.UTF-8"; + LC_TELEPHONE = "de_DE.UTF-8"; + LC_TIME = "de_DE.UTF-8"; + }; + + services.greetd = { + enable = true; + package = pkgs.greetd.gtkgreet; + settings = { + default_session = { + command = "Hyprland --config /etc/greetd/hyprland.conf"; + user = "greeter"; + }; + }; + }; + environment.etc."greetd/environments".text = '' + Hyprland + ''; + environment.etc."greetd/hyprland.conf".text = '' + monitor = DP-3,2560x1440@144,1920x0,1 + monitor = HDMI-A-5,1920x1080@75,0x0,1 + misc { + disable_hyprland_logo = true + } + + exec-once = gtkgreet -l -b /etc/greetd/wallpaper.jpg -s /etc/greetd/style.css; hyprctl dispatch exit + ''; + environment.etc."greetd/wallpaper.jpg".source = ./hypr/wallpaper.jpg; + environment.etc."greetd/style.css".text = '' + window { + background-position: center; + background-repeat: no-repeat; + background-size: cover; + background-color: black; + } + ''; + + # Configure console keymap + console.keyMap = "us"; + + # Enable CUPS to print documents. + services.avahi = { + enable = true; + nssmdns = true; + openFirewall = true; + }; + services.printing = { + enable = true; + drivers = [ pkgs.splix ]; + }; + + # bluetooth + hardware.bluetooth.enable = true; + hardware.bluetooth.powerOnBoot = true; + services.blueman.enable = true; + + # Enable sound with pipewire. + sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + + # Define a user account. + users.users.leonv = { + isNormalUser = true; + description = "Leon Vatthauer"; + extraGroups = [ "networkmanager" "wheel" ]; + initialPassword = "leonv"; # just for setup + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. + environment.systemPackages = + with pkgs; + let + catp-gtk = pkgs.catppuccin-gtk.override { + accents = [ "flamingo" ]; # You can specify multiple accents here to output multiple themes + size = "compact"; + tweaks = [ "rimless" "black" ]; # You can also specify multiple tweaks here + variant = "macchiato"; + }; + in [ + # for connecting to nas + nfs-utils + + # some standards for convenience + vim + parted + os-prober + qpdfview + swww + + # greeter + greetd.gtkgreet + catp-gtk + + # deps for hyprland / eww + socat + ]; + + system.stateVersion = "23.11"; + + # NFS setup + services.rpcbind.enable = true; # needed for NFS + systemd.mounts = [{ + type = "nfs"; + mountConfig = { + Options = "noatime"; + }; + what = "192.168.178.20:/volume1/MiniDrive"; + where = "/MiniDrive"; + }]; + + systemd.automounts = [{ + wantedBy = [ "multi-user.target" ]; + automountConfig = { + TimeoutIdleSec = "10"; + }; + where = "/MiniDrive"; + }]; + + # source zsh + programs.zsh.enable = true; + users.defaultUserShell = pkgs.zsh; + + # Binary Cache for Haskell.nix + nix.settings.trusted-public-keys = [ + "hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=" + ]; + nix.settings.substituters = [ + "https://aseipp-nix-cache.global.ssl.fastly.net" + "https://cache.iog.io" + ]; + + # environment variables + environment.sessionVariables = { + ## disable logging when direnv changes + DIRENV_LOG_FORMAT = []; + # GTK theme (set here for greetd) + GTK_THEME = "Catppuccin-Macchiato-Compact-Flamingo-Dark"; + }; + + # fonts + fonts = { + packages = with pkgs; [ + ((nerdfonts.override { fonts = [ "Hack" "DejaVuSansMono" "DroidSansMono" "Noto" ]; })) + mononoki + # noto-fonts + noto-fonts-cjk + noto-fonts-emoji + ]; + enableDefaultPackages = true; + fontconfig = { + defaultFonts = { + monospace = [ "Berkeley Mono Nerd Font" ]; + sansSerif = [ "NotoSans Nerd Font" ]; + serif = [ "NotoSans Nerd Font" ]; + emoji = [ "Noto Color Emoji" ]; + }; + }; + }; + + # enable flakes + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # hyprland + programs.hyprland.enable = true; + + # ssh + programs.ssh.startAgent = true; + programs.ssh.extraConfig = '' + AddKeysToAgent yes + IdentityFile ~/.ssh/git + ''; + + programs.steam.enable = true; + + # thunar + programs.thunar = { + enable = true; + plugins = with pkgs.xfce; [ + thunar-archive-plugin + thunar-volman + ]; + }; + services.gvfs.enable = true; # Mount, trash, and others + services.tumbler.enable = true; # thumbnail support for images +} diff --git a/gunther/hardware-configuration.nix b/gunther/hardware-configuration.nix new file mode 100644 index 0000000..02a15e5 --- /dev/null +++ b/gunther/hardware-configuration.nix @@ -0,0 +1,34 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/2191540a-8cf9-400e-b4bc-9dbf71527b07"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/3DD6-C061"; + fsType = "vfat"; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/7c6d727e-1d40-472a-a409-205db0776d20"; } + ]; + + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/gunther/hypr/catppuccin-macchiato.rasi b/gunther/hypr/catppuccin-macchiato.rasi new file mode 100644 index 0000000..696d769 --- /dev/null +++ b/gunther/hypr/catppuccin-macchiato.rasi @@ -0,0 +1,111 @@ +* { + bg-col: #24273a; + bg-col-light: #24273a; + border-col: #24273a; + selected-col: #24273a; + blue: #8aadf4; + fg-col: #cad3f5; + fg-col2: #ed8796; + grey: #6e738d; + + width: 600; + font: "JetBrainsMono Nerd Font 14"; +} + +element-text, element-icon , mode-switcher { + background-color: inherit; + text-color: inherit; +} + +window { + height: 360px; + border: 3px; + border-color: @border-col; + background-color: @bg-col; +} + +mainbox { + background-color: @bg-col; +} + +inputbar { + children: [prompt,entry]; + background-color: @bg-col; + border-radius: 5px; + padding: 2px; +} + +prompt { + background-color: @blue; + padding: 6px; + text-color: @bg-col; + border-radius: 3px; + margin: 20px 0px 0px 20px; +} + +textbox-prompt-colon { + expand: false; + str: ":"; +} + +entry { + padding: 6px; + margin: 20px 0px 0px 10px; + text-color: @fg-col; + background-color: @bg-col; +} + +listview { + border: 0px 0px 0px; + padding: 6px 0px 0px; + margin: 10px 0px 0px 20px; + columns: 2; + lines: 5; + background-color: @bg-col; +} + +element { + padding: 5px; + background-color: @bg-col; + text-color: @fg-col ; +} + +element-icon { + size: 25px; +} + +element selected { + background-color: @selected-col ; + text-color: @fg-col2 ; +} + +mode-switcher { + spacing: 0; + } + +button { + padding: 10px; + background-color: @bg-col-light; + text-color: @grey; + vertical-align: 0.5; + horizontal-align: 0.5; +} + +button selected { + background-color: @bg-col; + text-color: @blue; +} + +message { + background-color: @bg-col-light; + margin: 2px; + padding: 2px; + border-radius: 5px; +} + +textbox { + padding: 6px; + margin: 20px 0px 0px 20px; + text-color: @blue; + background-color: @bg-col-light; +} diff --git a/gunther/hypr/hyprland.nix b/gunther/hypr/hyprland.nix new file mode 100644 index 0000000..8a162f2 --- /dev/null +++ b/gunther/hypr/hyprland.nix @@ -0,0 +1,181 @@ +{ pkgs, ... }: +{ + # hyprland setup + wayland.windowManager.hyprland = { + enable = true; + xwayland.enable = true; + settings = { + monitor = [ + "DP-3 , 2560x1440@144, 1920x0, 1" + "HDMI-A-5, 1920x1080@75 , 0x0 , 1" + ]; + input = { + kb_layout = "de"; + kb_variant = "us"; + follow_mouse = 1; + }; + "$mod" = "SUPER"; + "$modd" = "SUPER_SHIFT"; + general = { + gaps_in = 8; + gaps_out = 15; + border_size = 3; + + resize_on_border = true; + layout = "dwindle"; + + "col.active_border" = "rgba(cba6f7ff) rgba(89b4faff) rgba(94e2d5ff) 10deg"; + "col.inactive_border" = "0xff45475a"; + "col.nogroup_border" = "0xff89dceb"; + "col.nogroup_border_active" = "0xfff9e2af"; + }; + decoration = { + blur = { + new_optimizations = true; + size = 1; + passes = 1; + }; + drop_shadow = true; + shadow_range = 100; + shadow_render_power = 5; + "col.shadow" = "0x33000000"; + "col.shadow_inactive" = "0x22000000"; + rounding = 15; + }; + animations = { + enabled = 1; + bezier = "overshot,0.13,0.99,0.29,1.1"; + animation = [ + "windows,1,4,overshot,slide" + "border,1,10,default" + "fade,1,10,default" + "workspaces,1,6,overshot,slidevert" + ]; + }; + misc = { + disable_hyprland_logo = true; + }; + bind = [ + # opening programs + "$mod, Return, exec, foot" + "$mod, D, exec, rofi -show drun -show-icons" + "$mod, M, exit, " + "$mod, Q, killactive, " + + # moving around + "$mod, left , movefocus, l" + "$mod, right, movefocus, r" + "$mod, down , movefocus, d" + "$mod, up , movefocus, u" + + # moving windows + "$modd, left , movewindow, l" + "$modd, right, movewindow, r" + "$modd, down , movewindow, d" + "$modd, up , movewindow, u" + + # workspaces + "$mod, 1, workspace, 1" + "$mod, 2, workspace, 2" + "$mod, 3, workspace, 3" + "$mod, 4, workspace, 4" + "$modd, 1, movetoworkspacesilent, 1" + "$modd, 2, movetoworkspacesilent, 2" + "$modd, 3, movetoworkspacesilent, 3" + "$modd, 4, movetoworkspacesilent, 4" + + # fullscreen + "$mod, F11, fullscreen, 0" + "$mod, m, fullscreen, 1" # maximize + + # floating + "$mod, F, togglefloating, active" + + # screenshot + ", Print, exec, grimblast copysave area $HOME\"/screenshots/\"$(date +'%F-%T.png');" + + + ]; + bindm = [ + "$mod, mouse:272, movewindow" + ]; + bindle = [ + ", XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+" + ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-" + ", XF86AudioMute, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%" + ]; + exec-once = [ + "bash ~/Git/nixos/gunther/hypr/start.sh" + ]; + }; + }; + + # tell electron to use wayland + home.sessionVariables.NIXOS_OZONE_WL = "1"; + + # terminal + programs.foot = { + enable = true; + settings = { + main = { + font = "monospace:size=12"; + dpi-aware = "yes"; + }; + colors = { + foreground = "cad3f5"; + background = "24273a"; + regular0 = "494d64"; + regular1 = "ed8796"; + regular3 = "eed49f"; + regular4 = "8aadf4"; + regular5 = "f5bde6"; + regular6 = "8bd5ca"; + regular7 = "b8c0e0"; + bright0 = "5b6078"; + bright1 = "ed8796"; + bright3 = "eed49f"; + bright4 = "8aadf4"; + bright5 = "f5bde6"; + bright6 = "8bd5ca"; + bright7 = "a5adcb"; + }; + }; + }; + + programs.rofi = { + enable = true; + package = pkgs.rofi-wayland; + theme = ./catppuccin-macchiato.rasi; + font = "monospace 14"; + terminal = "foot"; + extraConfig = { + modi = "drun,run,top"; + }; + plugins = [ + pkgs.rofi-top + ]; + }; + + services.mako = { + enable = true; + extraConfig = '' + background-color=#24273a + text-color=#cad3f5 + border-color=#8aadf4 + progress-color=over #363a4f + sort=-time + layer=overlay + width=300 + height=110 + border-size=2 + border-radius=15 + max-icon-size=64 + default-timeout=5000 + ignore-timeout=1 + + [urgency=high] + border-color=#f5a97f + ''; + }; + +} diff --git a/gunther/hypr/hyprpaper.conf b/gunther/hypr/hyprpaper.conf new file mode 100644 index 0000000..df79657 --- /dev/null +++ b/gunther/hypr/hyprpaper.conf @@ -0,0 +1,5 @@ +preload = ~/Git/nixos/gunther/hypr/wallpaper.jpg +# +#set the default wallpaper(s) seen on inital workspace(s) --depending on the number of monitors used +wallpaper = monitor1,~/Git/nixos/gunther/hypr/wallpaper.jpg +wallpaper = monitor2,~/Git/nixos/gunther/hypr/wallpaper.jpg diff --git a/gunther/hypr/start.sh b/gunther/hypr/start.sh new file mode 100755 index 0000000..c25dc87 --- /dev/null +++ b/gunther/hypr/start.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# init nmapplet +# TODO add back once eww supports tray +# nm-applet --indicator & +swww init +swww img /home/leonv/Git/nixos/gunther/hypr/wallpaper.jpg + +eww daemon +eww open top-bar + +# notification +mako diff --git a/gunther/hypr/wallpaper.jpg b/gunther/hypr/wallpaper.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c36b7fdde54836ec0febb892b0688ab7e6d00c8d GIT binary patch literal 85902 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

D@|^vc?_I^}l2U(2@YW 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 literal 0 HcmV?d00001 diff --git a/gunther/leonv.nix b/gunther/leonv.nix new file mode 100755 index 0000000..b9f9f2f --- /dev/null +++ b/gunther/leonv.nix @@ -0,0 +1,137 @@ +{ config, pkgs, inputs, ... }: +{ + imports = [ + ./../common + ./hypr/hyprland.nix + ./../common/eww + ]; + /* The home.stateVersion option does not have a default and must be set */ + home.stateVersion = "23.11"; + home.username = "leonv"; + home.homeDirectory = "/home/leonv"; + + home.packages = with pkgs; [ + # theme for gtk applications + orchis-theme + + # stuff + jq + vlc + openvpn + signal-desktop + webcord + firefox-wayland + ungoogled-chromium + thunderbird + gimp + qpdfview + wget + fontforge + gparted + eza + ripgrep + fd + zoom-us + + # development + jetbrains.idea-ultimate + gnumake + texlive.combined.scheme-full + ltex-ls + ghostscript + jdk11 + coq + gcc + ghc + cabal-install + haskell-language-server + python3 + python3Packages.pygments + nodejs_20 + unifont + anki + pandoc + + # games + prismlauncher + + # hyprland + kitty + networkmanagerapplet + mako + libnotify + pavucontrol + hyprpaper + qimgv + playerctl + hyprpicker + wev + inputs.hyprland-contrib.packages.${pkgs.system}.grimblast + bluez + htop + archiver + gnome.file-roller + discord + zip + emacs + shellcheck + + # yubikey + yubico-pam + yubikey-manager + + # agda + + (agda.withPackages [ + agdaPackages.standard-library + agdaPackages.agda-categories + ]) + ]; + + programs.home-manager.enable = true; + + programs.zsh = { + enable = true; + shellAliases = { + clean = "sudo nix-env --delete-generations old --profile /nix/var/nix/profiles/system && sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch && sudo nix-store --gc"; + ls = "eza"; + ll = "eza -l"; + l = "eza -lah"; + }; + initExtra = '' + function rebuild () { + sudo nixos-rebuild switch --flake /home/leonv/Git/nixos + sudo cp -r /home/leonv/Git/nixos /etc/ + } + ''; + oh-my-zsh.enable = true; + }; + + gtk = { + enable = true; + theme = { + name = "Catppuccin-Macchiato-Compact-Flamingo-Dark"; + package = pkgs.catppuccin-gtk.override { + accents = [ "flamingo" ]; + size = "compact"; + tweaks = [ "rimless" "black" ]; + variant = "macchiato"; + }; + }; + iconTheme = { + name = "Dracula"; + package = pkgs.dracula-icon-theme; + }; + font = { + name = "NotoSans Nerd Font"; + }; + }; + home.sessionVariables.GTK_THEME = "Catppuccin-Macchiato-Compact-Flamingo-Dark"; + home.sessionPath = [ "$HOME/.config/emacs/bin" ]; + + services.syncthing = { + enable = true; + }; + + services.mpris-proxy.enable = true; +} diff --git a/iso/configuration.nix b/iso/configuration.nix new file mode 100644 index 0000000..a22999f --- /dev/null +++ b/iso/configuration.nix @@ -0,0 +1,105 @@ + +{ config, pkgs, lib, ... }: +{ + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.leonv = { + isNormalUser = true; + description = "Leon Vatthauer"; + extraGroups = [ "networkmanager" "wheel" ]; + initialPassword = "leonv"; + }; + + networking.hostName = "gunther"; # Define your hostname. + # Enable networking + networking.networkmanager = { + enable = true; + }; + + # Set your time zone. + time.timeZone = "Europe/Berlin"; + + i18n.supportedLocales = [ + "en_US.UTF-8/UTF-8" + "de_DE.UTF-8/UTF-8" + ]; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LANG = "en_US.UTF-8"; + LC_ALL = "en_US.UTF-8"; + LANGUAGE = "en_US.UTF-8"; + LC_ADDRESS = "de_DE.UTF-8"; + LC_IDENTIFICATION = "de_DE.UTF-8"; + LC_MEASUREMENT = "de_DE.UTF-8"; + LC_MONETARY = "de_DE.UTF-8"; + LC_NAME = "de_DE.UTF-8"; + LC_NUMERIC = "de_DE.UTF-8"; + LC_PAPER = "de_DE.UTF-8"; + LC_TELEPHONE = "de_DE.UTF-8"; + LC_TIME = "de_DE.UTF-8"; + }; + + # Enable sound with pipewire. + sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. + environment.systemPackages = with pkgs; [ + # for connecting to nas + nfs-utils + + # some standards for convenience + vim + parted + git + ]; + + system.stateVersion = "23.11"; # Did you read the comment? + + # NFS setup + services.rpcbind.enable = true; # needed for NFS + systemd.mounts = [{ + type = "nfs"; + mountConfig = { + Options = "noatime"; + }; + what = "192.168.178.20:/volume1/MiniDrive"; + where = "/MiniDrive"; + }]; + + systemd.automounts = [{ + wantedBy = [ "multi-user.target" ]; + automountConfig = { + TimeoutIdleSec = "10"; + }; + where = "/MiniDrive"; + }]; + + # source zsh + programs.zsh.enable = true; + users.defaultUserShell = pkgs.zsh; + + # Binary Cache for Haskell.nix + nix.settings.trusted-public-keys = [ + "hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=" + ]; + nix.settings.substituters = [ + "https://aseipp-nix-cache.global.ssl.fastly.net" + "https://cache.iog.io" + ]; + + # flakes + nix.settings.experimental-features = [ "nix-command" "flakes" ]; +} \ No newline at end of file diff --git a/shinx/default.nix b/shinx/default.nix new file mode 100755 index 0000000..28ab0d2 --- /dev/null +++ b/shinx/default.nix @@ -0,0 +1,27 @@ +# hosts/YourHostName/default.nix +{ pkgs, home-manager, inputs, ... }@mod-inputs: +{ + + # Make sure the nix daemon always runs + services.nix-daemon.enable = true; + # Installs a version of nix, that dosen't need "experimental-features = nix-command flakes" in /etc/nix/nix.conf + #services.nix-daemon.package = pkgs.nixFlakes; + + # if you use zsh (the default on new macOS installations), + # you'll need to enable this so nix-darwin creates a zshrc sourcing needed environment changes + programs.zsh.enable = true; + # bash is enabled by default + home-manager = { + extraSpecialArgs = { inherit (mod-inputs) inputs; }; + useGlobalPkgs = true; + useUserPackages = true; + users.leonvatthauer = import ./leonvatthauer.nix; + }; + nixpkgs.config.allowUnfree = true; + users.users.leonvatthauer = { + home="/Users/leonvatthauer"; + }; + fonts.fonts = [ + pkgs.mononoki + ]; +} diff --git a/shinx/leonvatthauer.nix b/shinx/leonvatthauer.nix new file mode 100755 index 0000000..8c38fde --- /dev/null +++ b/shinx/leonvatthauer.nix @@ -0,0 +1,70 @@ +{ pkgs, lib, config, inputs, ... }: +{ + home.stateVersion = "23.11"; + imports = [ + ./../common/default.nix + ]; + + home.activation = { + trampolineApps = let + mac-app-util = inputs.mac-app-util.packages.${pkgs.stdenv.system}.default; + in lib.hm.dag.entryAfter [ "writeBoundary" ] '' + fromDir="$HOME/Applications/Home Manager Apps" + toDir="$HOME/Applications/Home Manager Trampolines" + ${mac-app-util}/bin/mac-app-util sync-trampolines "$fromDir" "$toDir" + ''; + }; + + home.packages = with pkgs; [ + zsh + oh-my-zsh + coq + openvpn + ghc + haskell-language-server + cabal-install + haskellPackages.alex + haskellPackages.happy + python3 + python3Packages.pygments + nodejs_20 + iterm2 + (agda.withPackages [ + agdaPackages.standard-library + agdaPackages.agda-categories + ]) + texlive.combined.scheme-full + pandoc + gh + #yubico-pam + #yubikey-manager + # programs for emacs + emacs + fd + ripgrep + gnugrep + nixfmt + shellcheck + fontconfig + coreutils + coreutils-prefixed + ]; + + programs.home-manager.enable = true; + programs.kitty = { + enable = true; + font.name = "Berkeley Mono"; + + }; + programs.zsh = { + enable = true; + oh-my-zsh = { + enable = true; + plugins = [ "git" ]; + theme = "robbyrussell"; + }; + initExtra = '' + export PATH="/opt/homebrew/bin:$PATH" + ''; + }; +} diff --git a/willem/README.md b/willem/README.md new file mode 100644 index 0000000..7a1a1cf --- /dev/null +++ b/willem/README.md @@ -0,0 +1,20 @@ +# Willem + +Willem is a server running on a Raspberry Pi 400 offering the following services: +- [Gitea](git.vatthauer.xyz) +- [Vaultwarden](bitwarden.vatthauer.xyz) + +There are daily backups of the Gitea instance using Restic via B2. +## Installation on Raspberry Pi 400 +### Resources +- https://nixos.wiki/wiki/NixOS_on_ARM/Raspberry_Pi_4 +- https://nixos.wiki/wiki/NixOS_on_ARM#Installation + +### Step by step +1. Follow the [generic installation steps](https://nixos.wiki/wiki/NixOS_on_ARM#Installation) to get NixOS up and running on the Pi. +2. Generate the default `configuration.nix` via `sudo nixos-generate-config` and do a first rebuild `sudo nixos-rebuild switch` +3. Somehow get this repository onto the machine and `cd` into it +4. We need git: `nix-shell -p git` +5. Build the flake via `sudo nixos-rebuild switch --flake .` +6. At this point you can restart +7. Login, set password, move the repository to `/home/leonv/nixos` \ No newline at end of file diff --git a/willem/configuration.nix b/willem/configuration.nix new file mode 100644 index 0000000..b7ebe0e --- /dev/null +++ b/willem/configuration.nix @@ -0,0 +1,77 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running 'nixos-help'). + +{ config, pkgs, lib, ... }: + +{ + imports = + [ + ./hardware-configuration.nix + ./services + ./programs + ]; + + # enable flakes + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) + boot.loader.grub.enable = false; + # Enables the generation of /boot/extlinux/extlinux.conf + boot.loader.generic-extlinux-compatible.enable = true; + + networking.hostName = "willem"; # Define your hostname. + #networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + networking.firewall.allowedTCPPorts = [ 22 80 443 631 8096 8920 ]; + networking.firewall.allowedUDPPorts = [ 22 80 443 631 1900 7359 ]; + + # Set your time zone. + time.timeZone = "Europe/Berlin"; + + # Define a user account. Don't forget to set a password with 'passwd'. + users.users.leonv = { + isNormalUser = true; + initialPassword = "leonv"; + extraGroups = [ "wheel" ]; # Enable 'sudo' for the user. + packages = with pkgs; [ + ]; + }; + users.defaultUserShell = pkgs.zsh; + + # List packages installed in system profile. + environment.systemPackages = with pkgs; [ + wget + git + zsh + oh-my-zsh + restic + ]; + environment.variables = { + EDITOR = "nvim"; + + # bitwarden key + YUBICO_CLIENT_ID = "${../nix-secrets/willem/vaultwarden/yubico-id}"; + YUBICO_SECRET_KEY = "${../nix-secrets/willem/vaultwarden/yubico-secret}"; + }; + environment.shells = [ pkgs.zsh ]; + + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ + "plexmediaserver" + ]; + + services.plex = { + enable = true; + openFirewall = true; + }; + + services.jellyfin.enable = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It's perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? +} + diff --git a/willem/hardware-configuration.nix b/willem/hardware-configuration.nix new file mode 100644 index 0000000..c6a3513 --- /dev/null +++ b/willem/hardware-configuration.nix @@ -0,0 +1,26 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" "uas" "pcie-brcmstb" "reset-raspberrypi" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-partuuid/45e5879b-02"; + fsType = "ext4"; + }; + + swapDevices = [ ]; + + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; +} diff --git a/willem/programs/default.nix b/willem/programs/default.nix new file mode 100644 index 0000000..5316865 --- /dev/null +++ b/willem/programs/default.nix @@ -0,0 +1,8 @@ +{ + imports = [ + ./neovim.nix + ./ssh.nix + ./starship.nix + ./zsh.nix + ]; +} diff --git a/willem/programs/neovim.nix b/willem/programs/neovim.nix new file mode 100644 index 0000000..37a1ea9 --- /dev/null +++ b/willem/programs/neovim.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: +{ + programs.neovim = { + enable = true; + configure = { + customRC = ''''; + packages.myVimPackage = with pkgs.vimPlugins; { + start = [ vim-nix ]; + }; + }; + viAlias = true; + vimAlias = true; + }; +} \ No newline at end of file diff --git a/willem/programs/ssh.nix b/willem/programs/ssh.nix new file mode 100644 index 0000000..e4c886d --- /dev/null +++ b/willem/programs/ssh.nix @@ -0,0 +1,6 @@ +{ + programs.ssh.startAgent = true; + programs.ssh.extraConfig = '' + AddKeysToAgent yes + ''; +} \ No newline at end of file diff --git a/willem/programs/starship.nix b/willem/programs/starship.nix new file mode 100644 index 0000000..a2d4525 --- /dev/null +++ b/willem/programs/starship.nix @@ -0,0 +1,8 @@ +{ + programs.starship = { + enable = true; + settings = { + gradle.symbol = "🐘"; + }; + }; +} \ No newline at end of file diff --git a/willem/programs/zsh.nix b/willem/programs/zsh.nix new file mode 100644 index 0000000..d4e9708 --- /dev/null +++ b/willem/programs/zsh.nix @@ -0,0 +1,19 @@ +{ + programs.zsh = { + enable = true; + shellAliases = { + clean = "sudo nix-env --delete-generations old --profile /nix/var/nix/profiles/system && sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch && sudo nix-store --gc"; + }; + shellInit = '' + function rebuild () { + sudo nixos-rebuild switch --flake /home/leonv/nixos + sudo cp -r /home/leonv/nixos /etc/ + } + ''; + ohMyZsh = { + enable = true; + plugins = [ "git" ]; + theme = "dpoggi"; + }; + }; +} \ No newline at end of file diff --git a/willem/services/acme.nix b/willem/services/acme.nix new file mode 100644 index 0000000..955c5f4 --- /dev/null +++ b/willem/services/acme.nix @@ -0,0 +1,8 @@ +{ + security.acme.acceptTerms = true; + security.acme.certs = { + "git.vatthauer.xyz".email = "leonvatthauer@outlook.com"; + "bitwarden.vatthauer.xyz".email = "leonvatthauer@outlook.com"; + "video.vatthauer.xyz".email = "leonvatthauer@outlook.com"; + }; +} diff --git a/willem/services/ddns.nix b/willem/services/ddns.nix new file mode 100644 index 0000000..76d79d0 --- /dev/null +++ b/willem/services/ddns.nix @@ -0,0 +1,16 @@ +{ pkgs, ... }: +{ + # dynamic dns + users.users.ddns = { + isSystemUser = true; + group = "ddns"; + }; + users.groups.ddns = {}; + systemd.services.ddns-updater = { + enable = true; + serviceConfig.User = "ddns"; + path = [ pkgs.curl ]; + script = "${../../nix-secrets/willem/ddns/update}"; + startAt = "hourly"; + }; +} diff --git a/willem/services/default.nix b/willem/services/default.nix new file mode 100644 index 0000000..69bc66f --- /dev/null +++ b/willem/services/default.nix @@ -0,0 +1,12 @@ +{ + imports = [ + ./acme.nix + ./ddns.nix + ./nginx.nix + ./gitea.nix + ./printing.nix + ./restic.nix + ./ssh.nix + ./vaultwarden.nix + ]; +} diff --git a/willem/services/gitea.nix b/willem/services/gitea.nix new file mode 100644 index 0000000..1c2bb15 --- /dev/null +++ b/willem/services/gitea.nix @@ -0,0 +1,23 @@ +{ pkgs, ...}: +{ + services.gitea = { + enable = true; + appName = "Lambda-Git"; + package = pkgs.forgejo; + stateDir = "/gitea"; + database = { + type = "sqlite3"; + }; + dump = { + enable = true; + interval = "02:00"; + }; + settings.server = { + ROOT_URL = "https://git.vatthauer.xyz"; + HTTP_PORT = 3001; + DOMAIN = "git.vatthauer.xyz"; + }; + settings.session.COOKIE_SECURE = true; + settings.service.DISABLE_REGISTRATION = true; + }; +} \ No newline at end of file diff --git a/willem/services/nginx.nix b/willem/services/nginx.nix new file mode 100644 index 0000000..96aebac --- /dev/null +++ b/willem/services/nginx.nix @@ -0,0 +1,33 @@ +{ + services.nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + }; + + services.nginx.virtualHosts."git.vatthauer.xyz" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:3001/"; + }; + }; + + services.nginx.virtualHosts."bitwarden.vatthauer.xyz" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:8222/"; + }; + }; + + services.nginx.virtualHosts."video.vatthauer.xyz" = { + enableACME = true; + forceSSL = false; + locations."/" = { + proxyPass = "http://localhost:8096"; + }; + }; +} diff --git a/willem/services/printing.nix b/willem/services/printing.nix new file mode 100644 index 0000000..321e5b2 --- /dev/null +++ b/willem/services/printing.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: +{ + # Enable CUPS to print documents. + services.avahi = { + enable = true; + publish.enable = true; + publish.userServices = true; + }; + services.printing = { + enable = true; + drivers = [ pkgs.splix ]; + browsing = true; + listenAddresses = [ "*:631" ]; + allowFrom = [ "all" ]; + defaultShared = true; + extraConf = '' + BrowseLocalProtocols all + ''; + }; +} diff --git a/willem/services/restic.nix b/willem/services/restic.nix new file mode 100644 index 0000000..2b4f213 --- /dev/null +++ b/willem/services/restic.nix @@ -0,0 +1,17 @@ +{ + services.restic.backups = { + giteaBackup = { + paths = [ "/gitea/dump" ]; + # environmentFile = "/home/leonv/nixos/willem/private/gitea_backupCreds"; + # passwordFile = "/home/leonv/nixos/willem/private/restic-password"; + environmentFile = "${../../nix-secrets/willem/gitea/backupCreds}"; + passwordFile = "${../../nix-secrets/willem/restic/password}"; + repository = "b2:gitea-willem"; + initialize = true; + timerConfig = { + OnCalendar = "04:00"; + Persistent = true; + }; + }; + }; +} \ No newline at end of file diff --git a/willem/services/ssh.nix b/willem/services/ssh.nix new file mode 100644 index 0000000..dba27db --- /dev/null +++ b/willem/services/ssh.nix @@ -0,0 +1,4 @@ +{ + # Enable the OpenSSH daemon. + services.openssh.enable = true; +} \ No newline at end of file diff --git a/willem/services/vaultwarden.nix b/willem/services/vaultwarden.nix new file mode 100644 index 0000000..1f7d8a2 --- /dev/null +++ b/willem/services/vaultwarden.nix @@ -0,0 +1,19 @@ +{ + services.vaultwarden = { + enable = true; + config = { + DOMAIN = "https://bitwarden.vatthauer.xyz"; + SIGNUPS_ALLOWED = false; + + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = 8222; + + ROCKET_LOG = "critical"; + + ADMIN_TOKEN = "${../../nix-secrets/willem/vaultwarden/admin-token}"; + + YUBICO_CLIENT_ID = "${../../nix-secrets/willem/vaultwarden/yubico-id}"; + YUBICO_SECRET_KEY = "${../../nix-secrets/willem/vaultwarden/yubico-secret}"; + }; + }; +}