From 009318521649d24a7b4b9c1aaceded77721221cb Mon Sep 17 00:00:00 2001 From: kat Date: Fri, 29 Jul 2022 10:07:25 -0700 Subject: [PATCH] feat(home/vim): move to pure lua for neovim, base16 cterm --- flake.lock | 12 +- home/vim/default.nix | 166 +++++++-------- home/vim/init.lua | 74 ++++--- modules/home/disables.nix | 3 + modules/home/neovim.nix | 412 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 555 insertions(+), 112 deletions(-) create mode 100644 modules/home/disables.nix create mode 100644 modules/home/neovim.nix diff --git a/flake.lock b/flake.lock index 1cf1bc8a..57c779de 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "arcexprs": { "flake": false, "locked": { - "lastModified": 1658879683, - "narHash": "sha256-rwIY2aiTsY+nzNtKlFBEPcmL2JETrjyrrcZ/gcc+XwY=", + "lastModified": 1658896296, + "narHash": "sha256-TzRUsy8qj5BOjiYqsNFEXbkMG2PVE7eBP7xKkc9+b6k=", "owner": "arcnmx", "repo": "nixexprs", - "rev": "58a9041d8463aa750d1f1a5a12da9f72a5754fd6", + "rev": "4bbcdbce60a33065adc86570ebc22503bc85616a", "type": "github" }, "original": { @@ -405,11 +405,11 @@ }, "nur": { "locked": { - "lastModified": 1658862603, - "narHash": "sha256-cPm6LdtKaoDrYjsJoW5VyYeUYZWFCXcwj8u88GQNV64=", + "lastModified": 1658894697, + "narHash": "sha256-1PhtbuaLmYb6EvFgwlJvMWtsk+szKqHmx3XoIAzCvWs=", "owner": "nix-community", "repo": "nur", - "rev": "7368f482355bf01e256414cf1b31d9f6d7ae00d9", + "rev": "518cd7a2425ea83d59dff0ce75a4981f46c593dc", "type": "github" }, "original": { diff --git a/home/vim/default.nix b/home/vim/default.nix index 126ac40e..bf4042b0 100644 --- a/home/vim/default.nix +++ b/home/vim/default.nix @@ -1,89 +1,89 @@ { config, lib, pkgs, nixos, ... }: let - inherit (lib.modules) mkIf; - inherit (lib.strings) concatStringsSep; - inherit (lib.attrsets) mapAttrsToList; - initLua = pkgs.writeText "init.lua" ( - ''-- Kat's Base16 Colors - local base16 = { - ${concatStringsSep "\n" (mapAttrsToList(var: col: "${var} = '${col}',") config.kw.theme.base16)} - } - - ${builtins.readFile ./init.lua} - ''); +inherit (lib.modules) mkIf; +inherit (lib.strings) concatStringsSep fixedWidthNumber hasInfix; +inherit (lib.attrsets) mapAttrs filterAttrs; +packDir = builtins.toString(pkgs.vimUtils.packDir config.programs.neovim.generatedConfigViml.configure.packages); +initLua = pkgs.substituteAll ({ + name = "init.lua"; + src = ./init.lua; + inherit packDir; + base16ShellPath = config.base16.shell.package; + defaultSchemeName = config.base16.defaultSchemeName; + defaultSchemeSlug = config.base16.defaultScheme.slug; +} // mapAttrs (_: col: fixedWidthNumber 2 col.ansiIndex) + (filterAttrs (var: _: hasInfix "base" var) config.base16.defaultScheme)); in { - home.sessionVariables = mkIf config.programs.neovim.enable { EDITOR = "nvim"; }; + home.sessionVariables = mkIf config.programs.neovim.enable { EDITOR = "nvim"; }; - programs.neovim = { - enable = true; - vimAlias = true; - viAlias = true; - plugins = with pkgs.vimPlugins; [ - # Libraries - plenary-nvim - # Disables and re-enables highlighting when searching - vim-cool - # Colour highlighting - vim-hexokinase - # Git porcelain - vim-fugitive - # Start screen - vim-startify - # Re-open with cursor at the same place - vim-lastplace - # Status Bar - lualine-nvim - # EasyMotion Equivalent - hop-nvim - # org-mode for vim - neorg - # Fonts - nvim-web-devicons - # Completion - nvim-cmp - # base16 - nvim-base16 - # Fuzzy Finder - telescope-nvim - # Buffers - bufferline-nvim - # Language Server - nvim-lspconfig - (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: with pkgs.tree-sitter-grammars; [ - tree-sitter-c - tree-sitter-lua - tree-sitter-rust - tree-sitter-bash - tree-sitter-css - tree-sitter-dockerfile - tree-sitter-go - tree-sitter-hcl - tree-sitter-html - tree-sitter-javascript - tree-sitter-markdown - tree-sitter-nix - tree-sitter-norg - tree-sitter-python - tree-sitter-regex - tree-sitter-scss - ])) - # Treesitter Plugins - nvim-ts-rainbow - nvim-treesitter-context - twilight-nvim - ]; - extraPackages = with pkgs; [ - # For nvim-lspconfig, Terraform Language Server - terraform-ls - # For tree-sitter - tree-sitter - nodejs - clang - clangStdenv.cc - ]; - extraConfig = '' - luafile ${initLua} - ''; - }; + programs.neovim = { + enable = true; + vimAlias = true; + viAlias = true; + plugins = with pkgs.vimPlugins; [ +# Libraries + plenary-nvim +# Disables and re-enables highlighting when searching + vim-cool +# Colour highlighting + vim-hexokinase +# Git porcelain + vim-fugitive +# Start screen + vim-startify +# Re-open with cursor at the same place + vim-lastplace +# Status Bar + lualine-nvim +# EasyMotion Equivalent + hop-nvim +# org-mode for vim + neorg +# base16 + config.base16.vim.plugin +# Fonts + nvim-web-devicons +# Completion + nvim-cmp +# Fuzzy Finder + telescope-nvim +# Buffers + bufferline-nvim +# Language Server + nvim-lspconfig + (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: with pkgs.tree-sitter-grammars; [ + tree-sitter-c + tree-sitter-lua + tree-sitter-rust + tree-sitter-bash + tree-sitter-css + tree-sitter-dockerfile + tree-sitter-go + tree-sitter-hcl + tree-sitter-html + tree-sitter-javascript + tree-sitter-markdown + tree-sitter-nix + tree-sitter-norg + tree-sitter-python + tree-sitter-regex + tree-sitter-scss + ])) +# Treesitter Plugins + nvim-ts-rainbow + nvim-treesitter-context + twilight-nvim + ]; + extraPackages = with pkgs; [ +# For nvim-lspconfig, Terraform Language Server + terraform-ls +# For tree-sitter + tree-sitter + nodejs + clang + clangStdenv.cc + ]; + }; + xdg.configFile."nvim/init.lua".source = initLua; } diff --git a/home/vim/init.lua b/home/vim/init.lua index 17187335..54a2c2be 100644 --- a/home/vim/init.lua +++ b/home/vim/init.lua @@ -1,8 +1,55 @@ +----------------------------------------------------------- +-- Variables +----------------------------------------------------------- local g = vim.g -- Global variables local opt = vim.opt -- Set options (global/buffer/windows-scoped) local wo = vim.wo -- Window local variables local api = vim.api -- Lua API +----------------------------------------------------------- +-- Nix Fuckery +----------------------------------------------------------- +opt.packpath:prepend{"@packDir@"} +opt.runtimepath:prepend{"@packDir@"} + +----------------------------------------------------------- +-- Base16 +----------------------------------------------------------- +vim.g.base16colorspace = 256 +vim.g.base16background = "@defaultSchemeName@" +g.base16_shell_path = "@base16ShellPath@" +vim.cmd("colorscheme base16-@defaultSchemeSlug@") +g.colors_name = "@defaultSchemeSlug@" + +local base16 = { + base00 = "@base00@", + base01 = "@base01@", + base02 = "@base02@", + base03 = "@base03@", + base04 = "@base04@", + base05 = "@base05@", + base06 = "@base06@", + base07 = "@base07@", + base08 = "@base08@", + base09 = "@base09@", + base0A = "@base0A@", + base0B = "@base0B@", + base0C = "@base0C@", + base0D = "@base0D@", + base0E = "@base0E@", + base0F = "@base0F@" +} + +api.nvim_create_autocmd("vimenter", { + command = "highlight Normal guibg=NONE ctermbg=NONE" +}) +api.nvim_create_autocmd("SourcePost", { + command = "highlight Normal ctermbg=NONE guibg=NONE | " .. + "highlight LineNr ctermbg=NONE guibg=NONE | " .. + "highlight SignColumn ctermbg=NONE guibg=NONE" +}) + + ----------------------------------------------------------- -- General ----------------------------------------------------------- @@ -16,7 +63,6 @@ opt.ttimeoutlen = 100 -- Mapping timeout ----------------------------------------------------------- -- Neovim UI ----------------------------------------------------------- -vim.cmd("colorscheme base16-default-dark") -- Color scheme opt.number = true -- Show line number opt.relativenumber = true -- Relative line numbers opt.showmatch = true -- Highlight matching parenthesis @@ -29,7 +75,7 @@ opt.smartcase = true -- Ignore lowercase for the whole opt.wrap = true -- Wrap on word boundary opt.linebreak = true -- Wrap on word boundary opt.showbreak = " ↳" -- Character to use to display word boundary -opt.termguicolors = true -- Enable 24-bit RGB colors +opt.termguicolors = false -- Enable 24-bit RGB colors opt.laststatus = 3 -- Set global statusline opt.cursorline = true -- Highlight cursor screenline opt.cmdheight = 1 -- Command entry line height @@ -60,20 +106,6 @@ opt.lazyredraw = true -- Faster scrolling opt.synmaxcol = 240 -- Max column for syntax highlight opt.updatetime = 700 -- ms to wait for trigger an event ------------------------------------------------------------ --- Base16 ------------------------------------------------------------ -vim.base16colorspace=256 - -api.nvim_create_autocmd("vimenter", { - command = "highlight Normal guibg=NONE ctermbg=NONE" -}) -api.nvim_create_autocmd("SourcePost", { - command = "highlight Normal ctermbg=NONE guibg=NONE | " .. - "highlight LineNr ctermbg=NONE guibg=NONE | " .. - "highlight SignColumn ctermbg=NONE guibg=NONE" -}) - ----------------------------------------------------------- -- Plugins ----------------------------------------------------------- @@ -130,11 +162,7 @@ end ----------------------------------------------------------- -- lualine -require('lualine').setup({ - options = { - theme = "base16", - }, -}) +require('lualine').setup{} -- nvim-cmp local cmp = require('cmp') @@ -282,7 +310,7 @@ require('bufferline').setup { show_close_icon = false, show_tab_indicators = true, persist_buffer_sort = true, -- whether or not custom sorted buffers should persist - separator_style = "padded_slant", + separator_style = "slant", always_show_bufferline = true, } } @@ -300,7 +328,7 @@ local highlightItems = { local commandString = "" for item, ground in pairs(highlightItems) do - commandString = "highlight " .. item .. " gui" .. ground .. "=" .. barColor .. " | " .. commandString + commandString = "highlight " .. item .. " cterm" .. ground .. "=" .. barColor .. " | " .. commandString end api.nvim_create_autocmd("ColorScheme", { diff --git a/modules/home/disables.nix b/modules/home/disables.nix new file mode 100644 index 00000000..7ec5bb70 --- /dev/null +++ b/modules/home/disables.nix @@ -0,0 +1,3 @@ +{ config, modulesPath, ... }: { + disabledModules = map (x: /. + "${toString modulesPath}/${x}") [ "programs/neovim.nix" ]; +} diff --git a/modules/home/neovim.nix b/modules/home/neovim.nix new file mode 100644 index 00000000..60457e60 --- /dev/null +++ b/modules/home/neovim.nix @@ -0,0 +1,412 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.neovim; + + jsonFormat = pkgs.formats.json { }; + + extraPython3PackageType = mkOptionType { + name = "extra-python3-packages"; + description = "python3 packages in python.withPackages format"; + check = with types; + (x: if isFunction x then isList (x pkgs.python3Packages) else false); + merge = mergeOneOption; + }; + + # Currently, upstream Neovim is pinned on Lua 5.1 for LuaJIT support. + # This will need to be updated if Neovim ever migrates to a newer + # version of Lua. + extraLua51PackageType = mkOptionType { + name = "extra-lua51-packages"; + description = "lua5.1 packages in lua5_1.withPackages format"; + check = with types; + (x: if isFunction x then isList (x pkgs.lua51Packages) else false); + merge = mergeOneOption; + }; + + pluginWithConfigType = types.submodule { + options = { + config = mkOption { + type = types.lines; + description = + "Script to configure this plugin. The scripting language should match type."; + default = ""; + }; + + type = mkOption { + type = + types.either (types.enum [ "lua" "viml" "teal" "fennel" ]) types.str; + description = + "Language used in config. Configurations are aggregated per-language."; + default = "viml"; + }; + + optional = mkEnableOption "optional" // { + description = "Don't load by default (load with :packadd)"; + }; + + plugin = mkOption { + type = types.package; + description = "vim plugin"; + }; + }; + }; + + # A function to get the configuration string (if any) from an element of 'plugins' + pluginConfig = p: + if p ? plugin && (p.config or "") != "" then '' + " ${p.plugin.pname or p.plugin.name} {{{ + ${p.config} + " }}} + '' else + ""; + + allPlugins = cfg.plugins ++ optional cfg.coc.enable { + type = "viml"; + plugin = cfg.coc.package; + config = cfg.coc.pluginConfig; + optional = false; + }; + + moduleConfigure = { + packages.home-manager = { + start = remove null (map + (x: if x ? plugin && x.optional == true then null else (x.plugin or x)) + allPlugins); + opt = remove null + (map (x: if x ? plugin && x.optional == true then x.plugin else null) + allPlugins); + }; + beforePlugins = ""; + }; + + extraMakeWrapperArgs = lib.optionalString (cfg.extraPackages != [ ]) + ''--suffix PATH : "${lib.makeBinPath cfg.extraPackages}"''; + extraMakeWrapperLuaCArgs = lib.optionalString (cfg.extraLuaPackages != [ ]) '' + --suffix LUA_CPATH ";" "${ + lib.concatMapStringsSep ";" pkgs.lua51Packages.getLuaCPath + cfg.extraLuaPackages + }"''; + extraMakeWrapperLuaArgs = lib.optionalString (cfg.extraLuaPackages != [ ]) '' + --suffix LUA_PATH ";" "${ + lib.concatMapStringsSep ";" pkgs.lua51Packages.getLuaPath + cfg.extraLuaPackages + }"''; + +in { + imports = [ + (mkRemovedOptionModule [ "programs" "neovim" "withPython" ] + "Python2 support has been removed from neovim.") + (mkRemovedOptionModule [ "programs" "neovim" "extraPythonPackages" ] + "Python2 support has been removed from neovim.") + ]; + + options = { + programs.neovim = { + enable = mkEnableOption "Neovim"; + + viAlias = mkOption { + type = types.bool; + default = false; + description = '' + Symlink vi to nvim binary. + ''; + }; + + vimAlias = mkOption { + type = types.bool; + default = false; + description = '' + Symlink vim to nvim binary. + ''; + }; + + vimdiffAlias = mkOption { + type = types.bool; + default = false; + description = '' + Alias vimdiff to nvim -d. + ''; + }; + + withNodeJs = mkOption { + type = types.bool; + default = false; + description = '' + Enable node provider. Set to true to + use Node plugins. + ''; + }; + + withRuby = mkOption { + type = types.nullOr types.bool; + default = true; + description = '' + Enable ruby provider. + ''; + }; + + withPython3 = mkOption { + type = types.bool; + default = true; + description = '' + Enable Python 3 provider. Set to true to + use Python 3 plugins. + ''; + }; + generatedConfigViml = mkOption { + type = types.unspecified; + visible = true; + readOnly = true; + description = '' + Generated vimscript config. + ''; + }; + extraPython3Packages = mkOption { + type = with types; either extraPython3PackageType (listOf package); + default = (_: [ ]); + defaultText = literalExpression "ps: [ ]"; + example = literalExpression "(ps: with ps; [ python-language-server ])"; + description = '' + A function in python.withPackages format, which returns a + list of Python 3 packages required for your plugins to work. + ''; + }; + + extraLuaPackages = mkOption { + type = with types; either extraLua51PackageType (listOf package); + default = [ ]; + defaultText = literalExpression "[ ]"; + example = literalExpression "(ps: with ps; [ luautf8 ])"; + description = '' + A function in lua5_1.withPackages format, which returns a + list of Lua packages required for your plugins to work. + ''; + }; + + generatedConfigs = mkOption { + type = types.attrsOf types.lines; + visible = true; + readOnly = true; + example = literalExpression '' + { + viml = ''' + " Generated by home-manager + set packpath^=/nix/store/cn8vvv4ymxjf8cfzg7db15b2838nqqib-vim-pack-dir + set runtimepath^=/nix/store/cn8vvv4ymxjf8cfzg7db15b2838nqqib-vim-pack-dir + '''; + + lua = ''' + -- Generated by home-manager + vim.opt.background = "dark" + '''; + }''; + description = '' + Generated configurations with as key their language (set via type). + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.neovim-unwrapped; + defaultText = literalExpression "pkgs.neovim-unwrapped"; + description = "The package to use for the neovim binary."; + }; + + finalPackage = mkOption { + type = types.package; + visible = false; + readOnly = true; + description = "Resulting customized neovim package."; + }; + + configure = mkOption { + type = types.attrsOf types.anything; + default = { }; + example = literalExpression '' + configure = { + customRC = $'''' + " here your custom configuration goes! + $''''; + packages.myVimPackage = with pkgs.vimPlugins; { + # loaded on launch + start = [ fugitive ]; + # manually loadable by calling `:packadd $plugin-name` + opt = [ ]; + }; + }; + ''; + description = '' + Deprecated. Please use the other options. + + Generate your init file from your list of plugins and custom commands, + and loads it from the store via nvim -u /nix/store/hash-vimrc + + + + This option is mutually exclusive with extraConfig + and plugins. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + set nocompatible + set nobackup + ''; + description = '' + Custom vimrc lines. + + + + This option is mutually exclusive with configure. + ''; + }; + + extraPackages = mkOption { + type = with types; listOf package; + default = [ ]; + example = literalExpression "[ pkgs.shfmt ]"; + description = "Extra packages available to nvim."; + }; + + plugins = mkOption { + type = with types; listOf (either package pluginWithConfigType); + default = [ ]; + example = literalExpression '' + with pkgs.vimPlugins; [ + yankring + vim-nix + { plugin = vim-startify; + config = "let g:startify_change_to_vcs_root = 0"; + } + ] + ''; + description = '' + List of vim plugins to install optionally associated with + configuration to be placed in init.vim. + + + + This option is mutually exclusive with configure. + ''; + }; + + coc = { + enable = mkEnableOption "Coc"; + + package = mkOption { + type = types.package; + default = pkgs.vimPlugins.coc-nvim; + defaultText = literalExpression "pkgs.vimPlugins.coc-nvim"; + description = "The package to use for the CoC plugin."; + }; + + settings = mkOption { + type = jsonFormat.type; + default = { }; + example = literalExpression '' + { + "suggest.noselect" = true; + "suggest.enablePreview" = true; + "suggest.enablePreselect" = false; + "suggest.disableKind" = true; + languageserver = { + haskell = { + command = "haskell-language-server-wrapper"; + args = [ "--lsp" ]; + rootPatterns = [ + "*.cabal" + "stack.yaml" + "cabal.project" + "package.yaml" + "hie.yaml" + ]; + filetypes = [ "haskell" "lhaskell" ]; + }; + }; + }; + ''; + description = '' + Extra configuration lines to add to + $XDG_CONFIG_HOME/nvim/coc-settings.json + See + + for options. + ''; + }; + + pluginConfig = mkOption { + type = types.lines; + default = ""; + description = "Script to configure CoC. Must be viml."; + }; + }; + }; + }; + + config = let + # transform all plugins into an attrset + pluginsNormalized = map (x: + if (x ? plugin) then + x + else { + type = x.type or "viml"; + plugin = x; + config = ""; + optional = false; + }) allPlugins; + suppressNotVimlConfig = p: + if p.type != "viml" then p // { config = ""; } else p; + + neovimConfig = pkgs.neovimUtils.makeNeovimConfig { + inherit (cfg) extraPython3Packages withPython3 withRuby viAlias vimAlias; + withNodeJs = cfg.withNodeJs || cfg.coc.enable; + configure = cfg.configure // moduleConfigure; + plugins = map suppressNotVimlConfig pluginsNormalized; + customRC = cfg.extraConfig; + }; + + in mkIf cfg.enable { + warnings = optional (cfg.configure != { }) '' + programs.neovim.configure is deprecated. + Other programs.neovim options can override its settings or ignore them. + Please use the other options at your disposal: + configure.packages.*.opt -> programs.neovim.plugins = [ { plugin = ...; optional = true; }] + configure.packages.*.start -> programs.neovim.plugins = [ { plugin = ...; }] + configure.customRC -> programs.neovim.extraConfig + ''; + programs.neovim.generatedConfigViml = neovimConfig; + programs.neovim.generatedConfigs = let + grouped = lib.lists.groupBy (x: x.type) pluginsNormalized; + concatConfigs = lib.concatMapStrings (p: p.config); + in mapAttrs (name: vals: concatConfigs vals) grouped; + + home.packages = [ cfg.finalPackage ]; + + xdg.configFile."nvim/lua/init-home-manager.lua" = + mkIf (hasAttr "lua" config.programs.neovim.generatedConfigs) { + text = config.programs.neovim.generatedConfigs.lua; + }; + xdg.configFile."nvim/coc-settings.json" = mkIf cfg.coc.enable { + source = jsonFormat.generate "coc-settings.json" cfg.coc.settings; + }; + + programs.neovim.finalPackage = pkgs.wrapNeovimUnstable cfg.package + (neovimConfig // { + wrapperArgs = (lib.escapeShellArgs neovimConfig.wrapperArgs) + " " + + extraMakeWrapperArgs + " " + extraMakeWrapperLuaCArgs + " " + + extraMakeWrapperLuaArgs; + wrapRc = false; + }); + + programs.bash.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + programs.fish.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + programs.zsh.shellAliases = mkIf cfg.vimdiffAlias { vimdiff = "nvim -d"; }; + }; +}