From 5c5c106495d02854956d020b3ab1e2d432c41580 Mon Sep 17 00:00:00 2001 From: Lander Van den Bulcke Date: Fri, 10 Oct 2025 14:02:21 +0200 Subject: [PATCH] wip Signed-off-by: Lander Van den Bulcke --- flake.lock | 125 ++++++++----- flake.nix | 76 ++------ modules/flake/default.nix | 23 +++ modules/flake/devshell.nix | 32 ++++ overlays/default.nix | 12 ++ packages/default.nix | 37 ++++ plugins/blink-cmp.nix | 69 +++++++ plugins/buffer.nix | 86 +++++++++ plugins/common/colorscheme.nix | 43 +++++ plugins/common/default.nix | 149 +++++++++++++++ plugins/common/functions.nix | 40 ++++ plugins/common/icons.nix | 185 +++++++++++++++++++ plugins/common/mappings.nix | 309 +++++++++++++++++++++++++++++++ plugins/common/options.nix | 46 +++++ plugins/common/plugins.nix | 52 ++++++ plugins/default.nix | 33 ++++ plugins/git.nix | 150 +++++++++++++++ plugins/lang/default.nix | 9 + plugins/lang/nix.nix | 13 ++ plugins/lsp/conform.nix | 21 +++ plugins/lsp/default.nix | 108 +++++++++++ plugins/lsp/mappings.nix | 120 ++++++++++++ plugins/lualine/default.nix | 54 ++++++ plugins/lualine/sections.nix | 150 +++++++++++++++ plugins/noice.nix | 63 +++++++ plugins/snacks/default.nix | 323 +++++++++++++++++++++++++++++++++ plugins/snacks/mappings.nix | 126 +++++++++++++ plugins/treesitter.nix | 36 ++++ plugins/ux.nix | 64 +++++++ 29 files changed, 2445 insertions(+), 109 deletions(-) create mode 100644 modules/flake/default.nix create mode 100644 modules/flake/devshell.nix create mode 100644 overlays/default.nix create mode 100644 packages/default.nix create mode 100644 plugins/blink-cmp.nix create mode 100644 plugins/buffer.nix create mode 100644 plugins/common/colorscheme.nix create mode 100644 plugins/common/default.nix create mode 100644 plugins/common/functions.nix create mode 100644 plugins/common/icons.nix create mode 100644 plugins/common/mappings.nix create mode 100644 plugins/common/options.nix create mode 100644 plugins/common/plugins.nix create mode 100644 plugins/default.nix create mode 100644 plugins/git.nix create mode 100644 plugins/lang/default.nix create mode 100644 plugins/lang/nix.nix create mode 100644 plugins/lsp/conform.nix create mode 100644 plugins/lsp/default.nix create mode 100644 plugins/lsp/mappings.nix create mode 100644 plugins/lualine/default.nix create mode 100644 plugins/lualine/sections.nix create mode 100644 plugins/noice.nix create mode 100644 plugins/snacks/default.nix create mode 100644 plugins/snacks/mappings.nix create mode 100644 plugins/treesitter.nix create mode 100644 plugins/ux.nix diff --git a/flake.lock b/flake.lock index 34e516e..477dce5 100644 --- a/flake.lock +++ b/flake.lock @@ -73,10 +73,30 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1759523803, + "narHash": "sha256-PTod9NG+i3XbbnBKMl/e5uHDBYpwIWivQ3gOWSEuIEM=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "cfc9f7bb163ad8542029d303e599c0f7eee09835", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ - "pre-commit-hooks", + "git-hooks", "nixpkgs" ] }, @@ -124,16 +144,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1759036355, - "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", - "owner": "nixos", + "lastModified": 1759070547, + "narHash": "sha256-JVZl8NaVRYb0+381nl7LvPE+A774/dRpif01FKLrYFQ=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "rev": "647e5c14cbd5067f44ac86b74f014962df460840", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", + "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } @@ -153,7 +173,39 @@ "type": "github" } }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1759735786, + "narHash": "sha256-a0+h02lyP2KwSNrZz4wLJTu9ikujNsTWIC874Bv7IJ0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "20c4598c84a671783f741e02bf05cbfaf4907cff", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_2": { + "locked": { + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1758763312, "narHash": "sha256-puBMviZhYlqOdUUgEmMVJpXqC/ToEqSvkyZ30qQ09xM=", @@ -169,26 +221,10 @@ "type": "github" } }, - "nixpkgs_3": { - "locked": { - "lastModified": 1758029226, - "narHash": "sha256-TjqVmbpoCqWywY9xIZLTf6ANFvDCXdctCjoYuYPYdMI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "08b8f92ac6354983f5382124fef6006cade4a1c1", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "nixvim": { "inputs": { "flake-parts": "flake-parts_2", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs_3", "nuschtosSearch": "nuschtosSearch", "systems": "systems_2" }, @@ -229,32 +265,14 @@ "type": "github" } }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": "nixpkgs_3" - }, - "locked": { - "lastModified": 1758108966, - "narHash": "sha256-ytw7ROXaWZ7OfwHrQ9xvjpUWeGVm86pwnEd1QhzawIo=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "54df955a695a84cd47d4a43e08e1feaf90b1fd9b", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs", + "git-hooks": "git-hooks", + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable", "nixvim": "nixvim", - "pre-commit-hooks": "pre-commit-hooks" + "systems": "systems_3" } }, "systems": { @@ -286,6 +304,21 @@ "repo": "default", "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" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 7d22bdf..2eaa92d 100644 --- a/flake.nix +++ b/flake.nix @@ -1,75 +1,25 @@ { - description = "deCort.tech NeoVim configuration"; + description = "EscapeAngle NeoVim configuration"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.05"; flake-parts.url = "github:hercules-ci/flake-parts"; - nixvim = { - url = "github:nix-community/nixvim"; - }; - pre-commit-hooks = { - url = "github:cachix/pre-commit-hooks.nix"; - }; + nixvim.url = "github:nix-community/nixvim"; + systems.url = "github:nix-systems/default"; + git-hooks.url = "github:cachix/git-hooks.nix"; + git-hooks.flake = false; }; outputs = - { - nixpkgs, - nixvim, - flake-parts, - pre-commit-hooks, - ... - }@inputs: + inputs@{ flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } { - systems = [ - "aarch64-linux" - "x86_64-linux" - "aarch64-darwin" - "x86_64-darwin" + systems = import inputs.systems; + _module.args = { inherit inputs; }; + imports = [ + ./modules/flake + ./overlays + ./plugins ]; - - perSystem = - { - pkgs, - system, - self', - lib, - ... - }: - let - nixvimLib = nixvim.lib.${system}; - nixvim' = nixvim.legacyPackages.${system}; - nixvimModule = { - inherit pkgs; - module = import ./config; # import the module directly - # You can use `extraSpecialArgs` to pass additional arguments to your module files - extraSpecialArgs = { - # inherit (inputs) foo; - }; - }; - nvim = nixvim'.makeNixvimWithModule nixvimModule; - in - { - checks = { - default = nixvimLib.check.mkTestDerivationFromNixvimModule nixvimModule; - pre-commit-check = pre-commit-hooks.lib.${system}.run { - src = ./.; - hooks = { - statix.enable = true; - nixfmt-rfc-style.enable = true; - }; - }; - }; - - formatter = pkgs.nixfmt-rfc-style; - - packages = { - default = nvim; - }; - - devShells = { - default = with pkgs; mkShell { inherit (self'.checks.pre-commit-check) shellHook; }; - }; - }; }; } diff --git a/modules/flake/default.nix b/modules/flake/default.nix new file mode 100644 index 0000000..1b0281e --- /dev/null +++ b/modules/flake/default.nix @@ -0,0 +1,23 @@ +{ inputs, self, ... }: +{ + debug = true; + + imports = [ ./devshell.nix ]; + + perSystem = + { lib, system, ... }: + { + _module.args = { + flake = { inherit inputs self; }; + pkgs = import inputs.nixpkgs { + inherit system; + overlays = lib.attrValues self.overlays; + config.allowUnfree = true; + }; + }; + + imports = [ + (self + /packages) + ]; + }; +} diff --git a/modules/flake/devshell.nix b/modules/flake/devshell.nix new file mode 100644 index 0000000..4d3ac96 --- /dev/null +++ b/modules/flake/devshell.nix @@ -0,0 +1,32 @@ +{ inputs, ... }: +{ + imports = [ + (inputs.git-hooks + /flake-module.nix) + ]; + + perSystem = + { config, pkgs, ... }: + { + devShells.default = pkgs.mkShell rec { + name = "nixvim"; + meta.description = "Dev environment for nixvim configuration"; + + inputsFrom = [ config.pre-commit.devShell ]; + + packages = with pkgs; [ + nil + nix-output-monitor + nixfmt-rfc-style + ]; + + shellHook = '' + echo 1>&2 "🐼: $(id -un) | 🧬: $(nix eval --raw --impure --expr 'builtins.currentSystem') | 🐧: $(uname -r) " + echo 1>&2 "Ready to work on ${name}!" + ''; + }; + + pre-commit.settings = { + hooks.nixfmt-rfc-style.enable = true; + }; + }; +} diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..85bef0c --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,12 @@ +{ inputs, self, ... }: +{ + flake.overlays.default = ( + final: prev: { + stable = import inputs.nixpkgs-stable { + allowUnfree = true; + inherit (prev) system; + overlays = prev.lib.attrValues self.overlays; + }; + } + ); +} diff --git a/packages/default.nix b/packages/default.nix new file mode 100644 index 0000000..880852d --- /dev/null +++ b/packages/default.nix @@ -0,0 +1,37 @@ +{ + flake, + inputs', + self', + ... +}: +let + mkNixVim = + module: + inputs'.nixvim.legacyPackages.makeNixvimWithModule { + extraSpecialArgs = { inherit inputs self; }; + inherit module; + }; + inherit (flake) inputs self; + bareModules = [ + self.myvimPlugins.common + self.myvimPlugins.buffer + self.myvimPlugins.snacks + self.myvimPlugins.ux + ]; + coreModules = bareModules ++ [ + self.myvimPlugins.blink-cmp + self.myvimPlugins.git + self.myvimPlugins.lang + self.myvimPlugins.lsp + self.myvimPlugins.lualine + self.myvimPlugins.noice + self.myvimPlugins.treesitter + ]; +in +{ + packages = { + default = self'.packages.core; + bare = mkNixVim bareModules; + core = mkNixVim coreModules; + }; +} diff --git a/plugins/blink-cmp.nix b/plugins/blink-cmp.nix new file mode 100644 index 0000000..f5d431d --- /dev/null +++ b/plugins/blink-cmp.nix @@ -0,0 +1,69 @@ +{ lib, ... }: +let + inherit (lib.nixvim) mkRaw; +in +{ + plugins = { + blink-cmp = { + enable = true; + + settings = { + completion.menu.border = "rounded"; + + keymap = { + "" = [ + "select_next" + "fallback" + ]; + "" = [ + "select_prev" + "fallback" + ]; + + "" = [ + "snippet_forward" + "fallback" + ]; + "" = [ + "snippet_backward" + "fallback" + ]; + "" = [ + "scroll_documentation_up" + "fallback" + ]; + "" = [ + "scroll_documentation_down" + "fallback" + ]; + "" = [ + ( + # lua + mkRaw '' + function(cmp) + local ok,_ = pcall(require, "copilot") + if ok then + vim.g.copilot_no_tab_map = true + vim.g.copilot_assume_mapped = true + vim.g.copilot_tab_fallback = "" + + local suggestion = require("copilot.suggestion") + if suggestion.is_visible() then + suggestion.accept() + else + if cmp.snippet_active() then + return cmp.select_and_accept() + else + return cmp.accept() + end + end + end + end + '' + ) + ]; + }; + }; + }; + }; +} diff --git a/plugins/buffer.nix b/plugins/buffer.nix new file mode 100644 index 0000000..fc20baa --- /dev/null +++ b/plugins/buffer.nix @@ -0,0 +1,86 @@ +{ config, lib, ... }: +let + inherit (config.myvim.mkKey) mkKeymap wKeyObj; + inherit (lib.nixvim) mkRaw; +in +{ + plugins = { + bufferline = { + enable = true; + settings.options = rec { + diagnostics = "nvim_lsp"; + buffer_close_icon = "󰅙"; + close_icon = buffer_close_icon; + always_show_bufferline = true; + hover = { + enabled = true; + delay = 200; + reveal = [ "close" ]; + }; + }; + }; + + harpoon.enable = true; + }; + + wKeyList = [ + (wKeyObj [ + "b" + "" + "buffers" + ]) + (wKeyObj [ + "" + "" + "tabs" + ]) + ]; + + keymaps = [ + (mkKeymap "n" "b." ( + # lua + mkRaw '' + function() + harpoon = require("harpoon") + harpoon:list():add() + end + '' + ) "Add File to Harpoon") + (mkKeymap "n" "bb" ( + # lua + mkRaw '' + function() + harpoon = require("harpoon") + harpoon.ui:toggle_quick_menu(harpoon:list()) + end + '' + ) "Harpoon ui") + + (mkKeymap "n" "bp" ":BufferLinePick" "Buffer Line Pick") + (mkKeymap "n" "qc" ":bp | bd #" "Buffer close") + + (mkKeymap "n" "bP" "BufferLineTogglePin" "Buffer Pin") + (mkKeymap "n" "bd" "BufferLineSortByDirectory" "Buffer Sort by dir") + (mkKeymap "n" "be" "BufferLineSortByExtension" "Buffer Sort by ext") + (mkKeymap "n" "bt" "BufferLineSortByTabs" "Buffer Sort by Tabs") + (mkKeymap "n" "bL" "BufferLineCloseRight" "Buffer close all to right") + (mkKeymap "n" "bH" "BufferLineCloseLeft" "Buffer close all to left") + (mkKeymap "n" "bc" "BufferLineCloseOther" + "Buffer close all except the current buffer" + ) + (mkKeymap "n" "" "BufferLineMovePrev" "Move buffer to left") + (mkKeymap "n" "" "BufferLineMoveNext" "Move buffer to right") + + (mkKeymap "n" "" ":BufferLineCyclePrev" "Buffer Previous") + (mkKeymap "n" "" ":BufferLineCycleNext" "Buffer Next") + + (mkKeymap "n" "j" "tabn" "Next Tab") + (mkKeymap "n" "k" "tabp" "Previous Tab") + (mkKeymap "n" "l" "tabn" "Next Tab") + (mkKeymap "n" "h" "tabp" "Previous Tab") + + (mkKeymap "n" "qt" "tabclose" "Close Tab") + (mkKeymap "n" "q" "tabclose" "Close Tab") + (mkKeymap "n" "n" "tabnew" "New Tab") + ]; +} diff --git a/plugins/common/colorscheme.nix b/plugins/common/colorscheme.nix new file mode 100644 index 0000000..ce575b9 --- /dev/null +++ b/plugins/common/colorscheme.nix @@ -0,0 +1,43 @@ +{ config, ... }: +{ + colorschemes = { + catppuccin = { + enable = false; + settings = { + integrations.native_lsp = { + enabled = true; + underlines = { + errors = [ "undercurl" ]; + hints = [ "undercurl" ]; + warnings = [ "undercurl" ]; + information = [ "undercurl" ]; + }; + }; + flavor = "mocha"; + italic = true; + bold = true; + dimInactive = false; + transparent_background = true; + }; + }; + }; + + colorschemes.tokyonight = { + enable = true; + settings = { + style = "night"; + transparent = config.myvim.transparent; + styles = { + floats = if config.myvim.transparent then "transparent" else "dark"; + sidebars = if config.myvim.transparent then "transparent" else "dark"; + comments.italic = true; + functions.italic = true; + variables.italic = true; + keyword = { + italic = true; + bold = true; + }; + }; + }; + }; +} diff --git a/plugins/common/default.nix b/plugins/common/default.nix new file mode 100644 index 0000000..1dd6af9 --- /dev/null +++ b/plugins/common/default.nix @@ -0,0 +1,149 @@ +{ config, lib, ... }: +let + inherit (config.myvim) icons; + inherit (lib.nixvim) mkRaw; +in +{ + imports = + with builtins; + with lib; + map (fn: ./${fn}) ( + filter (fn: (fn != "default.nix" && hasSuffix ".nix" "${fn}")) (attrNames (readDir ./.)) + ); + + luaLoader.enable = false; + + extraConfigLua = + with icons.diagnostics; + # lua + '' + local function my_paste(reg) + return function(lines) + local content = vim.fn.getreg('"') + return vim.split(content, '\n') + end + end + if (os.getenv('SSH_TTY') ~= nil) + then + vim.g.clipboard = { + name = 'OSC 52', + copy = { + ['+'] = require('vim.ui.clipboard.osc52').copy('+'), + ['*'] = require('vim.ui.clipboard.osc52').copy('*'), + }, + paste = { + ["+"] = my_paste("+"), + ["*"] = my_paste("*"), + }, + } + end + + + + vim.opt.whichwrap:append("<>[]hl") + vim.opt.listchars:append("space:·") + + -- below part set's the Diagnostic icons/colors + local signs = { + Hint = "${BoldHint}", + Info = "${BoldInformation}", + Warn = "${BoldWarning}", + Error = "${BoldError}", + } + + for type, icon in pairs(signs) do + local hl = "DiagnosticSign" .. type + vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl }) + end + ''; + + globals = { + mapleader = config.myvim.leader; + floating_window_options.border = config.myvim.border; + }; + + opts = { + clipboard = "unnamedplus"; + cursorline = true; + cursorlineopt = "number"; + + pumblend = 0; + pumheight = 10; + + expandtab = true; + shiftwidth = 2; + smartindent = true; + tabstop = 2; + softtabstop = 2; + + ignorecase = true; + smartcase = true; + mouse = "a"; + cmdheight = 0; + + number = true; + relativenumber = true; + numberwidth = 2; + ruler = false; + + signcolumn = "yes"; + splitbelow = true; + splitright = true; + splitkeep = "screen"; + termguicolors = true; + + conceallevel = 2; + + undofile = true; + + wrap = false; + + virtualedit = "block"; + winminwidth = 5; + fileencoding = "utf-8"; + list = true; + smoothscroll = true; + autoread = true; + autowrite = true; + swapfile = false; + fillchars = { + eob = " "; + }; + + updatetime = 500; + }; + + autoCmd = [ + { + desc = "Highlight on yank"; + event = [ "TextYankPost" ]; + callback = + # lua + mkRaw '' + function() + vim.highlight.on_yank() + end + ''; + } + { + desc = "Check file changes"; + event = [ + "FocusGained" + "BufEnter" + "CursorHold" + ]; + pattern = [ "*" ]; + callback = + # lua + mkRaw '' + function() + if vim.fn.mode() ~= "c" then + vim.cmd("checktime") + end + end + ''; + } + ]; + + extraLuaPackages = lp: with lp; [ luarocks ]; +} diff --git a/plugins/common/functions.nix b/plugins/common/functions.nix new file mode 100644 index 0000000..42cdea6 --- /dev/null +++ b/plugins/common/functions.nix @@ -0,0 +1,40 @@ +{ lib, ... }: +{ + myvim.mkKey = rec { + # set of functions that returns attrs for keymap list + mkKeymap = mode: key: action: desc: { + inherit mode key action; + + options = { + inherit desc; + silent = true; + noremap = true; + remap = true; + }; + }; + + # use when no description is to be passed + mkKeymap' = + mode: key: action: + mkKeymap mode key action null; + + mkKeymapWithOpts = + mode: key: action: desc: opts: + (mkKeymap mode key action desc) // { options = opts; }; + + # for which-key icon generation + # accepts a list of strings and returns a list of objects + # [{ __unkeyed, icon, group, hidden }] + wKeyObj = + with builtins; + list: + { + __unkeyed = elemAt list 0; + icon = elemAt list 1; + group = elemAt list 2; + } + // lib.optionalAttrs (length list > 3) { + hidden = elemAt list 3; + }; + }; +} diff --git a/plugins/common/icons.nix b/plugins/common/icons.nix new file mode 100644 index 0000000..ad997ee --- /dev/null +++ b/plugins/common/icons.nix @@ -0,0 +1,185 @@ +{ + config.myvim.icons = { + kind = { + Array = ""; + Boolean = ""; + Class = ""; + Color = ""; + Constant = ""; + Constructor = ""; + Enum = ""; + EnumMember = ""; + Event = ""; + Field = ""; + File = ""; + Folder = ""; + Function = ""; + Interface = ""; + Key = ""; + Keyword = ""; + Method = ""; + Module = ""; + Namespace = ""; + Null = "ﳠ"; + Number = ""; + Object = ""; + Operator = ""; + Package = ""; + Property = ""; + Reference = ""; + Snippet = ""; + String = ""; + Struct = ""; + Text = ""; + TypeParameter = ""; + Unit = ""; + Value = ""; + Variable = ""; + Copilot = ""; + TabNine = "⌬"; + }; + git = { + LineAdded = ""; + LineModified = ""; + LineRemoved = ""; + FileDeleted = ""; + FileIgnored = "󰫙"; + FileRenamed = ""; + FileStaged = "✓"; + FileUnmerged = ""; + FileMerged = ""; + FileUnstaged = ""; + FileUntracked = "◌"; + FileChanged = "󰉺"; + Copied = "󰆏"; + Ignored = ""; + Diff = ""; + Repo = ""; + Octoface = ""; + Branch = ""; + }; + ui = { + lazy = { + ft = ""; + lazy = "󰂠 "; + loaded = ""; + not_loaded = ""; + }; + ArrowCircleDown = ""; + ArrowCircleLeft = ""; + ArrowCircleRight = ""; + ArrowCircleUp = ""; + BoldArrowDown = ""; + BoldArrowLeft = ""; + BoldArrowRight = ""; + BoldArrowUp = ""; + BoldClose = ""; + BoldDividerLeft = ""; + BoldDividerRight = ""; + BoldLineLeft = "▎"; + BookMark = ""; + BoxChecked = ""; + Bug = ""; + Stacks = ""; + Scopes = ""; + Watches = ""; + DebugConsole = ""; + Calendar = ""; + Check = ""; + ChevronRight = ">"; + ChevronShortDown = ""; + ChevronShortLeft = ""; + ChevronShortRight = ""; + ChevronShortUp = ""; + Circle = ""; + Close = ""; + CloudDownload = ""; + Code = ""; + Comment = ""; + Dashboard = ""; + DividerLeft = ""; + DividerRight = ""; + DoubleChevronRight = "»"; + Ellipsis = ""; + EmptyFolder = ""; + EmptyFolderOpen = ""; + ExitCircle = "󰿅"; + File = ""; + FileSymlink = ""; + Files = ""; + FileRename = ""; + FindFile = "󰈞"; + FindText = ""; + Fire = ""; + Folder = ""; + FolderOpen = ""; + FolderSymlink = ""; + Forward = ""; + Gear = ""; + History = ""; + Lightbulb = ""; + LineLeft = "▏"; + LineMiddle = "│"; + List = ""; + Lock = ""; + NewFile = ""; + Note = ""; + Package = ""; + Pencil = "󰏫"; + Plus = ""; + Project = ""; + Search = ""; + SignIn = ""; + SignOut = ""; + Tab = ""; + Table = ""; + Target = "󰀘"; + Telescope = ""; + Text = ""; + Tree = ""; + Triangle = "󰐊"; + TriangleShortArrowDown = ""; + TriangleShortArrowLeft = ""; + TriangleShortArrowRight = ""; + TriangleShortArrowUp = ""; + }; + diagnostics = { + BoldError = ""; + Error = ""; + BoldWarning = ""; + Warning = ""; + BoldInformation = ""; + Information = ""; + BoldQuestion = ""; + Question = ""; + BoldHint = ""; + Hint = "󰌶"; + Debug = ""; + Trace = "✎"; + }; + misc = { + Robot = "ﮧ"; + Squirrel = ""; + Tag = ""; + Watch = ""; + Smiley = ""; + Package = ""; + CircuitBoard = ""; + LualineFmt = ""; + }; + nvtree_chad = { + default = "󰈚"; + symlink = ""; + folder = { + default = ""; + empty = ""; + empty_open = ""; + open = ""; + symlink = ""; + symlink_open = ""; + arrow_open = ""; + arrow_closed = ""; + }; + }; + }; +} diff --git a/plugins/common/mappings.nix b/plugins/common/mappings.nix new file mode 100644 index 0000000..cdc05c9 --- /dev/null +++ b/plugins/common/mappings.nix @@ -0,0 +1,309 @@ +{ config, lib, ... }: +let + inherit (config.myvim.mkKey) mkKeymap mkKeymapWithOpts wKeyObj; + inherit (lib.nixvim) mkRaw; + + # general mappings + v = [ + (mkKeymap "v" "" ":w" "Saving File") + (mkKeymap "v" "" "" "Escape") + + (mkKeymap "v" "" ":m '>+1gv-gv" "Move Selected Line Down") + (mkKeymap "v" "" ":m '-2gv-gv" "Move Selected Line Up") + + (mkKeymap "v" "<" "" ">gv" "Indent in") + + (mkKeymap "v" "" "" "Mapped to Nothing") + ]; + + xv = [ + (mkKeymapWithOpts "x" "j" ''v:count || mode(1)[0:1] == "no" ? "j" : "gj"'' "Move down" { + expr = true; + }) + (mkKeymapWithOpts "x" "k" ''v:count || mode(1)[0:1] == "no" ? "k" : "gk"'' "Move up" { + expr = true; + }) + ]; + + insert = [ + (mkKeymap "i" "jk" "" "Normal Mode") + (mkKeymap "i" "" ":w ++p" "Save file") + (mkKeymap "i" "" ":m .+1==gi" "Move Line Down") + (mkKeymap "i" "" ":m .-2==gi" "Move Line Up") + ]; + + normal = [ + (mkKeymap "n" "" ":lua require('smart-splits').resize_left()" "Resize Left") + (mkKeymap "n" "" ":lua require('smart-splits').resize_down()" "Resize Down") + (mkKeymap "n" "" ":lua require('smart-splits').resize_up()" "Resize Up") + (mkKeymap "n" "" ":lua require('smart-splits').resize_right()" "Resize Right") + (mkKeymap "n" "?" ( + # lua + mkRaw '' + function() + require('flash').jump({ + forward = true, wrap = true, multi_window = true + }) + end + '' + ) "Flash Search") + + (mkKeymap "n" "" ":lua require('smart-splits').move_cursor_left()" "Move Cursor Left") + (mkKeymap "n" "" ":lua require('smart-splits').move_cursor_down()" "Move Cursor Down") + (mkKeymap "n" "" ":lua require('smart-splits').move_cursor_up()" "Move Cursor Up") + (mkKeymap "n" "" ":lua require('smart-splits').move_cursor_right()" "Move Cursor Right") + (mkKeymap "n" "" ":lua require('smart-splits').move_cursor_previous()" + "Move Cursor Previous" + ) + (mkKeymap "n" "dd" + ( + # lua + mkRaw '' + function() + local any_diff = false + for _, w in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if vim.api.nvim_win_get_option(w, "diff") then + any_diff = true + break + end + end + + if any_diff then + vim.cmd("windo diffoff") + else + vim.cmd("windo diffthis") + end + end + '' + ) + + "Toggle Diff the opened windows" + ) + + (mkKeymap "n" "" "w ++p" "Save the file") + (mkKeymap "n" "" "" "Increase Number") + (mkKeymap "n" "" "" "Decrease Number") + + (mkKeymap "n" "" "m .+1==" "Move line Down") + (mkKeymap "n" "" "m .-2==" "Move line up") + + (mkKeymap "n" "qq" "quitall!" "Quit!") + (mkKeymap "n" "qw" ( + # lua + mkRaw '' + function() + local wins = vim.api.nvim_tabpage_list_wins(0) + if #wins > 1 then + local ok, err = pcall(vim.cmd, 'close') + if not ok then + vim.notify("Cannot close the last window!", vim.log.levels.WARN) + end + else + vim.notify("Cannot close the last window!", vim.log.levels.WARN) + end + end + '' + ) "Close Window!") + + (mkKeymap "n" "" "nohl" "no highlight!") + (mkKeymap "n" "" ":nohlsearch" "escape") + (mkKeymap "n" "A" "ggVG" "select All") + + (mkKeymap "n" "|" "vsplit" "vertical split") + (mkKeymap "n" "-" "split" "horizontal split") + + # quickfix + (mkKeymap "n" "cn" "cnext" "quickfix next") + (mkKeymap "n" "cp" "cprev" "quickfix prev") + (mkKeymap "n" "cq" "cclose" "quit quickfix") + + (mkKeymap "n" "id" ( + # lua + mkRaw '' + function() + local date = "# " .. os.date("%d-%m-%y") + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + local line = vim.api.nvim_get_current_line() + + -- Insert date at cursor position + local new_line = line:sub(1, col) .. date .. line:sub(col + 1) + vim.api.nvim_set_current_line(new_line) + + -- Move cursor to next line + vim.api.nvim_win_set_cursor(0, { row + 1, 0 }) + end + '' + ) "Insert Date at cursor position") + + (mkKeymap "n" "n" "nzzzv" "Move to center") + (mkKeymap "n" "N" "Nzzzv" "Moving to center") + (mkKeymap "n" "uC" ( + # lua + mkRaw '' + require('stay-centered').toggle + '' + ) "Toggle stay-centered.nvim") + (mkKeymap "n" "ft" ( + # lua + mkRaw '' + function() + vim.ui.input({ prompt = "Enter FileType: " }, function(input) + local ft = input + if not input or input == "" then + ft = vim.bo.filetype + end + vim.o.filetype = ft + end) + end + '' + ) "Set Filetype") + + (mkKeymap "n" "o" ( + # lua + mkRaw '' + function() + local word = vim.fn.expand("") -- Gets file-like word under cursor + + if word:match("^https?://") then + -- Detect OS and choose browser opener + local open_cmd + if vim.fn.has("macunix") == 1 then + open_cmd = "open" + elseif vim.fn.has("unix") == 1 then + open_cmd = "xdg-open" + elseif vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1 then + open_cmd = "start" + else + print("Unsupported OS") + return + end + + vim.fn.jobstart({ open_cmd, word }, { detach = true }) + + elseif vim.fn.filereadable(word) == 1 or vim.fn.isdirectory(word) == 1 then + -- It's a file or directory; open in current window + vim.cmd("edit " .. vim.fn.fnameescape(word)) + else + print("Not a valid file or URL: " .. word) + end + end + '' + ) "Open") + + (mkKeymapWithOpts "n" "j" ''v:count || mode(1)[0:1] == "no" ? "j" : "gj"'' "Move down" { + expr = true; + }) + (mkKeymapWithOpts "n" "k" ''v:count || mode(1)[0:1] == "no" ? "k" : "gk"'' "Move up" { + expr = true; + }) + + ]; +in +{ + keymaps = insert ++ normal ++ v ++ xv; + + wKeyList = [ + (wKeyObj [ + "A" + "" + "" + "true" + ]) + (wKeyObj [ + "" + "" + "" + "true" + ]) + (wKeyObj [ + "q" + "" + "quit/session" + ]) + (wKeyObj [ + "i" + "" + "Insert" + ]) + (wKeyObj [ + "v" + "󰩬" + "Insert" + ]) + (wKeyObj [ + "z" + "" + "fold" + ]) + (wKeyObj [ + "g" + "" + "goto" + ]) + (wKeyObj [ + "[" + "" + "next" + ]) + (wKeyObj [ + "]" + "" + "prev" + ]) + (wKeyObj [ + "u" + "󰔎" + "ui" + ]) + (wKeyObj [ + "o" + "" + "Open" + ]) + (wKeyObj [ + "d" + "" + "diff" + ]) + (wKeyObj [ + "|" + "" + "vsplit" + ]) + (wKeyObj [ + "-" + "" + "split" + ]) + (wKeyObj [ + "c" + "󰁨" + "quickfix" + ]) + ]; + + extraConfigLua = # lua + '' + -- Use black hole register for 'x', 'X', 'c', 'C' + vim.api.nvim_set_keymap('n', 'x', '"_x', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('n', 'X', '"_X', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('n', 'c', '"_c', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('n', 'C', '"_C', { noremap = true, silent = true }) + + -- Visual mode + vim.api.nvim_set_keymap('v', 'x', '"_d', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('v', 'X', '"_d', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('v', 'c', '"_c', { noremap = true, silent = true }) + vim.api.nvim_set_keymap('v', 'C', '"_c', { noremap = true, silent = true }) + + -- In visual mode, paste from the clipboard without overwriting it + vim.api.nvim_set_keymap("v", "p", '"_dP', { noremap = true, silent = true }) + + -- Only this hack works in command mode + vim.cmd([[ + cnoremap + cnoremap + ]]) + ''; +} diff --git a/plugins/common/options.nix b/plugins/common/options.nix new file mode 100644 index 0000000..2f11547 --- /dev/null +++ b/plugins/common/options.nix @@ -0,0 +1,46 @@ +{ lib, ... }: +with lib; +{ + options = { + wKeyList = mkOption { + type = types.listOf types.attrs; + }; + + myvim = { + mkKey = mkOption { + type = types.attrs; + default = { }; + }; + + icons = mkOption { + type = types.attrs; + default = { }; + }; + + leader = mkOption { + description = "The leader key for nvim."; + type = types.str; + default = " "; + }; + + border = mkOption { + description = "The border style for nvim."; + type = types.enum [ + "single" + "double" + "rounded" + "solid" + "shadow" + "curved" + "bold" + "none" + ]; + default = "rounded"; + }; + + transparent = mkEnableOption "transparent" // { + default = true; + }; + }; + }; +} diff --git a/plugins/common/plugins.nix b/plugins/common/plugins.nix new file mode 100644 index 0000000..b76d8a4 --- /dev/null +++ b/plugins/common/plugins.nix @@ -0,0 +1,52 @@ +{ pkgs, config, ... }: +let + inherit (config.myvim.mkKey) mkKeymap; +in +{ + extraPlugins = with pkgs.vimPlugins; [ + stay-centered-nvim + ]; + + plugins = { + comment = { + enable = true; + settings = { + toggler.line = "/"; + opleader.line = "/"; + }; + }; + + flash = { + enable = true; + settings = { + modes.char.enabled = false; + }; + }; + + lz-n.enable = true; + nvim-autopairs.enable = true; + nvim-surround.enable = true; + smart-splits.enable = true; + trim.enable = true; + visual-multi.enable = true; + web-devicons.enable = true; + + which-key = { + enable = true; + settings = { + spec = config.wKeyList; + preset = "helix"; + }; + }; + }; + + opts = { + timeout = true; + timeoutlen = 250; + }; + + keymaps = [ + (mkKeymap "n" "vt" ":lua require('flash').treesitter()" "Select Treesitter Node") + (mkKeymap "n" "ut" ":TrimToggle" "Toggle Trim") + ]; +} diff --git a/plugins/default.nix b/plugins/default.nix new file mode 100644 index 0000000..fcd502a --- /dev/null +++ b/plugins/default.nix @@ -0,0 +1,33 @@ +{ lib, ... }: +let + mapAttrsMaybe = + f: attrs: + lib.pipe attrs [ + (lib.mapAttrsToList f) + (builtins.filter (x: x != null)) + builtins.listToAttrs + ]; + forAllNixFiles = + dir: f: + if builtins.pathExists dir then + lib.pipe dir [ + builtins.readDir + (mapAttrsMaybe ( + fn: type: + if type == "regular" then + let + name = lib.removeSuffix ".nix" fn; + in + lib.nameValuePair name (f "${dir}/${fn}") + else if type == "directory" && builtins.pathExists "${dir}/${fn}/default.nix" then + lib.nameValuePair fn (f "${dir}/${fn}") + else + null + )) + ] + else + { }; +in +{ + flake.myvimPlugins = forAllNixFiles ./. (fn: fn); +} diff --git a/plugins/git.nix b/plugins/git.nix new file mode 100644 index 0000000..2047199 --- /dev/null +++ b/plugins/git.nix @@ -0,0 +1,150 @@ +{ config, lib, ... }: +let + inherit (lib.nixvim) mkRaw; + inherit (config.myvim) icons; + inherit (config.myvim.mkKey) mkKeymap wKeyObj; +in +{ + plugins = { + git-conflict = { + enable = true; + settings.default_mappings = true; + }; + + gitsigns = { + enable = true; + + settings = { + current_line_blame = true; + preview_config = { + border = "rounded"; + }; + signs = with icons.ui; { + add.text = "${LineLeft}"; + change.text = "${LineLeft}"; + delete.text = "${LineLeft}"; + topdelete.text = "${Triangle}"; + changedelete.text = "${BoldLineLeft}"; + }; + }; + }; + }; + + wKeyList = [ + (wKeyObj [ + "g" + "" + "git" + ]) + (wKeyObj [ + "gh" + "󰫅" + "hunks" + ]) + (wKeyObj [ + "gb" + "󰭐" + "blame" + ]) + ]; + + keymaps = [ + + # Navigation + (mkKeymap "n" "]h" ( + # lua + mkRaw '' + function () + if vim.wo.diff then + vim.cmd.normal ({ ' ]c', bang = true}) + else + require('gitsigns').nav_hunk('next') + end + end + '' + ) "Next Hunk") + + (mkKeymap "n" "[h" ( + # lua + mkRaw '' + function() + if vim.wo.diff then + vim.cmd.normal({'[c', bang = true}) + else + require('gitsigns').nav_hunk('prev') + end + end + '' + ) "Prev Hunk") + + (mkKeymap "n" "]H" (mkRaw "function() require('gitsigns').nav_hunk('last') end") "Last Hunk") + + (mkKeymap "n" "[H" (mkRaw "function() require('gitsigns').nav_hunk('first') end") "First Hunk") + + # Stage / Reset + (mkKeymap "n" "gs" "lua require('gitsigns').stage_buffer()" "Stage Buffer") + (mkKeymap "v" "gs" ( + # lua + mkRaw '' + function() + require('gitsigns').stage_hunk({ vim.fn.line('.'), vim.fn.line('v') }) + end + '' + ) "Stage/Unstage Selection") + + (mkKeymap "n" "gr" "lua require('gitsigns').reset_buffer()" "Reset Buffer") + (mkKeymap "v" "gr" ( + # lua + mkRaw '' + function() + require('gitsigns').reset_hunk({ vim.fn.line('.'), vim.fn.line('v') }) + end + '' + ) "Reset Selection") + + # Undo + (mkKeymap "n" "gu" "lua require('gitsigns').undo_stage_hunk()" "Undo Stage Hunk") + + # Preview / Diff + (mkKeymap "n" "gp" "lua require('gitsigns').preview_hunk_inline()" + "Preview Hunk Inline" + ) + (mkKeymap "n" "gP" "lua require('gitsigns').preview_hunk()" "Preview Hunk (Popup)") + (mkKeymap "v" "gp" ( + # lua + mkRaw '' + function() + require('gitsigns').preview_hunk_inline({ vim.fn.line('.'), vim.fn.line('v') }) + end + '' + ) "Preview Selection") + + (mkKeymap "n" "dg" "lua require('gitsigns').diffthis()" "Git Diff ") + (mkKeymap "n" "dG" (mkRaw "function() require('gitsigns').diffthis('~') end") + "Git diff last commit (HEAD~)" + ) + + # Blame + (mkKeymap "n" "gk" (mkRaw "function() require('gitsigns').blame_line({ full = true }) end") + "Blame Line (Full)" + ) + (mkKeymap "n" "gK" ":lua require('gitsigns').blame()" "Blame File") + + # Quickfix + (mkKeymap "n" "gq" ":lua require('gitsigns').setqflist()" "Hunks to Quickfix") + (mkKeymap "n" "gQ" (mkRaw "function() require('gitsigns').setqflist('all') end") + "All Hunks to Quickfix" + ) + + # Toggles + (mkKeymap "n" "gb" "lua require('gitsigns').toggle_current_line_blame()" + "Toggle Blame (Line)" + ) + (mkKeymap "n" "gw" "lua require('gitsigns').toggle_word_diff()" "Toggle Word Diff") + + # Text object + (mkKeymap "o" "ih" ":Gitsigns select_hunk" "Select Hunk") + (mkKeymap "x" "ih" ":Gitsigns select_hunk" "Select Hunk") + + ]; +} diff --git a/plugins/lang/default.nix b/plugins/lang/default.nix new file mode 100644 index 0000000..8bd0794 --- /dev/null +++ b/plugins/lang/default.nix @@ -0,0 +1,9 @@ +{ lib, ... }: +{ + imports = + with builtins; + with lib; + map (fn: ./${fn}) ( + filter (fn: (fn != "default.nix" && !hasSuffix ".md" "${fn}")) (attrNames (readDir ./.)) + ); +} diff --git a/plugins/lang/nix.nix b/plugins/lang/nix.nix new file mode 100644 index 0000000..8576940 --- /dev/null +++ b/plugins/lang/nix.nix @@ -0,0 +1,13 @@ +{ + plugins = { + lsp.servers = { + nil_ls = { + enable = true; + }; + + statix = { + enable = true; + }; + }; + }; +} diff --git a/plugins/lsp/conform.nix b/plugins/lsp/conform.nix new file mode 100644 index 0000000..d6a30b8 --- /dev/null +++ b/plugins/lsp/conform.nix @@ -0,0 +1,21 @@ +# formatter with lsp fallback +{ lib, pkgs, ... }: +{ + plugins.conform-nvim = { + enable = true; + + settings = { + default_format_opts.lsp_format = "prefer"; + + formatters_by_ft = { + "_" = [ + "squeeze_blanks" + "trim_whitespace" + "trim_newlines" + ]; + }; + + formatters.squeeze_blanks.command = lib.getExe' pkgs.coreutils "cat"; + }; + }; +} diff --git a/plugins/lsp/default.nix b/plugins/lsp/default.nix new file mode 100644 index 0000000..d9f7bf1 --- /dev/null +++ b/plugins/lsp/default.nix @@ -0,0 +1,108 @@ +{ config, lib, ... }: +let + inherit (config.myvim.mkKey) mkKeymap; +in +{ + opts = { + foldcolumn = "1"; + foldlevel = 99; + foldlevelstart = -1; + foldenable = true; + }; + + diagnostic.settings = { + virtual_text = false; + underline = true; + signs = true; + severity_sort = true; + + float = { + border = config.myvim.border; + source = "always"; + focusable = false; + }; + }; + + plugins = { + lsp = { + enable = true; + + keymaps.extra = [ + (mkKeymap "n" "lO" "lua require('otter').activate()" "Force Otter") + ]; + + inlayHints = true; + + servers = { + typos_lsp = { + enable = true; + extraOptions.init_options.diagnosticSeverity = "Hint"; + }; + }; + + keymaps = { + silent = true; + + diagnostic = { + "lj" = "goto_next"; + "lk" = "goto_prev"; + }; + }; + }; + + lspsaga = { + enable = true; + + settings = { + lightbulb = { + enable = false; + virtualText = false; + }; + + outline.keys.jump = ""; + ui.bortder = config.myvim.border; + + scrollPreview = { + scrollDown = ""; + scrollUp = ""; + }; + }; + }; + + nvim-ufo = { + enable = true; + + settings = { + provider_selector = # lua + '' + function() + return { "lsp", "indent" } + end + ''; + + preview.mappings = { + close = "q"; + switch = "K"; + }; + }; + }; + + otter = { + enable = true; + + settings.buffers = { + set_filetype = true; + }; + }; + + tiny-inline-diagnostic.enable = true; + trouble.enable = true; + }; + + imports = + with builtins; + with lib; + map (fn: ./${fn}) ( + filter (fn: (fn != "default.nix" && !hasSuffix ".md" "${fn}")) (attrNames (readDir ./.)) + ); +} diff --git a/plugins/lsp/mappings.nix b/plugins/lsp/mappings.nix new file mode 100644 index 0000000..2038e17 --- /dev/null +++ b/plugins/lsp/mappings.nix @@ -0,0 +1,120 @@ +{ config, lib, ... }: +let + inherit (lib.nixvim) mkRaw; + inherit (config.myvim.mkKey) mkKeymap wKeyObj; +in +{ + + wKeyList = [ + (wKeyObj [ + "lg" + "" + "goto" + ]) + (wKeyObj [ + "l" + "󰿘" + "lsp" + ]) + ]; + + plugins.lsp.keymaps.extra = [ + (mkKeymap "n" "lO" "lua require('otter').activate()" "Force Otter") + + # Lspsaga + + (mkKeymap "n" "la" ":Lspsaga code_action" "Code Action") + (mkKeymap "n" "lo" "Lspsaga outline" "Outline") + (mkKeymap "n" "lw" "Lspsaga show_workspace_diagnostics" "Workspace Diagnostics") + (mkKeymap "n" "gd" "Lspsaga goto_definition" "Definitions") + (mkKeymap "n" "lr" "Lspsaga rename ++project" "Rename") + (mkKeymap "n" "gt" "Lspsaga goto_type_definition" "Type Definitions") + (mkKeymap "n" "l." "Lspsaga show_line_diagnostics" "Line Diagnostics") + (mkKeymap "n" "gpd" "Lspsaga peek_definition" "Peek Definition") + (mkKeymap "n" "gpt" "Lspsaga peek_type_definition" "Peek Type Definition") + (mkKeymap "n" "[e" "Lspsaga diagnostic_jump_prev" "Jump Prev Diagnostic") + (mkKeymap "n" "]e" "Lspsaga diagnostic_jump_next" "Jump Next Diagnostic") + (mkKeymap "n" "K" (mkRaw '' + function() + local ok, ufo = pcall(require, "ufo") + if ok then + winid = ufo.peekFoldedLinesUnderCursor() + end + if not winid then + vim.cmd("Lspsaga hover_doc") + end + end + '') "Hover Doc") + + # UFO + (mkKeymap "n" "zR" ( + # lua + mkRaw '' + function() + require("ufo").openAllFolds() + end + '' + ) "Open all folds") + (mkKeymap "n" "zM" ( + # lua + mkRaw '' + function() + require("ufo").closeAllFolds() + end + '' + ) "Close All Folds") + (mkKeymap "n" "zK" ( + # lua + mkRaw '' + function() + local winid = require("ufo").peekFoldedLinesUnderCursor() + if not winid then + vim.lsp.buf.hover() + end + end + '' + ) "Peek Folded Lines") + + (mkKeymap "n" "lq" "LspStop" "Stop LSP") + (mkKeymap "n" "li" "LspInfo" "LSP Info") + (mkKeymap "n" "ls" "LspStart" "Start LSP") + (mkKeymap "n" "lR" "LspRestart" "Restart LSP") + + (mkKeymap "n" "" ":lua vim.lsp.buf.signature_help()" "Signature Help") + (mkKeymap "n" "lD" ":lua Snacks.picker.lsp_definitions()" "Definitions list") + (mkKeymap "n" "ls" ":lua Snacks.picker.lsp_symbols()" "Definitions list") + + (mkKeymap "n" "lf" ":lua require('conform').format()" "Format file") + (mkKeymap "x" "lf" ":lua require('conform').format()" "Format File") + (mkKeymap "v" "lf" ":lua require('conform').format()" "Format File") + + (mkKeymap "n" "[d" ":lua vim.diagnostic.goto_prev()" "Previous Diagnostic") + (mkKeymap "n" "]d" ":lua vim.diagnostic.goto_next()" "Next Diagnostic") + (mkKeymap "n" "lL" ( + # lua + mkRaw '' + function() + if vim.g.diagnostics_visible == nil or vim.g.diagnostics_visible then + vim.g.diagnostics_visible = false + vim.diagnostic.disable() + else + vim.g.diagnostics_visible = true + vim.diagnostic.enable() + end + end + '' + ) "Toggle Diagnostics") + (mkKeymap "n" "ll" ( + # lua + mkRaw '' + function() + if vim.diagnostic.config().virtual_text == false then + vim.diagnostic.config({ virtual_text = { source = "always" } }) + else + vim.diagnostic.config({ virtual_text = false }) + end + end + '' + ) "Toggle Virtual Text") + ]; +} diff --git a/plugins/lualine/default.nix b/plugins/lualine/default.nix new file mode 100644 index 0000000..7cfdac7 --- /dev/null +++ b/plugins/lualine/default.nix @@ -0,0 +1,54 @@ +{ lib, ... }: +{ + extraConfigLua = # lua + '' + vim.cmd([[hi StatusLine guibg=NONE ctermbg=NONE]]) + ''; + + plugins.lualine = { + enable = true; + + settings = + let + separators = { + left = ""; + right = ""; + }; + transparent = { + a.fg = "none"; + c.bg = "none"; + }; + in + { + options = { + theme = { + normal = transparent; + insert = transparent; + visual = transparent; + replace = transparent; + command = transparent; + inactive = transparent; + }; + always_divide_middle = true; + globalstatus = true; + icons_enable = true; + component_separators = separators; + section_separatros = separators; + disabled_filetypes = [ + "Outline" + "neo-tree" + "dashboard" + "snacks_dashboard" + "snacks_terminal" + ]; + }; + }; + }; + + imports = + with builtins; + with lib; + map (fn: ./${fn}) ( + filter (fn: (fn != "default.nix" && !hasSuffix ".md" "${fn}")) (attrNames (readDir ./.)) + ); +} diff --git a/plugins/lualine/sections.nix b/plugins/lualine/sections.nix new file mode 100644 index 0000000..159af39 --- /dev/null +++ b/plugins/lualine/sections.nix @@ -0,0 +1,150 @@ +{ config, lib, ... }: +let + inherit (config.myvim) icons; + inherit (lib.nixvim) mkRaw; +in +{ + plugins.lualine.settings.sections = { + lualine_a = [ + { + __unkeyed = "fileformat"; + cond = null; + padding = { + left = 1; + right = 1; + }; + color = "SLGreen"; + } + ]; + lualine_b = [ "encoding" ]; + lualine_c = [ + { + __unkeyed = "b:gitsigns_head"; + icon = "${icons.git.Branch}"; + color.gui = "bold"; + } + { + __unkeyed = "diff"; + source = + # lua + mkRaw '' + (function() + local gitsigns = vim.b.gitsigns_status_dict + if vim.b.gitsigns_status_dict then + return { + added = gitsigns.added, + modified = gitsigns.changed, + removed = gitsigns.removed, + } + end + end) + ''; + symbols = { + added = mkRaw ''"${icons.git.LineAdded}" .. " " ''; + modified = mkRaw ''"${icons.git.LineModified}".. " "''; + removed = mkRaw ''"${icons.git.LineRemoved}".. " "''; + }; + } + { + __unkeyed = "diagnostics"; + sources = { + __unkeyed = "nvim_diagnostic"; + }; + symbols = { + error = mkRaw ''"${icons.diagnostics.BoldError}" .. " "''; + warn = mkRaw ''"${icons.diagnostics.BoldWarning}" .. " "''; + info = mkRaw ''"${icons.diagnostics.BoldInformation}" .. " "''; + hint = mkRaw ''"${icons.diagnostics.BoldHint}" .. " "''; + }; + } + ]; + lualine_x = [ + { + color = { + fg = "#ff9e64"; + }; + cond = mkRaw '' + function() + local ok, noice = pcall(require, "noice") + if not ok then + return false + end + return noice.api.status.mode.has() + end + ''; + __unkeyed = + # lua + mkRaw '' + function() + local ok, noice = pcall(require, "noice") + if not ok then + return false + end + return noice.api.status.mode.get() + end + ''; + } + { + __unkeyed = + # lua + mkRaw '' + function() + local clients = vim.lsp.get_clients() + local lsp_names = {} + if next(clients) == nil then + return "Ls Inactive" + end + for _, client in ipairs(clients) do + if client.name ~= "copilot" and client.name ~= "null-ls" and client.name ~= "typos_lsp" then + local name = client.name:gsub("%[%d+%]", "") -- makes otter-ls[number] -> otter-ls + table.insert(lsp_names, name) + end + end + + local formatters = require("conform").list_formatters() + local con_names = {} + + for _, formatter in ipairs(formatters) do + local name = formatter.name + if formatter.available and (name ~= "squeeze_blanks" and name ~= "trim_whitespace" and name ~= "trim_newlines") then + table.insert(con_names, formatter.name) + end + end + local names = {} + vim.list_extend(names, lsp_names) + vim.list_extend(names, con_names) + return "[" .. table.concat(vim.fn.uniq(names), ", ") .. "]" + end + ''; + } + + { + __unkeyed = "filetype"; + cond = null; + padding = { + left = 1; + right = 1; + }; + } + ]; + lualine_y = [ "progress" ]; + lualine_z = [ + "location" + { + __unkeyed = + # lua + mkRaw '' + function() + local lsp_clients = vim.lsp.get_clients() + for _, client in ipairs(lsp_clients) do + if client.name == "copilot" then + return "%#SLGreen#" .. "${icons.kind.Copilot}" + end + end + return "" + end + ''; + } + ]; + }; +} diff --git a/plugins/noice.nix b/plugins/noice.nix new file mode 100644 index 0000000..069bc63 --- /dev/null +++ b/plugins/noice.nix @@ -0,0 +1,63 @@ +{ + plugins.noice = { + enable = true; + + settings = { + presets.bottom_search = true; + + routes = [ + # FIXME: + { + filter = { + event = "msg_show"; + kind = [ "shell_out" ]; + }; + view = "notify"; + opts = { + level = "info"; + title = "stdout"; + }; + } + { + filter = { + event = "msg_show"; + kind = [ "shell_err" ]; + }; + view = "notify"; + opts = { + level = "error"; + title = "stderr"; + }; + } + ]; + + views = { + cmdline_popup = { + position = { + row = -2; + col = "50%"; + }; + }; + cmdline_popupmenu = { + position = { + row = -5; + col = "50%"; + }; + }; + }; + + lsp = { + override = { + "vim.lsp.util.convert_input_to_markdown_lines" = true; + "vim.lsp.util.stylize_markdown" = true; + "cmp.entry.get_documentation" = true; + }; + + hover.enabled = false; + message.enabled = false; + signature.enabled = false; + progress.eabled = false; + }; + }; + }; +} diff --git a/plugins/snacks/default.nix b/plugins/snacks/default.nix new file mode 100644 index 0000000..a013c76 --- /dev/null +++ b/plugins/snacks/default.nix @@ -0,0 +1,323 @@ +{ lib, pkgs, ... }: +let + inherit (lib.nixvim) utils mkRaw; +in +{ + plugins = { + neoscroll.enable = true; + todo-comments.enable = true; + + snacks = { + enable = true; + + settings = { + bigfile.enabled = true; + dim.enabled = true; + scroll.enabled = false; + lazygit.config.os.edit = + # lua + mkRaw '' + '[ -z "\"$NVIM\"" ] && (nvim -- {{filename}}) || (nvim --server "\"$NVIM\"" --remote-send "\"q\"" && nvim --server "\"$NVIM\"" --remote {{filename}})' + ''; + quickfile.enbled = true; + indent.enabled = true; + words.enabled = true; + statuscolumn.enabled = true; + + dashboard = { + enabled = true; + sections = + # lua + mkRaw '' + { + { section = "header" }, + { + pane = 2, + section = "terminal", + cmd = "colorscript -e square", + height = 5, + padding = 1, + }, + { section = "keys", gap = 1, padding = 1 }, + { + pane = 2, + icon = " ", + desc = "Browse Repo", + padding = 1, + key = "b", + action = function() + Snacks.gitbrowse() + end, + }, + function() + local in_git = Snacks.git.get_root() ~= nil + local cmds = { + { + title = "Notifications", + cmd = "gh notify -s -a -n5", + action = function() + vim.ui.open("https://github.com/notifications") + end, + key = "n", + icon = " ", + height = 5, + enabled = true, + }, + { + title = "Open Issues", + cmd = "gh issue list -L 3", + key = "i", + action = function() + vim.fn.jobstart("gh issue list --web", { detach = true }) + end, + icon = " ", + height = 7, + }, + { + icon = " ", + title = "Open PRs", + cmd = "gh pr list -L 3", + key = "P", + action = function() + vim.fn.jobstart("gh pr list --web", { detach = true }) + end, + height = 7, + }, + { + icon = " ", + title = "Git Status", + cmd = "git --no-pager diff --stat -B -M -C", + height = 10, + }, + } + return vim.tbl_map(function(cmd) + return vim.tbl_extend("force", { + pane = 2, + section = "terminal", + enabled = in_git, + padding = 1, + ttl = 5 * 60, + indent = 3, + }, cmd) + end, cmds) + end, + -- { section = "startup" }, + } + ''; + }; + + picker = + let + keys = { + "" = (utils.listToUnkeyedAttrs [ "preview_scroll_down" ]) // { + mode = "n"; + }; + "" = (utils.listToUnkeyedAttrs [ "preview_scroll_up" ]) // { + mode = "n"; + }; + "-" = (utils.listToUnkeyedAttrs [ "edit_split" ]) // { + mode = "n"; + }; + "|" = (utils.listToUnkeyedAttrs [ "edit_vsplit" ]) // { + mode = "n"; + }; + "" = + # lua + mkRaw '' + { { "pick_win", "jump" } } + ''; + }; + in + { + enabled = true; + actions.pick_win = + # lua FIXME: on non overridden theme the picker window opens buffer with bg + mkRaw '' + function(picker) + if not picker.layout.split then + picker.layout:hide() + end + local win = Snacks.picker.util.pick_win { + main = picker.main, + float = false, + filter = function(_, buf) + local ft = vim.bo[buf].ft + return ft == 'snacks_dashboard' or not ft:find '^snacks' + end, + } + if not win then + if not picker.layout.split then + picker.layout:unhide() + end + return true + end + picker.main = win + if not picker.layout.split then + vim.defer_fn(function() + if not picker.closed then + picker.layout:unhide() + end + end, 100) + end + end + ''; + sources.explorer = + # lua + mkRaw '' + { + on_show = function(picker) + local show = false + local gap = 1 + local clamp_width = function(value) + return math.max(20, math.min(100, value)) + end + -- + local position = picker.resolved_layout.layout.position + local rel = picker.layout.root + local update = function(win) ---@param win snacks.win + local border = win:border_size().left + win:border_size().right + win.opts.row = vim.api.nvim_win_get_position(rel.win)[1] + win.opts.height = 0.8 + if position == 'left' then + win.opts.col = vim.api.nvim_win_get_width(rel.win) + gap + win.opts.width = clamp_width(vim.o.columns - border - win.opts.col) + end + if position == 'right' then + win.opts.col = -vim.api.nvim_win_get_width(rel.win) - gap + win.opts.width = clamp_width(vim.o.columns - border + win.opts.col) + end + win:update() + end + local preview_win = Snacks.win.new { + relative = 'editor', + external = false, + focusable = false, + border = 'rounded', + backdrop = false, + show = show, + bo = { + filetype = 'snacks_float_preview', + buftype = 'nofile', + buflisted = false, + swapfile = false, + undofile = false, + }, + on_win = function(win) + update(win) + picker:show_preview() + end, + } + rel:on('WinLeave', function() + vim.schedule(function() + if not picker:is_focused() then + picker.preview.win:close() + end + end) + end) + rel:on('WinResized', function() + update(preview_win) + end) + picker.preview.win = preview_win + picker.main = preview_win.win + end, + on_close = function(picker) + picker.preview.win:close() + end, + layout = { + preset = 'sidebar', + layout = { + backdrop = false, + width = 40, -- Pfff.. 40. I have 60! + min_width = 40, + height = 0, + position = 'right', + border = 'none', + box = 'vertical', + { win = 'list', border = 'none' }, + { win = 'preview', title = '{preview}', height = 0.4, border = 'top' }, + }, + preview = false, ---@diagnostic disable-line + }, + actions = { + toggle_preview = function(picker) --[[Override]] + picker.preview.win:toggle() + end, + }, + } + ''; + win = { + input.keys = keys; + list.keys = keys; + }; + }; + + image = { + enabled = true; + border = "none"; + doc.inline = false; + }; + + notifier = { + enabled = true; + style = "minimal"; + top_down = false; + }; + }; + }; + }; + + extraPackages = with pkgs; [ + gh + imagemagick + ghostscript_headless + tectonic + mermaid-cli + dwt1-shell-color-scripts + ]; # for image support + + autoCmd = [ + { + desc = "Pre init Function"; + event = [ "VimEnter" ]; + callback = + # lua + mkRaw '' + -- Taken from https://github.com/folke/snacks.nvim?tab=readme-ov-file#-usage + function() + -- Setup some globals for debugging (lazy-loaded) + _G.dd = function (...) + Snacks.debug.inspect + (...) + end + _G.bt = function() + Snacks.debug.backtrace() + end + vim.print = _G.dd -- Override print to use snacks for `:=` command + + -- Create some toggle mappings + Snacks.toggle.diagnostics():map("ud") + Snacks.toggle.line_number():map("ul") + Snacks.toggle.inlay_hints():map("uh") + Snacks.toggle.treesitter():map("uT") + Snacks.toggle.option("spell", + { name = "Spelling" }):map("us") + Snacks.toggle.option("wrap", + { name = "Wrap" }):map("uw") + Snacks.toggle.option("relativenumber", + { name = "Relative Number" }):map("uL") + Snacks.toggle.option("conceallevel", + { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 }):map("uc") + Snacks.toggle.option("background", + { off = "light", on = "dark", name = "Dark Background" }):map("ub") + end + ''; + } + ]; + + imports = + with builtins; + with lib; + map (fn: ./${fn}) ( + filter (fn: (fn != "default.nix" && !hasSuffix ".md" "${fn}")) (attrNames (readDir ./.)) + ); +} diff --git a/plugins/snacks/mappings.nix b/plugins/snacks/mappings.nix new file mode 100644 index 0000000..da68a3a --- /dev/null +++ b/plugins/snacks/mappings.nix @@ -0,0 +1,126 @@ +{ config, lib, ... }: +let + inherit (lib.nixvim) mkRaw; + inherit (config.myvim.mkKey) mkKeymap wKeyObj; +in +{ + wKeyList = [ + (wKeyObj [ + "." + "" + "Scratch Buffer" + ]) + (wKeyObj [ + ":" + "" + "" + true + ]) + (wKeyObj [ + "s" + "" + "search" + ]) + (wKeyObj [ + "f" + "" + "file/find" + ]) + (wKeyObj [ + "e" + "󰙅" + "Explorer" + ]) + ]; + + keymaps = [ + (mkKeymap "n" "e" ":lua Snacks.explorer()" "Explorer") + (mkKeymap "n" ".." ":lua Snacks.scratch()" "Toggle Scratch Buffer") + (mkKeymap "n" ".s" ":lua Snacks.scratch.select()" "Select Scratch Buffer") + (mkKeymap "n" "sn" ":lua Snacks.notifier.show_history()" "Notification History") + (mkKeymap "n" ".r" ":lua Snacks.rename.rename_file()" "Rename file/variable +lsp") + (mkKeymap "n" "gB" ":lua Snacks.gitbrowse()" "Git Browse") + (mkKeymap "n" "gf" ":lua Snacks.lazygit.log_file()" "Lazygit Current File History") + (mkKeymap "n" "gB" ":lua Snacks.gitbrowse()" "Git Browse") + (mkKeymap "n" "gf" ":lua Snacks.lazygit.log_file()" "Lazygit Current File History") + (mkKeymap "n" "gg" ":lua Snacks.lazygit()" "Lazygit") + (mkKeymap "n" "gl" ":lua Snacks.lazygit.log()" "Lazygit Log (cwd)") + (mkKeymap "n" "gL" ":lua Snacks.picker.git_log()" "Git Log (cwd)") + (mkKeymap "n" "un" ":lua Snacks.notifier.hide()" "Dismiss All Notifications") + + (mkKeymap "n" "sb" ":lua Snacks.picker.lines() " "Buffer Lines") + (mkKeymap "n" "sB" ":lua Snacks.picker.grep_buffers() " "Grep Open Buffers") + (mkKeymap "n" "sg" ":lua Snacks.picker.grep() " "Grep") + (mkKeymap "n" "sw" ":lua Snacks.picker.grep_word() " "Visual selection or word") + (mkKeymap "x" "sw" ":lua Snacks.picker.grep_word() " "Visual selection or word") + (mkKeymap "n" ''s"'' ":lua Snacks.picker.registers() " "Registers") + (mkKeymap "n" "sa" ":lua Snacks.picker.autocmds() " "Autocmds") + (mkKeymap "n" "sb" ":lua Snacks.picker.lines() " "Buffer Lines") + (mkKeymap "n" "sc" ":lua Snacks.picker.command_history() " "Command History") + (mkKeymap "n" "sC" ":lua Snacks.picker.commands() " "Commands") + (mkKeymap "n" "sd" ":lua Snacks.picker.diagnostics() " "Diagnostics") + (mkKeymap "n" "sD" ":lua Snacks.picker.diagnostics_buffer() " "Buffer Diagnostics") + (mkKeymap "n" "sH" ":lua Snacks.picker.highlights() " "Highlights") + (mkKeymap "n" "si" ":lua Snacks.picker.icons() " "Icons") + (mkKeymap "n" "sj" ":lua Snacks.picker.jumps() " "Jumps") + (mkKeymap "n" "sl" ":lua Snacks.picker.loclist() " "Location List") + (mkKeymap "n" "sm" ":lua Snacks.picker.marks() " "Marks") + (mkKeymap "n" "sM" ":lua Snacks.picker.man() " "Man Pages") + (mkKeymap "n" "sq" ":lua Snacks.picker.qflist() " "Quickfix List") + (mkKeymap "n" "sR" ":lua Snacks.picker.resume() " "Resume") + (mkKeymap "n" "su" ":lua Snacks.picker.undo() " "Undo History") + + (mkKeymap "n" "gd" ":lua Snacks.picker.lsp_definitions() " "Goto Definition") + (mkKeymap "n" "gD" ":lua Snacks.picker.lsp_declarations() " "Goto Declaration") + (mkKeymap "n" "gr" ":lua Snacks.picker.lsp_references() " "References") + (mkKeymap "n" "gI" ":lua Snacks.picker.lsp_implementations() " "Goto Implementation") + (mkKeymap "n" "gy" ":lua Snacks.picker.lsp_type_definitions() " "Goto T[y]pe Definition") + (mkKeymap "n" "ss" ":lua Snacks.picker.lsp_symbols() " "LSP Symbols") + (mkKeymap "n" "sS" ":lua Snacks.picker.lsp_workspace_symbols() " + "LSP Workspace Symbols" + ) + + # Telescope replacement + (mkKeymap "n" "sP" ":lua Snacks.picker()" "Pickers") + (mkKeymap "n" "ss" ":lua Snacks.picker.smart()" "Smart") + (mkKeymap "n" "st" ":lua Snacks.picker.todo_comments({layout = 'ivy'})" "Todo") + (mkKeymap "n" "sT" + '':lua Snacks.picker.todo_comments({keywords = {"TODO", "FIX", "FIXME"}, layout = 'ivy'})'' + "Todo" + ) + (mkKeymap "n" "s:" '':lua Snacks.picker.command_history({ layout = 'ivy'})'' + "Command History" + ) + (mkKeymap "n" "s," ":lua Snacks.picker.buffers({layout = 'ivy'})" "Buffers") + (mkKeymap "n" "sh" '':lua Snacks.picker.help()'' "Help Pages") + (mkKeymap "n" "sk" '':lua Snacks.picker.keymaps({layout = 'vscode'})'' "Keymaps") + + (mkKeymap "n" "su" ( + # lua + mkRaw '' + function() + Snacks.picker.undo({ + win = { + input = { + keys = { + ["y"] = { "yank_add", mode = "n" }, + ["Y"] = { "yank_del", mode = "n" }, + }, + }, + }, + }) + end + '' + ) "Undo") + + (mkKeymap "n" "ff" ":lua Snacks.picker.files()" "Find Files") + (mkKeymap "n" "fF" ":lua Snacks.picker.smart()" "Smart") + (mkKeymap "n" "f/" ":lua Snacks.picker.grep()" "Grep") + (mkKeymap "n" "f?" + ":lua Snacks.picker.grep({layout = 'ivy', args = { '--vimgrep', '--smart-case', '--fixed-strings' } })" + "Grep" + ) + (mkKeymap "n" "fr" ":lua Snacks.picker.recent()" "Recent") + (mkKeymap "n" "fp" ":lua Snacks.picker.projects()" "Projects") + ]; +} diff --git a/plugins/treesitter.nix b/plugins/treesitter.nix new file mode 100644 index 0000000..295b7fe --- /dev/null +++ b/plugins/treesitter.nix @@ -0,0 +1,36 @@ +{ + plugins = { + mini-ai.enable = true; + sleuth.enable = true; + + treesitter = { + enable = true; + + settings = { + highlight = { + enable = true; + + disable = [ + "latex" + "markdown" + ]; + }; + + auto_install = true; + indent_enable = true; + folding = true; + autoLoad = true; + incemental_selection.enable = true; + }; + }; + + treesitter-context = { + enable = true; + + settings = { + max_lines = 4; + min_window_height = 40; + }; + }; + }; +} diff --git a/plugins/ux.nix b/plugins/ux.nix new file mode 100644 index 0000000..1d6033f --- /dev/null +++ b/plugins/ux.nix @@ -0,0 +1,64 @@ +{ pkgs, config, ... }: +{ + extraPlugins = [ + pkgs.vimPlugins.windows-nvim + ]; + + extraConfigLua = '' + vim.o.winwidth = 10 + vim.o.winminwidth = 10 + vim.o.equalalways = false + require('windows').setup({ + ignore = { + filetype = { "snacks_picker_list", "snacks_layout_box" }, + }, + }) + ''; + + plugins = { + colorizer = { + enable = true; + settings = { + filetypes = { + __unkeyed = "*"; + }; + user_default_options = { + names = true; + RRGGBBAA = true; + AARRGGBB = true; + rgb_fn = true; + hsl_fn = true; + css = true; + css_fn = true; + tailwind = true; + mode = "virtualtext"; + virtualtext = "■"; + always_update = true; + }; + }; + }; + + dressing = { + enable = true; + settings.input.mappings.n = { + "q" = "Close"; + "k" = "HistoryPrev"; + "j" = "HistoryNext"; + }; + }; + + fidget = { + enable = true; + settings = { + progress.display.progress_icon = [ "moon" ]; + notification.window = { + relative = "editor"; + winblend = 0; + border = "none"; + }; + }; + }; + + lastplace.enable = true; + }; +}