diff --git a/docs/man/header.5 b/docs/man/header.5 index a28fc3dd..556a113a 100644 --- a/docs/man/header.5 +++ b/docs/man/header.5 @@ -1,13 +1,16 @@ -.TH "nvf" "5" "01/01/1980" "nvf" +.TH "nvf" "5" "January 1, 1980" "nvf" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" enable line breaks after slashes .cflags 4 / + .SH "NAME" -nvf configuration specification -.SH "OPTIONS" -.PP -You can use the following options to configure nvf: -.PP +nvf \- Configuration specification for the nvf. + +.SH "DESCRIPTION" +The nvf configuration specification provides a declarative structure for configuring Neovim using Nix with few +lines of Nix. This document outlines the available options and their usage to create modular, reusable, and +reproducible configurations using nvf's module system options. For tips, tricks and possible quirks with available +plugins please visit https://notashelf.github.io/nvf/ diff --git a/docs/man/nvf.1 b/docs/man/nvf.1 index 0f1e36dc..d7519651 100644 --- a/docs/man/nvf.1 +++ b/docs/man/nvf.1 @@ -1,5 +1,5 @@ .Dd January 1, 1980 -.Dt nvf 1 +.Dt NVF 1 .Os nvf .\" disable hyphenation .nh @@ -7,27 +7,46 @@ .ad l .\" enable line breaks after slashes .cflags 4 / + .Sh NAME .Nm nvf -.Nd A highly modular, extensible and distro-agnostic Neovim configuration framework for Nix/NixOS. -. +.Nd A modular, extensible, and distro-agnostic Neovim configuration framework for Nix/NixOS. + +.Sh DESCRIPTION +.Nm nvf +is a highly modular, configurable, extensible, and easy-to-use Neovim configuration in Nix. +Designed for flexibility and ease of use, nvf allows you to easily configure your fully featured +Neovim instance with a few lines of Nix. + +.Sh COMMANDS +The following commands are bundled with nvf to allow easier debugging of your configuration. + +.Bl -tag -width Ds +.It Nm nvf-print-config +Outputs the full configuration of the current `nvf` setup. This command is useful for debugging +or inspecting the applied configuration. +.Pp +.It Nm nvf-print-config-path +Prints the file path to the configuration file currently in use. This command is helpful for locating +the source configuration file for troubleshooting or easily sharing it via online paste utilities. +.El + .Sh BUGS .Pp -Please report any bugs that you might encounter on the -\m[blue]\fBproject issue tracker\fR\m[]\&. +Please report any bugs on the project issue tracker: +.Lk https://github.com/notashelf/nvf/issues .Sh SEE ALSO .Pp -\fBnvf\fR(5) +.Fn nvf 5 .Sh AUTHOR .Pp -\fBnvf contributors\fR +.Fn nvf contributors .RS 4 -Author. +Primary contributors and maintainers of the project. .RE .Sh COPYRIGHT -.br -Copyright \(co 2023\(en2024 nvf contributors -.br +.Pp +Copyright (c) 2023–2025 nvf contributors. diff --git a/docs/release-notes/rl-0.8.md b/docs/release-notes/rl-0.8.md index 95bb6661..f5e9d0a0 100644 --- a/docs/release-notes/rl-0.8.md +++ b/docs/release-notes/rl-0.8.md @@ -31,6 +31,12 @@ your Editorconfig configuration, or use an autocommand to set indentation values for buffers with the Nix filetype. +- Add [](#opt-vim.lsp.lightbulb.autocmd.enable) for manually managing the + previously managed lightbulb autocommand. + - A warning will occur if [](#opt-vim.lsp.lightbulb.autocmd.enable) and + `vim.lsp.lightbulb.setupOpts.autocmd.enabled` are both set at the same time. + Pick only one. + [amadaluzia](https://github.com/amadaluzia): [haskell-tools.nvim]: https://github.com/MrcJkb/haskell-tools.nvim @@ -59,7 +65,8 @@ - Add `vim.snippets.luasnip.setupOpts`, which was previously missing. - Add `"prettierd"` as a formatter option in `vim.languages.markdown.format.type`. -- Add the following plugins from [mini.nvim](https://github.com/echasnovski/mini.nvim) +- Add the following plugins from + [mini.nvim](https://github.com/echasnovski/mini.nvim) - `mini.ai` - `mini.align` - `mini.animate` @@ -102,7 +109,8 @@ - `mini.trailspace` - `mini.visits` - Add [fzf-lua](https://github.com/ibhagwan/fzf-lua) in `vim.fzf-lua` -- Add [rainbow-delimiters](https://github.com/HiPhish/rainbow-delimiters.nvim) in `vim.visuals.rainbow-delimiters` +- Add [rainbow-delimiters](https://github.com/HiPhish/rainbow-delimiters.nvim) + in `vim.visuals.rainbow-delimiters` - Add options to define highlights under [](#opt-vim.highlight) [kaktu5](https://github.com/kaktu5): @@ -122,3 +130,8 @@ [ruff]: (https://github.com/astral-sh/ruff) - Add [ruff] as a formatter option in `vim.languages.python.format.type`. + +[ARCIII](https://github.com/ArmandoCIII): + +- Add `vim.languages.zig.dap` support through pkgs.lldb dap adapter. Code + Inspiration from `vim.languages.clang.dap` implementation. diff --git a/modules/plugins/languages/tex/build/builders/custom.nix.bak b/modules/plugins/languages/tex/build/builders/custom.nix.bak deleted file mode 100644 index 01b5913c..00000000 --- a/modules/plugins/languages/tex/build/builders/custom.nix.bak +++ /dev/null @@ -1,66 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: let - inherit (lib.options) mkOption; - inherit (lib.modules) mkIf; - inherit (lib.types) bool listOf package str; - inherit (lib) mkDefault; - - cfg = config.vim.languages.tex; - - # --- Enable Options --- - mkEnableDefaultOption = default: description: (mkOption { - type = bool; - default = default; - example = !default; - description = description; - }); - - collateArgs = buildConfig: buildConfig.builders.custom.args; -in { - options.vim.languages.tex.build.builders.custom = { - enable = mkEnableDefaultOption false "Whether to enable using a custom build package"; - package = mkOption { - type = package; - default = pkgs.tectonic; - description = "build/compiler package"; - }; - executable = mkOption { - type = str; - default = "tectonic"; - description = "The executable name from the build package that will be used to build/compile the tex."; - }; - args = mkOption { - type = listOf str; - default = [ - "-X" - "compile" - "%f" - "--synctex" - "--keep-logs" - "--keep-intermediates" - ]; - description = '' - Defines additional arguments that are passed to the configured LaTeX build tool. - Note that flags and their arguments need to be separate elements in this array. - To pass the arguments -foo bar to a build tool, args needs to be ["-foo" "bar"]. - The placeholder `%f` will be replaced by the server. - - Placeholders: - - `%f`: The path of the TeX file to compile. - ''; - }; - }; - - config = mkIf (cfg.enable && cfg.build.builders.custom.enable) { - vim.languages.tex.build.builder = { - name = mkDefault "custom"; - args = mkDefault (collateArgs cfg.build); - package = mkDefault (cfg.build.builders.custom.package); - executable = mkDefault (cfg.build.builders.custom.executable); - }; - }; -} diff --git a/modules/plugins/languages/tex/build/builders/default.nix b/modules/plugins/languages/tex/build/builders/default.nix index 0e4eb8d8..4586b768 100644 --- a/modules/plugins/languages/tex/build/builders/default.nix +++ b/modules/plugins/languages/tex/build/builders/default.nix @@ -3,15 +3,14 @@ pkgs, lib, ... -}: -let +}: let inherit (lib.options) mkOption; inherit (lib.types) enum listOf package str; - inherit (builtins) attrNames; + inherit (lib.nvim.config) mkBool; + inherit (builtins) attrNames filter isAttrs hasAttr elemAt length; cfg = config.vim.languages.tex; -in -{ +in { imports = [ ./latexmk.nix ./tectonic.nix @@ -27,6 +26,8 @@ in This is just the default custom option. By setting any of the builders to true, this will be overwritten by that builder's parameters. + Setting this parameter to the name of a declared builder will + not automatically enable that builder. ''; }; args = mkOption { @@ -45,7 +46,7 @@ in }; package = mkOption { type = package; - default = (pkgs.texlive.withPackages (ps: [ ps.latexmk ])); + default = pkgs.texlive.withPackages (ps: [ps.latexmk]); description = '' The tex builder package to use. @@ -67,4 +68,3 @@ in }; }; } - diff --git a/modules/plugins/languages/tex/build/builders/latexmk.nix b/modules/plugins/languages/tex/build/builders/latexmk.nix index 1cc4eb51..edc46584 100644 --- a/modules/plugins/languages/tex/build/builders/latexmk.nix +++ b/modules/plugins/languages/tex/build/builders/latexmk.nix @@ -1,6 +1,5 @@ # TODO: I need testing. { - config, pkgs, lib, ... @@ -13,16 +12,6 @@ inherit (lib.options) mkOption mkEnableOption; inherit (lib.types) bool package str; - - cfg = config.vim.languages.tex; - - # --- Enable Options --- - mkEnableDefaultOption = default: description: (mkOption { - type = bool; - default = default; - example = !default; - description = description; - }); in ( template { inherit name moduleInheritencePackage; diff --git a/modules/plugins/languages/tex/build/builders/tectonic.nix b/modules/plugins/languages/tex/build/builders/tectonic.nix index 71facf1e..ec6e253c 100644 --- a/modules/plugins/languages/tex/build/builders/tectonic.nix +++ b/modules/plugins/languages/tex/build/builders/tectonic.nix @@ -11,18 +11,11 @@ template = import ./builderTemplate.nix; inherit (lib.options) mkOption mkEnableOption; - inherit (lib.types) bool enum ints listOf package str; + inherit (lib.types) enum ints listOf package str; + inherit (lib.nvim.config) mkBool; inherit (builtins) concatLists elem map toString; cfg = config.vim.languages.tex; - - # --- Enable Options --- - mkEnableDefaultOption = default: description: (mkOption { - type = bool; - default = default; - example = !default; - description = description; - }); in ( template { inherit name moduleInheritencePackage; @@ -43,26 +36,30 @@ in ( }; # -- Flags -- - keepIntermediates = mkEnableDefaultOption false '' + keepIntermediates = mkBool false '' Keep the intermediate files generated during processing. If texlab is reporting build errors when there shouldn't be, disable this option. ''; - keepLogs = mkEnableDefaultOption true '' + keepLogs = mkBool true '' Keep the log files generated during processing. Without the keepLogs flag, texlab won't be able to report compilation warnings. ''; - onlyCached = mkEnableDefaultOption false "Use only resource files cached locally"; - synctex = mkEnableDefaultOption true "Generate SyncTeX data"; - untrustedInput = mkEnableDefaultOption false "Input is untrusted -- disable all known-insecure features"; + onlyCached = mkBool false "Use only resource files cached locally"; + synctex = mkBool true "Generate SyncTeX data"; + untrustedInput = mkBool false "Input is untrusted -- disable all known-insecure features"; # -- Options -- reruns = mkOption { type = ints.unsigned; default = 0; example = 2; - description = "Rerun the TeX engine exactly this many times after the first"; + description = '' + Rerun the TeX engine exactly this many times after the first. + + Setting this value to 0 will diable setting this option. + ''; }; bundle = mkOption { diff --git a/modules/plugins/languages/tex/build/builders/tectonic.nix.bak b/modules/plugins/languages/tex/build/builders/tectonic.nix.bak deleted file mode 100644 index 82f4b8b2..00000000 --- a/modules/plugins/languages/tex/build/builders/tectonic.nix.bak +++ /dev/null @@ -1,217 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: let - inherit (lib.options) mkOption mkEnableOption; - inherit (lib.modules) mkIf; - inherit - (lib.types) - bool - enum - ints - listOf - package - str - ; - inherit (builtins) concatLists elem map toString; - - cfg = config.vim.languages.tex; - - # --- Enable Options --- - mkEnableDefaultOption = default: description: (mkOption { - type = bool; - default = default; - example = !default; - description = description; - }); - - # --- Arg Collation Functions -- - collateArgs = buildConfig: let - selfConfig = buildConfig.builders.tectonic; - in ( - # Base args - [ - "-X" - "compile" - "%f" - ] - # Flags - ++ ( - if selfConfig.keepIntermediates - then ["--keep-intermediates"] - else [] - ) - ++ ( - if selfConfig.keepLogs - then ["--keep-logs"] - else [] - ) - ++ ( - if selfConfig.onlyCached - then ["--only-cached"] - else [] - ) - ++ ( - if selfConfig.synctex - then ["--synctex"] - else [] - ) - ++ ( - if selfConfig.untrustedInput - then ["--untrusted"] - else [] - ) - # Options - ++ ( - if selfConfig.reruns > 0 - then ["--reruns" "${toString selfConfig.reruns}"] - else [] - ) - ++ ( - if selfConfig.bundle != "" - then ["--bundle" "${toString selfConfig.bundle}"] - else [] - ) - ++ ( - if selfConfig.webBundle != "" - then ["--web-bundle" "${toString selfConfig.webBundle}"] - else [] - ) - ++ ( - if selfConfig.outfmt != "" - then ["--outfmt" "${toString selfConfig.outfmt}"] - else [] - ) - ++ (concatLists (map (x: ["--hide" x]) selfConfig.hidePaths)) - ++ ( - if selfConfig.format != "" - then ["--format" "${toString selfConfig.format}"] - else [] - ) - ++ ( - if selfConfig.color != "" - then ["--color" "${toString selfConfig.color}"] - else [] - ) - # Still options but these are not defined by builder specific options but - # instead synchronize options between the global build options and builder - # specific options - ++ ( - if !(elem buildConfig.pdfDirectory ["." ""]) - then ["--outdir" "${buildConfig.pdfDirectory}"] - else [] - ) - ); -in { - options.vim.languages.tex.build.builders.tectonic = { - enable = mkEnableOption "Whether to enable Tex Compilation Via Tectonic"; - - package = mkOption { - type = package; - default = pkgs.tectonic; - description = "tectonic package"; - }; - - executable = mkOption { - type = str; - default = "tectonic"; - description = "The executable name from the build package that will be used to build/compile the tex."; - }; - - # -- Flags -- - keepIntermediates = mkEnableDefaultOption false '' - Keep the intermediate files generated during processing. - - If texlab is reporting build errors when there shouldn't be, disable this option. - ''; - keepLogs = mkEnableDefaultOption true '' - Keep the log files generated during processing. - - Without the keepLogs flag, texlab won't be able to report compilation warnings. - ''; - onlyCached = mkEnableDefaultOption false "Use only resource files cached locally"; - synctex = mkEnableDefaultOption true "Generate SyncTeX data"; - untrustedInput = mkEnableDefaultOption false "Input is untrusted -- disable all known-insecure features"; - - # -- Options -- - reruns = mkOption { - type = ints.unsigned; - default = 0; - example = 2; - description = "Rerun the TeX engine exactly this many times after the first"; - }; - - bundle = mkOption { - type = str; - default = ""; - description = "Use this directory or Zip-format bundle file to find resource files instead of the default"; - }; - - webBundle = mkOption { - type = str; - default = ""; - description = "Use this URL to find resource files instead of the default"; - }; - - outfmt = mkOption { - type = enum [ - "pdf" - "html" - "xdv" - "aux" - "fmt" - "" - ]; - default = ""; - description = "The kind of output to generate"; - }; - - hidePaths = mkOption { - type = listOf str; - default = []; - example = [ - "./secrets.tex" - "./passwords.tex" - ]; - description = "Tell the engine that no file at exists, if it tries to read it."; - }; - - format = mkOption { - type = str; - default = ""; - description = "The name of the \"format\" file used to initialize the TeX engine"; - }; - - color = mkOption { - type = enum [ - "always" - "auto" - "never" - "" - ]; - default = ""; - example = "always"; - description = "Enable/disable colorful log output"; - }; - - extraOptions = { - type = listOf str; - default = []; - description = '' - Add extra command line options to include in the tectonic build command. - Extra options added here will not overwrite the options set in as nvf options. - ''; - }; - }; - - config = mkIf (cfg.enable && cfg.build.builders.tectonic.enable) { - vim.languages.tex.build.builder = { - name = "tectonic"; - args = collateArgs cfg.build; - package = cfg.build.builders.tectonic.package; - executable = cfg.build.builders.tectonic.executable; - }; - }; -} diff --git a/modules/plugins/languages/tex/build/default.nix b/modules/plugins/languages/tex/build/default.nix index cbc9dca7..fe07775b 100644 --- a/modules/plugins/languages/tex/build/default.nix +++ b/modules/plugins/languages/tex/build/default.nix @@ -4,34 +4,71 @@ ... }: let inherit (lib.options) mkOption; - inherit (lib.types) bool str; + inherit (lib.types) str nullOr; + inherit (builtins) filter isAttrs hasAttr attrNames length elemAt; + inherit (lib.nvim.config) mkBool; cfg = config.vim.languages.tex; + + enabledBuildersCount = let + # This function will sort through the builder options and count how many + # builders have been enabled. + getEnabledBuildersCount = { + enabledBuildersCount ? 0, + index ? 0, + builderNamesList ? ( + filter ( + x: let + y = cfg.build.builders.${x}; + in (isAttrs y && hasAttr "enable" y) + ) (attrNames cfg.build.builders) + ), + }: let + currentBuilderName = elemAt builderNamesList index; + currentBuilder = cfg.build.builders.${currentBuilderName}; + nextIndex = index + 1; + newEnabledBuildersCount = + if currentBuilder.enable + then enabledBuildersCount + 1 + else enabledBuildersCount; + in + if length builderNamesList > nextIndex + then + getEnabledBuildersCount { + inherit builderNamesList; + enabledBuildersCount = newEnabledBuildersCount; + index = nextIndex; + } + else newEnabledBuildersCount; + in (getEnabledBuildersCount {}); in { imports = [ ./builders ]; options.vim.languages.tex.build = { - forwardSearchAfter = mkOption { - type = bool; - default = false; - description = "Set this property to true if you want to execute a forward search after a build."; - }; - onSave = mkOption { - type = bool; - default = false; - description = "Set this property to true if you want to compile the project after saving a file."; - }; - useFileList = mkOption { - type = bool; - default = false; - description = '' - When set to true, the server will use the .fls files produced by the TeX engine as an additional input for the project detection. + enable = + mkBool ( + if enabledBuildersCount > 1 + then throw "nvf-tex-language does not support having more than 1 builders enabled!" + else (enabledBuildersCount == 1) + ) '' + Whether to enable configuring the builder. - Note that enabling this property might have an impact on performance. + By enabling any of the builders, this option will be automatically set. + If you enable more than one builder then an error will be thrown. ''; - }; + + forwardSearchAfter = mkBool false "Set this property to true if you want to execute a forward search after a build."; + + onSave = mkBool false "Set this property to true if you want to compile the project after saving a file."; + + useFileList = mkBool false '' + When set to true, the server will use the .fls files produced by the TeX engine as an additional input for the project detection. + + Note that enabling this property might have an impact on performance. + ''; + auxDirectory = mkOption { type = str; default = "."; @@ -42,6 +79,7 @@ in { When using a latexmkrc file, texlab will automatically infer the correct setting. ''; }; + logDirectory = mkOption { type = str; default = "."; @@ -52,6 +90,7 @@ in { When using a latexmkrc file, texlab will automatically infer the correct setting. ''; }; + pdfDirectory = mkOption { type = str; default = "."; @@ -62,9 +101,10 @@ in { When using a latexmkrc file, texlab will automatically infer the correct setting. ''; }; + filename = mkOption { - type = str; - default = ""; + type = nullOr str; + default = null; description = '' Allows overriding the default file name of the build artifact. This setting is used to find the correct PDF file to open during forward search. ''; diff --git a/modules/plugins/languages/tex/lsp/texlab.nix b/modules/plugins/languages/tex/lsp/texlab.nix index fd319a6d..2ce47dc7 100644 --- a/modules/plugins/languages/tex/lsp/texlab.nix +++ b/modules/plugins/languages/tex/lsp/texlab.nix @@ -1,16 +1,7 @@ # TODO: # - Add Texlab LSP settings: # - chktex -# - diagnosticsDelay -# - diagnostics # - symbols -# - formatterLineLength -# - bibtexFormatter -# - latexFormatter -# - latexindent -# - completion -# - inlayHints -# - experimental { config, pkgs, @@ -19,40 +10,15 @@ }: let inherit (lib.options) mkOption; inherit (lib.modules) mkIf; - inherit - (lib.types) - bool - listOf - package - str - ; - inherit - (builtins) - attrNames - concatStringsSep - elemAt - filter - hasAttr - isAttrs - length - map - throw - toString - ; + inherit (lib.types) listOf package str attrs ints enum either path nullOr; + inherit (lib.nvim.config) mkBool; cfg = config.vim.languages.tex; - - # --- Enable Options --- - mkEnableDefaultOption = default: description: (mkOption { - type = bool; - default = default; - example = !default; - description = description; - }); - mkEnableLspOption = mkEnableDefaultOption config.vim.languages.enableLSP; + texlabCfg = cfg.lsp.texlab; + builderCfg = cfg.build.builder; in { options.vim.languages.tex.lsp.texlab = { - enable = mkEnableLspOption "Whether to enable Tex LSP support (texlab)"; + enable = mkBool config.vim.languages.enableLSP "Whether to enable Tex LSP support (texlab)"; package = mkOption { type = package; @@ -61,19 +27,15 @@ in { }; forwardSearch = { - enable = mkOption { - type = bool; - default = false; - example = true; - description = '' - Whether to enable forward search. + enable = mkBool false '' + Whether to enable forward search. - Enable this option if you want to have the compiled document appear in your chosen PDF viewer. + Enable this option if you want to have the compiled document appear in your chosen PDF viewer. + + For some options see [here](https://github.com/latex-lsp/texlab/wiki/Previewing). + Note this is not all the options, but can act as a guide to help you allong with custom configs. + ''; - For some options see [here](https://github.com/latex-lsp/texlab/wiki/Previewing). - Note this is not all the options, but can act as a guide to help you allong with custom configs. - ''; - }; package = mkOption { type = package; default = pkgs.okular; @@ -82,6 +44,7 @@ in { This viewer needs to support Synctex. ''; }; + executable = mkOption { type = str; default = "okular"; @@ -89,6 +52,7 @@ in { Defines the executable of the PDF previewer. The previewer needs to support SyncTeX. ''; }; + args = mkOption { type = listOf str; default = [ @@ -107,12 +71,212 @@ in { }; }; - extraLuaSettings = mkOption { - type = str; - default = ""; - example = '' - formatterLineLength = 80, + diagnostics = { + delay = mkOption { + type = ints.positive; + default = 300; + description = "Delay in milliseconds before reporting diagnostics."; + }; + + allowedPatterns = mkOption { + type = listOf str; + default = []; + description = '' + A list of regular expressions used to filter the list of reported diagnostics. + If specified, only diagnostics that match at least one of the specified patterns are sent to the client. + + See also texlab.diagnostics.ignoredPatterns. + + Hint: If both allowedPatterns and ignoredPatterns are set, then allowed patterns are applied first. + Afterwards, the results are filtered with the ignored patterns. + ''; + }; + + ignoredPatterns = mkOption { + type = listOf str; + default = []; + description = '' + A list of regular expressions used to filter the list of reported diagnostics. + If specified, only diagnostics that match none of the specified patterns are sent to the client. + + See also texlab.diagnostics.allowedPatterns. + ''; + }; + }; + + latexindent = { + local = mkOption { + type = nullOr (either str path); + default = null; + description = '' + Defines the path of a file containing the latexindent configuration. + This corresponds to the --local=file.yaml flag of latexindent. + By default the configuration inside the project root directory is used. + ''; + }; + + modifyLineBreaks = mkBool false '' + Modifies linebreaks before, during, and at the end of code blocks when formatting with latexindent. + This corresponds to the --modifylinebreaks flag of latexindent. ''; + + replacement = mkOption { + type = nullOr (enum ["-r" "-rv" "-rr"]); + default = null; + description = '' + Defines an additional replacement flag that is added when calling latexindent. This can be one of the following: + - "-r" + - "-rv" + - "-rr" + - null + By default no replacement flag is passed. + ''; + }; + }; + + completion.matcher = mkOption { + type = str; + default = "fuzzy-ignore-case"; + description = '' + Modifies the algorithm used to filter the completion items returned to the client. Possibles values are: + - fuzzy: Fuzzy string matching (case sensitive) + - fuzzy-ignore-case: Fuzzy string matching (case insensitive) + - prefix: Filter out items that do not start with the search text (case sensitive) + - prefix-ignore-case: Filter out items that do not start with the search text (case insensitive) + ''; + }; + + inlayHints = { + labelDefinitions = mkBool true "When enabled, the server will return inlay hints for `\\label-like` commands."; + + labelReferences = mkBool true "When enabled, the server will return inlay hints for `\\ref``-like commands."; + + maxLength = mkOption { + type = nullOr ints.positive; + default = null; + description = "When set, the server will truncate the text of the inlay hints to the specified length."; + }; + }; + + experimental = { + followPackageLinks = mkBool false "If set to true, dependencies of custom packages are resolved and included in the dependency graph."; + + mathEnvironments = mkOption { + type = listOf str; + default = []; + description = "Allows extending the list of environments which the server considers as math environments (for example `align*` or `equation`)."; + }; + + enumEnvironments = mkOption { + type = listOf str; + default = []; + description = "Allows extending the list of environments which the server considers as enumeration environments (for example `enumerate` or `itemize`)."; + }; + + verbatimEnvironments = mkOption { + type = listOf str; + default = []; + description = '' + Allows extending the list of environments which the server considers as verbatim environments (for example `minted` or `lstlisting`). + This can be used to suppress diagnostics from environments that do not contain LaTeX code. + ''; + }; + + citationCommands = mkOption { + type = listOf str; + default = []; + description = '' + Allows extending the list of commands which the server considers as citation commands (for example `\cite`). + + Hint: Additional commands need to be written without a leading `\` (e. g. `foo` instead of `\foo`). + ''; + }; + labelDefinitionCommands = mkOption { + type = listOf str; + default = []; + description = '' + Allows extending the list of `\label`-like commands. + + Hint: Additional commands need to be written without a leading `\` (e. g. `foo` instead of `\foo`). + ''; + }; + + labelReferenceCommands = mkOption { + type = listOf str; + default = []; + description = '' + Allows extending the list of `\ref`-like commands. + + Hint: Additional commands need to be written without a leading `\` (e. g. `foo` instead of `\foo`). + ''; + }; + + labelReferenceRangeCommands = mkOption { + type = listOf str; + default = []; + description = '' + Allows extending the list of `\crefrange`-like commands. + + Hint: Additional commands need to be written without a leading `\` (e. g. `foo` instead of `\foo`). + ''; + }; + + labelDefinitionPrefixes = mkOption { + type = listOf (listOf str); + default = []; + description = '' + Allows associating a label definition command with a custom prefix. Consider, + ``` + \newcommand{\thm}[1]{\label{thm:#1}} + \thm{foo} + ``` + Then setting `texlab.experimental.labelDefinitionPrefixes` to `[["thm", "thm:"]]` and adding "thm" + to `texlab.experimental.labelDefinitionCommands` will make the server recognize the `thm:foo` label. + ''; + }; + + labelReferencePrefixes = mkOption { + type = listOf (listOf str); + default = []; + description = '' + Allows associating a label reference command with a custom prefix. + See `texlab.experimental.labelDefinitionPrefixes` for more details. + ''; + }; + }; + + formatterLineLength = mkOption { + type = ints.positive; + default = 80; + description = "Defines the maximum amount of characters per line (0 = disable) when formatting BibTeX files."; + }; + + bibtexFormatter = mkOption { + type = enum ["texlab" "latexindent"]; + default = "texlab"; + description = '' + Defines the formatter to use for BibTeX formatting. + Possible values are either texlab or latexindent. + ''; + }; + + latexFormatter = mkOption { + type = enum ["texlab" "latexindent"]; + default = "latexindent"; + description = '' + Defines the formatter to use for LaTeX formatting. + Possible values are either texlab or latexindent. + Note that texlab is not implemented yet. + ''; + }; + + extraLuaSettings = mkOption { + type = attrs; + default = {}; + example = { + foo = "bar"; + baz = 314; + }; description = '' For any options that do not have options provided through nvf this can be used to add them. Options already declared in nvf config will NOT be overridden. @@ -136,97 +300,76 @@ in { config = mkIf (cfg.enable && (cfg.lsp.texlab.enable)) ( let - tl = cfg.lsp.texlab; - builder = cfg.build.builder; + # ----- Setup Config ----- + # Command to start the LSP + setupConfig.cmd = ["${texlabCfg.package}/bin/texlab"]; - listToLua = list: nullOnEmpty: - if length list == 0 - then - if nullOnEmpty - then "null" - else "{ }" - else "{ ${concatStringsSep ", " (map (x: ''"${toString x}"'') list)} }"; + # Create texlab settings section + setupConfig.settings.texlab = ( + { + # -- General Settings -- + formatterLineLength = texlabCfg.formatterLineLength; - stringToLua = string: nullOnEmpty: - if string == "" - then - if nullOnEmpty - then "null" - else "" - else ''"${string}"''; + # -- Formatters -- + bibtexFormatter = texlabCfg.bibtexFormatter; + latexFormatter = texlabCfg.latexFormatter; - boolToLua = boolean: - if boolean - then "true" - else "false"; + # -- Diagnostics -- + diagnosticsDelay = texlabCfg.diagnostics.delay; + diagnostics = { + allowedPatterns = texlabCfg.diagnostics.allowedPatterns; + ignoredPatterns = texlabCfg.diagnostics.ignoredPatterns; + }; - # -- Build -- - buildConfig = let - # This function will sort through the builder options and count how many - # builders have been enabled. - getEnabledBuildersCount = { - enabledBuildersCount ? 0, - index ? 0, - builderNamesList ? ( - filter ( - x: let - y = cfg.build.builders.${x}; - in (isAttrs y && hasAttr "enable" y) - ) (attrNames cfg.build.builders) - ), - }: let - currentBuilderName = elemAt builderNamesList index; - currentBuilder = cfg.build.builders.${currentBuilderName}; - nextIndex = index + 1; - newEnabledBuildersCount = - if currentBuilder.enable - then enabledBuildersCount + 1 - else enabledBuildersCount; - in - if length builderNamesList > nextIndex - then - getEnabledBuildersCount { - inherit builderNamesList; - enabledBuildersCount = newEnabledBuildersCount; - index = nextIndex; - } - else newEnabledBuildersCount; + # -- Latex Indent -- + latexindent = texlabCfg.latexindent; - enabledBuildersCount = getEnabledBuildersCount {}; - in - if enabledBuildersCount == 0 - then "" - else if enabledBuildersCount > 1 - then throw "Texlab does not support having more than 1 builders enabled!" - else '' - build = { - executable = "${builder.package}/bin/${builder.executable}", - args = ${listToLua builder.args false}, - forwardSearchAfter = ${boolToLua cfg.build.forwardSearchAfter}, - onSave = ${boolToLua cfg.build.onSave}, - useFileList = ${boolToLua cfg.build.useFileList}, - auxDirectory = ${stringToLua cfg.build.auxDirectory true}, - logDirectory = ${stringToLua cfg.build.logDirectory true}, - pdfDirectory = ${stringToLua cfg.build.pdfDirectory true}, - filename = ${stringToLua cfg.build.filename true}, - }, - ''; - in { - vim.lsp.lspconfig.sources.texlab = '' - lspconfig.texlab.setup { - cmd = { "${tl.package}/bin/texlab" }, - settings = { - texlab = { - ${buildConfig} - forwardSearch = { - executable = "${tl.forwardSearch.package}/bin/${tl.forwardSearch.executable}", - args = ${listToLua tl.forwardSearch.args true} - }, - ${tl.extraLuaSettings} - } - } + # -- Completion -- + completion.matcher = texlabCfg.completion.matcher; + + # -- Inlay Hints -- + inlayHints = texlabCfg.inlayHints; + + # -- Experimental -- + experimental = texlabCfg.experimental; } - ''; + # + # -- Forward Search -- + // ( + if texlabCfg.forwardSearch.enable + then { + forwardSearch = { + executable = "${texlabCfg.forwardSearch.package}/bin/${texlabCfg.forwardSearch.executable}"; + args = texlabCfg.forwardSearch.args; + }; + } + else {} + ) + # + # -- Build -- + // ( + if cfg.build.enable + then { + build = { + executable = "${builderCfg.package}/bin/${builderCfg.executable}"; + args = builderCfg.args; + forwardSearchAfter = cfg.build.forwardSearchAfter; + onSave = cfg.build.onSave; + useFileList = cfg.build.useFileList; + auxDirectory = cfg.build.auxDirectory; + logDirectory = cfg.build.logDirectory; + pdfDirectory = cfg.build.pdfDirectory; + filename = cfg.build.filename; + }; + } + else {} + ) + # + # -- Extra Settings -- + // texlabCfg.extraLuaSettings + ); + in { + vim.lsp.lspconfig.sources.texlab = "lspconfig.texlab.setup(${lib.nvim.lua.toLuaObject setupConfig})"; } ); } diff --git a/modules/plugins/languages/zig.nix b/modules/plugins/languages/zig.nix index 1b9a588b..2aa0e2b6 100644 --- a/modules/plugins/languages/zig.nix +++ b/modules/plugins/languages/zig.nix @@ -8,10 +8,12 @@ inherit (lib.options) mkEnableOption mkOption; inherit (lib.modules) mkIf mkMerge mkDefault; inherit (lib.lists) isList; - inherit (lib.types) either listOf package str enum; + inherit (lib.types) bool either listOf package str enum; inherit (lib.nvim.lua) expToLua; inherit (lib.nvim.types) mkGrammarOption; + cfg = config.vim.languages.zig; + defaultServer = "zls"; servers = { zls = { @@ -31,7 +33,35 @@ }; }; - cfg = config.vim.languages.zig; + # TODO: dap.adapter.lldb is duplicated when enabling the + # vim.languages.clang.dap module. This does not cause + # breakage... but could be cleaner. + defaultDebugger = "lldb-vscode"; + debuggers = { + lldb-vscode = { + package = pkgs.lldb; + dapConfig = '' + dap.adapters.lldb = { + type = 'executable', + command = '${cfg.dap.package}/bin/lldb-dap', + name = 'lldb' + } + dap.configurations.zig = { + { + name = 'Launch', + type = 'lldb', + request = 'launch', + program = function() + return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') + end, + cwd = "''${workspaceFolder}", + stopOnEntry = false, + args = {}, + }, + } + ''; + }; + }; in { options.vim.languages.zig = { enable = mkEnableOption "Zig language support"; @@ -56,6 +86,26 @@ in { default = pkgs.zls; }; }; + + dap = { + enable = mkOption { + type = bool; + default = config.vim.languages.enableDAP; + description = "Enable Zig Debug Adapter"; + }; + + debugger = mkOption { + type = enum (attrNames debuggers); + default = defaultDebugger; + description = "Zig debugger to use"; + }; + + package = mkOption { + type = package; + default = debuggers.${cfg.dap.debugger}.package; + description = "Zig debugger package."; + }; + }; }; config = mkIf cfg.enable (mkMerge [ @@ -77,5 +127,12 @@ in { globals.zig_fmt_autosave = mkDefault 0; }; }) + + (mkIf cfg.dap.enable { + vim = { + debugger.nvim-dap.enable = true; + debugger.nvim-dap.sources.zig-debugger = debuggers.${cfg.dap.debugger}.dapConfig; + }; + }) ]); } diff --git a/modules/plugins/lsp/lightbulb/config.nix b/modules/plugins/lsp/lightbulb/config.nix index f17b8ad9..17e740ad 100644 --- a/modules/plugins/lsp/lightbulb/config.nix +++ b/modules/plugins/lsp/lightbulb/config.nix @@ -4,6 +4,7 @@ ... }: let inherit (lib.modules) mkIf; + inherit (lib.strings) optionalString; inherit (lib.nvim.dag) entryAnywhere; inherit (lib.nvim.lua) toLuaObject; @@ -12,13 +13,29 @@ in { config = mkIf (cfg.enable && cfg.lightbulb.enable) { vim = { startPlugins = ["nvim-lightbulb"]; - pluginRC.lightbulb = entryAnywhere '' - vim.api.nvim_command('autocmd CursorHold,CursorHoldI * lua require\'nvim-lightbulb\'.update_lightbulb()') - - -- Enable trouble diagnostics viewer - require'nvim-lightbulb'.setup(${toLuaObject cfg.lightbulb.setupOpts}) + local nvim_lightbulb = require("nvim-lightbulb") + nvim_lightbulb.setup(${toLuaObject cfg.lightbulb.setupOpts}) + ${optionalString cfg.lightbulb.autocmd.enable '' + vim.api.nvim_create_autocmd(${toLuaObject cfg.lightbulb.autocmd.events}, { + pattern = ${toLuaObject cfg.lightbulb.autocmd.pattern}, + callback = function() + nvim_lightbulb.update_lightbulb() + end, + }) + ''} ''; }; + + warnings = [ + # This could have been an assertion, but the chances of collision is very low and asserting here + # might be too dramatic. Let's only warn the user, *in case* this occurs and is not intended. No + # error will be thrown if 'lightbulb.setupOpts.autocmd.enable' has not been set by the user. + (mkIf (cfg.lightbulb.autocmd.enable -> (cfg.lightbulb.setupOpts.autocmd.enabled or false)) '' + Both 'vim.lsp.lightbulb.autocmd.enable' and 'vim.lsp.lightbulb.setupOpts.autocmd.enable' are set + simultaneously. This might have performance implications due to frequent updates. Please set only + one option to handle nvim-lightbulb autocmd. + '') + ]; }; } diff --git a/modules/plugins/lsp/lightbulb/lightbulb.nix b/modules/plugins/lsp/lightbulb/lightbulb.nix index 4341cac6..012d54aa 100644 --- a/modules/plugins/lsp/lightbulb/lightbulb.nix +++ b/modules/plugins/lsp/lightbulb/lightbulb.nix @@ -1,11 +1,29 @@ {lib, ...}: let - inherit (lib.options) mkEnableOption; - inherit (lib.nvim.types) mkPluginSetupOption; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) listOf str either; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; in { options.vim.lsp = { lightbulb = { enable = mkEnableOption "Lightbulb for code actions. Requires an emoji font"; setupOpts = mkPluginSetupOption "nvim-lightbulb" {}; + autocmd = { + enable = mkEnableOption "updating lightbulb glyph automatically" // {default = true;}; + events = mkOption { + type = listOf str; + default = ["CursorHold" "CursorHoldI"]; + description = "Events on which to update nvim-lightbulb glyphs"; + }; + + pattern = mkOption { + type = either str luaInline; + default = "*"; + description = '' + File patterns or buffer names to match, determining which files or buffers trigger + glyph updates. + ''; + }; + }; }; }; }