Merge remote-tracking branch 'upstream/main'

This commit is contained in:
PartyWumpus 2025-09-17 18:51:17 +01:00
commit 31eb99a846
360 changed files with 11321 additions and 6338 deletions

View file

@ -1,4 +1,5 @@
{
self,
inputs,
lib,
}: {
@ -23,7 +24,7 @@
specialArgs =
extraSpecialArgs
// {
inherit inputs;
inherit self inputs;
modulesPath = toString ./.;
};
modules = concatLists [

View file

@ -4,6 +4,7 @@
inherit (lib.nvim.config) batchRenameOptions;
renamedVimOpts = batchRenameOptions ["vim"] ["vim" "options"] {
# 2024-12-01
colourTerm = "termguicolors";
mouseSupport = "mouse";
cmdHeight = "cmdheight";
@ -15,6 +16,9 @@
autoIndent = "autoindent";
wordWrap = "wrap";
showSignColumn = "signcolumn";
# 2025-02-07
scrollOffset = "scrolloff";
};
in {
imports = concatLists [
@ -93,9 +97,31 @@ in {
# 2024-12-02
(mkRenamedOptionModule ["vim" "enableEditorconfig"] ["vim" "globals" "editorconfig"])
# 2025-02-06
(mkRemovedOptionModule ["vim" "disableArrows"] ''
Top-level convenience options are now in the process of being removed from nvf as
their behaviour was abstract, and confusing. Please use 'vim.options' or 'vim.luaConfigRC'
to replicate previous behaviour.
'')
# 2025-04-04
(mkRemovedOptionModule ["vim" "lsp" "lsplines"] ''
lsplines module has been removed from nvf, as its functionality is now built into Neovim
under the diagnostics module. Please consider using one of 'vim.diagnostics.config' or
'vim.luaConfigRC' to configure LSP lines for Neovim through its own diagnostics API.
'')
# 2025-05-04
(mkRemovedOptionModule ["vim" "useSystemClipboard"] ''
Clipboard behaviour should now be controlled through the new, more fine-grained module
interface found in 'vim.clipboard'. To replicate previous behaviour, you may either
add 'vim.opt.clipboard:append("unnamedplus")' in luaConfigRC, or preferably set it
in 'vim.clipboard.registers'. Please see the documentation for the new module for more
details, or open an issue if you are confused.
'')
]
# 2024-12-01
# Migrated via batchRenameOptions. Further batch renames must be below this line.
renamedVimOpts
];

View file

@ -23,7 +23,9 @@
"completion"
"dashboard"
"debugger"
"diagnostics"
"filetree"
"formatter"
"git"
"languages"
"lsp"
@ -31,11 +33,12 @@
"minimap"
"notes"
"projects"
"repl"
"rich-presence"
"runner"
"session"
"snippets"
# "spellcheck" # FIXME: see neovim/init/spellcheck.nix
"spellcheck"
"statusline"
"tabline"
"terminal"

View file

@ -0,0 +1,188 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.lists) filter;
inherit (lib.strings) optionalString;
inherit (lib.types) nullOr submodule listOf str bool;
inherit (lib.nvim.types) luaInline;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.dag) entryAfter;
autocommandType = submodule {
options = {
enable =
mkEnableOption ""
// {
default = true;
description = "Whether to enable this autocommand.";
};
event = mkOption {
type = nullOr (listOf str);
default = null;
example = ["BufRead" "BufWritePre"];
description = "The event(s) that trigger the autocommand.";
};
pattern = mkOption {
type = nullOr (listOf str);
default = null;
example = ["*.lua" "*.vim"];
description = "The file pattern(s) that determine when the autocommand applies.";
};
callback = mkOption {
type = nullOr luaInline;
default = null;
example = literalExpression ''
lib.generators.mkLuaInline '''
function()
print("Saving a Lua file...")
end
''''
'';
description = "Lua function to be called when the event(s) are triggered.";
};
command = mkOption {
type = nullOr str;
default = null;
description = ''
Vim command to be executed when the event(s) are triggered.
Cannot be defined if the `callback` option is already defined.
'';
};
group = mkOption {
type = nullOr str;
default = null;
example = "MyAutoCmdGroup";
description = "An optional autocommand group to manage related autocommands.";
};
desc = mkOption {
type = nullOr str;
default = null;
example = "Notify when saving a Lua file";
description = "A description for the autocommand.";
};
once = mkOption {
type = bool;
default = false;
description = "Whether to run the autocommand only once.";
};
nested = mkOption {
type = bool;
default = false;
description = "Whether to allow nested autocommands to trigger.";
};
};
};
autogroupType = submodule {
options = {
enable =
mkEnableOption ""
// {
default = true;
description = "Whether to enable this autocommand group.";
};
name = mkOption {
type = str;
example = "MyAutoCmdGroup";
description = "The name of the autocommand group.";
};
clear = mkOption {
type = bool;
default = true;
description = ''
Whether to clear existing autocommands in this group before defining new ones.
This helps avoid duplicate autocommands.
'';
};
};
};
cfg = config.vim;
in {
options.vim = {
augroups = mkOption {
type = listOf autogroupType;
default = [];
description = ''
A list of Neovim autogroups, which are used to organize and manage related
autocommands together. Groups allow multiple autocommands to be cleared
or redefined collectively, preventing duplicate definitions.
Each autogroup consists of a name and a boolean indicating whether to clear
existing autocommands.
'';
};
autocmds = mkOption {
type = listOf autocommandType;
default = [];
description = ''
A list of Neovim autocommands to be registered.
Each entry defines an autocommand, specifying events, patterns, a callback or Vim
command, an optional group, a description, and execution settings.
'';
};
};
config = {
vim = let
enabledAutocommands = filter (cmd: cmd.enable) cfg.autocmds;
enabledAutogroups = filter (au: au.enable) cfg.augroups;
in {
luaConfigRC = {
augroups = entryAfter ["pluginConfigs"] (optionalString (enabledAutogroups != []) ''
local nvf_autogroups = {}
for _, group in ipairs(${toLuaObject enabledAutogroups}) do
if group.name then
nvf_autogroups[group.name] = { clear = group.clear }
end
end
for group_name, options in pairs(nvf_autogroups) do
vim.api.nvim_create_augroup(group_name, options)
end
'');
autocmds = entryAfter ["pluginConfigs"] (optionalString (enabledAutocommands != []) ''
local nvf_autocommands = ${toLuaObject enabledAutocommands}
for _, autocmd in ipairs(nvf_autocommands) do
vim.api.nvim_create_autocmd(
autocmd.event,
{
group = autocmd.group,
pattern = autocmd.pattern,
buffer = autocmd.buffer,
desc = autocmd.desc,
callback = autocmd.callback,
command = autocmd.command,
once = autocmd.once,
nested = autocmd.nested
}
)
end
'');
};
};
assertions = [
{
assertion = builtins.all (cmd: (cmd.command == null || cmd.callback == null)) cfg.autocmds;
message = "An autocommand cannot have both 'command' and 'callback' defined at the same time.";
}
];
};
}

View file

@ -6,46 +6,27 @@
inherit (lib.options) mkOption mkEnableOption literalMD;
inherit (lib.strings) optionalString;
inherit (lib.attrsets) optionalAttrs;
inherit (lib.types) enum bool str int either;
inherit (lib.types) enum bool str either;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.dag) entryAfter;
inherit (lib.nvim.binds) pushDownDefault;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.types) luaInline;
cfg = config.vim;
in {
options.vim = {
disableArrows = mkOption {
type = bool;
default = false;
description = "Set to prevent arrow keys from moving cursor";
};
hideSearchHighlight = mkOption {
type = bool;
default = false;
description = "Hide search highlight so it doesn't stay highlighted";
};
scrollOffset = mkOption {
type = int;
default = 8;
description = "Start scrolling this number of lines from the top or bottom of the page.";
};
syntaxHighlighting = mkOption {
type = bool;
default = !config.vim.treesitter.highlight.enable;
description = "Enable syntax highlighting";
};
useSystemClipboard = mkOption {
type = bool;
default = false;
description = "Make use of the clipboard for default yank and paste operations. Don't use * and +";
};
lineNumberMode = mkOption {
type = enum ["relative" "number" "relNumber" "none"];
default = "relNumber";
@ -150,10 +131,6 @@ in {
# to pre-set Neovim options. Fear not, though as the Lua DAG is still as powerful as it
# could be.
luaConfigRC.basic = entryAfter ["globalsScript"] ''
${optionalString cfg.useSystemClipboard ''
vim.opt.clipboard:append("unnamedplus")
''}
${optionalString cfg.syntaxHighlighting ''
vim.cmd("syntax on")
''}

View file

@ -0,0 +1,80 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) str submodule;
inherit (lib.attrsets) mapAttrs mapAttrsToList filterAttrs;
cfg = config.vim.clipboard;
in {
options = {
vim = {
clipboard = {
enable = mkEnableOption ''
clipboard management for Neovim. Users may still choose to manage their
clipboard through [](#opt-vim.options) should they wish to avoid using
this module.
'';
registers = mkOption {
type = str;
default = "";
example = "unnamedplus";
description = ''
The register to be used by the Neovim clipboard. Recognized types are:
* unnamed: Vim will use the clipboard register `"*"` for all yank, delete,
change and put operations which would normally go to the unnamed register.
* unnamedplus: A variant of the "unnamed" flag which uses the clipboard register
`"+"` ({command}`:h quoteplus`) instead of register `"*"` for all yank, delete,
change and put operations which would normally go to the unnamed register.
When `unnamed` and `unnamedplus` is included simultaneously as `"unnamed,unnamedplus"`,
yank and delete operations (but not put) will additionally copy the text into register `"*"`.
Please see {command}`:h clipboard` for more details.
'';
};
providers = mkOption {
type = submodule {
options = let
clipboards = {
# name = "package name";
wl-copy = "wl-clipboard";
xclip = "xclip";
xsel = "xsel";
};
in
mapAttrs (name: pname: {
enable = mkEnableOption name;
package = mkPackageOption pkgs pname {nullable = true;};
})
clipboards;
};
default = {};
description = ''
Clipboard providers for which packages will be added to nvf's
{option}`extraPackages`. The `package` field may be set to `null`
if related packages are already found in system packages to
potentially reduce closure sizes.
'';
};
};
};
};
config = mkIf cfg.enable {
vim = {
options.clipboard = cfg.registers;
extraPackages = mapAttrsToList (_: v: v.package) (
filterAttrs (_: v: v.enable && v.package != null) cfg.providers
);
};
};
}

View file

@ -1,8 +1,12 @@
{
imports = [
./autocmds.nix
./basic.nix
./clipboard.nix
./debug.nix
./diagnostics.nix
./highlight.nix
./lsp.nix
./spellcheck.nix
];
}

View file

@ -0,0 +1,116 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.types) attrsOf anything oneOf bool submodule;
inherit (lib.nvim.dag) entryAfter;
inherit (lib.nvim.types) luaInline;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.diagnostics;
# Takes a boolean, a table, or a Lua list ({key = value}). We
# would like to allow all of those types, while clearly expressing
# them in the option's type. As such, this type is what it is.
diagnosticType = oneOf [(attrsOf anything) bool luaInline];
diagnosticsSubmodule = submodule {
# The table might need to be extended, so let's allow that case
# with a freeform type of what is supported by diagnostics opts.
freeformType = attrsOf diagnosticType;
options = {
underline = mkOption {
type = diagnosticType;
default = true;
description = "Use underline for diagnostics.";
};
virtual_text = mkOption {
type = diagnosticType;
default = false;
example = literalExpression ''
{
format = lib.generators.mkLuaInline '''
function(diagnostic)
return string.format("%s (%s)", diagnostic.message, diagnostic.source)
end
''';
}
'';
description = ''
Use virtual text for diagnostics. If multiple diagnostics are set for a namespace,
one prefix per diagnostic + the last diagnostic message are shown.
'';
};
virtual_lines = mkOption {
type = diagnosticType;
default = false;
description = ''
Use virtual lines for diagnostics.
'';
};
signs = mkOption {
type = diagnosticType;
default = false;
example = literalExpression ''
signs.text = lib.generators.mkLuaInline '''
{
[vim.diagnostic.severity.ERROR] = "󰅚 ",
[vim.diagnostic.severity.WARN] = "󰀪 ",
}
''';
'';
description = ''
Use signs for diagnostics. See {command}`:help diagnostic-signs`.
:::{.note}
The code presented in that example section uses Lua expressions as object keys which
only translate well if you use `lib.generators.mkLuaInline` as in the example.
:::
'';
};
update_in_insert = mkOption {
type = bool;
default = false;
description = ''
Update diagnostics in Insert mode. If `false`, diagnostics will
be updated on InsertLeave ({command}`:help InsertLeave`).
'';
};
};
};
in {
options.vim = {
diagnostics = {
enable = mkEnableOption "diagnostics module for Neovim";
config = mkOption {
type = diagnosticsSubmodule;
default = {};
description = ''
Values that will be passed to `vim.diagnostic.config` after being converted
to a Lua table. Possible values for each key can be found in the help text
for `vim.diagnostics.Opts`. You may find more about the diagnostics API of
Neovim in {command}`:help diagnostic-api`.
:::{.note}
This option is freeform. You may set values that are not present in nvf
documentation, but those values will not be fully type checked. Please
refer to the help text for `vim.diagnostic.Opts` for appropriate values.
:::
'';
};
};
};
config.vim = mkIf cfg.enable {
luaConfigRC.diagnostics = entryAfter ["basic"] ''
vim.diagnostic.config(${toLuaObject cfg.config})
'';
};
}

View file

@ -5,15 +5,14 @@
}: let
inherit (lib.options) mkOption;
inherit (lib.types) nullOr attrsOf listOf submodule bool ints str enum;
inherit (lib.strings) hasPrefix concatLines;
inherit (lib.strings) concatLines;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.nvim.dag) entryBetween;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.types) hexColor;
mkColorOption = target:
mkOption {
type = nullOr hexColor;
type = nullOr str;
default = null;
example = "#ebdbb2";
description = ''

View file

@ -0,0 +1,93 @@
{
config,
lib,
...
}: let
inherit (builtins) filter;
inherit (lib.modules) mkIf mkMerge mkDefault;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.types) attrsOf;
inherit (lib.strings) concatLines;
inherit (lib.attrsets) mapAttrsToList attrNames filterAttrs;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.languages) lspOptions;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.lsp;
lspConfigurations =
mapAttrsToList (
name: value: ''
vim.lsp.config["${name}"] = ${toLuaObject value}
''
)
cfg.servers;
enabledServers = filterAttrs (_: u: u.enable) cfg.servers;
in {
options = {
vim.lsp = {
enable = mkEnableOption ''
global LSP functionality for Neovim.
This option controls whether to enable LSP functionality within modules under
{option}`vim.languages`. You do not need to set this to `true` for language
servers defined in {option}`vim.lsp.servers` to take effect, since they are
enabled automatically.
'';
servers = mkOption {
type = attrsOf lspOptions;
default = {};
example = ''
{
"*" = {
root_markers = [".git"];
capabilities = {
textDocument = {
semanticTokens = {
multilineTokenSupport = true;
};
};
};
};
"clangd" = {
filetypes = ["c"];
};
}
'';
description = ''
LSP configurations that will be managed using `vim.lsp.config()` and related
utilities added in Neovim 0.11. LSPs defined here will be added to the
resulting {file}`init.lua` using `vim.lsp.config` and enabled through
`vim.lsp.enable()` API from Neovim below the configuration table.
You may review the generated configuration by running {command}`nvf-print-config`
in a shell. Please see {command}`:help lsp-config` for more details
on the underlying API.
'';
};
};
};
config = mkMerge [
{
vim.lsp.servers."*" = {
capabilities = mkDefault (mkLuaInline "capabilities");
on_attach = mkDefault (mkLuaInline "default_on_attach");
};
}
(mkIf (cfg.servers != {}) {
vim.luaConfigRC.lsp-servers = entryAnywhere ''
-- Individual LSP configurations managed by nvf.
${concatLines lspConfigurations}
-- Enable configured LSPs explicitly
vim.lsp.enable(${toLuaObject (filter (name: name != "*") (attrNames enabledServers))})
'';
})
];
}

View file

@ -94,6 +94,8 @@ in {
Enabling this option will unconditionally set
{option}`vim.spellcheck.enable` to true as vim-dirtytalk
depends on spellchecking having been set up.
Run {command}`:DirtytalkUpdate` on first use to download the spellfile.
:::
'';
};

View file

@ -3,7 +3,7 @@
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.modules) mkMerge;
inherit (lib.trivial) pipe;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.lists) flatten;
@ -26,34 +26,6 @@
in {
config = {
vim.keymaps = mkMerge [
(
mkIf cfg.disableArrows [
{
key = "<up>";
mode = ["n" "i"];
action = "<nop>";
noremap = false;
}
{
key = "<down>";
mode = ["n" "i"];
action = "<nop>";
noremap = false;
}
{
key = "<left>";
mode = ["n" "i"];
action = "<nop>";
noremap = false;
}
{
key = "<right>";
mode = ["n" "i"];
action = "<nop>";
noremap = false;
}
]
)
(
pipe cfg.maps
[

View file

@ -0,0 +1,341 @@
{lib, ...}: let
inherit (lib.options) mkOption mkEnableOption literalMD;
inherit (lib.types) int str enum nullOr attrs bool;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.assistant = {
avante-nvim = {
enable = mkEnableOption "complementary Neovim plugin for avante.nvim";
setupOpts = mkPluginSetupOption "avante-nvim" {
provider = mkOption {
type = nullOr str;
default = null;
description = "The provider used in Aider mode or in the planning phase of Cursor Planning Mode.";
};
providers = mkOption {
type = nullOr attrs;
default = null;
description = "Define settings for builtin and custom providers.";
example = literalMD ''
```nix
openai = {
endpoint = "https://api.openai.com/v1";
model = "gpt-4o"; # your desired model (or use gpt-4o, etc.)
timeout = 30000; # Timeout in milliseconds, increase this for reasoning models
extra_request_body = {
temperature = 0;
max_completion_tokens = 8192; # Increase this to include reasoning tokens (for reasoning models)
reasoning_effort = "medium"; # low|medium|high, only used for reasoning models
};
};
ollama = {
endpoint = "http://127.0.0.1:11434";
timeout = 30000; # Timeout in milliseconds
extra_request_body = {
options = {
temperature = 0.75;
num_ctx = 20480;
keep_alive = "5m";
};
};
};
groq = {
__inherited_from = "openai";
api_key_name = "GROQ_API_KEY";
endpoint = "https://api.groq.com/openai/v1/";
model = "llama-3.3-70b-versatile";
disable_tools = true;
extra_request_body = {
temperature = 1;
max_tokens = 32768; # remember to increase this value, otherwise it will stop generating halfway
};
};
```
'';
};
auto_suggestions_provider = mkOption {
type = str;
default = "claude";
description = ''
Since auto-suggestions are a high-frequency operation and therefore expensive,
currently designating it as `copilot` provider is dangerous because:
https://github.com/yetone/avante.nvim/issues/1048
Of course, you can reduce the request frequency by increasing `suggestion.debounce`.
'';
};
cursor_applying_provider = mkOption {
type = nullOr str;
default = null;
description = ''
The provider used in the applying phase of Cursor Planning Mode, defaults to `nil`,
Config.provider will be used as the provider for the applying phase when `nil`.
'';
};
dual_boost = {
enabled = mkEnableOption "dual_boost mode.";
first_provider = mkOption {
type = str;
default = "openai";
description = "The first provider to generate response.";
};
second_provider = mkOption {
type = str;
default = "claude";
description = "The second provider to generate response.";
};
prompt = mkOption {
type = str;
default = ''
Based on the two reference outputs below, generate a response that incorporates
elements from both but reflects your own judgment and unique perspective.
Do not provide any explanation, just give the response directly. Reference Output 1:
[{{provider1_output}}], Reference Output 2: [{{provider2_output}}'';
description = "The prompt to generate response based on the two reference outputs.";
};
timeout = mkOption {
type = int;
default = 60000;
description = "Timeout in milliseconds.";
};
};
behaviour = {
auto_suggestions =
mkEnableOption "auto suggestions.";
auto_set_highlight_group =
mkEnableOption "automatically set the highlight group for the current line."
// {
default = true;
};
auto_set_keymaps =
mkEnableOption "automatically set the keymap for the current line."
// {
default = true;
};
auto_apply_diff_after_generation =
mkEnableOption "automatically apply diff after LLM response.";
support_paste_from_clipboard = mkEnableOption ''
pasting image from clipboard.
This will be determined automatically based whether img-clip is available or not.
'';
minimize_diff =
mkEnableOption "remove unchanged lines when applying a code block."
// {
default = true;
};
enable_token_counting =
mkEnableOption "token counting."
// {
default = true;
};
enable_cursor_planning_mode =
mkEnableOption "Cursor Planning Mode.";
enable_claude_text_editor_tool_mode =
mkEnableOption "Claude Text Editor Tool Mode.";
};
mappings = {
diff = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps for diff.";
};
suggestion = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps for suggestion actions.";
};
jump = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps for jump actions.";
};
submit = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps for submit actions.";
};
cancel = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps for cancel actions.";
};
sidebar = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps for sidebar actions.";
};
};
hints.enabled =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable hints.
'';
};
windows = {
position = mkOption {
type = enum ["right" "left" "top" "bottom"];
default = "right";
description = "The position of the sidebar.";
};
wrap =
mkEnableOption ""
// {
default = true;
description = ''
similar to vim.o.wrap.
'';
};
width = mkOption {
type = int;
default = 30;
description = "Default % based on available width.";
};
sidebar_header = {
enabled = mkOption {
type = bool;
default = true;
description = "enable/disable the header.";
};
align = mkOption {
type = enum ["right" "center" "left"];
default = "center";
description = "Position of the title.";
};
rounded = mkOption {
type = bool;
default = true;
description = "Enable rounded sidebar header";
};
};
input = {
prefix = mkOption {
type = str;
default = "> ";
description = "The prefix used on the user input.";
};
height = mkOption {
type = int;
default = 8;
description = ''
Height of the input window in vertical layout.
'';
};
};
edit = {
border = mkOption {
type = str;
default = "rounded";
description = "The border type on the edit window.";
};
start_insert = mkOption {
type = bool;
default = true;
description = ''
Start insert mode when opening the edit window.
'';
};
};
ask = {
floating = mkOption {
type = bool;
default = false;
description = ''
Open the 'AvanteAsk' prompt in a floating window.
'';
};
start_insert = mkOption {
type = bool;
default = true;
description = ''
Start insert mode when opening the ask window.
'';
};
border = mkOption {
type = str;
default = "rounded";
description = "The border type on the ask window.";
};
focus_on_apply = mkOption {
type = enum ["ours" "theirs"];
default = "ours";
description = "Which diff to focus after applying.";
};
};
};
diff = {
autojump =
mkEnableOption ""
// {
default = true;
description = "Automatically jumps to the next change.";
};
override_timeoutlen = mkOption {
type = int;
default = 500;
example = -1;
description = ''
Override the 'timeoutlen' setting while hovering over a diff (see {command}`:help timeoutlen`).
Helps to avoid entering operator-pending mode with diff mappings starting with `c`.
Disable by setting to -1.
'';
};
};
suggestion = {
debounce = mkOption {
type = int;
default = 600;
description = "Suggestion debounce in milliseconds.";
};
throttle = mkOption {
type = int;
default = 600;
description = "Suggestion throttle in milliseconds.";
};
};
};
};
};
}

View file

@ -0,0 +1,41 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.lists) optionals;
cfg = config.vim.assistant.avante-nvim;
in {
config = mkIf cfg.enable {
vim = {
startPlugins =
[
"nvim-treesitter"
"plenary-nvim"
"dressing-nvim"
"nui-nvim"
]
++ (optionals config.vim.mini.pick.enable ["mini-pick"])
++ (optionals config.vim.telescope.enable ["telescope"])
++ (optionals config.vim.autocomplete.nvim-cmp.enable ["nvim-cmp"])
++ (optionals config.vim.fzf-lua.enable ["fzf-lua"])
++ (optionals config.vim.visuals.nvim-web-devicons.enable ["nvim-web-devicons"])
++ (optionals config.vim.utility.images.img-clip.enable ["img-clip"]);
lazy.plugins = {
avante-nvim = {
package = "avante-nvim";
setupModule = "avante";
inherit (cfg) setupOpts;
event = ["DeferredUIEnter"];
};
};
treesitter.enable = true;
languages.markdown.extensions.render-markdown-nvim.setupOpts.file_types = lib.mkAfter ["Avante"];
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./config.nix
./avante-nvim.nix
];
}

View file

@ -31,16 +31,27 @@ in {
config = mkIf cfg.enable {
vim = {
startPlugins = [
"chatgpt"
"chatgpt-nvim"
# Dependencies
"nui-nvim"
"plenary-nvim"
];
# ChatGPT.nvim explicitly depends on Telescope.
telescope.enable = true;
pluginRC.chagpt = entryAnywhere ''
require("chatgpt").setup(${toLuaObject cfg.setupOpts})
'';
maps.normal = mkMerge [
(mkSetBinding mappings.chatGpt "<cmd>ChatGPT<CR>")
maps
];
maps.visual = maps;
maps = {
visual = maps;
normal = mkMerge [
(mkSetBinding mappings.chatGpt "<cmd>ChatGPT<CR>")
maps
];
};
};
};
}

View file

@ -0,0 +1,301 @@
{lib, ...}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.types) int str enum nullOr attrs;
inherit (lib.nvim.types) mkPluginSetupOption luaInline;
in {
options.vim.assistant = {
codecompanion-nvim = {
enable = mkEnableOption "complementary neovim plugin for codecompanion.nvim";
setupOpts = mkPluginSetupOption "codecompanion-nvim" {
opts = {
send_code =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable code being sent to the LLM.
'';
};
log_level = mkOption {
type = enum ["DEBUG" "INFO" "ERROR" "TRACE"];
default = "ERROR";
description = "Change the level of logging.";
};
language = mkOption {
type = str;
default = "English";
description = "Specify which language an LLM should respond in.";
};
};
display = {
diff = {
enabled =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable a diff view
to see the changes made by the LLM.
'';
};
close_chat_at = mkOption {
type = int;
default = 240;
description = ''
Close an open chat buffer if the
total columns of your display are less than...
'';
};
layout = mkOption {
type = enum ["vertical" "horizontal"];
default = "vertical";
description = "Type of split for default provider.";
};
provider = mkOption {
type = enum ["default" "mini_diff"];
default = "default";
description = "The preferred kind of provider.";
};
};
inline = {
layout = mkOption {
type = enum ["vertical" "horizontal" "buffer"];
default = "vertical";
description = "Customize how output is created in new buffer.";
};
};
chat = {
auto_scroll =
mkEnableOption ""
// {
default = true;
description = "Whether to enable automatic page scrolling.";
};
show_settings = mkEnableOption ''
LLM settings to appear at the top of the chat buffer.
'';
start_in_insert_mode = mkEnableOption ''
opening the chat buffer in insert mode.
'';
show_header_separator = mkEnableOption ''
header separators in the chat buffer.
Set this to false if you're using an
external markdown formatting plugin.
'';
show_references =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable references in the chat buffer.
'';
};
show_token_count =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable the token count for each response.
'';
};
intro_message = mkOption {
type = str;
default = "Welcome to CodeCompanion ! Press ? for options.";
description = "Message to appear in chat buffer.";
};
separator = mkOption {
type = str;
default = "";
description = ''
The separator between the
different messages in the chat buffer.
'';
};
icons = {
pinned_buffer = mkOption {
type = str;
default = " ";
description = "The icon to represent a pinned buffer.";
};
watched_buffer = mkOption {
type = str;
default = "👀 ";
description = "The icon to represent a watched buffer.";
};
};
};
action_palette = {
width = mkOption {
type = int;
default = 95;
description = "Width of the action palette.";
};
height = mkOption {
type = int;
default = 10;
description = "Height of the action palette.";
};
prompt = mkOption {
type = str;
default = "Prompt ";
description = "Prompt used for interactive LLM calls.";
};
provider = mkOption {
type = enum ["default" "telescope" "mini_pick"];
default = "default";
description = "Provider used for the action palette.";
};
opts = {
show_default_actions =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable showing default
actions in the action palette.
'';
};
show_default_prompt_library =
mkEnableOption ""
// {
default = true;
description = ''
Whether to enable showing default
prompt library in the action palette.
'';
};
};
};
};
adapters = mkOption {
type = nullOr luaInline;
default = null;
description = "An adapter is what connects Neovim to an LLM.";
};
strategies = {
chat = {
adapter = mkOption {
type = nullOr str;
default = null;
description = "Adapter used for the chat strategy.";
};
keymaps = mkOption {
type = nullOr attrs;
default = null;
description = "Define or override the default keymaps.";
};
variables = mkOption {
type = nullOr luaInline;
default = null;
description = ''
Define your own variables
to share specific content.
'';
};
slash_commands = mkOption {
type = nullOr luaInline;
default = null;
description = ''
Slash Commands (invoked with /) let you dynamically
insert context into the chat buffer,
such as file contents or date/time.
'';
};
tools = mkOption {
type = nullOr attrs;
default = null;
description = ''
Configure tools to perform specific
tasks when invoked by an LLM.
'';
};
roles = mkOption {
type = nullOr luaInline;
default = null;
description = ''
The chat buffer places user and LLM responses under a H2 header.
These can be customized in the configuration.
'';
};
};
inline = {
adapter = mkOption {
type = nullOr str;
default = null;
description = "Adapter used for the inline strategy.";
};
variables = mkOption {
type = nullOr luaInline;
default = null;
description = ''
Define your own variables
to share specific content.
'';
};
keymaps = {
accept_change = {
n = mkOption {
type = str;
default = "ga";
description = "Accept the suggested change.";
};
};
reject_change = {
n = mkOption {
type = str;
default = "gr";
description = "Reject the suggested change.";
};
};
};
};
};
prompt_library = mkOption {
type = nullOr attrs;
default = null;
description = ''
A prompt library is a collection of prompts
that can be used in the action palette.
'';
};
};
};
};
}

View file

@ -0,0 +1,42 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.assistant.codecompanion-nvim;
in {
config = mkIf cfg.enable {
vim = {
startPlugins = [
"plenary-nvim"
];
lazy.plugins = {
codecompanion-nvim = {
package = "codecompanion-nvim";
setupModule = "codecompanion";
inherit (cfg) setupOpts;
};
};
treesitter = {
enable = true;
# Codecompanion depends on the YAML grammar being added. Below is
# an easy way of adding an user-configurable grammar package exposed
# by the YAML language module *without* enabling the whole YAML language
# module. The package is defined even when the module is disabled.
grammars = [
config.vim.languages.yaml.treesitter.package
];
};
autocomplete.nvim-cmp = {
sources = {codecompanion-nvim = "[codecompanion]";};
sourcePlugins = ["codecompanion-nvim"];
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./config.nix
./codecompanion-nvim.nix
];
}

View file

@ -5,7 +5,6 @@
}: let
inherit (builtins) toJSON;
inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString;
cfg = config.vim.assistant.copilot;
@ -37,6 +36,12 @@ in {
inherit (cfg) setupOpts;
after = mkIf cfg.cmp.enable "require('copilot_cmp').setup()";
event = [
{
event = "User";
pattern = "LazyFile";
}
];
cmd = ["Copilot" "CopilotAuth" "CopilotDetach" "CopilotPanel" "CopilotStop"];
keys = [
(mkLuaKeymap ["n"] cfg.mappings.panel.accept (wrapPanelBinding ''require("copilot.panel").accept'' cfg.mappings.panel.accept) "[copilot] Accept suggestion" {})

View file

@ -2,5 +2,8 @@
imports = [
./chatgpt
./copilot
./codecompanion
./supermaven-nvim
./avante
];
}

View file

@ -0,0 +1,17 @@
{
config,
lib,
...
}: let
cfg = config.vim.assistant.supermaven-nvim;
in {
config = lib.mkIf cfg.enable {
vim.lazy.plugins = {
supermaven-nvim = {
package = "supermaven-nvim";
setupModule = "supermaven-nvim";
inherit (cfg) setupOpts;
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./supermaven-nvim.nix
./config.nix
];
}

View file

@ -0,0 +1,94 @@
{lib, ...}: let
inherit
(lib.types)
nullOr
str
bool
attrsOf
ints
enum
;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.nvim.types) mkPluginSetupOption luaInline;
in {
options.vim.assistant.supermaven-nvim = {
enable = mkEnableOption "Supermaven AI assistant";
setupOpts = mkPluginSetupOption "Supermaven" {
keymaps = {
accept_suggestion = mkOption {
type = nullOr str;
default = null;
example = "<Tab>";
description = "The key to accept a suggestion";
};
clear_suggestion = mkOption {
type = nullOr str;
default = null;
example = "<C-]>";
description = "The key to clear a suggestion";
};
accept_word = mkOption {
type = nullOr str;
default = null;
example = "<C-j>";
description = "The key to accept a word";
};
};
ignore_file = mkOption {
type = nullOr (attrsOf bool);
default = null;
example = {
markdown = true;
};
description = "List of fileto ignore";
};
color = {
suggestion_color = mkOption {
type = nullOr str;
default = null;
example = "#ffffff";
description = "The hex color of the suggestion";
};
cterm = mkOption {
type = nullOr ints.u8;
default = null;
example = 244;
description = "The cterm color of the suggestion";
};
};
log_level = mkOption {
type = nullOr (enum [
"off"
"trace"
"debug"
"info"
"warn"
"error"
]);
default = null;
example = "info";
description = "The log level. Set to `\"off\"` to disable completely";
};
disable_inline_completion = mkOption {
type = nullOr bool;
default = null;
description = "Disable inline completion for use with cmp";
};
disable_keymaps = mkOption {
type = nullOr bool;
default = null;
description = "Disable built-in keymaps for more manual control";
};
condition = mkOption {
type = nullOr luaInline;
default = null;
description = ''
Condition function to check for stopping supermaven.
A returned `true` means to stop supermaven
'';
};
};
};
}

View file

@ -0,0 +1,205 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption mkOption literalMD;
inherit (lib.types) bool listOf str either attrsOf submodule enum anything int nullOr;
inherit (lib.nvim.types) mkPluginSetupOption luaInline pluginType;
inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.config) mkBool;
keymapType = submodule {
freeformType = attrsOf (listOf (either str luaInline));
options = {
preset = mkOption {
type = enum ["default" "none" "super-tab" "enter" "cmdline"];
default = "none";
description = "keymap presets";
};
};
};
providerType = submodule {
freeformType = anything;
options = {
module = mkOption {
type = nullOr str;
default = null;
description = "Provider module.";
};
};
};
in {
options.vim.autocomplete.blink-cmp = {
enable = mkEnableOption "blink.cmp";
setupOpts = mkPluginSetupOption "blink.cmp" {
sources = {
default = mkOption {
type = listOf str;
default = ["lsp" "path" "snippets" "buffer"];
description = "Default list of sources to enable for completion.";
};
providers = mkOption {
type = attrsOf providerType;
default = {};
description = "Settings for completion providers.";
};
};
cmdline = {
sources = mkOption {
type = nullOr (listOf str);
default = null;
description = "List of sources to enable for cmdline. Null means use default source list.";
};
keymap = mkOption {
type = keymapType;
default = {};
description = "blink.cmp cmdline keymap";
};
};
completion = {
documentation = {
auto_show = mkBool true "Show documentation whenever an item is selected";
auto_show_delay_ms = mkOption {
type = int;
default = 200;
description = "Delay before auto show triggers";
};
};
menu.auto_show = mkOption {
type = bool;
default = true;
description = ''
Manages the appearance of the completion menu. You may prevent the menu
from automatically showing by this option to `false` and manually showing
it with the show keymap command.
'';
};
};
keymap = mkOption {
type = keymapType;
default = {};
description = "blink.cmp keymap";
example = literalMD ''
```nix
vim.autocomplete.blink-cmp.setupOpts.keymap = {
preset = "none";
"<Up>" = ["select_prev" "fallback"];
"<C-n>" = [
(lib.generators.mkLuaInline ''''
function(cmp)
if some_condition then return end -- runs the next command
return true -- doesn't run the next command
end,
'''')
"select_next"
];
};
```
'';
};
fuzzy = {
prebuilt_binaries = {
download = mkBool false ''
Auto-downloads prebuilt binaries.
::: .{warning}
Do not enable this option, as it does **not work** on Nix!
:::
'';
};
implementation = mkOption {
type = enum ["lua" "prefer_rust" "rust" "prefer_rust_with_warning"];
default = "prefer_rust";
description = ''
fuzzy matcher implementation for Blink.
* `"lua"`: slower, Lua native fuzzy matcher implementation
* `"rust": use the SIMD fuzzy matcher, 'frizbee'
* `"prefer_rust"`: use the rust implementation, but fall back to lua
* `"prefer_rust_with_warning"`: use the rust implementation, and fall back to lua
if it is not available after emitting a warning.
'';
};
};
};
mappings = {
complete = mkMappingOption "Complete [blink.cmp]" "<C-Space>";
confirm = mkMappingOption "Confirm [blink.cmp]" "<CR>";
next = mkMappingOption "Next item [blink.cmp]" "<Tab>";
previous = mkMappingOption "Previous item [blink.cmp]" "<S-Tab>";
close = mkMappingOption "Close [blink.cmp]" "<C-e>";
scrollDocsUp = mkMappingOption "Scroll docs up [blink.cmp]" "<C-d>";
scrollDocsDown = mkMappingOption "Scroll docs down [blink.cmp]" "<C-f>";
};
sourcePlugins = let
sourcePluginType = submodule {
options = {
enable = mkEnableOption "this source";
package = mkOption {
type = pluginType;
description = ''
`blink-cmp` source plugin package.
'';
};
module = mkOption {
type = str;
description = ''
Value of {option}`vim.autocomplete.blink-cmp.setupOpts.sources.providers.<name>.module`.
Should be present in the source's documentation.
'';
};
};
};
in
mkOption {
type = submodule {
freeformType = attrsOf sourcePluginType;
options = let
defaultSourcePluginOption = name: package: module: {
package = mkOption {
type = pluginType;
default = package;
description = ''
`blink-cmp` ${name} source plugin package.
'';
};
module = mkOption {
type = str;
default = module;
description = ''
Value of {option}`vim.autocomplete.blink-cmp.setupOpts.sources.providers.${name}.module`.
'';
};
enable = mkEnableOption "${name} source";
};
in {
# emoji completion after :
emoji = defaultSourcePluginOption "emoji" "blink-emoji-nvim" "blink-emoji";
# spelling suggestions as completions
spell = defaultSourcePluginOption "spell" "blink-cmp-spell" "blink-cmp-spell";
# words from nearby files
ripgrep = defaultSourcePluginOption "ripgrep" "blink-ripgrep-nvim" "blink-ripgrep";
};
};
default = {};
description = ''
`blink.cmp` sources.
Attribute names must be source names used in {option}`vim.autocomplete.blink-cmp.setupOpts.sources.default`.
'';
};
friendly-snippets.enable = mkEnableOption "friendly-snippets for blink to source from automatically";
};
}

View file

@ -0,0 +1,149 @@
{
lib,
config,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString;
inherit (lib.attrsets) optionalAttrs;
inherit (lib.generators) mkLuaInline;
inherit (lib.attrsets) attrValues filterAttrs mapAttrsToList;
inherit (lib.lists) map optional optionals elem;
inherit (lib.nvim.lua) toLuaObject;
inherit (builtins) concatStringsSep typeOf tryEval attrNames mapAttrs removeAttrs;
cfg = config.vim.autocomplete.blink-cmp;
cmpCfg = config.vim.autocomplete.nvim-cmp;
inherit (cfg) mappings;
getPluginName = plugin:
if typeOf plugin == "string"
then plugin
else if (plugin ? pname && (tryEval plugin.pname).success)
then plugin.pname
else plugin.name;
enabledBlinkSources = filterAttrs (_source: definition: definition.enable) cfg.sourcePlugins;
blinkSourcePlugins = map (definition: definition.package) (attrValues enabledBlinkSources);
blinkBuiltins = [
"path"
"lsp"
"snippets"
"buffer"
"omni"
];
in {
assertions =
mapAttrsToList (provider: definition: {
assertion = elem provider blinkBuiltins || definition.module != null;
message = "`config.vim.autocomplete.blink-cmp.setupOpts.sources.providers.${provider}.module` is `null`: non-builtin providers must set `module`.";
})
cfg.setupOpts.sources.providers;
vim = mkIf cfg.enable {
startPlugins = ["blink-compat"] ++ blinkSourcePlugins ++ (optional cfg.friendly-snippets.enable "friendly-snippets");
lazy.plugins = {
blink-cmp = {
package = "blink-cmp";
setupModule = "blink.cmp";
inherit (cfg) setupOpts;
# TODO: lazy disabled until lspconfig is lazy loaded
#
# event = ["InsertEnter" "CmdlineEnter"];
after =
# lua
''
${optionalString (config.vim.lazy.enable && cmpCfg.enable)
(concatStringsSep "\n" (map
(package: "require('lz.n').trigger_load(${toLuaObject (getPluginName package)})")
cmpCfg.sourcePlugins))}
'';
};
};
autocomplete = {
enableSharedCmpSources = true;
blink-cmp.setupOpts = {
sources = let
# We do not want nvim-cmp compat sources overriding built-in blink sources
filteredCmpSources = removeAttrs cmpCfg.sources blinkBuiltins;
in {
default =
[
"lsp"
"path"
"snippets"
"buffer"
]
++ optionals cmpCfg.enable (attrNames filteredCmpSources)
++ (attrNames enabledBlinkSources);
providers =
optionalAttrs cmpCfg.enable (
mapAttrs (name: _: {
inherit name;
module = "blink.compat.source";
})
filteredCmpSources
)
// (mapAttrs (name: definition: {
inherit name;
inherit (definition) module;
})
enabledBlinkSources);
};
snippets = mkIf config.vim.snippets.luasnip.enable {
preset = "luasnip";
};
keymap = {
${mappings.complete} = ["show" "fallback"];
${mappings.close} = ["hide" "fallback"];
${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"];
${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"];
${mappings.confirm} = ["accept" "fallback"];
${mappings.next} = [
"select_next"
"snippet_forward"
(mkLuaInline
# lua
''
function(cmp)
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
has_words_before = col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
if has_words_before then
return cmp.show()
end
end
'')
"fallback"
];
${mappings.previous} = [
"select_prev"
"snippet_backward"
"fallback"
];
};
# cmdline is not enabled by default, we're just providing keymaps in
# case the user enables them
cmdline.keymap = {
${mappings.complete} = ["show" "fallback"];
${mappings.close} = ["hide" "fallback"];
${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"];
${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"];
# NOTE: mappings.confirm is skipped because our default, <CR> would
# lead to accidental triggers of blink.accept instead of executing
# the cmd
${mappings.next} = ["select_next" "show" "fallback"];
${mappings.previous} = ["select_prev" "fallback"];
};
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./blink-cmp.nix
./config.nix
];
}

View file

@ -0,0 +1,34 @@
{
lib,
config,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (builtins) typeOf tryEval;
cfg = config.vim.autocomplete;
getPluginName = plugin:
if typeOf plugin == "string"
then plugin
else if (plugin ? pname && (tryEval plugin.pname).success)
then plugin.pname
else plugin.name;
in {
config.vim = mkIf cfg.enableSharedCmpSources {
startPlugins = ["rtp-nvim"];
lazy.plugins =
mapListToAttrs (package: {
name = getPluginName package;
value = {
inherit package;
lazy = true;
after = ''
local path = vim.fn.globpath(vim.o.packpath, 'pack/*/opt/${getPluginName package}')
require("rtp_nvim").source_after_plugin_dir(path)
'';
};
})
cfg.nvim-cmp.sourcePlugins;
};
}

View file

@ -1,5 +1,9 @@
{
imports = [
./module.nix
./config.nix
./nvim-cmp
./blink-cmp
];
}

View file

@ -0,0 +1,7 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
in {
options.vim.autocomplete = {
enableSharedCmpSources = mkEnableOption "sources shared by blink.cmp and nvim-cmp";
};
}

View file

@ -3,11 +3,10 @@
config,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (builtins) attrNames typeOf tryEval concatStringsSep;
borders = config.vim.ui.borders.plugins.nvim-cmp;
@ -24,114 +23,97 @@
in {
config = mkIf cfg.enable {
vim = {
startPlugins = ["rtp-nvim"];
lazy.plugins = mkMerge [
(mapListToAttrs (package: {
name = getPluginName package;
value = {
inherit package;
lazy = true;
after = ''
local path = vim.fn.globpath(vim.o.packpath, 'pack/*/opt/${getPluginName package}')
require("rtp_nvim").source_after_plugin_dir(path)
lazy.plugins = {
nvim-cmp = {
package = "nvim-cmp";
after = ''
${optionalString luasnipEnable "local luasnip = require('luasnip')"}
local cmp = require("cmp")
local kinds = require("cmp.types").lsp.CompletionItemKind
local deprio = function(kind)
return function(e1, e2)
if e1:get_kind() == kind then
return false
end
if e2:get_kind() == kind then
return true
end
return nil
end
end
cmp.setup(${toLuaObject cfg.setupOpts})
${optionalString config.vim.lazy.enable
(concatStringsSep "\n" (map
(package: "require('lz.n').trigger_load(${toLuaObject (getPluginName package)})")
cfg.sourcePlugins))}
'';
event = ["InsertEnter" "CmdlineEnter"];
};
};
autocomplete = {
enableSharedCmpSources = true;
nvim-cmp = {
sourcePlugins = ["cmp-buffer" "cmp-path"];
setupOpts = {
sources = map (s: {name = s;}) (attrNames cfg.sources);
window = mkIf borders.enable {
completion.border = borders.style;
documentation.border = borders.style;
};
formatting.format = cfg.format;
# `cmp` and `luasnip` are defined above, in the `nvim-cmp` section
mapping = {
${mappings.complete} = mkLuaInline "cmp.mapping.complete()";
${mappings.close} = mkLuaInline "cmp.mapping.abort()";
${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)";
${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)";
${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })";
${mappings.next} = mkLuaInline ''
cmp.mapping(function(fallback)
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
if cmp.visible() then
cmp.select_next_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(1) then
luasnip.jump(1)
''}
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end)
'';
${mappings.previous} = mkLuaInline ''
cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
''}
else
fallback()
end
end)
'';
};
})
cfg.sourcePlugins)
{
nvim-cmp = {
package = "nvim-cmp";
after = ''
${optionalString luasnipEnable "local luasnip = require('luasnip')"}
local cmp = require("cmp")
local kinds = require("cmp.types").lsp.CompletionItemKind
local deprio = function(kind)
return function(e1, e2)
if e1:get_kind() == kind then
return false
end
if e2:get_kind() == kind then
return true
end
return nil
end
end
cmp.setup(${toLuaObject cfg.setupOpts})
${optionalString config.vim.lazy.enable
(concatStringsSep "\n" (map
(package: "require('lz.n').trigger_load(${toLuaObject (getPluginName package)})")
cfg.sourcePlugins))}
'';
event = ["InsertEnter" "CmdlineEnter"];
};
}
];
autocomplete.nvim-cmp = {
sources = {
nvim-cmp = null;
buffer = "[Buffer]";
path = "[Path]";
};
sourcePlugins = ["cmp-buffer" "cmp-path"];
setupOpts = {
sources = map (s: {name = s;}) (attrNames cfg.sources);
window = mkIf borders.enable {
completion.border = borders.style;
documentation.border = borders.style;
};
formatting.format = cfg.format;
# `cmp` and `luasnip` are defined above, in the `nvim-cmp` section
mapping = {
${mappings.complete} = mkLuaInline "cmp.mapping.complete()";
${mappings.close} = mkLuaInline "cmp.mapping.abort()";
${mappings.scrollDocsUp} = mkLuaInline "cmp.mapping.scroll_docs(-4)";
${mappings.scrollDocsDown} = mkLuaInline "cmp.mapping.scroll_docs(4)";
${mappings.confirm} = mkLuaInline "cmp.mapping.confirm({ select = true })";
${mappings.next} = mkLuaInline ''
cmp.mapping(function(fallback)
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
if cmp.visible() then
cmp.select_next_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(1) then
luasnip.jump(1)
''}
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end)
'';
${mappings.previous} = mkLuaInline ''
cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
''}
else
fallback()
end
end)
'';
};
};
};

View file

@ -3,7 +3,7 @@
config,
...
}: let
inherit (lib.options) mkEnableOption mkOption literalExpression literalMD;
inherit (lib.options) mkEnableOption mkOption literalMD;
inherit (lib.types) str attrsOf nullOr either listOf;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.binds) mkMappingOption;
@ -98,14 +98,16 @@ in {
sources = mkOption {
type = attrsOf (nullOr str);
default = {};
default = {
nvim-cmp = null;
buffer = "[Buffer]";
path = "[Path]";
};
example = {
nvim-cmp = null;
buffer = "[Buffer]";
};
description = "The list of sources used by nvim-cmp";
example = literalExpression ''
{
nvim-cmp = null;
buffer = "[Buffer]";
}
'';
};
sourcePlugins = mkOption {

View file

@ -1,7 +1,23 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) listOf attrsOf anything nullOr enum;
in {
options.vim.dashboard.alpha = {
enable = mkEnableOption "fast and fully programmable greeter for neovim [alpha.mvim]";
enable = mkEnableOption "fast and fully programmable greeter for neovim [alpha.nvim]";
theme = mkOption {
type = nullOr (enum ["dashboard" "startify" "theta"]);
default = "dashboard";
description = "Alpha default theme to use";
};
layout = mkOption {
type = listOf (attrsOf anything);
default = [];
description = "Alpha dashboard layout";
};
opts = mkOption {
type = attrsOf anything;
default = {};
description = "Optional global options";
};
};
}

View file

@ -4,9 +4,11 @@
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.dashboard.alpha;
themeDefined = cfg.theme != null;
layoutDefined = cfg.layout != [];
in {
config = mkIf cfg.enable {
vim.startPlugins = [
@ -14,207 +16,30 @@ in {
"nvim-web-devicons"
];
# the entire credit for this dashboard configuration to https://github.com/Rishabh672003
# honestly, excellent work
vim.pluginRC.alpha = entryAnywhere ''
local alpha = require("alpha")
local plenary_path = require("plenary.path")
local dashboard = require("alpha.themes.dashboard")
local cdir = vim.fn.getcwd()
local if_nil = vim.F.if_nil
local nvim_web_devicons = {
enabled = true,
highlight = true,
}
local function get_extension(fn)
local match = fn:match("^.+(%..+)$")
local ext = ""
if match ~= nil then
ext = match:sub(2)
end
return ext
end
local function icon(fn)
local nwd = require("nvim-web-devicons")
local ext = get_extension(fn)
return nwd.get_icon(fn, ext, { default = true })
end
local function file_button(fn, sc, short_fn)
short_fn = short_fn or fn
local ico_txt
local fb_hl = {}
if nvim_web_devicons.enabled then
local ico, hl = icon(fn)
local hl_option_type = type(nvim_web_devicons.highlight)
if hl_option_type == "boolean" then
if hl and nvim_web_devicons.highlight then
table.insert(fb_hl, { hl, 0, 3 })
end
end
if hl_option_type == "string" then
table.insert(fb_hl, { nvim_web_devicons.highlight, 0, 3 })
end
ico_txt = ico .. " "
else
ico_txt = ""
end
local file_button_el = dashboard.button(sc, ico_txt .. short_fn, "<cmd>e " .. fn .. " <CR>")
local fn_start = short_fn:match(".*[/\\]")
if fn_start ~= nil then
table.insert(fb_hl, { "Comment", #ico_txt - 2, #fn_start + #ico_txt })
end
file_button_el.opts.hl = fb_hl
return file_button_el
end
local default_mru_ignore = { "gitcommit" }
local mru_opts = {
ignore = function(path, ext)
return (string.find(path, "COMMIT_EDITMSG")) or (vim.tbl_contains(default_mru_ignore, ext))
end,
}
--- @param start number
--- @param cwd string optional
--- @param items_number number optional number of items to generate, default = 10
local function mru(start, cwd, items_number, opts)
opts = opts or mru_opts
items_number = if_nil(items_number, 15)
local oldfiles = {}
for _, v in pairs(vim.v.oldfiles) do
if #oldfiles == items_number then
break
end
local cwd_cond
if not cwd then
cwd_cond = true
else
cwd_cond = vim.startswith(v, cwd)
end
local ignore = (opts.ignore and opts.ignore(v, get_extension(v))) or false
if (vim.fn.filereadable(v) == 1) and cwd_cond and not ignore then
oldfiles[#oldfiles + 1] = v
end
end
local target_width = 35
local tbl = {}
for i, fn in ipairs(oldfiles) do
local short_fn
if cwd then
short_fn = vim.fn.fnamemodify(fn, ":.")
else
short_fn = vim.fn.fnamemodify(fn, ":~")
end
if #short_fn > target_width then
short_fn = plenary_path.new(short_fn):shorten(1, { -2, -1 })
if #short_fn > target_width then
short_fn = plenary_path.new(short_fn):shorten(1, { -1 })
end
end
local shortcut = tostring(i + start - 1)
local file_button_el = file_button(fn, shortcut, short_fn)
tbl[i] = file_button_el
end
return {
type = "group",
val = tbl,
opts = {},
}
end
local default_header = {
type = "text",
val = {
[[ ]],
[[ ]],
[[ ]],
[[ ]],
[[ ]],
-- [[ __ ]],
-- [[ ___ ___ ___ __ __ /\_\ ___ ___ ]],
-- [[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\ ]],
-- [[/\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \ ]],
-- [[\ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]],
-- [[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]],
},
opts = {
position = "center",
hl = "Type",
-- wrap = "overflow";
},
}
local section_mru = {
type = "group",
val = {
{
type = "text",
val = "Recent files",
opts = {
hl = "SpecialComment",
shrink_margin = false,
position = "center",
},
},
{ type = "padding", val = 1 },
{
type = "group",
val = function()
return { mru(0, cdir) }
end,
opts = { shrink_margin = false },
},
},
}
local buttons = {
type = "group",
val = {
{ type = "text", val = "Quick links", opts = { hl = "SpecialComment", position = "center" } },
{ type = "padding", val = 1 },
-- TODO: buttons should be added based on whether or not the relevant plugin is available
dashboard.button("e", " New file", "<cmd>ene<CR>"), -- available all the time
dashboard.button("SPC F", "󰈞 Find file"), -- telescope
dashboard.button("SPC ff", "󰊄 Live grep"), -- telescope
dashboard.button("SPC p", " Projects"), -- any project
dashboard.button("q", "󰅚 Quit", "<cmd>qa<CR>"), -- available all the time
},
position = "center",
}
local config = {
layout = {
{ type = "padding", val = 2 },
default_header,
{ type = "padding", val = 2 },
section_mru,
{ type = "padding", val = 2 },
buttons,
},
opts = {
margin = 5,
setup = function()
vim.cmd([[
autocmd alpha_temp DirChanged * lua require('alpha').redraw()
]])
end,
},
}
alpha.setup(config)
vim.pluginRC.alpha = let
setupOpts =
if themeDefined
then lib.generators.mkLuaInline "require'alpha.themes.${cfg.theme}'.config"
else {
inherit (cfg) layout opts;
};
in ''
require('alpha').setup(${toLuaObject setupOpts})
'';
assertions = [
{
assertion = themeDefined || layoutDefined;
message = ''
One of 'theme' or 'layout' should be defined in Alpha configuration.
'';
}
{
assertion = !(themeDefined && layoutDefined);
message = ''
'theme' and 'layout' cannot be defined at the same time.
'';
}
];
};
}

View file

@ -3,46 +3,47 @@
inherit (lib.types) listOf attrs bool enum str oneOf int;
in {
options.vim.dashboard.startify = {
enable = mkEnableOption "dashboard via vim-startify";
enable = mkEnableOption "fancy start screen for Vim [vim-startify]";
bookmarks = mkOption {
default = [];
description = ''List of book marks to disaply on start page'';
type = listOf attrs;
default = [];
example = {"c" = "~/.vimrc";};
description = "List of book marks to display on start page";
};
changeToDir = mkOption {
default = true;
description = "Should vim change to the directory of the file you open";
type = bool;
default = true;
description = "Whether Vim should change to the directory of the file you open";
};
changeToVCRoot = mkOption {
default = false;
description = "Should vim change to the version control root when opening a file";
type = bool;
default = false;
description = "Whether Vim should change to the version control root when opening a file";
};
changeDirCmd = mkOption {
default = "lcd";
description = "Command to change the current window with. Can be cd, lcd or tcd";
type = enum ["cd" "lcd" "tcd"];
default = "lcd";
description = "Command to change the current window with.";
};
customHeader = mkOption {
type = listOf str;
default = [];
description = "Text to place in the header";
type = listOf str;
};
customFooter = mkOption {
type = listOf str;
default = [];
description = "Text to place in the footer";
type = listOf str;
};
lists = mkOption {
type = listOf attrs;
default = [
{
type = "files";
@ -66,121 +67,136 @@ in {
}
];
description = "Specify the lists and in what order they are displayed on startify.";
type = listOf attrs;
};
skipList = mkOption {
type = listOf str;
default = [];
description = "List of regex patterns to exclude from MRU lists";
type = listOf str;
};
updateOldFiles = mkOption {
type = bool;
default = false;
description = "Set if you want startify to always update and not just when neovim closes";
type = bool;
};
sessionAutoload = mkOption {
default = false;
description = "Make startify auto load Session.vim files from the current directory";
type = bool;
default = false;
description = "Make vim-startify auto load Session.vim files from the current directory";
};
commands = mkOption {
type = listOf (oneOf [str attrs (listOf str)]);
default = [];
description = "Commands that are presented to the user on startify page";
type = listOf (oneOf [str attrs (listOf str)]);
};
filesNumber = mkOption {
type = int;
default = 10;
description = "How many files to list";
type = int;
};
customIndices = mkOption {
type = listOf str;
default = [];
description = "Specify a list of default characters to use instead of numbers";
type = listOf str;
};
disableOnStartup = mkOption {
default = false;
description = "Prevent startify from opening on startup but can be called with :Startify";
type = bool;
default = false;
description = ''
Whether vim-startify should be disabled on startup.
This will prevent startify from opening on startup, but it can still
be called with `:Startify`
'';
};
unsafe = mkOption {
default = false;
description = "Turns on unsafe mode for Startify. Stops resolving links, checking files are readable and filtering bookmark list";
type = bool;
default = false;
description = ''
Whether to turn on unsafe mode for Startify.
While enabld, vim-startify will stops resolving links, checking files
are readable and filtering bookmark list
'';
};
paddingLeft = mkOption {
type = int;
default = 3;
description = "Number of spaces used for left padding.";
type = int;
};
useEnv = mkOption {
type = bool;
default = false;
description = "Show environment variables in path if name is shorter than value";
type = bool;
};
sessionBeforeSave = mkOption {
type = listOf str;
default = [];
description = "Commands to run before saving a session";
type = listOf str;
};
sessionPersistence = mkOption {
type = bool;
default = false;
description = "Persist session before leaving vim or switching session";
type = bool;
};
sessionDeleteBuffers = mkOption {
type = bool;
default = true;
description = "Delete all buffers when loading or closing a session";
type = bool;
};
sessionDir = mkOption {
type = str;
default = "~/.vim/session";
description = "Directory to save and load sessions from";
type = str;
};
skipListServer = mkOption {
type = listOf str;
default = [];
description = "List of vim servers to not load startify for";
type = listOf str;
};
sessionRemoveLines = mkOption {
type = listOf str;
default = [];
description = "Patterns to remove from session files";
type = listOf str;
};
sessionSavevars = mkOption {
type = listOf str;
default = [];
description = "List of variables to save into a session file.";
type = listOf str;
};
sessionSavecmds = mkOption {
type = listOf str;
default = [];
description = "List of commands to run when loading a session.";
type = listOf str;
};
sessionSort = mkOption {
default = false;
description = "Set if you want items sorted by date rather than alphabetically";
type = bool;
default = false;
example = true;
description = ''
While true, sessions will be sorted by date rather than alphabetically.
'';
};
};
}

View file

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

View file

@ -0,0 +1,52 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.diagnostics.nvim-lint;
in {
config = mkMerge [
(mkIf cfg.enable {
vim = {
startPlugins = ["nvim-lint"];
pluginRC.nvim-lint = entryAnywhere ''
require("lint").linters_by_ft = ${toLuaObject cfg.linters_by_ft}
local linters = require("lint").linters
local nvf_linters = ${toLuaObject cfg.linters}
for linter, config in pairs(nvf_linters) do
if linters[linter] == nil then
linters[linter] = config
else
for key, val in pairs(config) do
linters[linter][key] = val
end
end
end
nvf_lint = ${toLuaObject cfg.lint_function}
'';
};
})
(mkIf (cfg.enable && cfg.lint_after_save) {
vim = {
augroups = [{name = "nvf_nvim_lint";}];
autocmds = [
{
event = ["BufWritePost"];
callback = mkLuaInline ''
function(args)
nvf_lint(args.buf)
end
'';
}
];
};
})
];
}

View file

@ -0,0 +1,6 @@
{
imports = [
./nvim-lint.nix
./config.nix
];
}

View file

@ -0,0 +1,187 @@
{lib, ...}: let
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.types) nullOr attrsOf listOf str either submodule bool enum;
inherit (lib.nvim.types) luaInline;
inherit (lib.generators) mkLuaInline;
linterType = submodule {
options = {
name = mkOption {
type = nullOr str;
default = null;
description = "Name of the linter";
};
cmd = mkOption {
type = nullOr str;
default = null;
description = "Command of the linter";
};
args = mkOption {
type = nullOr (listOf (either str luaInline));
default = null;
description = "Arguments to pass";
};
stdin = mkOption {
type = nullOr bool;
default = null;
description = "Send content via stdin.";
};
append_fname = mkOption {
type = nullOr bool;
default = null;
description = ''
Automatically add the current file name to the commands arguments. Only
has an effect if stdin is false
'';
};
stream = mkOption {
type = nullOr (enum ["stdout" "stderr" "both"]);
default = null;
description = "Result stream";
};
ignore_exitcode = mkOption {
type = nullOr bool;
default = null;
description = ''
Declares if exit code != 1 should be ignored or result in a warning.
'';
};
env = mkOption {
type = nullOr (attrsOf str);
default = null;
description = "Environment variables to use";
};
cwd = mkOption {
type = nullOr str;
default = null;
description = "Working directory of the linter";
};
parser = mkOption {
type = nullOr luaInline;
default = null;
description = "Parser function";
};
required_files = mkOption {
type = nullOr (listOf str);
default = null;
example = ["eslint.config.js"];
description = ''
Required files to lint. These files must exist relative to the cwd
of the linter or else this linter will be skipped
::: {.note}
This option is an nvf extension that only takes effect if you
use the `nvf_lint()` lua function.
See {option}`vim.diagnostics.nvim-lint.lint_function`.
:::
'';
};
};
};
in {
options.vim.diagnostics.nvim-lint = {
enable = mkEnableOption "asynchronous linter plugin for Neovim [nvim-lint]";
# nvim-lint does not have a setup table.
linters_by_ft = mkOption {
type = attrsOf (listOf str);
default = {};
example = {
text = ["vale"];
markdown = ["vale"];
};
description = ''
Map of filetype to formatters. This option takes a set of `key = value`
format where the `value` will be converted to its Lua equivalent
through `toLuaObject. You are responsible for passing the correct Nix
data types to generate a correct Lua value that conform is able to
accept.
'';
};
linters = mkOption {
type = attrsOf linterType;
default = {};
example = ''
{
phpcs = {
args = ["-q" "--report-json" "-"];
# this will replace the builtin's env table if it exists
env = {
ENV_VAR = "something";
};
};
}
'';
description = ''
Linter configurations. Builtin linters will be updated and not
replaced, but note that this is not a deep extend operation, i.e. if
you define an `env` option, it will replace the entire `env` table
provided by the builtin (if it exists).
'';
};
lint_after_save = mkEnableOption "autocmd to lint after each save" // {default = true;};
lint_function = mkOption {
type = luaInline;
default = mkLuaInline ''
function(buf)
local ft = vim.api.nvim_get_option_value("filetype", { buf = buf })
local linters = require("lint").linters
local linters_from_ft = require("lint").linters_by_ft[ft]
-- if no linter is configured for this filetype, stops linting
if linters_from_ft == nil then return end
for _, name in ipairs(linters_from_ft) do
local linter = linters[name]
assert(linter, 'Linter with name `' .. name .. '` not available')
if type(linter) == "function" then
linter = linter()
end
-- for require("lint").lint() to work, linter.name must be set
linter.name = linter.name or name
local cwd = linter.required_files
-- if no configuration files are configured, lint
if cwd == nil then
require("lint").lint(linter)
else
-- if configuration files are configured and present in the project, lint
for _, fn in ipairs(cwd) do
local path = vim.fs.joinpath(linter.cwd or vim.fn.getcwd(), fn);
if vim.uv.fs_stat(path) then
require("lint").lint(linter)
break
end
end
end
end
end
'';
example = literalExpression ''
mkLuaInline '''
function(buf)
require("lint").try_lint()
end
'''
'';
description = "Define the global function nvf_lint which is used by nvf to lint.";
};
};
}

View file

@ -683,15 +683,48 @@ in {
};
git_placement = mkOption {
type = enum ["before" "after" "signcolumn"];
description = "Place where the git icons will be rendered. `signcolumn` requires `view.signcolumn` to be enabled.";
type = enum ["before" "after" "signcolumn" "right_align"];
default = "before";
description = ''
Place where the git icons will be rendered.
`signcolumn` requires `view.signcolumn` to be enabled.
'';
};
modified_placement = mkOption {
type = enum ["before" "after" "signcolumn"];
description = "Place where the modified icons will be rendered. `signcolumn` requires `view.signcolumn` to be enabled.";
type = enum ["before" "after" "signcolumn" "right_align"];
default = "after";
description = ''
Place where the modified icons will be rendered.
`signcolumn` requires `view.signcolumn` to be enabled.
'';
};
hidden_placement = mkOption {
type = enum ["before" "after" "signcolumn" "right_align"];
default = "after";
description = ''
Place where the hidden icons will be rendered.
`signcolumn` requires `view.signcolumn` to be enabled.
'';
};
diagnostics_placement = mkOption {
type = enum ["before" "after" "signcolumn" "right_align"];
default = "after";
description = ''
Place where the diagnostics icons will be rendered.
`signcolumn` requires `view.signcolumn` to be enabled.
'';
};
bookmarks_placement = mkOption {
type = enum ["before" "after" "signcolumn" "right_align"];
default = "after";
description = ''
Place where the bookmark icons will be rendered.
`signcolumn` requires `view.signcolumn` to be enabled.
'';
};
padding = mkOption {

View file

@ -0,0 +1,20 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.formatter.conform-nvim;
in {
config = mkIf cfg.enable {
vim = {
startPlugins = ["conform-nvim"];
pluginRC.conform-nvim = entryAnywhere ''
require("conform").setup(${toLuaObject cfg.setupOpts})
'';
};
};
}

View file

@ -0,0 +1,73 @@
{lib, ...}: let
inherit (lib.generators) mkLuaInline;
inherit (lib.options) mkOption mkEnableOption literalMD;
inherit (lib.types) attrs either nullOr;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.types) luaInline mkPluginSetupOption;
in {
options.vim.formatter.conform-nvim = {
enable = mkEnableOption "lightweight yet powerful formatter plugin for Neovim [conform-nvim]";
setupOpts = mkPluginSetupOption "conform.nvim" {
formatters_by_ft = mkOption {
type = attrs;
default = {};
example = {lua = ["stylua"];};
description = ''
Map of filetype to formatters. This option takes a set of
`key = value` format where the `value will` be converted
to its Lua equivalent. You are responsible for passing the
correct Nix data types to generate a correct Lua value that
conform is able to accept.
'';
};
default_format_opts = mkOption {
type = attrs;
default = {lsp_format = "fallback";};
description = "Default values when calling `conform.format()`";
};
format_on_save = mkOption {
type = nullOr (either attrs luaInline);
default = mkLuaInline ''
function()
if not vim.g.formatsave or vim.b.disableFormatSave then
return
else
return {lsp_format = "fallback", timeout_ms = 500}
end
end
'';
defaultText = literalMD ''
enabled by default, and respects {option}`vim.lsp.formatOnSave` and
{option}`vim.lsp.mappings.toggleFormatSave`
'';
description = ''
Attribute set or Lua function that will be passed to
`conform.format()`. If this is set, Conform will run the formatter
on save.
'';
};
format_after_save = let
defaultFormatAfterSaveOpts = {lsp_format = "fallback";};
in
mkOption {
type = nullOr (either attrs luaInline);
default = mkLuaInline ''
function()
if not vim.g.formatsave or vim.b.disableFormatSave then
return
else
return ${toLuaObject defaultFormatAfterSaveOpts}
end
end
'';
description = ''
Table or function(luainline) that will be passed to `conform.format()`. If this
is set, Conform will run the formatter asynchronously after save.
'';
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./conform-nvim.nix
./config.nix
];
}

View file

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

View file

@ -3,7 +3,11 @@
in {
imports = [
./gitsigns
./hunk-nvim
./vim-fugitive
./git-conflict
./gitlinker-nvim
./neogit
];
options.vim.git = {
@ -11,8 +15,12 @@ in {
git integration suite.
Enabling this option will enable the following plugins:
* gitsigns
* hunk-nvim
* vim-fugitive
* git-conflict
* gitlinker-nvim
'';
};
}

View file

@ -0,0 +1,40 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetBinding;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.git.git-conflict;
self = import ./git-conflict.nix {inherit lib config;};
gcMappingDefinitions = self.options.vim.git.git-conflict.mappings;
gcMappings = addDescriptionsToMappings cfg.mappings gcMappingDefinitions;
in {
config = mkIf cfg.enable (mkMerge [
{
vim = {
startPlugins = ["git-conflict-nvim"];
maps = {
normal = mkMerge [
(mkSetBinding gcMappings.ours "<Plug>(git-conflict-ours)")
(mkSetBinding gcMappings.theirs "<Plug>(git-conflict-theirs)")
(mkSetBinding gcMappings.both "<Plug>(git-conflict-both)")
(mkSetBinding gcMappings.none "<Plug>(git-conflict-none)")
(mkSetBinding gcMappings.prevConflict "<Plug>(git-conflict-prev-conflict)")
(mkSetBinding gcMappings.nextConflict "<Plug>(git-conflict-next-conflict)")
];
};
pluginRC.git-conflict = entryAnywhere ''
require('git-conflict').setup(${toLuaObject ({default_mappings = false;} // cfg.setupOpts)})
'';
};
}
]);
}

View file

@ -0,0 +1,6 @@
{
imports = [
./config.nix
./git-conflict.nix
];
}

View file

@ -0,0 +1,23 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption;
inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.git.git-conflict = {
enable = mkEnableOption "git-conflict" // {default = config.vim.git.enable;};
setupOpts = mkPluginSetupOption "git-conflict" {};
mappings = {
ours = mkMappingOption "Choose Ours [Git-Conflict]" "<leader>co";
theirs = mkMappingOption "Choose Theirs [Git-Conflict]" "<leader>ct";
both = mkMappingOption "Choose Both [Git-Conflict]" "<leader>cb";
none = mkMappingOption "Choose None [Git-Conflict]" "<leader>c0";
prevConflict = mkMappingOption "Go to the previous Conflict [Git-Conflict]" "]x";
nextConflict = mkMappingOption "Go to the next Conflict [Git-Conflict]" "[x";
};
};
}

View file

@ -0,0 +1,22 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.git.gitlinker-nvim;
in {
config = mkIf cfg.enable {
vim = {
lazy.plugins = {
"gitlinker-nvim" = {
package = "gitlinker-nvim";
setupModule = "gitlinker";
inherit (cfg) setupOpts;
cmd = ["GitLink"];
};
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./config.nix
./gitlinker-nvim.nix
];
}

View file

@ -0,0 +1,13 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.git.gitlinker-nvim = {
enable = mkEnableOption "gitlinker-nvim" // {default = config.vim.git.enable;};
setupOpts = mkPluginSetupOption "gitlinker-nvim" {};
};
}

View file

@ -5,6 +5,7 @@
}: let
inherit (builtins) toJSON;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetExprBinding mkSetLuaBinding pushDownDefault;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
@ -32,6 +33,7 @@ in {
return '<Ignore>'
end
'')
(mkSetExprBinding gsMappings.previousHunk ''
function()
if vim.wo.diff then return ${toJSON gsMappings.previousHunk.value} end
@ -67,7 +69,7 @@ in {
};
binds.whichKey.register = pushDownDefault {
"<leader>g" = "+Gitsigns";
"<leader>h" = "+Gitsigns";
};
pluginRC.gitsigns = entryAnywhere ''
@ -77,13 +79,14 @@ in {
}
(mkIf cfg.codeActions.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.gitsigns-ca = ''
table.insert(
ls_sources,
null_ls.builtins.code_actions.gitsigns
)
'';
vim.lsp.null-ls = {
enable = true;
setupOpts.sources = [
(mkLuaInline ''
require("null-ls").builtins.code_actions.gitsigns
'')
];
};
})
]);
}

View file

@ -0,0 +1,27 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.git.hunk-nvim;
in {
config = mkIf cfg.enable {
vim = {
startPlugins = [
# dependencies
"nui-nvim" # ui library
"nvim-web-devicons" # glyphs
];
lazy.plugins = {
"hunk-nvim" = {
package = "hunk-nvim";
setupModule = "hunk";
inherit (cfg) setupOpts;
};
};
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./hunk-nvim.nix
./config.nix
];
}

View file

@ -0,0 +1,13 @@
{
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.git.hunk-nvim = {
enable = mkEnableOption "tool for splitting diffs in Neovim [hunk-nvim]" // {default = config.vim.git.enable;};
setupOpts = mkPluginSetupOption "hunk-nvim" {};
};
}

View file

@ -0,0 +1,39 @@
{
options,
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.nvim.binds) pushDownDefault mkKeymap;
cfg = config.vim.git.neogit;
keys = cfg.mappings;
inherit (options.vim.git.neogit) mappings;
in {
config = mkIf cfg.enable {
vim = {
startPlugins = ["plenary-nvim"];
lazy.plugins.neogit = {
package = "neogit";
setupModule = "neogit";
inherit (cfg) setupOpts;
cmd = ["Neogit"];
keys = [
(mkKeymap "n" keys.open "<Cmd>Neogit<CR>" {desc = mappings.open.description;})
(mkKeymap "n" keys.commit "<Cmd>Neogit commit<CR>" {desc = mappings.commit.description;})
(mkKeymap "n" keys.pull "<Cmd>Neogit pull<CR>" {desc = mappings.pull.description;})
(mkKeymap "n" keys.push "<Cmd>Neogit push<CR>" {desc = mappings.push.description;})
];
};
binds.whichKey.register = pushDownDefault {
"<leader>g" = "+Git";
};
};
};
}

View file

@ -1,6 +1,6 @@
{
imports = [
./config.nix
./lsplines.nix
./neogit.nix
];
}

View file

@ -0,0 +1,17 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
options.vim.git.neogit = {
enable = mkEnableOption "An Interactive and powerful Git interface [Neogit]";
setupOpts = mkPluginSetupOption "neogit" {};
mappings = {
open = mkMappingOption "Git Status [Neogit]" "<leader>gs";
commit = mkMappingOption "Git Commit [Neogit]" "<leader>gc";
pull = mkMappingOption "Git pull [Neogit]" "<leader>gp";
push = mkMappingOption "Git push [Neogit]" "<leader>gP";
};
};
}

View file

@ -0,0 +1,22 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.hydra;
in {
config = mkIf cfg.enable {
vim = {
startPlugins = [];
lazy.plugins.hydra = {
package = "hydra.nvim";
setupModule = "hydra";
inherit (cfg) setupOpts;
event = ["DeferredUIEnter"];
cmd = ["MCstart" "MCvisual" "MCclear" "MCpattern" "MCvisualPattern" "MCunderCursor"];
};
};
};
}

View file

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

View file

@ -0,0 +1,7 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
in {
options.vim.utility.hydra = {
enable = mkEnableOption "utility for creating custom submodes and menus [nvimtools/hydra.nvim]";
};
}

View file

@ -20,7 +20,7 @@ in {
};
lsp = {
enable = mkEnableOption "Assembly LSP support (asm-lsp)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Assembly LSP support (asm-lsp)" // {default = config.vim.lsp.enable;};
package = mkOption {
type = package;

View file

@ -11,7 +11,6 @@
inherit (lib.meta) getExe;
inherit (lib.types) enum either listOf package str;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.nvim.types) mkGrammarOption diagnostics;
cfg = config.vim.languages.astro;
@ -22,7 +21,7 @@
package = pkgs.astro-language-server;
lspConfig = ''
lspconfig.astro.setup {
capabilities = capabilities;
capabilities = capabilities,
on_attach = attach_keymaps,
cmd = ${
if isList cfg.lsp.package
@ -38,43 +37,36 @@
defaultFormat = "prettier";
formats = {
prettier = {
package = pkgs.nodePackages.prettier;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettier.with({
command = "${cfg.format.package}/bin/prettier",
})
)
'';
package = pkgs.prettier;
};
prettierd = {
package = pkgs.prettierd;
};
biome = {
package = pkgs.biome;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.biome.with({
command = "${cfg.format.package}/bin/biome",
})
)
'';
};
};
# TODO: specify packages
defaultDiagnosticsProvider = ["eslint_d"];
diagnosticsProviders = {
eslint_d = {
package = pkgs.eslint_d;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.eslint_d.with({
command = "${getExe pkg}",
})
)
'';
eslint_d = let
pkg = pkgs.eslint_d;
in {
package = pkg;
config = {
cmd = getExe pkg;
required_files = [
"eslint.config.js"
"eslint.config.mjs"
".eslintrc"
".eslintrc.json"
".eslintrc.js"
".eslintrc.yml"
];
};
};
};
in {
@ -88,19 +80,19 @@ in {
};
lsp = {
enable = mkEnableOption "Astro LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Astro LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Astro LSP server to use";
type = enum (attrNames servers);
default = defaultServer;
description = "Astro LSP server to use";
};
package = mkOption {
description = "Astro LSP server package, or the command to run as a list of strings";
example = ''[lib.getExe pkgs.astro-language-server "--minify" "--stdio"]'';
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
example = ''[lib.getExe pkgs.astro-language-server "--minify" "--stdio"]'';
description = "Astro LSP server package, or the command to run as a list of strings";
};
};
@ -143,16 +135,22 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.astro-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.astro = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "astro";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.astro = cfg.extraDiagnostics.types;
linters =
mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;})
cfg.extraDiagnostics.types);
};
})
]);

View file

@ -6,10 +6,10 @@
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.types) enum either package listOf str bool;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.nvim.types) diagnostics mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
@ -37,14 +37,6 @@
formats = {
shfmt = {
package = pkgs.shfmt;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.shfmt.with({
command = "${pkgs.shfmt}/bin/shfmt",
})
)
'';
};
};
@ -52,15 +44,6 @@
diagnosticsProviders = {
shellcheck = {
package = pkgs.shellcheck;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.shellcheck.with({
command = "${pkg}/bin/shellcheck",
diagnostics_format = "#{m} [#{c}]"
})
)
'';
};
};
in {
@ -73,7 +56,7 @@ in {
};
lsp = {
enable = mkEnableOption "Enable Bash LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Enable Bash LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Bash LSP server to use";
@ -83,7 +66,7 @@ in {
package = mkOption {
description = "bash-language-server package, or the command to run as a list of strings";
example = literalExpression ''[lib.getExe pkgs.nodePackages.bash-language-server "start"]'';
example = literalExpression ''[lib.getExe pkgs.bash-language-server "start"]'';
type = either package (listOf str);
default = pkgs.bash-language-server;
};
@ -130,16 +113,23 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.bash-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.sh = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "bash";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.sh = cfg.extraDiagnostics.types;
linters = mkMerge (map (name: {
${name}.cmd = getExe diagnosticsProviders.${name}.package;
})
cfg.extraDiagnostics.types);
};
})
]);

View file

@ -98,7 +98,7 @@ in {
};
lsp = {
enable = mkEnableOption "clang LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "clang LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "The clang LSP server to use";

View file

@ -0,0 +1,56 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.lists) isList;
inherit (lib.types) either listOf package str;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
cfg = config.vim.languages.clojure;
in {
options.vim.languages.clojure = {
enable = mkEnableOption "Clojure language support";
treesitter = {
enable = mkEnableOption "Clojure treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "clojure";
};
lsp = {
enable = mkEnableOption "Clojure LSP support" // {default = config.vim.lsp.enable;};
package = mkOption {
type = either package (listOf str);
default = pkgs.clojure-lsp;
description = "Clojure LSP";
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.clojure-lsp = ''
lspconfig.clojure_lsp.setup {
capabilities = capabilities;
on_attach = default_on_attach;
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{"${getExe cfg.lsp.package}"}''
};
}
'';
})
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
]);
}

View file

@ -75,8 +75,8 @@
};
extraServerPlugins = {
omnisharp = ["omnisharp-extended"];
csharp_ls = ["csharpls-extended"];
omnisharp = ["omnisharp-extended-lsp-nvim"];
csharp_ls = ["csharpls-extended-lsp-nvim"];
};
cfg = config.vim.languages.csharp;
@ -91,7 +91,7 @@ in {
};
lsp = {
enable = mkEnableOption "C# LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "C# LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "C# LSP server to use";
type = enum (attrNames servers);

View file

@ -6,6 +6,7 @@
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.types) enum either listOf package str;
@ -41,15 +42,7 @@
defaultFormat = "prettier";
formats = {
prettier = {
package = pkgs.nodePackages.prettier;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettier.with({
command = "${cfg.format.package}/bin/prettier",
})
)
'';
package = pkgs.prettier;
};
prettierd = {
@ -87,7 +80,7 @@ in {
};
lsp = {
enable = mkEnableOption "CSS LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "CSS LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "CSS LSP server to use";
@ -132,8 +125,13 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.css-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.css = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
]);
}

View file

@ -0,0 +1,51 @@
{
pkgs,
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.types) package;
inherit (lib.nvim.types) mkGrammarOption;
cfg = config.vim.languages.cue;
in {
options.vim.languages.cue = {
enable = mkEnableOption "CUE language support";
treesitter = {
enable = mkEnableOption "CUE treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "cue";
};
lsp = {
enable = mkEnableOption "CUE LSP support" // {default = config.vim.lsp.enable;};
package = mkOption {
type = package;
default = pkgs.cue;
description = "cue lsp implementation";
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.cue-lsp = ''
lspconfig.cue.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = {"${cfg.lsp.package}/bin/cue", "lsp"},
}
'';
})
]);
}

View file

@ -13,7 +13,7 @@
inherit (lib.strings) optionalString;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.dag) entryAfter;
cfg = config.vim.languages.dart;
ftcfg = cfg.flutter-tools;
@ -77,20 +77,29 @@ in {
flutter-tools = {
enable = mkOption {
type = bool;
default = config.vim.languages.enableLSP;
default = config.vim.lsp.enable;
description = "Enable flutter-tools for flutter support";
};
flutterPackage = mkOption {
type = nullOr package;
default = pkgs.flutter;
description = "Flutter package, or null to detect the flutter path at runtime instead.";
};
enableNoResolvePatch = mkOption {
type = bool;
default = true;
default = false;
description = ''
Whether to patch flutter-tools so that it doesn't resolve
symlinks when detecting flutter path.
This is required if you want to use a flutter package built with nix.
If you are using a flutter SDK installed from a different source
and encounter the error "`dart` missing from PATH", disable this option.
::: {.note}
This is required if `flutterPackage` is set to null and the flutter
package in your `PATH` was built with Nix. If you are using a flutter
SDK installed from a different source and encounter the error "`dart`
missing from `PATH`", leave this option disabled.
:::
'';
};
@ -122,25 +131,30 @@ in {
};
};
config = mkIf cfg.enable (mkMerge [
config.vim = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
treesitter.enable = true;
treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.dart-lsp = servers.${cfg.lsp.server}.lspConfig;
lsp.lspconfig.enable = true;
lsp.lspconfig.sources.dart-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf ftcfg.enable {
vim.startPlugins =
if ftcfg.enableNoResolvePatch
then ["flutter-tools-patched"]
else ["flutter-tools"];
startPlugins = [
(
if ftcfg.enableNoResolvePatch
then "flutter-tools-patched"
else "flutter-tools-nvim"
)
"plenary-nvim"
];
vim.pluginRC.flutter-tools = entryAnywhere ''
pluginRC.flutter-tools = entryAfter ["lsp-setup"] ''
require('flutter-tools').setup {
${optionalString (ftcfg.flutterPackage != null) "flutter_path = \"${ftcfg.flutterPackage}/bin/flutter\","}
lsp = {
color = { -- show the derived colours for dart variables
enabled = ${boolToString ftcfg.color.enable}, -- whether or not to highlight color variables at all, only supported on flutter >= 2.10
@ -152,7 +166,6 @@ in {
capabilities = capabilities,
on_attach = default_on_attach;
flags = lsp_flags,
},
${optionalString cfg.dap.enable ''
debugger = {

View file

@ -1,17 +1,22 @@
{lib, ...}: let
inherit (lib.modules) mkRenamedOptionModule;
inherit (lib.nvim.languages) mkEnable;
in {
imports = [
./asm.nix
./astro.nix
./bash.nix
./cue.nix
./dart.nix
./clang.nix
./clojure.nix
./css.nix
./elixir.nix
./fsharp.nix
./gleam.nix
./go.nix
./hcl.nix
./helm.nix
./kotlin.nix
./html.nix
./haskell.nix
@ -39,11 +44,15 @@ in {
./nu.nix
./odin.nix
./wgsl.nix
./yaml.nix
./ruby.nix
# This is now a hard deprecation.
(mkRenamedOptionModule ["vim" "languages" "enableLSP"] ["vim" "lsp" "enable"])
];
options.vim.languages = {
enableLSP = mkEnable "LSP";
# Those are still managed by plugins, and should be enabled here.
enableDAP = mkEnable "Debug Adapter";
enableTreesitter = mkEnable "Treesitter";
enableFormat = mkEnable "Formatting";

View file

@ -38,14 +38,9 @@
formats = {
mix = {
package = pkgs.elixir;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.mix.with({
command = "${cfg.format.package}/bin/mix",
})
)
'';
config = {
command = "${cfg.format.package}/bin/mix";
};
};
};
in {
@ -58,7 +53,7 @@ in {
};
lsp = {
enable = mkEnableOption "Elixir LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Elixir LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Elixir LSP server to use";
@ -107,12 +102,16 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.elixir-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.elixir = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} =
formats.${cfg.format.type}.config;
};
})
(mkIf cfg.elixir-tools.enable {
vim.startPlugins = ["elixir-tools"];
vim.startPlugins = ["elixir-tools-nvim"];
vim.pluginRC.elixir-tools = entryAnywhere ''
local elixir = require("elixir")
local elixirls = require("elixir.elixirls")

View file

@ -0,0 +1,107 @@
{
lib,
pkgs,
config,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) either listOf package str enum;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
defaultServer = "fsautocomplete";
servers = {
fsautocomplete = {
package = pkgs.fsautocomplete;
internalFormatter = false;
lspConfig = ''
lspconfig.fsautocomplete.setup {
capabilities = capabilities;
on_attach = default_on_attach;
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else "{'${cfg.lsp.package}/bin/fsautocomplete'}"
},
}
'';
};
};
defaultFormat = "fantomas";
formats = {
fantomas = {
package = pkgs.fantomas;
};
};
cfg = config.vim.languages.fsharp;
in {
options = {
vim.languages.fsharp = {
enable = mkEnableOption "F# language support";
treesitter = {
enable = mkEnableOption "F# treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "fsharp";
};
lsp = {
enable = mkEnableOption "F# LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
type = enum (attrNames servers);
default = defaultServer;
description = "F# LSP server to use";
};
package = mkOption {
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
example = ''[lib.getExe pkgs.fsautocomplete "--state-directory" "~/.cache/fsautocomplete"]'';
description = "F# LSP server package, or the command to run as a list of strings";
};
};
format = {
enable = mkEnableOption "F# formatting" // {default = config.vim.languages.enableFormat;};
type = mkOption {
type = enum (attrNames formats);
default = defaultFormat;
description = "F# formatter to use";
};
package = mkOption {
type = package;
default = formats.${cfg.format.type}.package;
description = "F# formatter package";
};
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.fsharp-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf cfg.format.enable {
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.fsharp = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
]);
}

View file

@ -41,7 +41,7 @@ in {
};
lsp = {
enable = mkEnableOption "Gleam LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Gleam LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
type = enum (attrNames servers);

View file

@ -5,7 +5,7 @@
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.options) mkEnableOption mkOption literalMD;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.lists) isList;
@ -34,6 +34,22 @@
};
};
defaultFormat = "gofmt";
formats = {
gofmt = {
package = pkgs.go;
config.command = "${cfg.format.package}/bin/gofmt";
};
gofumpt = {
package = pkgs.gofumpt;
config.command = getExe cfg.format.package;
};
golines = {
package = pkgs.golines;
config.command = "${cfg.format.package}/bin/golines";
};
};
defaultDebugger = "delve";
debuggers = {
delve = {
@ -51,7 +67,7 @@ in {
};
lsp = {
enable = mkEnableOption "Go LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Go LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Go LSP server to use";
@ -67,6 +83,29 @@ in {
};
};
format = {
enable =
mkEnableOption "Go formatting"
// {
default = !cfg.lsp.enable && config.vim.languages.enableFormat;
defaultText = literalMD ''
disabled if Go LSP is enabled, otherwise follows {option}`vim.languages.enableFormat`
'';
};
type = mkOption {
description = "Go formatter to use";
type = enum (attrNames formats);
default = defaultFormat;
};
package = mkOption {
description = "Go formatter package";
type = package;
default = formats.${cfg.format.type}.package;
};
};
dap = {
enable = mkOption {
description = "Enable Go Debug Adapter via nvim-dap-go plugin";
@ -99,6 +138,14 @@ in {
vim.lsp.lspconfig.sources.go-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf cfg.format.enable {
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.go = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = formats.${cfg.format.type}.config;
};
})
(mkIf cfg.dap.enable {
vim = {
startPlugins = ["nvim-dap-go"];

View file

@ -25,7 +25,7 @@ in {
};
lsp = {
enable = mkEnableOption "LSP support for Haskell" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "LSP support for Haskell" // {default = config.vim.lsp.enable;};
package = mkOption {
description = "Haskell LSP package or command to run the Haskell LSP";
example = ''[ (lib.getExe pkgs.haskellPackages.haskell-language-server) "--debug" ]'';

View file

@ -6,6 +6,7 @@
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.types) package bool enum;
inherit (lib.nvim.types) mkGrammarOption;
@ -30,14 +31,6 @@
formats = {
hclfmt = {
package = pkgs.hclfmt;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.hclfmt.with({
command = "${lib.getExe cfg.format.package}",
})
)
'';
};
};
in {
@ -50,7 +43,7 @@ in {
};
lsp = {
enable = mkEnableOption "HCL LSP support (terraform-ls)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "HCL LSP support (terraform-ls)" // {default = config.vim.lsp.enable;};
# TODO: (maybe, is it better?) it would be cooler to use vscode-extensions.hashicorp.hcl probably, shouldn't be too hard
package = mkOption {
type = package;
@ -110,8 +103,13 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.hcl-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.hcl = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
]);
}

View file

@ -0,0 +1,89 @@
{
pkgs,
config,
lib,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.types) enum either listOf package str;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
cfg = config.vim.languages.helm;
yamlCfg = config.vim.languages.yaml;
helmCmd =
if isList cfg.lsp.package
then cfg.lsp.package
else ["${cfg.lsp.package}/bin/helm_ls" "serve"];
yamlCmd =
if isList yamlCfg.lsp.package
then builtins.elemAt yamlCfg.lsp.package 0
else "${yamlCfg.lsp.package}/bin/yaml-language-server";
defaultServer = "helm-ls";
servers = {
helm-ls = {
package = pkgs.helm-ls;
lspConfig = ''
lspconfig.helm_ls.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = ${expToLua helmCmd},
settings = {
['helm-ls'] = {
yamlls = {
path = "${yamlCmd}"
}
}
}
}
'';
};
};
in {
options.vim.languages.helm = {
enable = mkEnableOption "Helm language support";
treesitter = {
enable = mkEnableOption "Helm treesitter" // {default = config.vim.languages.enableTreesitter;};
package = mkGrammarOption pkgs "helm";
};
lsp = {
enable = mkEnableOption "Helm LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Helm LSP server to use";
type = enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "Helm LSP server package";
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.helm-lsp = servers.${cfg.lsp.server}.lspConfig;
})
{
# Enables filetype detection
vim.startPlugins = [pkgs.vimPlugins.vim-helm];
}
]);
}

View file

@ -23,7 +23,7 @@ in {
};
lsp = {
enable = mkEnableOption "Java LSP support (java-language-server)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Java LSP support (java-language-server)" // {default = config.vim.lsp.enable;};
package = mkOption {
description = "java language server package, or the command to run as a list of strings";
example = ''[lib.getExe pkgs.jdt-language-server "-data" "~/.cache/jdtls/workspace"]'';

View file

@ -78,7 +78,7 @@ in {
lsp = {
enable = mkOption {
type = bool;
default = config.vim.languages.enableLSP;
default = config.vim.lsp.enable;
description = ''
Whether to enable Julia LSP support.

View file

@ -7,7 +7,6 @@
inherit (lib.options) mkEnableOption mkOption literalExpression;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.types) either package listOf str;
inherit (lib.nvim.types) mkGrammarOption diagnostics;
inherit (lib.lists) isList;
@ -19,14 +18,6 @@
diagnosticsProviders = {
ktlint = {
package = pkgs.ktlint;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.ktlint.with({
command = "${getExe pkg}",
})
)
'';
};
};
in {
@ -39,7 +30,7 @@ in {
};
lsp = {
enable = mkEnableOption "Kotlin LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Kotlin LSP support" // {default = config.vim.lsp.enable;};
package = mkOption {
description = "kotlin_language_server package with Kotlin runtime";
@ -76,11 +67,13 @@ in {
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "kotlin";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.kotlin = cfg.extraDiagnostics.types;
linters = mkMerge (map (name: {
${name}.cmd = getExe diagnosticsProviders.${name}.package;
})
cfg.extraDiagnostics.types);
};
})

View file

@ -4,18 +4,37 @@
lib,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.lists) isList;
inherit (lib.strings) optionalString;
inherit (lib.types) either listOf package str;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.types) bool either enum listOf package str;
inherit (lib.nvim.types) diagnostics mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.dag) entryBefore;
cfg = config.vim.languages.lua;
defaultFormat = "stylua";
formats = {
stylua = {
package = pkgs.stylua;
};
};
defaultDiagnosticsProvider = ["luacheck"];
diagnosticsProviders = {
luacheck = {
package = pkgs.luajitPackages.luacheck;
};
};
in {
imports = [
(lib.mkRemovedOptionModule ["vim" "languages" "lua" "lsp" "neodev"] ''
neodev has been replaced by lazydev
'')
];
options.vim.languages.lua = {
enable = mkEnableOption "Lua language support";
treesitter = {
@ -24,7 +43,7 @@ in {
};
lsp = {
enable = mkEnableOption "Lua LSP support via LuaLS" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Lua LSP support via LuaLS" // {default = config.vim.lsp.enable;};
package = mkOption {
description = "LuaLS package, or the command to run as a list of strings";
@ -32,7 +51,35 @@ in {
default = pkgs.lua-language-server;
};
neodev.enable = mkEnableOption "neodev.nvim integration, useful for neovim plugin developers";
lazydev.enable = mkEnableOption "lazydev.nvim integration, useful for neovim plugin developers";
};
format = {
enable = mkOption {
type = bool;
default = config.vim.languages.enableFormat;
description = "Enable Lua formatting";
};
type = mkOption {
type = enum (attrNames formats);
default = defaultFormat;
description = "Lua formatter to use";
};
package = mkOption {
type = package;
default = formats.${cfg.format.type}.package;
description = "Lua formatter package";
};
};
extraDiagnostics = {
enable = mkEnableOption "extra Lua diagnostics" // {default = config.vim.languages.enableExtraDiagnostics;};
types = diagnostics {
langDesc = "Lua";
inherit diagnosticsProviders;
inherit defaultDiagnosticsProvider;
};
};
};
@ -49,7 +96,6 @@ in {
lspconfig.lua_ls.setup {
capabilities = capabilities;
on_attach = default_on_attach;
${optionalString cfg.lsp.neodev.enable "before_init = require('neodev.lsp').before_init;"}
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
@ -59,12 +105,38 @@ in {
'';
})
(mkIf cfg.lsp.neodev.enable {
vim.startPlugins = ["neodev-nvim"];
vim.pluginRC.neodev = entryBefore ["lua-lsp"] ''
require("neodev").setup({})
(mkIf cfg.lsp.lazydev.enable {
vim.startPlugins = ["lazydev-nvim"];
vim.pluginRC.lazydev = entryBefore ["lua-lsp"] ''
require("lazydev").setup({
enabled = function(root_dir)
return not vim.uv.fs_stat(root_dir .. "/.luarc.json")
end,
library = { { path = "''${3rd}/luv/library", words = { "vim%.uv" } } },
})
'';
})
(mkIf cfg.format.enable {
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.lua = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.lua = cfg.extraDiagnostics.types;
linters = mkMerge (map (name: {
${name}.cmd = getExe diagnosticsProviders.${name}.package;
})
cfg.extraDiagnostics.types);
};
})
]))
];
}

View file

@ -5,12 +5,13 @@
...
}: let
inherit (builtins) attrNames;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.lists) isList concatLists;
inherit (lib.types) bool enum either package listOf str;
inherit (lib.lists) isList;
inherit (lib.types) bool enum either package listOf str nullOr;
inherit (lib.nvim.lua) expToLua toLuaObject;
inherit (lib.nvim.types) mkGrammarOption mkPluginSetupOption;
inherit (lib.nvim.types) diagnostics mkGrammarOption mkPluginSetupOption;
inherit (lib.nvim.dag) entryAnywhere;
cfg = config.vim.languages.markdown;
@ -32,31 +33,23 @@
};
};
defaultFormat = "denofmt";
defaultFormat = "deno_fmt";
formats = {
# for backwards compatibility
denofmt = {
package = pkgs.deno;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.deno_fmt.with({
filetypes = ${expToLua (concatLists [cfg.format.extraFiletypes ["markdown"]])},
command = "${cfg.format.package}/bin/deno",
})
)
'';
};
deno_fmt = {
package = pkgs.deno;
};
prettierd = {
package = pkgs.prettierd;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettierd.with({
filetypes = ${expToLua (concatLists [cfg.format.extraFiletypes ["markdown"]])},
command = "${cfg.format.package}/bin/prettierd",
})
)
'';
};
};
defaultDiagnosticsProvider = ["markdownlint-cli2"];
diagnosticsProviders = {
markdownlint-cli2 = {
package = pkgs.markdownlint-cli2;
};
};
in {
@ -74,7 +67,7 @@ in {
};
lsp = {
enable = mkEnableOption "Enable Markdown LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Enable Markdown LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
type = enum (attrNames servers);
@ -96,7 +89,7 @@ in {
type = mkOption {
type = enum (attrNames formats);
default = defaultFormat;
description = "Markdown formatter to use";
description = "Markdown formatter to use. `denofmt` is deprecated and currently aliased to deno_fmt.";
};
package = mkOption {
@ -121,18 +114,43 @@ in {
[render-markdown.nvim]: https://github.com/MeanderingProgrammer/render-markdown.nvim
Inline Markdown rendering with [render-markdown.nvim]
'';
};
setupOpts = mkPluginSetupOption "render-markdown" {
auto_override_publish_diagnostics = mkOption {
description = "Automatically override the publish_diagnostics handler";
type = bool;
default = true;
file_types = lib.mkOption {
type = nullOr (listOf str);
default = null;
description = ''
List of buffer filetypes to enable this plugin in.
This will cause the plugin to attach to new buffers who
have any of these filetypes.
'';
};
};
};
markview-nvim = {
enable =
mkEnableOption ""
// {
description = ''
[markview.nvim]: https://github.com/OXY2DEV/markview.nvim
[markview.nvim] - a hackable markdown, Typst, latex, html(inline) & YAML previewer
'';
};
setupOpts = mkPluginSetupOption "markview-nvim" {};
};
};
extraDiagnostics = {
enable = mkEnableOption "extra Markdown diagnostics" // {default = config.vim.languages.enableExtraDiagnostics;};
types = diagnostics {
langDesc = "Markdown";
inherit diagnosticsProviders;
inherit defaultDiagnosticsProvider;
};
};
};
@ -148,8 +166,17 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.markdown-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.markdown = [cfg.format.type];
setupOpts.formatters.${
if cfg.format.type == "denofmt"
then "deno_fmt"
else cfg.format.type
} = {
command = getExe cfg.format.package;
};
};
})
# Extensions
@ -159,5 +186,23 @@ in {
require("render-markdown").setup(${toLuaObject cfg.extensions.render-markdown-nvim.setupOpts})
'';
})
(mkIf cfg.extensions.markview-nvim.enable {
vim.startPlugins = ["markview-nvim"];
vim.pluginRC.markview-nvim = entryAnywhere ''
require("markview").setup(${toLuaObject cfg.extensions.markview-nvim.setupOpts})
'';
})
(mkIf cfg.extraDiagnostics.enable {
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.markdown = cfg.extraDiagnostics.types;
linters = mkMerge (map (name: {
${name}.cmd = getExe diagnosticsProviders.${name}.package;
})
cfg.extraDiagnostics.types);
};
})
]);
}

View file

@ -38,14 +38,9 @@
formats = {
nimpretty = {
package = pkgs.nim;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.nimpretty.with({
command = "${pkgs.nim}/bin/nimpretty",
})
)
'';
config = {
command = "${cfg.format.package}/bin/nimpretty";
};
};
};
in {
@ -58,7 +53,7 @@ in {
};
lsp = {
enable = mkEnableOption "Nim LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Nim LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Nim LSP server to use";
type = str;
@ -110,8 +105,11 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.nim-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.nim = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = formats.${cfg.format.type}.config;
};
})
]);
}

View file

@ -6,14 +6,14 @@
}: let
inherit (builtins) attrNames;
inherit (lib) concatStringsSep;
inherit (lib.meta) getExe;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.strings) optionalString;
inherit (lib.types) enum either listOf package str;
inherit (lib.types) anything attrsOf enum either listOf nullOr package str;
inherit (lib.nvim.types) mkGrammarOption diagnostics;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.nvim.lua) expToLua toLuaObject;
cfg = config.vim.languages.nix;
@ -59,35 +59,44 @@
}
'';
};
nixd = let
settings.nixd = {
inherit (cfg.lsp) options;
formatting.command =
if !cfg.format.enable
then null
else if cfg.format.type == "alejandra"
then ["${cfg.format.package}/bin/alejandra" "--quiet"]
else ["${cfg.format.package}/bin/nixfmt"];
};
in {
package = pkgs.nixd;
internalFormatter = true;
lspConfig = ''
lspconfig.nixd.setup{
capabilities = capabilities,
${
if cfg.format.enable
then useFormat
else noFormat
},
cmd = ${packageToCmd cfg.lsp.package "nixd"},
settings = ${toLuaObject settings},
}
'';
};
};
defaultFormat = "alejandra";
formats = {
alejandra = {
package = pkgs.alejandra;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.alejandra.with({
command = "${cfg.format.package}/bin/alejandra"
})
)
'';
};
nixfmt = {
package = pkgs.nixfmt-rfc-style;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.nixfmt.with({
command = "${cfg.format.package}/bin/nixfmt"
})
)
'';
};
nixpkgs-fmt = null; # removed
};
defaultDiagnosticsProvider = ["statix" "deadnix"];
@ -126,7 +135,7 @@ in {
};
lsp = {
enable = mkEnableOption "Nix LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Nix LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Nix LSP server to use";
type = enum (attrNames servers);
@ -139,6 +148,12 @@ in {
type = either package (listOf str);
default = servers.${cfg.lsp.server}.package;
};
options = mkOption {
type = nullOr (attrsOf anything);
default = null;
description = "Options to pass to nixd LSP server";
};
};
format = {
@ -178,7 +193,6 @@ in {
${concatStringsSep ", " (attrNames formats)}
'';
}
{
assertion = cfg.lsp.server != "rnix";
message = ''
@ -199,17 +213,24 @@ in {
vim.lsp.lspconfig.sources.nix-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf (cfg.format.enable && !servers.${cfg.lsp.server}.internalFormatter) {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.nix-format = formats.${cfg.format.type}.nullConfig;
(mkIf (cfg.format.enable && (!cfg.lsp.enable || !servers.${cfg.lsp.server}.internalFormatter)) {
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.nix = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "nix";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.nix = cfg.extraDiagnostics.types;
linters = mkMerge (map (name: {
${name}.cmd = getExe diagnosticsProviders.${name}.package;
})
cfg.extraDiagnostics.types);
};
})
]);

View file

@ -40,7 +40,7 @@ in {
};
lsp = {
enable = mkEnableOption "Nu LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Nu LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
type = str;
default = defaultServer;

View file

@ -37,14 +37,6 @@
formats = {
ocamlformat = {
package = pkgs.ocamlPackages.ocamlformat;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.ocamlformat.with({
command = "${cfg.format.package}/bin/ocamlformat",
})
)
'';
};
};
in {
@ -57,7 +49,7 @@ in {
};
lsp = {
enable = mkEnableOption "OCaml LSP support (ocaml-lsp)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "OCaml LSP support (ocaml-lsp)" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "OCaml LSP server to user";
type = enum (attrNames servers);
@ -97,9 +89,13 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.ocamlformat = formats.${cfg.format.type}.nullConfig;
vim.extraPackages = [formats.${cfg.format.type}.package];
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.ocaml = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
]);
}

View file

@ -41,7 +41,7 @@ in {
};
lsp = {
enable = mkEnableOption "Odin LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Odin LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
type = enum (attrNames servers);

View file

@ -64,6 +64,26 @@
}
'';
};
intelephense = {
package = pkgs.intelephense;
lspConfig = ''
lspconfig.intelephense.setup{
capabilities = capabilities,
on_attach = default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''
{
"${getExe cfg.lsp.package}",
"--stdio"
},
''
}
}
'';
};
};
in {
options.vim.languages.php = {
@ -75,7 +95,7 @@ in {
};
lsp = {
enable = mkEnableOption "PHP LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "PHP LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "PHP LSP server to use";

View file

@ -47,7 +47,7 @@
};
python-lsp-server = {
package = pkgs.python-lsp-server;
package = pkgs.python3Packages.python-lsp-server;
lspConfig = ''
lspconfig.pylsp.setup{
capabilities = capabilities;
@ -66,26 +66,10 @@
formats = {
black = {
package = pkgs.black;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.black.with({
command = "${cfg.format.package}/bin/black",
})
)
'';
};
isort = {
package = pkgs.isort;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.isort.with({
command = "${cfg.format.package}/bin/isort",
})
)
'';
};
black-and-isort = {
@ -96,15 +80,6 @@
black --quiet - "$@" | isort --profile black -
'';
};
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.black.with({
command = "${cfg.format.package}/bin/black",
})
)
'';
};
ruff = {
@ -115,14 +90,6 @@
ruff format -
'';
};
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.ruff.with({
command = "${cfg.format.package}/bin/ruff",
})
)
'';
};
};
@ -132,7 +99,7 @@
# idk if this is the best way to install/run debugpy
package = pkgs.python3.withPackages (ps: with ps; [debugpy]);
dapConfig = ''
dap.adapters.python = function(cb, config)
dap.adapters.debugpy = function(cb, config)
if config.request == 'attach' then
---@diagnostic disable-next-line: undefined-field
local port = (config.connect or config).port
@ -161,7 +128,7 @@
dap.configurations.python = {
{
-- The first three options are required by nvim-dap
type = 'python'; -- the type here established the link to the adapter definition: `dap.adapters.python`
type = 'debugpy'; -- the type here established the link to the adapter definition: `dap.adapters.debugpy`
request = 'launch';
name = "Launch file";
@ -202,7 +169,7 @@ in {
};
lsp = {
enable = mkEnableOption "Python LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Python LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Python LSP server to use";
@ -272,8 +239,22 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.python-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
# HACK: I'm planning to remove these soon so I just took the easiest way out
setupOpts.formatters_by_ft.python =
if cfg.format.type == "black-and-isort"
then ["black"]
else [cfg.format.type];
setupOpts.formatters =
if (cfg.format.type == "black-and-isort")
then {
black.command = "${cfg.format.package}/bin/black";
}
else {
${cfg.format.type}.command = getExe cfg.format.package;
};
};
})
(mkIf cfg.dap.enable {

View file

@ -24,28 +24,29 @@
package = pkgs.rWrapper.override {
packages = [pkgs.rPackages.styler];
};
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.styler.with({
command = "${cfg.format.package}/bin/R",
})
)
'';
config = {
command = "${cfg.format.package}/bin/R";
};
};
format_r = {
package = pkgs.rWrapper.override {
packages = [pkgs.rPackages.formatR];
};
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.format_r.with({
command = "${cfg.format.package}/bin/R",
})
)
'';
config = {
command = "${cfg.format.package}/bin/R";
stdin = true;
args = [
"--slave"
"--no-restore"
"--no-save"
"-s"
"-e"
''formatR::tidy_source(source="stdin")''
];
# TODO: range_args seem to be possible
# https://github.com/nvimtools/none-ls.nvim/blob/main/lua/null-ls/builtins/formatting/format_r.lua
};
};
};
@ -78,7 +79,7 @@ in {
};
lsp = {
enable = mkEnableOption "R LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "R LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "R LSP server to use";
@ -118,8 +119,11 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.r-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.r = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = formats.${cfg.format.type}.config;
};
})
(mkIf cfg.lsp.enable {

View file

@ -6,10 +6,12 @@
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.nvim.types) mkGrammarOption diagnostics;
inherit (lib.nvim.lua) expToLua;
inherit (lib.lists) isList;
inherit (lib.types) either listOf package str enum;
inherit (lib.nvim.languages) diagnosticsToLua;
cfg = config.vim.languages.ruby;
@ -24,7 +26,25 @@
flags = {
debounce_text_changes = 150,
},
cmd = { "${pkgs.solargraph}/bin/solargraph", "stdio" }
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{ "${cfg.lsp.package}/bin/solargraph", "stdio" }''
}
}
'';
};
rubylsp = {
package = pkgs.ruby-lsp;
lspConfig = ''
lspconfig.ruby_lsp.setup {
capabilities = capabilities,
on_attach = default_on_attach,
cmd = ${
if isList cfg.lsp.package
then expToLua cfg.lsp.package
else ''{ "${cfg.lsp.package}/bin/ruby-lsp" }''
}
}
'';
};
@ -35,24 +55,8 @@
defaultFormat = "rubocop";
formats = {
rubocop = {
# TODO: is this right?
package = pkgs.rubyPackages.rubocop;
nullConfig = ''
local conditional = function(fn)
local utils = require("null-ls.utils").make_conditional_utils()
return fn(utils)
end
table.insert(
ls_sources,
null_ls.builtins.formatting.rubocop.with({
command="${pkgs.bundler}/bin/bundle",
args = vim.list_extend(
{"exec", "rubocop", "-a" },
null_ls.builtins.formatting.rubocop._opts.args
),
})
)
'';
};
};
@ -60,14 +64,7 @@
diagnosticsProviders = {
rubocop = {
package = pkgs.rubyPackages.rubocop;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.rubocop.with({
command = "${lib.getExe pkg}",
})
)
'';
config.command = getExe cfg.format.package;
};
};
in {
@ -80,7 +77,7 @@ in {
};
lsp = {
enable = mkEnableOption "Ruby LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Ruby LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
type = enum (attrNames servers);
@ -136,16 +133,23 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.ruby-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.ruby = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "ruby";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.ruby = cfg.extraDiagnostics.types;
linters = mkMerge (map (name: {
${name}.cmd = getExe diagnosticsProviders.${name}.package;
})
cfg.extraDiagnostics.types);
};
})
]);

View file

@ -5,8 +5,9 @@
...
}: let
inherit (builtins) attrNames;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.options) mkOption mkEnableOption literalMD;
inherit (lib.strings) optionalString;
inherit (lib.trivial) boolToString;
inherit (lib.lists) isList;
@ -21,14 +22,6 @@
formats = {
rustfmt = {
package = pkgs.rustfmt;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.rustfmt.with({
command = "${cfg.format.package}/bin/rustfmt",
})
)
'';
};
};
in {
@ -50,7 +43,7 @@ in {
};
lsp = {
enable = mkEnableOption "Rust LSP support (rust-analyzer with extra tools)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Rust LSP support (rust-analyzer with extra tools)" // {default = config.vim.lsp.enable;};
package = mkOption {
description = "rust-analyzer package, or the command to run as a list of strings";
example = ''[lib.getExe pkgs.jdt-language-server "-data" "~/.cache/jdtls/workspace"]'';
@ -62,11 +55,27 @@ in {
description = "Options to pass to rust analyzer";
type = str;
default = "";
example = ''
['rust-analyzer'] = {
cargo = {allFeature = true},
checkOnSave = true,
procMacro = {
enable = true,
},
},
'';
};
};
format = {
enable = mkEnableOption "Rust formatting" // {default = config.vim.languages.enableFormat;};
enable =
mkEnableOption "Rust formatting"
// {
default = !cfg.lsp.enable && config.vim.languages.enableFormat;
defaultText = literalMD ''
Disabled if Rust LSP is enabled, otherwise follows {option}`vim.languages.enableFormat`
'';
};
type = mkOption {
description = "Rust formatter to use";
@ -119,8 +128,13 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.rust-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.rust = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf (cfg.lsp.enable || cfg.dap.enable) {
@ -142,6 +156,9 @@ in {
then expToLua cfg.lsp.package
else ''{"${cfg.lsp.package}/bin/rust-analyzer"}''
},
default_settings = {
${cfg.lsp.opts}
},
on_attach = function(client, bufnr)
default_on_attach(client, bufnr)
local opts = { noremap=true, silent=true, buffer = bufnr }

View file

@ -33,7 +33,7 @@ in {
};
lsp = {
enable = mkEnableOption "Scala LSP support (metals)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Scala LSP support (metals)" // {default = config.vim.lsp.enable;};
package = mkPackageOption pkgs "metals" {
default = ["metals"];
};

View file

@ -6,11 +6,11 @@
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.meta) getExe;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.lists) isList;
inherit (lib.types) enum either listOf package str;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.nvim.types) diagnostics;
cfg = config.vim.languages.sql;
@ -41,15 +41,10 @@
formats = {
sqlfluff = {
package = sqlfluffDefault;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.sqlfluff.with({
command = "${cfg.format.package}/bin/sqlfluff",
extra_args = {"--dialect", "${cfg.dialect}"}
})
)
'';
config = {
command = getExe cfg.format.package;
append_args = ["--dialect=${cfg.dialect}"];
};
};
};
@ -57,15 +52,10 @@
diagnosticsProviders = {
sqlfluff = {
package = sqlfluffDefault;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.sqlfluff.with({
command = "${pkg}/bin/sqlfluff",
extra_args = {"--dialect", "${cfg.dialect}"}
})
)
'';
config = {
cmd = getExe sqlfluffDefault;
args = ["lint" "--format=json" "--dialect=${cfg.dialect}"];
};
};
};
in {
@ -89,7 +79,7 @@ in {
};
lsp = {
enable = mkEnableOption "SQL LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "SQL LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "SQL LSP server to use";
@ -150,16 +140,20 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources."sql-format" = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.sql = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = formats.${cfg.format.type}.config;
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "sql";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.sql = cfg.extraDiagnostics.types;
linters =
mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;})
cfg.extraDiagnostics.types);
};
})
]);

View file

@ -11,7 +11,6 @@
inherit (lib.meta) getExe;
inherit (lib.types) enum either listOf package str;
inherit (lib.nvim.lua) expToLua;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.nvim.types) mkGrammarOption diagnostics;
cfg = config.vim.languages.svelte;
@ -19,7 +18,7 @@
defaultServer = "svelte";
servers = {
svelte = {
package = pkgs.nodePackages.svelte-language-server;
package = pkgs.svelte-language-server;
lspConfig = ''
lspconfig.svelte.setup {
capabilities = capabilities;
@ -38,43 +37,32 @@
defaultFormat = "prettier";
formats = {
prettier = {
package = pkgs.nodePackages.prettier;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettier.with({
command = "${cfg.format.package}/bin/prettier",
})
)
'';
package = pkgs.prettier;
};
biome = {
package = pkgs.biome;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.biome.with({
command = "${cfg.format.package}/bin/biome",
})
)
'';
};
};
# TODO: specify packages
defaultDiagnosticsProvider = ["eslint_d"];
diagnosticsProviders = {
eslint_d = {
package = pkgs.eslint_d;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.eslint_d.with({
command = "${getExe pkg}",
})
)
'';
eslint_d = let
pkg = pkgs.eslint_d;
in {
package = pkg;
config = {
cmd = getExe pkg;
required_files = [
"eslint.config.js"
"eslint.config.mjs"
".eslintrc"
".eslintrc.json"
".eslintrc.js"
".eslintrc.yml"
];
};
};
};
in {
@ -88,7 +76,7 @@ in {
};
lsp = {
enable = mkEnableOption "Svelte LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Svelte LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Svelte LSP server to use";
@ -143,16 +131,22 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.svelte-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.svelte = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "svelte";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.svelte = cfg.extraDiagnostics.types;
linters =
mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;})
cfg.extraDiagnostics.types);
};
})
]);

View file

@ -35,7 +35,7 @@ in {
enable = mkEnableOption "Tailwindcss language support";
lsp = {
enable = mkEnableOption "Tailwindcss LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Tailwindcss LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Tailwindcss LSP server to use";

View file

@ -20,7 +20,7 @@ in {
};
lsp = {
enable = mkEnableOption "Terraform LSP support (terraform-ls)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Terraform LSP support (terraform-ls)" // {default = config.vim.lsp.enable;};
package = mkOption {
description = "terraform-ls package";

View file

@ -12,7 +12,6 @@
inherit (lib.types) enum either listOf package str bool;
inherit (lib.nvim.lua) expToLua toLuaObject;
inherit (lib.nvim.types) mkGrammarOption diagnostics mkPluginSetupOption;
inherit (lib.nvim.languages) diagnosticsToLua;
inherit (lib.nvim.dag) entryAnywhere;
cfg = config.vim.languages.ts;
@ -76,56 +75,37 @@
defaultFormat = "prettier";
formats = {
prettier = {
package = pkgs.nodePackages.prettier;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettier.with({
command = "${cfg.format.package}/bin/prettier",
filetypes = { "typescript" },
})
)
'';
package = pkgs.prettier;
};
prettierd = {
package = pkgs.prettierd;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettier.with({
command = "${cfg.format.package}/bin/prettierd",
})
)
'';
};
biome = {
package = pkgs.biome;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.biome.with({
command = "${cfg.format.package}/bin/biome",
})
)
'';
};
};
# TODO: specify packages
defaultDiagnosticsProvider = ["eslint_d"];
diagnosticsProviders = {
eslint_d = {
package = pkgs.eslint_d;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.eslint_d.with({
command = "${getExe pkg}",
})
)
'';
eslint_d = let
pkg = pkgs.eslint_d;
in {
package = pkg;
config = {
cmd = getExe pkg;
required_files = [
"eslint.config.js"
"eslint.config.mjs"
".eslintrc"
".eslintrc.cjs"
".eslintrc.json"
".eslintrc.js"
".eslintrc.yml"
];
};
};
};
in {
@ -140,7 +120,7 @@ in {
};
lsp = {
enable = mkEnableOption "Typescript/Javascript LSP support" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Typescript/Javascript LSP support" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Typescript/Javascript LSP server to use";
@ -215,22 +195,34 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.ts-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts = {
formatters_by_ft.typescript = [cfg.format.type];
# .tsx files
formatters_by_ft.typescriptreact = [cfg.format.type];
formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
};
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = diagnosticsToLua {
lang = "ts";
config = cfg.extraDiagnostics.types;
inherit diagnosticsProviders;
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.typescript = cfg.extraDiagnostics.types;
linters_by_ft.typescriptreact = cfg.extraDiagnostics.types;
linters =
mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;})
cfg.extraDiagnostics.types);
};
})
# Extensions
(mkIf cfg.extensions."ts-error-translator".enable {
vim.startPlugins = ["ts-error-translator"];
vim.startPlugins = ["ts-error-translator-nvim"];
vim.pluginRC.ts-error-translator = entryAnywhere ''
require("ts-error-translator").setup(${toLuaObject cfg.extensions.ts-error-translator.setupOpts})
'';

View file

@ -9,7 +9,6 @@
inherit (lib.lists) isList;
inherit (lib.types) nullOr enum either attrsOf listOf package str bool int;
inherit (lib.attrsets) attrNames;
inherit (lib.generators) mkLuaInline;
inherit (lib.meta) getExe;
inherit (lib.nvim.binds) mkMappingOption mkKeymap;
inherit (lib.nvim.lua) expToLua toLuaObject;
@ -62,26 +61,10 @@
formats = {
typstfmt = {
package = pkgs.typstfmt;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.typstfmt.with({
command = "${cfg.format.package}/bin/typstfmt",
})
)
'';
};
# https://github.com/Enter-tainer/typstyle
typstyle = {
package = pkgs.typstyle;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.typstfmt.with({
command = "${cfg.format.package}/bin/typstyle",
})
)
'';
};
};
in {
@ -94,7 +77,7 @@ in {
};
lsp = {
enable = mkEnableOption "Typst LSP support (typst-lsp)" // {default = config.vim.languages.enableLSP;};
enable = mkEnableOption "Typst LSP support (typst-lsp)" // {default = config.vim.lsp.enable;};
server = mkOption {
description = "Typst LSP server to use";
@ -222,8 +205,13 @@ in {
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.typst-format = formats.${cfg.format.type}.nullConfig;
vim.formatter.conform-nvim = {
enable = true;
setupOpts.formatters_by_ft.typst = [cfg.format.type];
setupOpts.formatters.${cfg.format.type} = {
command = getExe cfg.format.package;
};
};
})
(mkIf cfg.lsp.enable {

Some files were not shown because too many files have changed in this diff Show more