diff --git a/docs/manual/configuring/languages.md b/docs/manual/configuring/languages.md index 252163fb..eb939b7b 100644 --- a/docs/manual/configuring/languages.md +++ b/docs/manual/configuring/languages.md @@ -19,6 +19,7 @@ formatting to diagnostics. The following languages have sections under the - Go: [vim.languages.go.enable](#opt-vim.languages.go.enable) - Lua: [vim.languages.lua.enable](#opt-vim.languages.lua.enable) - PHP: [vim.languages.php.enable](#opt-vim.languages.php.enable) +- Tex: [vim.languages.tex.enable](#opt-vim.languages.tex.enable) - F#: [vim.languages.fsharp.enable](#opt-vim.languages.fsharp.enable) Adding support for more languages, and improving support for existing ones are diff --git a/lib/types/default.nix b/lib/types/default.nix index c6239227..667a4e96 100644 --- a/lib/types/default.nix +++ b/lib/types/default.nix @@ -6,6 +6,6 @@ in { inherit (typesDag) dagOf; inherit (typesPlugin) pluginsOpt extraPluginType mkPluginSetupOption luaInline pluginType borderType; - inherit (typesLanguage) diagnostics mkGrammarOption; + inherit (typesLanguage) diagnostics mkGrammarOption mkEnableTreesitterOption; inherit (customTypes) char hexColor mergelessListOf; } diff --git a/lib/types/languages.nix b/lib/types/languages.nix index b1865c41..5e935159 100644 --- a/lib/types/languages.nix +++ b/lib/types/languages.nix @@ -1,7 +1,7 @@ {lib}: let inherit (lib.options) mkOption mkPackageOption; inherit (lib.attrsets) attrNames; - inherit (lib.types) listOf either enum submodule package; + inherit (lib.types) listOf either enum submodule package bool; diagnosticSubmodule = _: { options = { @@ -32,6 +32,13 @@ mkPackageOption pkgs ["${grammar} treesitter"] { default = ["vimPlugins" "nvim-treesitter" "builtGrammars" grammar]; }; + + mkEnableTreesitterOption = defaultCondition: language: + mkOption { + type = bool; + default = defaultCondition; + description = "Whether to enable ${language} treesitter"; + }; in { - inherit diagnostics diagnosticSubmodule mkGrammarOption; + inherit diagnostics diagnosticSubmodule mkGrammarOption mkEnableTreesitterOption; } diff --git a/modules/plugins/formatter/conform-nvim/builders/builderTemplate.nix b/modules/plugins/formatter/conform-nvim/builders/builderTemplate.nix new file mode 100644 index 00000000..02d20412 --- /dev/null +++ b/modules/plugins/formatter/conform-nvim/builders/builderTemplate.nix @@ -0,0 +1,66 @@ +# This function acts as a template for creating new builders. +# It enforces providing all the parameters required for creating +# a new builder for it to be able to work in the existing code. +# +# The first layer requirements are as follows: +{ + # This is the name of the builder, it will only be used internally and + # should match the .nix file that the builder is implemented in. + name, + # + # Module attribute set. This is the attribute set that the module that is + # defining a builder is passed as its input. + moduleInheritancePackage, + # + # These are the standard options for the builder just like creating any + # other module. Some options are required and are described below but + # it will also accept any other options that are provided to it. + options, + # + # These are the command line arguments that will accompany the executable + # when the build command is called. + # This is a function that will take in the cfg of its own builder. + # i.e. will be called as "args cfg.build.builders.${name}" + args, + ... +}: let + # Inherit the necessary variables available to any module. + inherit (moduleInheritancePackage) lib config; + # + # Inherit other useful functions. + inherit (lib.modules) mkIf; + # + # Set the cfg variable + cfg = config.vim.languages.tex; +in { + # These are the options for the builder. It will accept any options + # provided to it but some options are mandatory: + options.vim.languages.tex.build.builders.${name} = ({ + # The enable option. This one is self explanatory. + enable, + # + # This is the package option for the builder. + package, + # + # This is the executable that will be used to call the builder. + # It, along with package will result in: + # "/bin/" + executable, + # + # Any other options provided are accepted. + ... + } @ opts: + opts) + options; + + # Check that the language and this builder have been enabled + # before making any config. + config = mkIf (cfg.enable && cfg.build.builders.${name}.enable) { + vim.languages.tex.build.builder = { + inherit name; + package = cfg.build.builders.${name}.package; + executable = cfg.build.builders.${name}.executable; + args = args cfg.build.builders.${name}; + }; + }; +} diff --git a/modules/plugins/formatter/conform-nvim/builders/default.nix b/modules/plugins/formatter/conform-nvim/builders/default.nix new file mode 100644 index 00000000..4586b768 --- /dev/null +++ b/modules/plugins/formatter/conform-nvim/builders/default.nix @@ -0,0 +1,70 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (lib.options) mkOption; + inherit (lib.types) enum listOf package str; + inherit (lib.nvim.config) mkBool; + inherit (builtins) attrNames filter isAttrs hasAttr elemAt length; + + cfg = config.vim.languages.tex; +in { + imports = [ + ./latexmk.nix + ./tectonic.nix + ]; + + options.vim.languages.tex.build.builder = { + name = mkOption { + type = enum (attrNames cfg.build.builders); + default = "latexmk"; + description = '' + The tex builder to use. + + 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 { + type = listOf str; + default = [ + "-pdf" + "%f" + ]; + description = '' + The list of args to pass to the builder. + + This is just the default custom option. By setting any of the + builders to true, this will be overwritten by that builder's + parameters. + ''; + }; + package = mkOption { + type = package; + default = pkgs.texlive.withPackages (ps: [ps.latexmk]); + description = '' + The tex builder package to use. + + This is just the default custom option. By setting any of the + builders to true, this will be overwritten by that builder's + parameters. + ''; + }; + executable = mkOption { + type = str; + default = "latexmk"; + description = '' + The tex builder executable to use. + + This is just the default custom option. By setting any of the + builders to true, this will be overwritten by that builder's + parameters. + ''; + }; + }; +} diff --git a/modules/plugins/formatter/conform-nvim/builders/latexmk.nix b/modules/plugins/formatter/conform-nvim/builders/latexmk.nix new file mode 100644 index 00000000..4d024eb3 --- /dev/null +++ b/modules/plugins/formatter/conform-nvim/builders/latexmk.nix @@ -0,0 +1,57 @@ +# TODO: I need testing. +{ + pkgs, + lib, + ... +} @ moduleInheritancePackage: let + # The name of the builder + name = "latexmk"; + + # The builder template + template = import ./builderTemplate.nix; + + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) bool package str; +in ( + template { + inherit name moduleInheritancePackage; + + options = { + enable = mkEnableOption "Whether to enable Tex Compilation Via latexmk"; + + package = mkOption { + type = package; + default = pkgs.texlive.withPackages (ps: [ps.latexmk]); + description = "latexmk package"; + }; + + executable = mkOption { + type = str; + default = "latexmk"; + description = "The executable name from the build package that will be used to build/compile the tex."; + }; + + # Flag options + pdfOutput = mkOption { + type = bool; + default = true; + example = false; + description = "Insure the output file is a pdf."; + }; + }; + + args = builderCfg: ( + # Flags + ( + if builderCfg.pdfOutput + then ["-pdf"] + else [] + ) + # Base args + ++ [ + "-quiet" + "%f" + ] + ); + } +) diff --git a/modules/plugins/formatter/conform-nvim/builders/tectonic.nix b/modules/plugins/formatter/conform-nvim/builders/tectonic.nix new file mode 100644 index 00000000..1b131b33 --- /dev/null +++ b/modules/plugins/formatter/conform-nvim/builders/tectonic.nix @@ -0,0 +1,203 @@ +{ + config, + pkgs, + lib, + ... +} @ moduleInheritancePackage: let + # The name of the builder + name = "tectonic"; + + # The builder template + template = import ./builderTemplate.nix; + + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) enum ints listOf package str; + inherit (lib.nvim.config) mkBool; + inherit (builtins) concatLists elem map toString; + + cfg = config.vim.languages.tex; +in ( + template { + inherit name moduleInheritancePackage; + + options = { + 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 = mkBool false '' + Keep the intermediate files generated during processing. + + If texlab is reporting build errors when there shouldn't be, disable this option. + ''; + keepLogs = mkBool true '' + Keep the log files generated during processing. + + Without the keepLogs flag, texlab won't be able to report compilation warnings. + ''; + 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. + + Setting this value to 0 will disable setting this option. + ''; + }; + + 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. + ''; + }; + }; + + args = builderCfg: ( + # Base args + [ + "-X" + "compile" + "%f" + ] + # Flags + ++ ( + if builderCfg.keepIntermediates + then ["--keep-intermediates"] + else [] + ) + ++ ( + if builderCfg.keepLogs + then ["--keep-logs"] + else [] + ) + ++ ( + if builderCfg.onlyCached + then ["--only-cached"] + else [] + ) + ++ ( + if builderCfg.synctex + then ["--synctex"] + else [] + ) + ++ ( + if builderCfg.untrustedInput + then ["--untrusted"] + else [] + ) + # Options + ++ ( + if builderCfg.reruns > 0 + then ["--reruns" "${toString builderCfg.reruns}"] + else [] + ) + ++ ( + if builderCfg.bundle != "" + then ["--bundle" "${toString builderCfg.bundle}"] + else [] + ) + ++ ( + if builderCfg.webBundle != "" + then ["--web-bundle" "${toString builderCfg.webBundle}"] + else [] + ) + ++ ( + if builderCfg.outfmt != "" + then ["--outfmt" "${toString builderCfg.outfmt}"] + else [] + ) + ++ (concatLists (map (x: ["--hide" x]) builderCfg.hidePaths)) + ++ ( + if builderCfg.format != "" + then ["--format" "${toString builderCfg.format}"] + else [] + ) + ++ ( + if builderCfg.color != "" + then ["--color" "${toString builderCfg.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 cfg.build.pdfDirectory ["." ""]) + then ["--outdir" "${cfg.build.pdfDirectory}"] + else [] + ) + ); + } +) diff --git a/modules/plugins/languages/default.nix b/modules/plugins/languages/default.nix index b889e60a..34f8a5af 100644 --- a/modules/plugins/languages/default.nix +++ b/modules/plugins/languages/default.nix @@ -12,7 +12,9 @@ in { ./cue.nix ./dart.nix ./clang.nix + ./csharp.nix ./css.nix + ./dart.nix ./elixir.nix ./fsharp.nix ./gleam.nix @@ -22,32 +24,35 @@ in { ./kotlin.nix ./html.nix ./haskell.nix + ./hcl.nix + ./html.nix ./java.nix + ./julia.nix + ./kotlin.nix ./lua.nix ./markdown.nix ./nim.nix - ./vala.nix ./nix.nix + ./nu.nix ./ocaml.nix + ./odin.nix ./php.nix ./python.nix ./r.nix + ./ruby.nix ./rust.nix ./scala.nix ./sql.nix ./svelte.nix ./tailwind.nix ./terraform.nix + ./tex ./ts.nix ./typst.nix - ./zig.nix - ./csharp.nix - ./julia.nix - ./nu.nix - ./odin.nix + ./vala.nix ./wgsl.nix ./yaml.nix - ./ruby.nix + ./zig.nix ]; options.vim.languages = { diff --git a/modules/plugins/languages/tex/build/builders/builderTemplate.nix b/modules/plugins/languages/tex/build/builders/builderTemplate.nix new file mode 100644 index 00000000..02d20412 --- /dev/null +++ b/modules/plugins/languages/tex/build/builders/builderTemplate.nix @@ -0,0 +1,66 @@ +# This function acts as a template for creating new builders. +# It enforces providing all the parameters required for creating +# a new builder for it to be able to work in the existing code. +# +# The first layer requirements are as follows: +{ + # This is the name of the builder, it will only be used internally and + # should match the .nix file that the builder is implemented in. + name, + # + # Module attribute set. This is the attribute set that the module that is + # defining a builder is passed as its input. + moduleInheritancePackage, + # + # These are the standard options for the builder just like creating any + # other module. Some options are required and are described below but + # it will also accept any other options that are provided to it. + options, + # + # These are the command line arguments that will accompany the executable + # when the build command is called. + # This is a function that will take in the cfg of its own builder. + # i.e. will be called as "args cfg.build.builders.${name}" + args, + ... +}: let + # Inherit the necessary variables available to any module. + inherit (moduleInheritancePackage) lib config; + # + # Inherit other useful functions. + inherit (lib.modules) mkIf; + # + # Set the cfg variable + cfg = config.vim.languages.tex; +in { + # These are the options for the builder. It will accept any options + # provided to it but some options are mandatory: + options.vim.languages.tex.build.builders.${name} = ({ + # The enable option. This one is self explanatory. + enable, + # + # This is the package option for the builder. + package, + # + # This is the executable that will be used to call the builder. + # It, along with package will result in: + # "/bin/" + executable, + # + # Any other options provided are accepted. + ... + } @ opts: + opts) + options; + + # Check that the language and this builder have been enabled + # before making any config. + config = mkIf (cfg.enable && cfg.build.builders.${name}.enable) { + vim.languages.tex.build.builder = { + inherit name; + package = cfg.build.builders.${name}.package; + executable = cfg.build.builders.${name}.executable; + args = args cfg.build.builders.${name}; + }; + }; +} diff --git a/modules/plugins/languages/tex/build/builders/default.nix b/modules/plugins/languages/tex/build/builders/default.nix new file mode 100644 index 00000000..fa51e70a --- /dev/null +++ b/modules/plugins/languages/tex/build/builders/default.nix @@ -0,0 +1,69 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (lib.options) mkOption; + inherit (lib.types) enum listOf package str; + inherit (builtins) attrNames; + + cfg = config.vim.languages.tex; +in { + imports = [ + ./latexmk.nix + ./tectonic.nix + ]; + + options.vim.languages.tex.build.builder = { + name = mkOption { + type = enum (attrNames cfg.build.builders); + default = "latexmk"; + description = '' + The tex builder to use. + + 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 { + type = listOf str; + default = [ + "-pdf" + "%f" + ]; + description = '' + The list of args to pass to the builder. + + This is just the default custom option. By setting any of the + builders to true, this will be overwritten by that builder's + parameters. + ''; + }; + package = mkOption { + type = package; + default = pkgs.texlive.withPackages (ps: [ps.latexmk]); + description = '' + The tex builder package to use. + + This is just the default custom option. By setting any of the + builders to true, this will be overwritten by that builder's + parameters. + ''; + }; + executable = mkOption { + type = str; + default = "latexmk"; + description = '' + The tex builder executable to use. + + This is just the default custom option. By setting any of the + builders to true, this will be overwritten by that builder's + parameters. + ''; + }; + }; +} diff --git a/modules/plugins/languages/tex/build/builders/latexmk.nix b/modules/plugins/languages/tex/build/builders/latexmk.nix new file mode 100644 index 00000000..bbb4ecd5 --- /dev/null +++ b/modules/plugins/languages/tex/build/builders/latexmk.nix @@ -0,0 +1,59 @@ +# TODO: I need testing. +{ + pkgs, + lib, + ... +} @ moduleInheritancePackage: let + # The name of the builder + name = "latexmk"; + + # The builder template + template = import ./builderTemplate.nix; + + inherit (lib) optionals; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) bool package str; +in ( + template { + inherit name moduleInheritancePackage; + + options = { + enable = mkEnableOption "Tex Compilation Via latexmk"; + + package = mkOption { + type = package; + default = pkgs.texlive.withPackages (ps: [ps.latexmk]); + description = "latexmk package"; + }; + + executable = mkOption { + type = str; + default = "latexmk"; + description = '' + The executable name from the build package that will be used to + build/compile the tex. + ''; + }; + + # Flag options + pdfOutput = mkOption { + type = bool; + default = true; + example = false; + description = "Insure the output file is a pdf."; + }; + }; + + # Optional flags must come before the base args because of how the latexmk + # command works + args = builderCfg: ( + # Flags + (optionals builderCfg.pdfOutput ["-pdf"]) + # Base args + ++ [ + "-quiet" + "%f" + ] + ); + } +) diff --git a/modules/plugins/languages/tex/build/builders/tectonic.nix b/modules/plugins/languages/tex/build/builders/tectonic.nix new file mode 100644 index 00000000..6c680cff --- /dev/null +++ b/modules/plugins/languages/tex/build/builders/tectonic.nix @@ -0,0 +1,229 @@ +{ + config, + pkgs, + lib, + ... +} @ moduleInheritancePackage: let + # The name of the builder + name = "tectonic"; + + # The builder template + template = import ./builderTemplate.nix; + + inherit (lib) optionals; + inherit (lib.options) mkOption mkEnableOption mkPackageOption; + inherit (lib.types) enum ints listOf str nullOr; + inherit (lib.nvim.config) mkBool; + inherit (builtins) concatLists elem map toString attrNames filter isList; + + notNull = x: x != null; + forceCheck = x: true; + toList = x: + if isList x + then x + else [x]; + + cfg = config.vim.languages.tex; +in ( + template { + inherit name moduleInheritancePackage; + + options = { + enable = mkEnableOption "Tex Compilation Via Tectonic"; + + package = mkPackageOption pkgs "tectonic" {}; + + 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 = mkBool false '' + Whether to keep the intermediate files generated during processing. + + If texlab is reporting build errors when there shouldn't be, disable + this option. + ''; + keepLogs = mkBool true '' + Whether to keep the log files generated during processing. + + Without the keepLogs flag, texlab won't be able to report compilation + warnings. + ''; + onlyCached = mkBool false '' + Whether to use only resource files cached locally + ''; + synctex = mkBool true "Whether to generate SyncTeX data"; + untrustedInput = mkBool false '' + Whether to disable all known-insecure features if the input is untrusted + ''; + + # -- Options -- + reruns = mkOption { + type = ints.unsigned; + default = 0; + example = 2; + description = '' + How many times to *rerun* the TeX build engine. + The build engine (if a builder is enabled) will always run at least + once. + + Setting this value to 0 will disable setting this option. + ''; + }; + + bundle = mkOption { + type = nullOr str; + default = null; + description = '' + The directory or Zip-format bundle file to find resource files instead + of the default. + ''; + }; + + webBundle = mkOption { + type = nullOr str; + default = null; + description = '' + Use this URL to find resource files instead of the default. + ''; + }; + + outfmt = mkOption { + type = nullOr (enum [ + "pdf" + "html" + "xdv" + "aux" + "fmt" + ]); + default = null; + description = '' + The kind of output to generate. + + Setting this to `null` (default) will let tectonic decide the most + appropriate output format, which usually be a pdf. + ''; + }; + + 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 = nullOr str; + default = null; + description = '' + The name of the \"format\" file used to initialize the TeX engine. + ''; + }; + + color = mkOption { + type = nullOr (enum [ + "always" + "auto" + "never" + ]); + default = null; + example = "always"; + description = "Enable/disable colorful log output"; + }; + + extraOptions = mkOption { + 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. + ''; + }; + }; + + # args = builderCfg: ( + # # Base args + # [ + # "-X" + # "compile" + # "%f" + # ] + # # Flags + # ++ (optionals builderCfg.keepIntermediates ["--keep-intermediates"]) + # ++ (optionals builderCfg.keepLogs ["--keep-logs"]) + # ++ (optionals builderCfg.onlyCached ["--only-cached"]) + # ++ (optionals builderCfg.synctex ["--synctex"]) + # ++ (optionals builderCfg.untrustedInput ["--untrusted"]) + # # Options + # ++ (optionals (builderCfg.reruns > 0) ["--reruns" "${toString builderCfg.reruns}"]) + # ++ (optionals (builderCfg.bundle != null) ["--bundle" "${toString builderCfg.bundle}"]) + # ++ (optionals (builderCfg.webBundle != null) ["--web-bundle" "${toString builderCfg.webBundle}"]) + # ++ (optionals (builderCfg.outfmt != null) ["--outfmt" "${toString builderCfg.outfmt}"]) + # ++ (concatLists (map (x: ["--hide" x]) builderCfg.hidePaths)) + # ++ (optionals (builderCfg.format != null) ["--format" "${toString builderCfg.format}"]) + # ++ (optionals (builderCfg.color != null) ["--color" "${toString builderCfg.color}"]) + # # Still options but these are not defined by builder specific options but + # # instead synchronize options between the global build options and builder + # # specific options + # ++ (optionals (!(elem cfg.build.pdfDirectory ["." ""])) ["--outdir" "${cfg.build.pdfDirectory}"]) + # ); + + args = builderCfg: let + option = setCheck: flag: {inherit setCheck flag;}; + args = { + baseArgs = ["-X" "compile" "%f"]; + + flags = { + keepIntermediates = "--keep-intermediates"; + keepLogs = "--keep-logs"; + onlyCached = "--only-cached"; + synctex = "--synctex"; + untrustedInput = "--untrusted"; + }; + + options = { + reruns = option (x: x > 0) "--reruns"; + bundle = option notNull "--bundle"; + webBundle = option notNull "--web-bundle"; + outfmt = option notNull "--outfmt"; + format = option notNull "--format"; + color = option notNull "--color"; + hidePaths = option forceCheck "--hide"; + }; + + externalOptions = concatLists [ + (optionals (!(elem cfg.build.pdfDirectory ["." ""])) ["--outdir" "${cfg.build.pdfDirectory}"]) + ]; + }; + + flags = map (flag: args.flags.${flag}) (filter (flag: builderCfg.${flag}) (attrNames args.flags)); + options = let + getOptionFlagsList = opt: + concatLists ( + map + (y: [args.options."${opt}".flag "${toString y}"]) + (toList builderCfg."${opt}") + ); + processOption = opt: + optionals + (args.options."${opt}".setCheck builderCfg."${opt}") + (getOptionFlagsList opt); + in (concatLists (map processOption (attrNames args.options))); + in + concatLists (with args; [baseArgs flags options externalOptions]); + } +) diff --git a/modules/plugins/languages/tex/build/default.nix b/modules/plugins/languages/tex/build/default.nix new file mode 100644 index 00000000..9f9c5bc3 --- /dev/null +++ b/modules/plugins/languages/tex/build/default.nix @@ -0,0 +1,140 @@ +{ + config, + lib, + ... +}: let + inherit (builtins) filter isAttrs hasAttr attrNames length elemAt; + inherit (lib.modules) mkIf; + inherit (lib.nvim.config) mkBool; + inherit (lib.options) mkOption; + inherit (lib.types) str nullOr; + + 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 = { + enable = mkBool (enabledBuildersCount == 1) '' + Whether to enable configuring the builder. + + 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. + + This can also be thought of as enabling auto updating for your pdf viewer. + ''; + + 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 = "."; + description = '' + When not using latexmk, provides a way to define the directory + containing the `.aux` files. + Note that you need to set the aux directory in `latex.build.args` too. + + When using a latexmkrc file, texlab will automatically infer the correct + setting. + ''; + }; + + logDirectory = mkOption { + type = str; + default = "."; + description = '' + When not using latexmk, provides a way to define the directory + containing the build log files. + Note that you need to change the output directory in your build + arguments too. + + When using a latexmkrc file, texlab will automatically infer the correct + setting. + ''; + }; + + pdfDirectory = mkOption { + type = str; + default = "."; + description = '' + When not using latexmk, provides a way to define the directory + containing the output files. + Note that you need to set the output directory in `latex.build.args` + too. + + When using a latexmkrc file, texlab will automatically infer the correct + setting. + ''; + }; + + filename = mkOption { + 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. + ''; + }; + }; + + config = mkIf (enabledBuildersCount > 0) { + assertions = [ + { + assertion = enabledBuildersCount < 2; + message = '' + The nvf-tex-language implementation does not support having more than + 1 builders enabled. + ''; + } + ]; + }; +} diff --git a/modules/plugins/languages/tex/default.nix b/modules/plugins/languages/tex/default.nix new file mode 100644 index 00000000..7dbe7e3a --- /dev/null +++ b/modules/plugins/languages/tex/default.nix @@ -0,0 +1,78 @@ +{ + config, + lib, + ... +}: let + inherit (lib.modules) mkIf mkMerge; + inherit (lib.nvim.config) mkBool; + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.types) enum; + + cfg = config.vim.languages.tex; +in { + imports = [ + ./build + ./lsp + ./pdfViewer + ./treesitter.nix + ]; + + options.vim.languages.tex = { + enable = mkEnableOption "Tex support"; + + extraOpts = { + texFlavor = { + enable = mkBool false '' + Whether to set the `vim.g.tex_flavor` (`g:tex_flavor`) option in + your Lua config. + + When opening a `.tex` file vim will try to automatically try to + determine the file type from the three options: `plaintex` (for + plain TeX), `context` (for ConTeXt), or `tex` (for LaTeX). + This can either be done by a indicator line of the form `%&` + on the first line or, if absent, vim will search the file for + keywords to try and determine the filetype. If no filetype can be + determined automatically then by default it will fallback to + plaintex. + + This option will enable setting the tex flavor in your lua config + and you can set its value using the + `vim.languages.tex.lsp.extraOpts.texFlavor.flavor = ` in + your nvf config. + + Setting this option to `false` will omit the + `vim.g.tex_flavor = ` line from your lua config entirely + (unless you manually set it elsewhere of course). + ''; + + flavor = mkOption { + type = enum [ + "plaintex" + "context" + "tex" + ]; + default = "plaintex"; + example = "tex"; + description = '' + The flavor to set as a fallback for when vim cannot automatically + determine the tex flavor when opening a `.tex` document. + + The options are: `plaintex` (for plain TeX), `context` (for + ConTeXt), or `tex` (for LaTeX). + + This can be particularly useful for when using + `vim.utility.new-file-template` options for creating templates when + no context has yet been added to a new file. + ''; + }; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + # Extra Lua config options + (mkIf cfg.extraOpts.texFlavor.enable { + vim.globals.tex_flavor = lib.mkDefault "${cfg.extraOpts.texFlavor.flavor}"; + }) + ]); +} diff --git a/modules/plugins/languages/tex/lsp/default.nix b/modules/plugins/languages/tex/lsp/default.nix new file mode 100644 index 00000000..244829d0 --- /dev/null +++ b/modules/plugins/languages/tex/lsp/default.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + ... +}: let + inherit (lib.modules) mkIf; + inherit (builtins) any attrValues; + + cfg = config.vim.languages.tex; +in { + imports = [ + ./texlab.nix + ]; + + config = + mkIf + ( + cfg.enable # Check if nvf is enabled. + && (any (x: x.enable) (attrValues cfg.lsp)) # Check if any of the LSPs have been enabled. + ) + { + vim.lsp.lspconfig.enable = lib.mkDefault true; # Enable lspconfig when any of the lsps are enabled + }; +} diff --git a/modules/plugins/languages/tex/lsp/texlab.nix b/modules/plugins/languages/tex/lsp/texlab.nix new file mode 100644 index 00000000..339fb40c --- /dev/null +++ b/modules/plugins/languages/tex/lsp/texlab.nix @@ -0,0 +1,598 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (builtins) isString map; + inherit (lib) optionalAttrs; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.nvim.config) mkBool; + inherit (lib.options) mkOption mkPackageOption; + inherit + (lib.types) + attrs + either + enum + ints + listOf + nullOr + package + path + str + submodule + ; + + cfg = config.vim.languages.tex; + texlabCfg = cfg.lsp.texlab; + builderCfg = cfg.build.builder; + + # Get the enabled pdf viewer. + pdfViewer = import ../pdfViewer/getEnabledPdfViewer.nix {inherit lib config;}; +in { + options.vim.languages.tex.lsp.texlab = { + enable = mkBool config.vim.languages.enableLSP '' + Whether to enable Tex LSP support (texlab). + ''; + + package = mkPackageOption pkgs "texlab" {}; + + chktex = { + enable = mkBool false "Whether to enable linting via chktex"; + + package = mkOption { + type = package; + default = pkgs.texlive.withPackages (ps: [ps.chktex]); + description = '' + The chktex package to use. + Must have the `chktex` executable. + ''; + }; + + onOpenAndSave = mkBool false '' + Lint using chktex after opening and saving a file. + ''; + + onEdit = mkBool false "Lint using chktex after editing a file."; + + additionalArgs = mkOption { + type = listOf str; + default = []; + description = '' + Additional command line arguments that are passed to chktex after + editing a file. + Don't redefine the `-I` and `-f` flags as they are set by the server. + ''; + }; + }; + + completion.matcher = mkOption { + type = enum [ + "fuzzy" + "fuzzy-ignore-case" + "prefix" + "prefix-ignore-case" + ]; + 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). + ''; + }; + + 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`. + ''; + }; + }; + + 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{\theorem}[1]{\label{theorem:#1}} + \theorem{foo} + ``` + Then setting `texlab.experimental.labelDefinitionPrefixes` to + `[["theorem", "theorem:"]]` and adding `theorem` to + `texlab.experimental.labelDefinitionCommands` will make the server + recognize the `theorem: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. + ''; + }; + }; + + 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. + + Options will be placed in: + ``` + lspconfig.texlab.setup { + settings = { + texlab = { + ... + + ... + + } + } + } + ``` + ''; + }; + + forwardSearch = { + 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. + + 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 + along with custom configs. + ''; + + package = mkOption { + type = package; + default = pdfViewer.package; + description = '' + The package to use as your PDF viewer. + This viewer needs to support Synctex. + + By default it is set to the package of the pdfViewer option. + ''; + }; + + executable = mkOption { + type = str; + default = pdfViewer.executable; + description = '' + Defines the executable of the PDF previewer. The previewer needs to + support SyncTeX. + + By default it is set to the executable of the pdfViewer option. + ''; + }; + + args = mkOption { + type = listOf str; + default = pdfViewer.args; + description = '' + Defines additional arguments that are passed to the configured + previewer to perform the forward search. + The placeholders `%f`, `%p`, `%l` will be replaced by the server. + + By default it is set to the args of the pdfViewer option. + + Placeholders: + - `%f`: The path of the current TeX file. + - `%p`: The path of the current PDF file. + - `%l`: The current line number. + ''; + }; + }; + + formatter = { + formatterLineLength = mkOption { + type = ints.unsigned; + default = 80; + description = '' + Defines the maximum amount of characters per line when formatting + BibTeX files. + + Setting this value to 0 will disable this option. + ''; + }; + + 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. + ''; + }; + }; + + 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. + ''; + }; + }; + + 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. + ''; + }; + }; + + symbols = { + enable = mkBool false "Whether to enable setting symbols config."; + + allowedPatterns = mkOption { + type = listOf str; + default = []; + description = '' + A list of regular expressions used to filter the list of reported + document symbols. + If specified, only symbols that match at least one of the specified + patterns are sent to the client. + Symbols are filtered recursively so nested symbols can still be sent + to the client even though the parent node is removed from the results. + + See also `texlab.symbols.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 + document symbols. + If specified, only symbols that match none of the specified patterns + are sent to the client. + + See also `texlab.symbols.allowedPatterns`. + ''; + }; + + customEnvironments = mkOption { + type = listOf (submodule { + options = { + name = mkOption { + type = str; + description = "The name of the environment."; + }; + displayName = mkOption { + type = nullOr str; + default = null; + description = '' + The name shown in the document symbols. + Defaults to the value of `name`. + ''; + }; + label = mkBool false '' + If set to `true`, the server will try to match a label to + environment and append its number. + ''; + }; + }); + default = []; + example = [ + { + name = "foo"; + displayName = "bar"; + label = false; + } + ]; + description = '' + A list of objects that allows extending the list of environments that + are part of the document symbols. + + See also `texlab.symbols.allowedPatterns`. + + Type: listOf submodule: + - name: + - type: str + - description: The name of the environment. + - required + - displayName: + - type: nullOr str + - description: The name shown in the document symbols. + - default: + - label: + - type: boolean + - description: If set, the server will try to match a label to + environment and append its number. + - default: false + + Note: This functionality may not be working, please follow + https://github.com/latex-lsp/texlab/pull/1311 for status updates. + ''; + }; + }; + }; + + config = mkIf cfg.enable ( + let + # ----- Setup Config ----- + # Command to start the LSP + setupConfig.cmd = ["${texlabCfg.package}/bin/texlab"]; + + # Create texlab settings section + setupConfig.settings.texlab = ( + { + # -- Completion -- + completion.matcher = texlabCfg.completion.matcher; + + # -- Diagnostics -- + diagnosticsDelay = texlabCfg.diagnostics.delay; + diagnostics = { + inherit (texlabCfg.diagnostics) allowedPatterns ignoredPatterns; + }; + + # -- Experimental -- + experimental = texlabCfg.experimental; + + # -- Formatters -- + inherit (texlabCfg.formatter) formatterLineLength bibtexFormatter latexFormatter; + + # -- Inlay Hints -- + inlayHints = texlabCfg.inlayHints; + + # -- Latex Indent -- + latexindent = texlabCfg.latexindent; + } + # + # -- Build -- + // (optionalAttrs cfg.build.enable { + build = { + inherit + (cfg.build) + onSave + useFileList + auxDirectory + logDirectory + pdfDirectory + filename + forwardSearchAfter + ; + inherit (builderCfg) args; + executable = "${builderCfg.package}/bin/${builderCfg.executable}"; + }; + }) + # + # -- Chktex -- + // (optionalAttrs texlabCfg.chktex.enable { + chktex = { + inherit (texlabCfg.chktex) onOpenAndSave onEdit additionalArgs; + }; + }) + # + # -- Forward Search -- + // (optionalAttrs texlabCfg.forwardSearch.enable { + forwardSearch = { + inherit (texlabCfg.forwardSearch) args; + executable = "${texlabCfg.forwardSearch.package}/bin/${texlabCfg.forwardSearch.executable}"; + }; + }) + # + # -- Symbols -- + // (optionalAttrs texlabCfg.symbols.enable { + symbols = { + inherit (texlabCfg.symbols) allowedPatterns ignoredPatterns; + + customEnvironments = + map (x: { + inherit (x) name label; + displayName = + if isString x.displayName + then x.displayName + else x.name; + }) + texlabCfg.symbols.customEnvironments; + }; + }) + # + # -- Extra Settings -- + // texlabCfg.extraLuaSettings + ); + in (mkMerge [ + (mkIf texlabCfg.enable { + vim.lsp.lspconfig.sources.texlab = "lspconfig.texlab.setup(${lib.nvim.lua.toLuaObject setupConfig})"; + }) + + (mkIf texlabCfg.chktex.enable { + vim.extraPackages = [texlabCfg.chktex.package]; + }) + ]) + ); +} diff --git a/modules/plugins/languages/tex/pdfViewer/default.nix b/modules/plugins/languages/tex/pdfViewer/default.nix new file mode 100644 index 00000000..ffa946af --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/default.nix @@ -0,0 +1,109 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib.options) mkOption; + inherit (lib.types) str package listOf; + + cfg = config.vim.languages.tex; + + pdfViewer = {name, ...}: { + options = { + enable = lib.mkEnableOption "${builtins.toString name} pdf viewer"; + + name = mkOption { + type = str; + example = "okular"; + description = '' + The name of the pdf viewer to use. + + This value will be automatically set when any of the viewers are + enabled. + + This value will be automatically set to the value of the parent + attribute set. ex. `...tex.pdfViewer..name = "$${name}"` + This value cannot and should not be changed to be different from this + parent value. + + Default values already exist such as `...tex.pdfViewer.okular` but + you can override the default values or created completely custom + pdf viewers should you wish. + ''; + }; + + package = mkOption { + type = package; + example = pkgs.kdePackages.okular; + description = "The package of the pdf viewer to use."; + }; + + executable = mkOption { + type = str; + default = "${builtins.toString name}"; + description = '' + The executable for the pdf viewer to use. + + It will be called as `/bin/`. + + By default, the name of the pdf viewer will be used. + ''; + }; + + args = mkOption { + type = listOf str; + default = []; + description = '' + The command line arguments to use when calling the pdf viewer command. + + These will be called as + `/bin/ ...`. + ''; + }; + }; + + # The name of the pdf viewer must be set to the parent attribute set name. + config.name = lib.mkForce name; + }; +in { + imports = [ + ./premadePdfViewers.nix + ]; + + options.vim.languages.tex.pdfViewer = mkOption { + type = with lib.types; attrsOf (submodule pdfViewer); + default = {}; + example = { + zathura.enable = true; + + customOkular = { + enable = false; + package = pkgs.kdePackages.okular; + executable = "okular"; + args = [ + "--unique" + "file:%p#src:%l%f" + ]; + }; + }; + }; + + config = let + # List form of all pdf viewers. + pdfViewers = builtins.attrValues cfg.pdfViewer; + + countPdfViewers = viewers: (lib.lists.count (x: x.enable) viewers); + in { + assertions = [ + { + # Assert that there is only one enabled pdf viewer. + assertion = (countPdfViewers pdfViewers) < 2; + message = '' + The nvf-tex-language implementation does not support having more than + 1 pdf viewers enabled. + ''; + } + ]; + }; +} diff --git a/modules/plugins/languages/tex/pdfViewer/getEnabledPdfViewer.nix b/modules/plugins/languages/tex/pdfViewer/getEnabledPdfViewer.nix new file mode 100644 index 00000000..e8790c84 --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/getEnabledPdfViewer.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + ... +}: let + # The attribute set of pdf viewers in this configuration. + pdfViewers = config.vim.languages.tex.pdfViewer; + + # The list of pdf viewers in this configuration. + pdfViewersList = builtins.attrValues pdfViewers; + + # The list of enabled pdf viewers. + enabledPdfViewersList = builtins.filter (x: x.enable) pdfViewersList; + + # The number of enabled pdf viewers. + enabledPdfViewersCount = lib.lists.count (x: x.enable) pdfViewersList; +in + if (enabledPdfViewersCount == 0) + # Use the fallback if no pdf viewer was enabled. + then pdfViewers.fallback + # Otherwise get the first enabled viewer. + else builtins.head enabledPdfViewersList diff --git a/modules/plugins/languages/tex/pdfViewer/premadePdfViewers.nix b/modules/plugins/languages/tex/pdfViewer/premadePdfViewers.nix new file mode 100644 index 00000000..622a058e --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/premadePdfViewers.nix @@ -0,0 +1,80 @@ +{ + pkgs, + lib, + ... +}: let + inherit (lib) mkDefault mkForce; + + mkPdfViewerDefaults = { + package, + executable, + args ? [], + }: { + package = mkDefault package; + executable = mkDefault executable; + args = mkDefault args; + }; +in { + config.vim.languages.tex.pdfViewer = { + okular = mkPdfViewerDefaults { + package = pkgs.kdePackages.okular; + executable = "okular"; + args = [ + "--unique" + "file:%p#src:%l%f" + ]; + }; + + sioyek = mkPdfViewerDefaults { + package = pkgs.sioyek; + executable = "sioyek"; + args = [ + "--reuse-window" + "--execute-command" + "toggle_synctex" + "--inverse-search" + "texlab inverse-search -i \"%%1\" -l %%2" + "--forward-search-file" + "%f" + "--forward-search-line" + "%l" + "%p" + ]; + }; + + qpdfview = mkPdfViewerDefaults { + package = pkgs.qpdfview; + executable = "qpdfview"; + args = [ + "--unique" + "%p#src:%f:%l:1" + ]; + }; + + zathura = mkPdfViewerDefaults { + package = pkgs.zathura; + executable = "zathura"; + args = [ + "--synctex-forward" + "%l:1:%f" + "%p" + ]; + }; + + # This is a special pdf viewer. It is force set to a basic and known + # working configuration of okular and is used where needed in the + # rest of the tex language configuration encase no other pdf viewer + # was enabled. + # It cannot be enabled on its own and exists purely as a fallback + # option for internal use. + fallback = { + enable = mkForce false; + package = mkForce pkgs.kdePackages.okular; + executable = mkForce "okular"; + args = mkForce [ + "--unique" + "file:%p#src:%l%f" + ]; + }; + }; +} diff --git a/modules/plugins/languages/tex/treesitter.nix b/modules/plugins/languages/tex/treesitter.nix new file mode 100644 index 00000000..d9c3754b --- /dev/null +++ b/modules/plugins/languages/tex/treesitter.nix @@ -0,0 +1,35 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (lib.modules) mkIf mkMerge; + inherit (lib.nvim.types) mkGrammarOption; + + mkEnableTreesitterOption = lib.nvim.types.mkEnableTreesitterOption config.vim.languages.enableTreesitter; + + cfg = config.vim.languages.tex; +in { + options.vim.languages.tex.treesitter = { + latex = { + enable = mkEnableTreesitterOption "latex"; + package = mkGrammarOption pkgs "latex"; + }; + bibtex = { + enable = mkEnableTreesitterOption "bibtex"; + package = mkGrammarOption pkgs "bibtex"; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf cfg.treesitter.latex.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.latex.package]; + }) + (mkIf cfg.treesitter.bibtex.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.bibtex.package]; + }) + ]); +} diff --git a/npins/sources.json b/npins/sources.json index a2122460..13049390 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -1550,14 +1550,14 @@ "type": "Git", "repository": { "type": "GitHub", - "owner": "otavioschwanck", + "owner": "isaacST08", "repo": "new-file-template.nvim" }, "branch": "master", - "submodules": false, - "revision": "6ac66669dbf2dc5cdee184a4fe76d22465ca67e8", - "url": "https://github.com/otavioschwanck/new-file-template.nvim/archive/6ac66669dbf2dc5cdee184a4fe76d22465ca67e8.tar.gz", - "hash": "0c7378c3w6bniclp666rq15c28akb0sjy58ayva0wpyin4k26hl3" + "revision": "dc3a58b1f490c86075c96670b9eb81370c2f2ca1", + "url": "https://github.com/isaacST08/new-file-template.nvim/archive/dc3a58b1f490c86075c96670b9eb81370c2f2ca1.tar.gz", + "hash": "0y6ip3k6bjaf32x1y1p6mmkwwdi71yvwr6klr26m252jrg8352pf", + "submodules": false }, "nix-develop-nvim": { "type": "Git",