neovim: add vale & ltex-lsp

This commit is contained in:
ooks-io 2025-01-24 22:30:45 +11:00
parent aa3af5f0e5
commit 5604745c78
16 changed files with 1442 additions and 18 deletions

View file

@ -4,5 +4,8 @@
lspkind.enable = true;
lspSignature.enable = true;
trouble = {enable = true;};
null-ls = {
enable = true;
};
};
}

View file

@ -2,9 +2,19 @@
vim = {
languages.markdown = {
enable = true;
vale.enable = true;
ltex.enable = true;
extensions = {
render-markdown-nvim = {
enable = true;
setupOpts = {
heading = {
border = true;
width = "block";
left_pad = 3;
right_pad = 4;
};
};
};
};
};

View file

@ -7,9 +7,11 @@
useSystemClipboard = true;
autopairs.nvim-autopairs.enable = true;
hideSearchHighlight = true;
spellcheck.enable = true;
theme = {
enable = false;
};
spellcheck = {
enable = true;
};
};
}

View file

@ -1,20 +1,31 @@
{
{hozen, ...}: let
inherit (hozen) color;
in {
vim.gruvbox-material = {
enable = true;
contrast = "medium";
italics = false;
transparent = false;
extraConfig =
# lua
''
local g_colors = require("gruvbox-material.colors")
local colors = g_colors.get(vim.o.background, "soft")
additionalHighlights = {
RenderMarkdownH1Bg = {bg = "#${color.layout.body}";};
RenderMarkdownH2Bg = {bg = "#${color.layout.body}";};
RenderMarkdownH3Bg = {bg = "#${color.layout.body}";};
RenderMarkdownH4Bg = {bg = "#${color.layout.body}";};
RenderMarkdownH5Bg = {bg = "#${color.layout.body}";};
RenderMarkdownH6Bg = {bg = "#${color.layout.body}";};
"@markup.heading.1" = {
fg = "#${color.green.base}";
bold = true;
};
"@markup.heading.2" = {
fg = "#${color.blue.base}";
bold = true;
};
-- Noice
vim.api.nvim_set_hl(0, "NoiceCmdlinePopupBorderHelp", { fg = colors.yellow })
vim.api.nvim_set_hl(0, "NoiceCmdlinePopupBorder", { fg = colors.grey1 })
vim.api.nvim_set_hl(0, "NoiceCmdlineIcon", { fg = colors.green })
vim.api.nvim_set_hl(0, "NoiceCmdLinePopupTitle", { fg = colors.grey1 })
'';
NoiceCmdlinePopupBorder = {fg = "#${color.border.active}";};
NoiceCmdlinePopupBorderHelp = {fg = "#${color.yellow.base}";};
NoiceCmdlineIcon = {fg = "#${color.green.base}";};
NoiceCmdLinePopupTitle = {fg = "#${color.typography.text}";};
};
};
}

View file

@ -2,7 +2,8 @@
imports = [
./gruvbox-material
./telescope
./obsidian
./theme
./notes
./languages
];
}

View file

@ -5,8 +5,105 @@
...
}: let
inherit (lib) mkOption mkIf boolToString;
inherit (lib.types) bool enum lines;
inherit (lib.nvim.dag) entryAfter;
inherit (lib.types) bool enum lines nullOr str submodule attrsOf;
inherit (lib.nvim.dag) entryBefore;
inherit (lib.nvim.lua) toLuaObject;
# hack to get around nvf's handling of prefixed @ in toLuaObject
wrapHighlights = highlights:
lib.mapAttrs' (
name: value:
if lib.hasPrefix "@" name
then lib.nameValuePair "hl_${name}" value
else lib.nameValuePair name value
)
highlights;
highlightOpts = submodule {
options = {
# https://neovim.io/doc/user/api.html#nvim_set_hl()
fg = mkOption {
type = nullOr str;
default = null;
description = "Foreground color";
};
bg = mkOption {
type = nullOr str;
default = null;
description = "Background color";
};
sp = mkOption {
type = nullOr str;
default = null;
description = "SP color";
};
blend = mkOption {
type = nullOr bool;
default = null;
description = "Blend attribute";
};
bold = mkOption {
type = nullOr bool;
default = null;
description = "Italic attribute";
};
standout = mkOption {
type = nullOr bool;
default = null;
description = "Standout attribute";
};
underline = mkOption {
type = nullOr bool;
default = null;
description = "underline attribute";
};
undercurl = mkOption {
type = nullOr bool;
default = null;
description = "Undercurl attribute";
};
underdouble = mkOption {
type = nullOr bool;
default = null;
description = "Underdouble attribute";
};
underdotted = mkOption {
type = nullOr bool;
default = null;
description = "Underdotted attribute";
};
underdashed = mkOption {
type = nullOr bool;
default = null;
description = "Underdashed attribute";
};
strikethrough = mkOption {
type = nullOr bool;
default = null;
description = "Strikethrough attribute";
};
italic = mkOption {
type = nullOr bool;
default = null;
description = "Bold attribute";
};
reverse = mkOption {
type = nullOr bool;
default = null;
description = "Reverse attribute";
};
nocombine = mkOption {
type = nullOr bool;
default = null;
description = "Nocombine attribute";
};
link = mkOption {
type = nullOr str;
default = null;
description = "Link attribute";
};
};
};
cfg = config.vim.gruvbox-material;
in {
@ -45,13 +142,18 @@ in {
type = lines;
description = "Additional lua configuration after";
};
additionalHighlights = mkOption {
type = attrsOf highlightOpts;
default = {};
description = "Additional highlight groups to be applied after theme setup.";
};
};
config = mkIf cfg.enable {
vim = {
startPlugins = [pkgs.vimPlugins.gruvbox-material-nvim];
luaConfigRC.theme =
entryAfter ["basic"]
entryBefore ["pluginConfigs" "lazyConfigs"]
/*
lua
*/
@ -72,7 +174,14 @@ in {
highlight = ${boolToString cfg.signsHighlight},
},
}
${cfg.extraConfig}
local extra_highlights = ${toLuaObject (wrapHighlights cfg.additionalHighlights)}
for group_name, settings in pairs(extra_highlights) do
-- Unwrap our prefixed names back to @ form
local actual_name = group_name:gsub("^hl_@", "@")
vim.api.nvim_set_hl(0, actual_name, settings)
end
'';
};
};

View file

@ -0,0 +1 @@
{imports = [./markdown.nix];}

View file

@ -0,0 +1,135 @@
# modules/plugins/vale/default.nix
{
config,
pkgs,
lib,
...
}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.types) package enum str;
languages = [
"auto"
"ar"
"ast-ES"
"be-BY"
"br-FR"
"ca-ES"
"ca-ES-valencia"
"da-DK"
"de"
"de-AT"
"de-CH"
"de-DE"
"de-DE-x-simple-language"
"el-GR"
"en"
"en-AU"
"en-CA"
"en-GB"
"en-NZ"
"en-US"
"en-ZA"
"eo"
"es"
"es-AR"
"fa"
"fr"
"ga-IE"
"gl-ES"
"it"
"ja-JP"
"km-KH"
"nl"
"nl-BE"
"pl-PL"
"pt"
"pt-AO"
"pt-BR"
"pt-MZ"
"pt-PT"
"ro-RO"
"ru-RU"
"sk-SK"
"sl-SI"
"sv"
"ta-IN"
"tl-PH"
"uk-UA"
"zh-CN"
];
cfg = config.vim.languages.markdown;
in {
options.vim.languages.markdown = {
vale = {
enable = mkEnableOption "Vale linting support";
package = mkOption {
type = package;
default = pkgs.vale.withStyles (styles: [
styles.proselint
styles.microsoft
styles.write-good
styles.readability
styles.alex
]);
description = "Vale package to use";
};
};
ltex = {
enable = mkEnableOption "Enable ltex-ls";
package = mkOption {
type = package;
default = pkgs.ltex-ls;
};
language = mkOption {
type = enum languages;
default = "en";
};
modelPath = mkOption {
type = str;
default = "~/.config/nvf/models/ngrams/";
};
};
};
config = mkMerge [
(mkIf cfg.vale.enable {
vim.lsp.null-ls = {
enable = true;
sources.vale-lint =
# lua
''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.vale.with({
command = "${cfg.vale.package}/bin/vale",
diagnostics_format = "#{m} [#{c}]"
})
)
'';
};
})
(mkIf cfg.ltex.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.ltex-lsp =
# lua
''
lspconfig.ltex.setup{
cmd = {"${cfg.ltex.package}/bin/ltex-ls"},
capabilities = capabilities;
on_attach = default_on_attach;
settings = {
ltex = {
language = "${cfg.ltex.language}",
additionalRules = {
languageModel = "${cfg.ltex.modelPath}",
},
},
},
}
'';
})
];
}

View file

@ -0,0 +1,3 @@
{
imports = [./obsidian];
}

View file

@ -0,0 +1,428 @@
{
lib,
config,
...
}: let
inherit (lib) mkOption mkEnableOption;
inherit (lib.types) str nullOr bool enum listOf int float attrsOf submodule;
inherit (lib.nvim.types) mkPluginSetupOption luaInline;
# All possible Neovim modes
neovimModes = [
"n"
"no"
"nov"
"noV"
"noCTRL-v"
"niI"
"niR"
"niV"
"nt"
"ntT"
"v"
"vs"
"V"
"Vs"
"CTRL-V"
"CTRL-Vs"
"s"
"S"
"CTRL-S"
"i"
"ic"
"ix"
"R"
"Rc"
"Rx"
"Rv"
"Rvc"
"Rvx"
"c"
"cr"
"cv"
"cvr"
"r"
"rm"
"r?"
"!"
"t"
];
# Preset options
presetOptions = enum ["obsidian" "lazy" "none"];
# Log level options
logLevelOptions = enum ["error" "warn" "info" "debug" "trace"];
# Anti-conceal ignore options submodule
antiConcealIgnoreOptions = submodule {
options = {
head_icon = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where head icon anti-conceal behavior will be ignored";
};
head_background = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where head background anti-conceal behavior will be ignored";
};
head_border = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where head border anti-conceal behavior will be ignored";
};
code_language = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where code language anti-conceal behavior will be ignored";
};
code_background = mkOption {
type = nullOr bool;
default = true;
description = "Whether to ignore code background anti-conceal behavior";
};
code_border = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where code border anti-conceal behavior will be ignored";
};
dash = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where dash anti-conceal behavior will be ignored";
};
bullet = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where bullet anti-conceal behavior will be ignored";
};
check_icon = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where check icon anti-conceal behavior will be ignored";
};
check_scope = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where check scope anti-conceal behavior will be ignored";
};
quote = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where quote anti-conceal behavior will be ignored";
};
table_border = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where table border anti-conceal behavior will be ignored";
};
callout = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where callout anti-conceal behavior will be ignored";
};
link = mkOption {
type = nullOr (listOf (enum neovimModes));
default = null;
description = "Modes where link anti-conceal behavior will be ignored";
};
sign = mkOption {
type = nullOr bool;
default = true;
description = "Whether to ignore sign anti-conceal behavior";
};
};
};
# Injection options submodule
injectionOptions = submodule {
options = {
enabled = mkOption {
type = nullOr bool;
default = null;
description = "Whether this injection is enabled";
};
query = mkOption {
type = luaInline;
description = "Treesitter query for the injection";
};
};
};
headingWidthType = enum ["block" "full"];
headingPositionType = enum ["right" "inline" "overlay"];
in {
options.vim.notes.render-markdown-nvim = {
enable = mkEnableOption "Inline markdown rendering";
setupOpts = mkPluginSetupOption "render-markdown" {
enabled = mkOption {
type = bool;
default = true;
description = "Whether Markdown should be rendered by default";
};
render_modes = mkOption {
type = listOf (enum neovimModes);
default = ["n" "c" "t"];
description = ''
Vim modes that will show a rendered view of the markdown file.
Individual components can be enabled for other modes.
'';
};
max_file_size = mkOption {
type = float;
default = 10.0;
description = "Maximum file size (in MB) that this plugin will attempt to render";
};
debounce = mkOption {
type = int;
default = 100;
description = "Milliseconds that must pass before updating marks";
};
preset = mkOption {
type = presetOptions;
default = "none";
description = "Pre-configured settings to mimic various target user experiences";
};
log_level = mkOption {
type = logLevelOptions;
default = "error";
description = "The level of logs to write to file";
};
log_runtime = mkOption {
type = bool;
default = false;
description = "Print runtime of main update method";
};
file_types = mkOption {
type = listOf str;
default = ["markdown"];
description = "Filetypes this plugin will run on";
};
injections = mkOption {
type = attrsOf injectionOptions;
default = {
gitcommit = {
enabled = true;
query = ''
((message) @injection.content
(#set! injection.combined)
(#set! injection.include-children)
(#set! injection.language "markdown"))
'';
};
};
description = "Language injections for known filetypes";
};
anti_conceal = {
enabled = mkOption {
type = bool;
default = true;
description = "Enable hiding added text on the cursor line";
};
ignore = mkOption {
type = antiConcealIgnoreOptions;
default = {
code_background = true;
sign = true;
};
description = "Elements to always show, ignoring anti-conceal behavior";
};
above = mkOption {
type = int;
default = 0;
description = "Number of lines above cursor to show";
};
below = mkOption {
type = int;
default = 0;
description = "Number of lines below cursor to show";
};
};
padding = {
highlight = mkOption {
type = str;
default = "Normal";
description = "Highlight to use when adding whitespace";
};
};
on = {
attach = mkOption {
type = nullOr luaInline;
default = null;
description = "Called when plugin initially attaches to a buffer";
};
render = mkOption {
type = nullOr luaInline;
default = null;
description = "Called after plugin renders a buffer";
};
};
latex = {
enabled = mkOption {
type = nullOr bool;
default = null;
description = "Whether LaTeX should be rendered";
};
render_modes = mkOption {
type = nullOr bool;
default = null;
description = "Additional modes to render LaTeX";
};
converter = mkOption {
type = nullOr str;
default = null;
description = "Executable used to convert latex formula to rendered unicode";
};
highlight = mkOption {
type = nullOr str;
default = null;
description = "Highlight for LaTeX blocks";
};
top_pad = mkOption {
type = nullOr int;
default = null;
description = "Amount of empty lines above LaTeX blocks";
};
bottom_pad = mkOption {
type = nullOr int;
default = null;
description = "Amount of empty lines below LaTeX blocks";
};
};
heading = {
enabled = mkOption {
type = nullOr bool;
default = null;
description = "Enable heading icon & background rendering";
};
render_modes = mkOption {
type = nullOr bool;
default = null;
description = "Additional modes to render headings";
};
sign = mkOption {
type = nullOr bool;
default = null;
description = "Turn on/off sign column related rendering";
};
icons = mkOption {
type = nullOr (listOf str);
default = null;
description = "Icons for different heading levels";
};
position = mkOption {
type = nullOr headingPositionType;
default = null;
description = "How icons fill available space";
};
signs = mkOption {
type = nullOr (listOf str);
default = null;
description = "Signs added to the sign column if enabled";
};
width = mkOption {
type = nullOr (either headingWidthType (listOf headingWidthType));
default = null;
description = "Width of the heading background";
};
left_margin = mkOption {
type = nullOr (either float (listOf float));
default = null;
description = "Margin to add to left of headings";
};
left_pad = mkOption {
type = nullOr (either float (listOf float));
default = null;
description = "Padding to add to left of headings";
};
right_pad = mkOption {
type = nullOr (either float (listOf float));
default = null;
description = "Padding to add to right of headings when width is 'block'";
};
min_width = mkOption {
type = nullOr (either int (listOf int));
default = null;
description = "Minimum width for headings when width is 'block'";
};
border = mkOption {
type = nullOr (either bool (listOf bool));
default = null;
description = "Add border above and below headings";
};
border_virtual = mkOption {
type = nullOr bool;
default = null;
description = "Always use virtual lines for heading borders";
};
border_prefix = mkOption {
type = nullOr bool;
default = null;
description = "Highlight border start using foreground highlight";
};
above = mkOption {
type = nullOr str;
default = null;
description = "Character used above heading for border";
};
below = mkOption {
type = nullOr str;
default = null;
description = "Character used below heading for border";
};
backgrounds = mkOption {
type = nullOr (listOf str);
default = null;
description = "Highlights for heading backgrounds per level";
};
foregrounds = mkOption {
type = nullOr (listOf str);
default = null;
description = "Highlights for heading and sign icons per level";
};
};
};
};
}