From 6543d4a7f3949ce7cd0922f92274a2f846545ff5 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 4 Feb 2026 19:03:10 +0100 Subject: [PATCH] feat: nixvim config currently only for dnsc-air. can simply be imported in other hosts --- AGENTS.md | 276 +++++++++++++++++++ flake.lock | 85 +++++- flake.nix | 3 +- home/darwin.nix | 5 +- modules/base/default.nix | 3 +- modules/fish/default.nix | 1 + modules/nixvim/ai.nix | 45 +++ modules/nixvim/colorscheme.nix | 13 + modules/nixvim/completion.nix | 21 ++ modules/nixvim/default.nix | 26 ++ modules/nixvim/editing.nix | 65 +++++ modules/nixvim/extraFiles/palette.lua | 33 +++ modules/nixvim/extraFiles/winterly.lua | 368 +++++++++++++++++++++++++ modules/nixvim/formatter.nix | 56 ++++ modules/nixvim/git.nix | 28 ++ modules/nixvim/keybindings.nix | 138 ++++++++++ modules/nixvim/lsp.nix | 67 +++++ modules/nixvim/options.nix | 47 ++++ modules/nixvim/picker.nix | 171 ++++++++++++ modules/nixvim/statusline.nix | 97 +++++++ modules/tmux/default.nix | 3 + 21 files changed, 1541 insertions(+), 10 deletions(-) create mode 100644 AGENTS.md create mode 100644 modules/nixvim/ai.nix create mode 100644 modules/nixvim/colorscheme.nix create mode 100644 modules/nixvim/completion.nix create mode 100644 modules/nixvim/default.nix create mode 100644 modules/nixvim/editing.nix create mode 100644 modules/nixvim/extraFiles/palette.lua create mode 100644 modules/nixvim/extraFiles/winterly.lua create mode 100644 modules/nixvim/formatter.nix create mode 100644 modules/nixvim/git.nix create mode 100644 modules/nixvim/keybindings.nix create mode 100644 modules/nixvim/lsp.nix create mode 100644 modules/nixvim/options.nix create mode 100644 modules/nixvim/picker.nix create mode 100644 modules/nixvim/statusline.nix diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..40df3e4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,276 @@ +# Agent Guide for nix-config + +This document provides guidelines for AI coding agents working in this Nix configuration repository. + +## Repository Overview + +This is a flake-based Nix configuration managing multiple hosts: +- `dnsc-air` (nix-darwin, macOS) +- `dnsc-work` (nix-darwin, macOS) +- `dnsc-deck` (home-manager only, Steam Deck) +- `dnsc-server` (NixOS) +- `dnsc-vps-sm` (NixOS) + +## Directory Structure + +``` +. +├── flake.nix # Main flake configuration +├── Justfile # Common build/deploy commands +├── hosts/ # Host-specific configurations +│ ├── dnsc-air/ +│ ├── dnsc-work/ +│ ├── dnsc-server/ +│ └── dnsc-vps-sm/ +├── home/ # Home-manager configurations +│ ├── darwin.nix +│ ├── darwin-work.nix +│ ├── linux.nix +│ ├── server.nix +│ └── deck.nix +├── modules/ # Reusable modules +│ ├── base/ +│ ├── fish/ +│ ├── git/ +│ ├── nixvim/ +│ └── [40+ other modules] +└── secrets/ # agenix encrypted secrets +``` + +## Build Commands + +### Validation and Testing +```bash +# Check flake evaluates correctly +nix flake check + +# Show flake metadata +nix flake show + +# Update flake inputs +just up + +# Update specific input +just upi i=home-manager +``` + +### Deployment + +**macOS (darwin-rebuild):** +```bash +# Deploy to current macOS host +just mre + +# Deploy with lock file recreation +just mup + +# Manual deployment +darwin-rebuild switch --flake . +``` + +**NixOS (nixos-rebuild):** +```bash +# Deploy NixOS configuration +just deploy + +# Deploy with debug output +just debug + +# Manual deployment +nixos-rebuild switch --flake . +``` + +**Steam Deck (home-manager):** +```bash +# Deploy to Steam Deck +just dre + +# Manual deployment +nix run home-manager/master -- switch --flake .#dnsc-deck +``` + +### Maintenance +```bash +# View system generation history +just history + +# Clean old generations (>7 days) +just clean + +# Run garbage collection +just gc + +# Open Nix REPL +just repl +``` + +## Code Style Guidelines + +### Nix Language Conventions + +**File Structure:** +```nix +{ + config, + inputs, + outputs, + lib, + pkgs, + ... +}: +{ + imports = [ + # List imports first + ]; + + # Configuration follows +} +``` + +**Formatting:** +- Use 2 spaces for indentation +- Opening braces on same line: `{ foo = "bar"; }` +- Function parameters use named pattern matching +- Multi-line lists: one item per line with trailing semicolons +- String interpolation: `"${variable}"` or `''${expression}''` + +**Naming Conventions:** +- Module files: `default.nix` in subdirectories +- Descriptive attribute names: `services.syncthing.enable` +- Host configurations: `dnsc-` +- Use kebab-case for file/directory names: `nixos-modules` +- Use camelCase for attribute names in Nix expressions + +**Imports:** +```nix +# In flake.nix +inputs.home-manager.nixosModules.home-manager + +# In configuration files +outputs.nixosModules.base +../../modules/docker +./hardware-configuration.nix +``` + +**Package Management:** +```nix +# System packages +environment.systemPackages = with pkgs; [ + git + btop + neovim +]; + +# Using lib.mkAfter for additions +environment.systemPackages = lib.mkAfter ( + with pkgs; [ + additional-package + ] +); +``` + +**Module Structure:** +- Keep modules focused and reusable +- Place in `modules//default.nix` +- Use option declarations when creating configurable modules +- Include modules in host configs via `imports = [ ]` + +### Configuration Patterns + +**Home Manager Integration:** +```nix +home-manager = { + extraSpecialArgs = { inherit inputs outputs; }; + useGlobalPkgs = true; + backupFileExtension = "backup"; + users = { + dennis = import ../../home/darwin.nix; + }; +}; +``` + +**Service Configuration:** +```nix +services.syncthing = { + enable = true; + user = "dennis"; + configDir = "/home/dennis/.config/syncthing"; + # ... additional settings +}; +``` + +**Secrets with agenix:** +```nix +age = { + identityPaths = [ "${config.users.users.dennis.home}/.ssh/id_ed25519" ]; + secrets."restic/password".file = ../../secrets/restic/password.age; +}; +``` + +### Fish Shell Functions + +**Function Style:** +```nix +functions = { + function_name = /* fish */ '' + # Fish shell code here + echo "example" + ''; +}; +``` + +**Inline Comments:** +Use `/* fish */` or `/* bash */` before multi-line strings to indicate language + +## Common Tasks + +### Adding a New Module + +1. Create `modules//default.nix` +2. Define module structure: + ```nix + { pkgs, ... }: + { + # Configuration here + } + ``` +3. Export in `flake.nix` if needed: + ```nix + nixosModules.moduleName = import ./modules/module-name; + ``` +4. Import in host configuration: + ```nix + imports = [ ../../modules/module-name ]; + ``` + +### Adding a New Host + +1. Create `hosts//default.nix` +2. Create `hosts//hardware-configuration.nix` (for NixOS) +3. Add configuration to `flake.nix`: + ```nix + nixosConfigurations.hostname = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { inherit inputs outputs; }; + modules = [ ./hosts/hostname ]; + }; + ``` + +### Modifying Home Manager Config + +1. Edit appropriate file in `home/`: + - `darwin.nix` for dnsc-air + - `darwin-work.nix` for dnsc-work + - `server.nix` for servers +2. Changes take effect on next deployment +3. Home configs import modules from `modules/` directory + +## Important Notes + +- **Never commit secrets**: Use agenix for sensitive data +- **Test before deploying**: Run `nix flake check` before major changes +- **System state version**: Don't change `system.stateVersion` without migration +- **Flake inputs**: Keep inputs up-to-date with `just up` +- **Git ignore**: `.DS_Store` files are ignored globally (see `modules/git/default.nix`) +- **No traditional package.json**: This is a Nix project, not a Node.js project +- **Experimental features**: This config uses `nix-command` and `flakes` features diff --git a/flake.lock b/flake.lock index 2cbcba1..dd5e0b1 100644 --- a/flake.lock +++ b/flake.lock @@ -80,6 +80,27 @@ "type": "gitlab" } }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768135262, + "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -276,6 +297,22 @@ } }, "nixpkgs_5": { + "locked": { + "lastModified": 1768875095, + "narHash": "sha256-dYP3DjiL7oIiiq3H65tGIXXIT1Waiadmv93JS0sS+8A=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ed142ab1b3a092c4d149245d0c4126a5d7ea00b0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { "locked": { "lastModified": 0, "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", @@ -287,7 +324,7 @@ "type": "indirect" } }, - "nixpkgs_6": { + "nixpkgs_7": { "locked": { "lastModified": 1728538411, "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=", @@ -303,7 +340,7 @@ "type": "github" } }, - "nixpkgs_7": { + "nixpkgs_8": { "locked": { "lastModified": 1768127708, "narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=", @@ -319,6 +356,26 @@ "type": "github" } }, + "nixvim": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_5", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1770025103, + "narHash": "sha256-Qlb19PP0n6s+v1MywVjROV5XwsCvA58XXiXHk0Govb4=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "31c3b3687dc85e3fbbf5c44728a5ee231608f8a9", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixvim", + "type": "github" + } + }, "root": { "inputs": { "agenix": "agenix", @@ -329,13 +386,14 @@ "nix-homebrew": "nix-homebrew", "nixpkgs": "nixpkgs_4", "nixpkgs-stable": "nixpkgs-stable", + "nixvim": "nixvim", "zellij-switch": "zellij-switch", "zen-browser": "zen-browser" } }, "rust-overlay": { "inputs": { - "nixpkgs": "nixpkgs_6" + "nixpkgs": "nixpkgs_7" }, "locked": { "lastModified": 1736476219, @@ -381,11 +439,26 @@ "type": "github" } }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "zellij-switch": { "inputs": { - "nixpkgs": "nixpkgs_5", + "nixpkgs": "nixpkgs_6", "rust-overlay": "rust-overlay", - "systems": "systems_2" + "systems": "systems_3" }, "locked": { "lastModified": 1742588229, @@ -404,7 +477,7 @@ "zen-browser": { "inputs": { "home-manager": "home-manager_3", - "nixpkgs": "nixpkgs_7" + "nixpkgs": "nixpkgs_8" }, "locked": { "lastModified": 1769748063, diff --git a/flake.nix b/flake.nix index 2811422..662fde5 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,6 @@ agenix.url = "github:ryantm/agenix"; nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11"; - home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; @@ -17,6 +16,7 @@ zellij-switch.url = "github:mostafaqanbaryan/zellij-switch"; zen-browser.url = "github:0xc000022070/zen-browser-flake"; firefox-addons.url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons"; + nixvim.url = "github:nix-community/nixvim"; }; outputs = @@ -28,6 +28,7 @@ nix-homebrew, agenix, zellij-switch, + nixvim, ... }@inputs: let diff --git a/home/darwin.nix b/home/darwin.nix index 5cb2d7b..51bc191 100644 --- a/home/darwin.nix +++ b/home/darwin.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ inputs, ... }: { home.username = "dennis"; @@ -13,11 +13,11 @@ xdg.enable = true; imports = [ + inputs.nixvim.homeModules.nixvim ../modules/ssh ../modules/git ../modules/zoxide ../modules/fish - ../modules/nvim ../modules/tmux ../modules/tmuxinator/personal.nix ../modules/ghostty @@ -25,4 +25,5 @@ ]; programs.home-manager.enable = true; + programs.nixvim.imports = [ ../modules/nixvim ]; } diff --git a/modules/base/default.nix b/modules/base/default.nix index a4dcedb..547ef33 100644 --- a/modules/base/default.nix +++ b/modules/base/default.nix @@ -35,7 +35,7 @@ fd sd bat - neovim + vim just tldr fortune @@ -52,5 +52,6 @@ nix-prefetch nix-prefetch-github dua + opencode ]; } diff --git a/modules/fish/default.nix b/modules/fish/default.nix index f03f75f..042f63d 100644 --- a/modules/fish/default.nix +++ b/modules/fish/default.nix @@ -177,6 +177,7 @@ setup_path = /* fish */ '' fish_add_path /run/wrappers/bin fish_add_path /run/current-system/sw/bin + fish_add_path $HOME/.nix-profile/bin if test "$(uname)" = "Darwin" fish_add_path /nix/var/nix/profiles/default/bin diff --git a/modules/nixvim/ai.nix b/modules/nixvim/ai.nix new file mode 100644 index 0000000..90794f9 --- /dev/null +++ b/modules/nixvim/ai.nix @@ -0,0 +1,45 @@ +{ ... }: + +{ + plugins.opencode = { + enable = true; + settings = { + provider.enabled = "tmux"; + }; + }; + + keymaps = [ + { + action.__raw = ''function() require("opencode").ask("@this: ", { submit = true }) end''; + key = "at"; + options.desc = "ask opencode about this"; + } + { + action.__raw = ''function() require("opencode").toggle() end''; + key = "aa"; + options.desc = "toggle opencode"; + } + { + action.__raw = ''function() require("opencode").select() end''; + key = "as"; + options.desc = "select an opencode action"; + } + { + mode = [ + "n" + "x" + ]; + action.__raw = ''function() return require("opencode").operator("@this ") end''; + key = "go"; + options.desc = "add range to opencode"; + } + { + mode = [ + "n" + ]; + action.__raw = ''function() return require("opencode").operator("@this ") .. "_" end''; + key = "go"; + options.desc = "add line to opencode"; + } + ]; +} diff --git a/modules/nixvim/colorscheme.nix b/modules/nixvim/colorscheme.nix new file mode 100644 index 0000000..bdb7a63 --- /dev/null +++ b/modules/nixvim/colorscheme.nix @@ -0,0 +1,13 @@ +{ ... }: + +{ + colorscheme = "winterly"; + + # Make palette available to this module but + # also for other configuration (e.g. lualine) + extraFiles."lua/dnsc/palette.lua".source = ./extraFiles/palette.lua; + + # Set custorscheme in neovims runtimepath so that neovim + # discovers it automatically + extraFiles."colors/winterly.lua".source = ./extraFiles/winterly.lua; +} diff --git a/modules/nixvim/completion.nix b/modules/nixvim/completion.nix new file mode 100644 index 0000000..ef2c362 --- /dev/null +++ b/modules/nixvim/completion.nix @@ -0,0 +1,21 @@ +{ + plugins.blink-cmp = { + enable = true; + settings = { + keymap = { + preset = "default"; + }; + appearance = { + nerd_font_variant = "mono"; + }; + completion = { + documentation = { + auto_show = false; + }; + }; + signature = { + enabled = true; + }; + }; + }; +} diff --git a/modules/nixvim/default.nix b/modules/nixvim/default.nix new file mode 100644 index 0000000..a6b9acd --- /dev/null +++ b/modules/nixvim/default.nix @@ -0,0 +1,26 @@ +{ ... }: + +# These options are imported in nixvim.imports and therefore +# every option here lives within `programs.nixvim` +{ + enable = true; + defaultEditor = true; + + # Setup some aliases + vimAlias = true; + vimdiffAlias = true; + + imports = [ + ./colorscheme.nix + ./completion.nix + ./editing.nix + ./picker.nix + ./formatter.nix + ./git.nix + ./lsp.nix + ./options.nix + ./statusline.nix + ./keybindings.nix + ./ai.nix + ]; +} diff --git a/modules/nixvim/editing.nix b/modules/nixvim/editing.nix new file mode 100644 index 0000000..f9ee3ab --- /dev/null +++ b/modules/nixvim/editing.nix @@ -0,0 +1,65 @@ +{ pkgs, ... }: + +{ + plugins.sleuth.enable = true; + plugins.nvim-surround.enable = true; + plugins.flash.enable = true; + + plugins.blink-pairs = { + enable = true; + }; + + plugins.treesitter = { + enable = true; + highlight.enable = true; + indent.enable = true; + folding.enable = true; + + grammarPackages = with pkgs.vimPlugins.nvim-treesitter.builtGrammars; [ + angular + bash + css + html + javascript + jsdoc + json + lua + make + markdown + markdown_inline + go + gomod + gotmpl + python + tsx + typescript + nix + regex + toml + vim + vimdoc + xml + yaml + ]; + }; + + plugins.substitute = { + enable = true; + luaConfig.post = /* lua */ '' + local sub = require("substitute") + vim.keymap.set("n", "s", sub.operator, { noremap = true }) + vim.keymap.set("n", "ss", sub.line, { noremap = true }) + vim.keymap.set("n", "S", sub.eol, { noremap = true }) + vim.keymap.set("x", "s", sub.visual, { noremap = true }) + ''; + }; + + autoCmd = [ + { + callback.__raw = "function() vim.highlight.on_yank() end"; + event = [ + "TextYankPost" + ]; + } + ]; +} diff --git a/modules/nixvim/extraFiles/palette.lua b/modules/nixvim/extraFiles/palette.lua new file mode 100644 index 0000000..1ab3504 --- /dev/null +++ b/modules/nixvim/extraFiles/palette.lua @@ -0,0 +1,33 @@ +return { + fg = "#ffffff", + fg_alt = "#bf8a9f", + fg_dim = "#807c9f", + bg = "#0f0b15", + bg_secondary = "#1d202f", + grey = "#807c9f", + grey_bright = "#807c9f", + red = "#f47359", + red_bright = "#ff6a7a", + red_subtle_bg = "#67182f", + green = "#29a444", + green_bright = "#00a392", + green_subtle_bg = "#10452f", + yellow = "#b58a52", + yellow_bright = "#df9080", + yellow_brighter = "#FCC1B6", + yellow_subtle_bg = "#54362a", + blue = "#3f95f6", + blue_bright = "#029fff", + blue_subtle_bg = "#2a346e", + blue_subtle_dark_bg = "#003045", + magenta = "#d369af", + magenta_bright = "#af85ea", + magenta_brighter = "#c57faf", + magenta_subtle_bg = "#572454", + magenta_subtle_bg_darker = "#331531", + cyan = "#4fbaef", + cyan_bright = "#35afbf", + cyan_subtle_bg = "#133d56", + silver = "#b8c6d5", + silver_bright = "#ffffff", +} diff --git a/modules/nixvim/extraFiles/winterly.lua b/modules/nixvim/extraFiles/winterly.lua new file mode 100644 index 0000000..d3b6a51 --- /dev/null +++ b/modules/nixvim/extraFiles/winterly.lua @@ -0,0 +1,368 @@ +local palette = require("dnsc.palette") + +vim.cmd.highlight("clear") +vim.g.colors_name = "winterly" + +local hi = function(name, val) + -- Force links + val.force = true + + -- Make sure that `cterm` attribute is not populated from `gui` + val.cterm = val.cterm or {} ---@type vim.api.keyset.highlight + + -- Define global highlight + vim.api.nvim_set_hl(0, name, val) +end + +-- General +hi("Normal", { fg = palette.fg }) + +hi("Conceal", { fg = palette.silver, bg = palette.grey, ctermfg = "LightGrey", ctermbg = "DarkGrey" }) +hi("Cursor", { bg = palette.magenta_bright }) +hi("DiffText", { bg = palette.yellow_subtle_bg, bold = true, ctermbg = "DarkYellow", cterm = { bold = true } }) +hi("ErrorMsg", { fg = palette.red_bright, bg = palette.red_subtle_bg, ctermfg = "White", ctermbg = "DarkRed" }) +hi("IncSearch", { bg = palette.magenta_subtle_bg, fg = palette.magenta }) +hi("ModeMsg", { bold = true, cterm = { bold = true } }) +hi("NonText", { fg = palette.grey, ctermfg = "DarkGrey" }) +hi("PmenuSbar", { bg = palette.grey, ctermbg = "Grey" }) +hi("StatusLine", { reverse = true, bold = true, cterm = { reverse = true, bold = true } }) +hi("StatusLineNC", { reverse = true, cterm = { reverse = true } }) +hi("TabLineFill", { reverse = true, cterm = { reverse = true } }) +hi("TabLineSel", { bold = true, cterm = { bold = true } }) +hi("TermCursor", { reverse = true, cterm = { reverse = true } }) +hi("WinBar", { bold = true, cterm = { bold = true } }) +hi("WildMenu", { fg = palette.bg, bg = palette.yellow_subtle_bg, ctermfg = "Black", ctermbg = "Yellow" }) + +hi("VertSplit", { link = "Comment" }) +hi("WinSeparator", { link = "VertSplit" }) +hi("WinBarNC", { link = "WinBar" }) +hi("DiffTextAdd", { link = "DiffText" }) +hi("EndOfBuffer", { link = "NonText" }) +hi("LineNrAbove", { link = "LineNr" }) +hi("LineNrBelow", { link = "LineNr" }) +hi("QuickFixLine", { link = "Search" }) +hi("CursorLineSign", { link = "SignColumn" }) +hi("CursorLineFold", { link = "FoldColumn" }) +hi("CurSearch", { link = "Search" }) +hi("PmenuKind", { link = "Pmenu" }) +hi("PmenuKindSel", { link = "PmenuSel" }) +hi("PmenuMatch", { link = "Pmenu" }) +hi("PmenuMatchSel", { link = "PmenuSel" }) +hi("PmenuExtra", { link = "Pmenu" }) +hi("PmenuExtraSel", { link = "PmenuSel" }) +hi("PreInsert", { link = "Added" }) +hi("ComplMatchIns", {}) +hi("ComplHint", { link = "NonText" }) +hi("ComplHintMore", { link = "MoreMsg" }) +hi("Whitespace", { link = "NonText" }) +hi("MsgSeparator", { link = "StatusLine" }) +hi("NormalFloat", { link = "Pmenu" }) +hi("FloatBorder", { bg = palette.bg_secondary, fg = palette.fg_dim }) +hi("FloatTitle", { bg = palette.bg_secondary, fg = palette.fg, bold = true }) +hi("FloatFooter", { link = "Title" }) + +hi("FloatShadow", { bg = palette.bg, blend = 80 }) +hi("FloatShadowThrough", { bg = palette.bg, blend = 100 }) +hi("RedrawDebugNormal", { reverse = true, cterm = { reverse = true } }) +hi("RedrawDebugClear", { bg = palette.yellow_subtle_bg, ctermbg = "DarkYellow" }) +hi("RedrawDebugComposed", { bg = palette.green_subtle_bg, ctermbg = "DarkGreen" }) +hi("RedrawDebugRecompose", { bg = palette.red_subtle_bg, ctermbg = "DarkRed" }) +hi("Error", { link = "ErrorMsg" }) +hi("NvimInternalError", { link = "ErrorMsg" }) +hi("Todo", { fg = palette.blue_bright, bg = palette.blue_subtle_bg, ctermbg = "DarkBlue", ctermfg = "LightBlue" }) + +hi("String", { link = "Constant" }) +hi("Character", { link = "Constant" }) +hi("Number", { link = "Boolean" }) +hi("Boolean", { fg = palette.magenta_bright, bold = true }) +hi("Float", { link = "Number" }) +hi("Function", { link = "Identifier" }) +hi("Conditional", { link = "Statement" }) +hi("Repeat", { link = "Statement" }) +hi("Label", { link = "Statement" }) +hi("Operator", { fg = palette.fg_alt, italic = false, ctermfg = "White" }) +hi("Keyword", { link = "Statement" }) +hi("Exception", { link = "Statement" }) +hi("Include", { link = "PreProc" }) +hi("Define", { link = "PreProc" }) +hi("Macro", { link = "PreProc" }) +hi("PreCondit", { link = "PreProc" }) +hi("StorageClass", { link = "Type" }) +hi("Structure", { link = "Type" }) +hi("Typedef", { bold = true, fg = palette.yellow_brighter, ctermfg = "LightYellow" }) +hi("Tag", { link = "Special" }) +hi("SpecialChar", { link = "Special" }) +hi("Delimiter", { link = "Special" }) +hi("SpecialComment", { link = "Special" }) +hi("Debug", { link = "Special" }) + +hi("DiagnosticError", { fg = palette.red_bright, ctermfg = 1 }) +hi("DiagnosticWarn", { fg = palette.yellow, ctermfg = 3 }) +hi("DiagnosticInfo", { fg = palette.cyan, ctermfg = 4 }) +hi("DiagnosticHint", { fg = palette.silver, ctermfg = 7 }) +hi("DiagnosticOk", { fg = palette.green_bright, ctermfg = 10 }) +hi("DiagnosticUnderlineError", { fg = palette.red_bright, undercurl = true, cterm = { underline = true } }) +hi("DiagnosticUnderlineWarn", { fg = palette.yellow, undercurl = true, cterm = { underline = true } }) +hi("DiagnosticUnderlineInfo", { fg = palette.cyan, undercurl = true, cterm = { underline = true } }) +hi("DiagnosticUnderlineHint", { fg = palette.silver, undercurl = true, cterm = { underline = true } }) +hi("DiagnosticUnderlineOk", { fg = palette.green_bright, undercurl = true, cterm = { underline = true } }) +hi("DiagnosticVirtualTextError", { link = "DiagnosticError" }) +hi("DiagnosticVirtualTextWarn", { link = "DiagnosticWarn" }) +hi("DiagnosticVirtualTextInfo", { link = "DiagnosticInfo" }) +hi("DiagnosticVirtualTextHint", { link = "DiagnosticHint" }) +hi("DiagnosticVirtualTextOk", { link = "DiagnosticOk" }) +hi("DiagnosticFloatingError", { link = "DiagnosticError" }) +hi("DiagnosticFloatingWarn", { link = "DiagnosticWarn" }) +hi("DiagnosticFloatingInfo", { link = "DiagnosticInfo" }) +hi("DiagnosticFloatingHint", { link = "DiagnosticHint" }) +hi("DiagnosticFloatingOk", { link = "DiagnosticOk" }) +hi("DiagnosticSignError", { link = "DiagnosticError" }) +hi("DiagnosticSignWarn", { link = "DiagnosticWarn" }) +hi("DiagnosticSignInfo", { link = "DiagnosticInfo" }) +hi("DiagnosticSignHint", { link = "DiagnosticHint" }) +hi("DiagnosticSignOk", { link = "DiagnosticOk" }) +hi("DiagnosticDeprecated", { fg = palette.red, strikethrough = true, cterm = { strikethrough = true } }) + +hi("DiagnosticUnnecessary", { link = "Unused" }) +hi("LspInlayHint", { link = "NonText" }) +hi("SnippetTabstop", { link = "Visual" }) +hi("SnippetTabstopActive", { link = "SnippetTabstop" }) + +-- Text +hi("@markup.raw", { link = "Special" }) +hi("@markup.link", { link = "Identifier" }) +hi("@markup.link.label", { link = "ConstantUnderlined" }) +hi("@markup.heading", { link = "Title" }) +hi("@markup.heading.gitcommit", { bg = palette.bg, fg = palette.fg, bold = true }) +hi("@markup.link.url", { link = "Underlined" }) +hi("@markup.underline", { link = "Underlined" }) +hi("@comment.todo", { link = "Todo" }) + +-- Miscs +hi("@comment", { link = "Comment" }) +hi("@punctuation", { link = "Delimiter" }) + +-- Constants +hi("@constant", { link = "Constant" }) +hi("@constant.builtin", { link = "Special" }) +hi("@constant.macro", { link = "Define" }) +hi("@keyword.directive", { link = "Define" }) +hi("@string", { link = "String" }) +hi("@string.escape", { link = "SpecialChar" }) +hi("@string.special", { link = "SpecialChar" }) +hi("@character", { link = "Character" }) +hi("@character.special", { link = "SpecialChar" }) +hi("@number", { link = "Number" }) +hi("@boolean", { link = "Boolean" }) +hi("@number.float", { link = "Float" }) + +-- Functions +hi("@function", { link = "Function" }) +hi("@function.builtin", { link = "Special" }) +hi("@function.macro", { link = "Macro" }) +hi("@function.method", { link = "Function" }) +hi("@variable.parameter", { link = "Identifier" }) +hi("@variable.parameter.builtin", { link = "Special" }) +hi("@variable.member", { link = "Identifier" }) +hi("@property", { link = "Identifier" }) +hi("@attribute", { link = "Macro" }) +hi("@attribute.builtin", { link = "Special" }) +hi("@constructor", { link = "Special" }) + +-- Keywords +hi("@keyword.conditional", { link = "Conditional" }) +hi("@keyword.repeat", { link = "Repeat" }) +hi("@keyword.type", { link = "Structure" }) +hi("@label", { link = "Label" }) +hi("@operator", { link = "Operator" }) +hi("@keyword", { link = "Keyword" }) +hi("@keyword.exception", { link = "Exception" }) + +hi("@variable", { link = "Identifier" }) +hi("@type", { link = "Type" }) +hi("@type.builtin", { link = "Type" }) +hi("@type.definition", { link = "Typedef" }) +hi("@module", { link = "Identifier" }) +hi("@keyword.import", { link = "Include" }) +hi("@keyword.directive", { link = "PreProc" }) +hi("@keyword.debug", { link = "Debug" }) +hi("@tag", { link = "Tag" }) +hi("@tag.tsx", { link = "Identifier" }) +hi("@tag.builtin", { link = "Special" }) + +-- LSP semantic tokens +hi("@lsp.type.class", { link = "Structure" }) +hi("@lsp.type.comment", { link = "Comment" }) +hi("@lsp.type.decorator", { link = "Function" }) +hi("@lsp.type.enum", { link = "Structure" }) +hi("@lsp.type.enumMember", { link = "Constant" }) +hi("@lsp.type.function", { link = "Function" }) +hi("@lsp.type.interface", { link = "Structure" }) +hi("@lsp.type.macro", { link = "Macro" }) +hi("@lsp.type.method", { link = "Function" }) +hi("@lsp.type.namespace", { link = "Structure" }) +hi("@lsp.type.parameter", { link = "Identifier" }) +hi("@lsp.type.property", { link = "Identifier" }) +hi("@lsp.type.struct", { link = "Structure" }) +hi("@lsp.type.type", { link = "Type" }) +hi("@lsp.type.typeParameter", { link = "TypeDef" }) +hi("@lsp.type.variable", { link = "Identifier" }) +hi("@lsp.typemod.keyword.documentation", { fg = palette.grey, bold = true }) + +if vim.o.background == "light" then +-- TODO: Define light scheme +else + -- Default colors only used with a dark background. + hi("ColorColumn", { bg = palette.red_subtle_bg, ctermbg = "DarkRed" }) + hi("CursorColumn", { bg = palette.grey, ctermbg = "DarkGrey" }) + hi("CursorLine", { bg = palette.magenta_subtle_bg_darker, cterm = { underline = true } }) + hi("CursorLineNr", { + fg = palette.fg, + bg = palette.magenta_subtle_bg_darker, + bold = true, + ctermfg = "White", + cterm = { underline = true }, + }) + hi("DiffAdd", { fg = palette.green_bright, bg = palette.green_subtle_bg, ctermbg = "DarkGreen" }) + hi("DiffChange", { fg = palette.yellow_brighter, bg = palette.yellow_subtle_bg, ctermbg = "DarkYellow" }) + hi("DiffDelete", { fg = palette.red_bright, bg = palette.red_subtle_bg, ctermbg = "DarkRed" }) + hi("Directory", { fg = palette.magenta, bold = true, ctermfg = "Magenta" }) + hi("FoldColumn", { fg = palette.cyan_bright, bg = palette.grey, ctermfg = "Cyan", ctermbg = "DarkGrey" }) + hi("Folded", { fg = palette.cyan_bright, bg = palette.grey, ctermfg = "Cyan", ctermbg = "DarkGrey" }) + hi("LineNr", { fg = palette.grey_bright, ctermfg = "Grey" }) + hi( + "MatchParen", + { fg = palette.fg_alt, bg = palette.magenta_subtle_bg, ctermbg = "DarkMagenta", ctermfg = "Black" } + ) + hi("MoreMsg", { fg = palette.grey, ctermfg = "DarkGrey" }) + hi("Pmenu", { bg = palette.bg_secondary, ctermfg = "White", ctermbg = "Black" }) + hi("PmenuSel", { + bg = palette.magenta_subtle_bg, + fg = palette.fg, + bold = true, + ctermfg = "LightMagenta", + ctermbg = "DarkMagenta", + }) + hi("PmenuThumb", { bg = palette.fg, ctermbg = "White" }) + hi("Question", { fg = palette.green_bright, bold = true, ctermfg = "LightGreen" }) + hi("Search", { link = "IncSearch" }) + hi("Substitute", { + fg = palette.green_bright, + bg = palette.green_subtle_bg, + bold = true, + ctermfg = "DarkBlue", + ctermbg = "LightBlue", + }) + hi("SignColumn", { fg = palette.grey_bright, bg = palette.bg, ctermfg = "Cyan", ctermbg = "DarkGrey" }) + hi("SpecialKey", { fg = palette.cyan_bright, ctermfg = "LightBlue" }) + hi("SpellBad", { fg = palette.red, undercurl = true, ctermbg = "Red" }) + hi("SpellCap", { fg = palette.blue, undercurl = true, ctermbg = "Blue" }) + hi("SpellLocal", { fg = palette.cyan, undercurl = true, ctermbg = "Cyan" }) + hi("SpellRare", { fg = palette.magenta, undercurl = true, ctermbg = "Magenta" }) + hi("StatusLineTerm", { + fg = palette.bg, + bg = palette.green_bright, + bold = true, + ctermfg = "Black", + ctermbg = "LightGreen", + cterm = { bold = true }, + }) + hi("StatusLineTermNC", { fg = palette.bg, bg = palette.green_bright, ctermfg = "Black", ctermbg = "LightGreen" }) + hi( + "TabLine", + { bg = palette.grey, underline = true, ctermfg = "White", ctermbg = "DarkGrey", cterm = { underline = true } } + ) + hi("Title", { fg = palette.magenta_bright, bold = true, ctermfg = "Magenta" }) + hi("Visual", { + fg = palette.magenta_brighter, + bg = palette.magenta_subtle_bg, + ctermfg = "LightMagenta", + ctermbg = "DarkMagenta", + }) + hi("WarningMsg", { fg = palette.red_bright, ctermfg = "LightRed" }) + hi("Comment", { fg = palette.grey, ctermfg = "Cyan" }) + hi("Unused", { fg = palette.grey_bright, undercurl = true, ctermfg = "LightGrey" }) + hi("Constant", { fg = palette.yellow_brighter, ctermfg = "LightYellow" }) + hi("ConstantUnderlined", { fg = palette.yellow_brighter, underline = true, ctermfg = "LightYellow" }) + hi("Special", { fg = palette.silver, ctermfg = "LightGrey" }) + hi("Identifier", { fg = palette.fg, ctermfg = "White", cterm = { bold = true } }) + hi("Statement", { fg = palette.fg_alt, bold = true, ctermfg = "White" }) + hi("PreProc", { fg = palette.magenta, ctermfg = "LightMagenta" }) + hi("Type", { fg = palette.silver, bold = true, ctermfg = "LightCyan" }) + hi("Underlined", { fg = palette.silver, underline = true, ctermfg = "LightGrey", cterm = { underline = true } }) + hi("Ignore", { fg = palette.bg, ctermfg = "Black" }) + hi( + "Added", + { fg = palette.green_bright, bg = palette.green_subtle_bg, ctermfg = "LightGreen", ctermbg = "DarkGreen" } + ) + hi( + "Changed", + { fg = palette.blue_bright, bg = palette.blue_subtle_bg, ctermfg = "LightBlue", ctermbg = "DarkBlue" } + ) + hi("Removed", { fg = palette.red_bright, bg = palette.red_subtle_bg, ctermfg = "LightRed", ctermbg = "DarkRed" }) + hi("NotificationInfo", { fg = palette.silver, bg = palette.bg, ctermfg = "White", ctermbg = "Black" }) + + -- Snacks + hi("SnacksIndentScope", { fg = palette.magenta, ctermfg = "LightGrey" }) + hi("SnacksIndent", { fg = palette.magenta_subtle_bg, ctermfg = "DarkGrey" }) + hi( + "SnacksPickerCursorLine", + { bg = palette.magenta_subtle_bg, fg = palette.fg, bold = true, cterm = { underline = true } } + ) + hi("SnacksPickerListCursorLine", { link = "SnacksPickerCursorLine" }) + hi("SnacksPickerTitle", { link = "FloatTitle" }) + hi("SnacksBackdrop", { link = "Pmenu" }) + + -- Flash + hi("FlashMatch", { reverse = true }) + hi("FlashLabel", { bg = palette.fg, fg = palette.bg }) + + -- FzfLua + hi("FzfLuaNormal", { link = "Pmenu" }) + hi("FzfLuaBorder", { link = "Pmenu" }) + hi("FzfLuaTitle", { link = "Pmenu" }) + hi("FzfLuaBackdrop", { link = "Pmenu" }) + hi("FzfLuaPreviewNormal", { link = "FzfLuaNormal" }) + hi("FzfLuaPreviewBorder", { link = "FzfLuaBorder" }) + hi("FzfLuaPreviewTitle", { link = "FzfLuaTitle" }) + hi( + "FzfLuaCursorLine", + { bg = palette.magenta_subtle_bg, fg = palette.fg, bold = true, cterm = { underline = true } } + ) + hi("FzfLuaTitleFlags", { link = "FzfLuaCursorLine" }) + hi("FzfLuaCursorLineNr", { link = "FzfLuaCursorLine" }) + hi("FzfLuaHeaderBind", { link = "Pmenu" }) + hi("FzfLuaHeaderText", { link = "Comment" }) + hi("FzfLuaPathLineNr", { link = "Pmenu" }) + hi("FzfLuaPathColNr", { link = "Pmenu" }) + hi("FzfLuaLivePrompt", { link = "Pmenu" }) + hi("FzfLuaCmdBuf", { link = "Comment" }) + hi("FzfLuaBufName", { link = "Pmenu" }) + hi("FzfLuaBufId", { link = "Special" }) + hi("FzfLuaBufLineNr", { link = "Special" }) + hi("FzfLuaBufFlagCur", { link = "Pmenu" }) + hi("FzfLuaBufFlagAlt", { link = "Comment" }) + + -- Blinkpairs + hi("BlinkPairsOrange", { link = "Comment" }) + hi("BlinkPairsPurple", { fg = palette.magenta_brighter }) + hi("BlinkPairsBlue", { fg = palette.magenta_bright }) + + -- Neogit + hi("NeogitDiffAdd", { link = "DiffAdd" }) + hi("NeogitDiffDelete", { link = "DiffDelete" }) + hi("NeogitDiffContext", { bg = palette.bg_secondary, fg = palette.fg }) + hi("NeogitDiffContextCursor", { bg = palette.magenta_subtle_bg_darker, fg = palette.magenta_brighter }) + hi("NeogitDiffAddCursor", { bg = palette.green_bright, fg = palette.green_subtle_bg }) + hi("NeogitDiffDeleteCursor", { bg = palette.red_bright, fg = palette.red_subtle_bg }) + hi("NeogitDiffContextHighlight", { link = "NeogitDiffContext" }) + hi("NeogitDiffAddHighlight", { link = "DiffAdd" }) + hi("NeogitDiffDeleteHighlight", { link = "DiffDelete" }) + hi("NeogitHunkHeader", { bg = palette.bg_secondary, fg = palette.grey_bright }) + hi("NeogitHunkMergeHeader", { link = "NeogitHunkHeader" }) + hi("NeogitHunkHeaderHighlight", { bg = palette.magenta_subtle_bg, fg = palette.magenta_brighter }) + hi("NeogitHunkHeaderCursor", { link = "NeogitHunkHeaderHighlight" }) + hi("NeogitCommitViewHeader", { bg = palette.bg_secondary, fg = palette.fg }) + hi("NeogitDiffHeader", { bg = palette.bg, fg = palette.grey_bright, bold = true }) + hi("NeogitActiveItem", { bg = palette.grey_bright, fg = palette.bg, bold = true }) +end diff --git a/modules/nixvim/formatter.nix b/modules/nixvim/formatter.nix new file mode 100644 index 0000000..37e1989 --- /dev/null +++ b/modules/nixvim/formatter.nix @@ -0,0 +1,56 @@ +{ pkgs, ... }: + +{ + plugins.conform-nvim = { + enable = true; + settings = { + formatters_by_ft = { + typescriptreact = { + __unkeyed-1 = "biome-check"; + __unkeyed-2 = "prettierd"; + stop_after_first = true; + }; + astro = [ "prettierd" ]; + typescript = { + __unkeyed-1 = "biome-check"; + __unkeyed-2 = "prettierd"; + stop_after_first = true; + }; + javascript = { + __unkeyed-1 = "biome-check"; + __unkeyed-2 = "prettierd"; + stop_after_first = true; + }; + javascriptreact = { + __unkeyed-1 = "biome-check"; + __unkeyed-2 = "prettierd"; + stop_after_first = true; + }; + html = [ "prettierd" ]; + htmlangular = [ "prettierd" ]; + css = { + __unkeyed-1 = "biome-check"; + __unkeyed-2 = "prettierd"; + stop_after_first = true; + }; + yaml = [ "prettierd" ]; + markdown = [ "prettierd" ]; + json = { + __unkeyed-1 = "biome-check"; + __unkeyed-2 = "prettierd"; + stop_after_first = true; + }; + lua = [ "stylua" ]; + go = [ "goimports" ]; + gomod = [ "goimports" ]; + gowork = [ "goimports" ]; + gotmpl = [ "goimports" ]; + }; + format_on_save = { + timeout_ms = 500; + lsp_format = "fallback"; + }; + }; + extraPackages = [pkgs.stylua]; + }; +} diff --git a/modules/nixvim/git.nix b/modules/nixvim/git.nix new file mode 100644 index 0000000..8efd6ad --- /dev/null +++ b/modules/nixvim/git.nix @@ -0,0 +1,28 @@ +{ + plugins.gitportal = { + enable = true; + }; + + keymaps = [ + { + key = "gll"; + action = "GitPortal"; + options.desc = "Open line in Git provider"; + } + { + key = "gll"; + action = "GitPortal"; + options.desc = "Open line in Git provider"; + } + { + key = "gly"; + action = "GitPortal copy_link_to_clipboard"; + options.desc = "Copy link to line at Git provider"; + } + { + key = "glo"; + action = "GitPortal open_link"; + options.desc = "Open link to line at Git provider"; + } + ]; +} diff --git a/modules/nixvim/keybindings.nix b/modules/nixvim/keybindings.nix new file mode 100644 index 0000000..35489ea --- /dev/null +++ b/modules/nixvim/keybindings.nix @@ -0,0 +1,138 @@ +{ + plugins.which-key.enable = true; + keymaps = [ + # Open + { + mode = [ "n" ]; + key = "od"; + action = "vsplit | lua vim.lsp.buf.definition()"; + options.desc = "Go to definition in other window"; + } + + # Buffer + { + mode = [ "n" ]; + key = "bn"; + action = "bn"; + options.desc = "Move to next buffer"; + } + { + mode = [ "n" ]; + key = "bp"; + action = "bp"; + options.desc = "Move to previous buffer"; + } + { + mode = [ "n" ]; + key = "bk"; + action = "bn"; + options.desc = "Kill buffer and window"; + } + + # File + { + mode = [ "n" ]; + key = "fn"; + action = "enew"; + options.desc = "Create a new file"; + } + { + mode = [ "n" ]; + key = "fs"; + action = "w"; + options.desc = "Save currently opened file"; + } + + # Quit + { + mode = [ "n" ]; + key = "qq"; + action = "qa!"; + options.desc = "Leave neovim"; + } + + # Diagnostics + { + mode = [ "n" ]; + key = "ta"; + action = "TodoQuickFix"; + options.desc = "Show all todo comments"; + } + + # Window + { + mode = [ "n" ]; + key = "w+"; + action = ":vertical resize +4"; + options.desc = "Increase window size"; + } + { + mode = [ "n" ]; + key = "w-"; + action = ":vertical resize -4"; + options.desc = "Decrease window size"; + } + { + mode = [ "n" ]; + key = "wx"; + action = ":bd"; + options.desc = "Kill active window and buffer"; + } + { + mode = [ "n" ]; + key = "wh"; + action = "h"; + options.desc = "Move to window on left"; + } + { + mode = [ "n" ]; + key = "wj"; + action = "j"; + options.desc = "Move to window on bottom"; + } + { + mode = [ "n" ]; + key = "wk"; + action = "k"; + options.desc = "Move to window on top"; + } + { + mode = [ "n" ]; + key = "wl"; + action = "l"; + options.desc = "Move to window on right"; + } + { + mode = [ "n" ]; + key = "ws"; + action = "sp"; + options.desc = "Split windows horizontally"; + } + { + mode = [ "n" ]; + key = "wv"; + action = "vsp"; + options.desc = "Split windows vertically"; + } + { + mode = [ "n" ]; + key = "wd"; + action = "close"; + options.desc = "Delete window only"; + } + + # Config + { + mode = [ "n" ]; + key = "xn"; + action = "set number relativenumber"; + options.desc = "Show relative numbers"; + } + { + mode = [ "n" ]; + key = "xr"; + action = "source $MYVIMRC"; + options.desc = "Reload config"; + } + ]; +} diff --git a/modules/nixvim/lsp.nix b/modules/nixvim/lsp.nix new file mode 100644 index 0000000..26f73fe --- /dev/null +++ b/modules/nixvim/lsp.nix @@ -0,0 +1,67 @@ +{ pkgs, ... }: + +{ + plugins.lspconfig.enable = true; + + lsp = { + enable = true; + + servers = { + lua_ls = { + enable = true; + package = pkgs.lua-language-server; + packageFallback = true; + }; + nil_ls = { + enable = true; + package = pkgs.nil; + packageFallback = true; + }; + ts_ls = { + enable = true; + package = pkgs.typescript-language-server; + packageFallback = true; + }; + jsonls = { + enable = true; + package = pkgs.vscode-langservers-extracted; + packageFallback = true; + }; + astro = { + enable = true; + package = pkgs.astro-language-server; + packageFallback = true; + }; + eslint = { + enable = true; + package = pkgs.vscode-langservers-extracted; + packageFallback = true; + }; + biome = { + enable = true; + package = pkgs.biome; + packageFallback = true; + }; + }; + + keymaps = [ + { + key = "ca"; + lspBufAction = "code_action"; + } + { + key = "e"; + action = "lua vim.diagnostic.open_float()"; + } + ]; + }; + + # Define diagnostic appearance + diagnostic.settings = { + virtual_text = false; + signs = true; + underline = true; + update_in_insert = false; + severity_sort = false; + }; +} diff --git a/modules/nixvim/options.nix b/modules/nixvim/options.nix new file mode 100644 index 0000000..4e16fc3 --- /dev/null +++ b/modules/nixvim/options.nix @@ -0,0 +1,47 @@ +{ + globals = { + mapleader = " "; + maplocalleader = " "; + }; + + clipboard.register = "unnamedplus"; + + opts = { + backup = false; + cmdheight = 1; + conceallevel = 0; + fileencoding = "utf-8"; + hlsearch = true; + ignorecase = true; + mouse = "a"; + pumheight = 10; + showmode = false; + smartindent = true; + breakindent = true; + showtabline = 0; + smartcase = true; + splitbelow = true; + splitright = true; + swapfile = false; + termguicolors = true; + timeoutlen = 600; + undofile = true; + updatetime = 230; + writebackup = false; + expandtab = true; + shiftwidth = 2; + tabstop = 2; + cursorline = true; + number = true; + relativenumber = true; + numberwidth = 2; + signcolumn = "yes"; + linebreak = true; + breakat = " ^I!@*-+;:,./?"; + scrolloff = 4; + sidescrolloff = 4; + winbar = ""; + foldlevel = 99; + foldlevelstart = 99; + }; +} diff --git a/modules/nixvim/picker.nix b/modules/nixvim/picker.nix new file mode 100644 index 0000000..0c254d5 --- /dev/null +++ b/modules/nixvim/picker.nix @@ -0,0 +1,171 @@ +{ pkgs, ... }: + +{ + plugins.oil = { + enable = true; + settings = { + keymaps = { + "q" = "actions.close"; + }; + columns = [ + "icon" + "permissions" + "size" + "mtime" + ]; + }; + }; + + extraPlugins = [ pkgs.vimPlugins.snacks-nvim ]; + extraConfigLua = /* lua */ '' + local Snacks = require("snacks"); + local filter_lsp_definitions = function(item) + if item.file:match("/react/ts5.0/") or item.file:match("react.d.ts") then + return false + end + return true + end + + Snacks.setup({ + bigfile = { enabled = true }, + bufdelete = { enabled = true }, + git = { enabled = true }, + indent = { enabled = true }, + input = { enabled = true }, + notifier = { enabled = true }, + picker = { + enabled = true, + prompt = "λ ", + layout = { preset = "ivy" }, + }, + statuscolumn = { enabled = true }, + }) + ''; + + keymaps = [ + # Git + { + key = "gb"; + action.__raw = "function() Snacks.git.blame_line() end"; + options.desc = "Show git blame for current line"; + } + # Picker + { + key = "."; + action.__raw = "function() Snacks.picker.files({ hidden = true }) end"; + options.desc = "Files"; + } + { + key = ""; + action.__raw = "function() Snacks.picker.git_files() end"; + options.desc = "Git files"; + } + # Find + { + key = "fr"; + action.__raw = "function() Snacks.picker.recent() end"; + options.desc = "Recent"; + } + { + key = "fp"; + action.__raw = "function() Snacks.picker.projects() end"; + options.desc = "Projects"; + } + { + key = "bb"; + action.__raw = "function() Snacks.picker.buffers() end"; + options.desc = "List buffers"; + } + { + key = "bd"; + action.__raw = "function() Snacks.bufdelete() end"; + options.desc = "Delete buffer"; + } + { + key = "bD"; + action.__raw = "function() Snacks.bufdelete.all() end"; + options.desc = "Delete all buffers"; + } + { + key = "bo"; + action.__raw = "function() Snacks.bufdelete.other() end"; + options.desc = "Delete other buffers"; + } + # Search + { + key = "ss"; + action.__raw = "function() Snacks.picker.grep() end"; + options.desc = "Grep"; + } + { + mode = [ + "n" + "x" + ]; + key = "sw"; + action.__raw = "function() Snacks.picker.grep_word() end"; + options.desc = "Visual selection or word"; + } + { + key = "su"; + action.__raw = "function() Snacks.picker.undo() end"; + options.desc = "Undo History"; + } + # Diagnostics + { + key = "td"; + action.__raw = "function() Snacks.picker.diagnostics_buffer() end"; + options.desc = "Buffer Diagnostics"; + } + { + key = "ta"; + action.__raw = "function() Snacks.picker.diagnostics() end"; + options.desc = "Diagnostics"; + } + # LSP + { + key = "gd"; + action.__raw = "function() Snacks.picker.lsp_definitions({ filter = { filter = filter_lsp_definitions } }) end"; + options.desc = "Goto Definition"; + } + { + key = "gD"; + action.__raw = "function() Snacks.picker.lsp_declarations() end"; + options.desc = "Goto Declaration"; + } + { + key = "grr"; + action.__raw = "function() Snacks.picker.lsp_references() end"; + options = { + desc = "References"; + nowait = true; + }; + } + { + key = "gI"; + action.__raw = "function() Snacks.picker.lsp_implementations() end"; + options.desc = "Goto Implementation"; + } + { + key = "gy"; + action.__raw = "function() Snacks.picker.lsp_type_definitions() end"; + options.desc = "Goto T[y]pe Definition"; + } + # Notifications and highlights + { + key = "on"; + action.__raw = "function() Snacks.notifier.show_history() end"; + options.desc = "Open notification history"; + } + { + key = "oh"; + action.__raw = "function() Snacks.picker.highlights() end"; + options.desc = "List highlights"; + } + { + key = "n"; + action = "Oil"; + options.desc = "Opens file explorer"; + } + ]; +} diff --git a/modules/nixvim/statusline.nix b/modules/nixvim/statusline.nix new file mode 100644 index 0000000..b430787 --- /dev/null +++ b/modules/nixvim/statusline.nix @@ -0,0 +1,97 @@ +{ + plugins.lualine = { + enable = true; + + settings = { + options = { + theme = { + __raw = "winterly_lualine"; + }; + icons_enabled = false; + component_separators = { + left = "|"; + right = "|"; + }; + section_separators = { + left = ""; + right = ""; + }; + }; + sections = { + lualine_a = [ + { + __unkeyed-1 = "mode"; + fmt = { + __raw = "function(str) return str:sub(1, 1) end"; + }; + } + ]; + }; + lualine_b = [ + { + __unkeyed-1 = "filename"; + file_status = true; + newfile_status = false; + path = 1; + shorting_target = 120; + symbols = { + modified = "[+]"; + readonly = "[-]"; + unnamed = "[No Name]"; + newfile = "[New]"; + }; + } + "encoding" + ]; + lualine_c = [ ]; + lualine_x = [ ]; + lualine_y = [ + "branch" + "diff" + "diagnostics" + ]; + lualine_z = [ + "location" + "progress" + ]; + }; + + # Sets up my custom colorscheme + luaConfig.pre = /* lua */ '' + local palette = require("dnsc.palette") + + local winterly_lualine = { + normal = { + a = { bg = palette.magenta, fg = palette.bg, gui = "bold" }, + b = { bg = palette.bg_secondary, fg = palette.magenta }, + c = { bg = palette.bg_secondary, fg = palette.magenta }, + }, + insert = { + a = { bg = palette.cyan_bright, fg = palette.bg, gui = "bold" }, + b = { bg = palette.bg_secondary, fg = palette.cyan_bright }, + c = { bg = palette.bg_secondary, fg = palette.cyan_bright }, + }, + visual = { + a = { bg = palette.blue_bright, fg = palette.bg, gui = "bold" }, + b = { bg = palette.bg_secondary, fg = palette.blue_bright }, + c = { bg = palette.bg_secondary, fg = palette.blue_bright }, + }, + replace = { + a = { bg = palette.red_bright, fg = palette.bg, gui = "bold" }, + b = { bg = palette.bg_secondary, fg = palette.red_bright }, + c = { bg = palette.bg_secondary, fg = palette.red_bright }, + }, + command = { + a = { bg = palette.green_bright, fg = palette.bg, gui = "bold" }, + b = { bg = palette.bg_secondary, fg = palette.green_bright }, + c = { bg = palette.bg_secondary, fg = palette.green_bright }, + }, + inactive = { + a = { bg = palette.bg_secondary, fg = palette.fg_dim }, + b = { bg = palette.bg_secondary, fg = palette.fg_dim }, + c = { bg = palette.bg_secondary, fg = palette.fg_dim }, + }, + } + ''; + }; +} diff --git a/modules/tmux/default.nix b/modules/tmux/default.nix index 292e383..c175083 100644 --- a/modules/tmux/default.nix +++ b/modules/tmux/default.nix @@ -66,6 +66,9 @@ unbind s bind s display-popup -h 50% -w 80% -E sessionizer + unbind g + bind g display-popup -h 90% -w 95% -E lazygit + unbind C-x bind C-x kill-session