Refactored pdfViewer and fixed infrec error

This commit is contained in:
isaacST08 2025-05-03 18:51:58 -06:00
commit 664b27cb2c
12 changed files with 194 additions and 430 deletions

View file

@ -44,6 +44,7 @@ in {
`vim.g.tex_flavor = <flavor>` line from your lua config entirely `vim.g.tex_flavor = <flavor>` line from your lua config entirely
(unless you manually set it elsewhere of course). (unless you manually set it elsewhere of course).
''; '';
flavor = mkOption { flavor = mkOption {
type = enum [ type = enum [
"plaintex" "plaintex"
@ -71,7 +72,7 @@ in {
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable (mkMerge [
# Extra Lua config options # Extra Lua config options
(mkIf cfg.extraOpts.texFlavor.enable { (mkIf cfg.extraOpts.texFlavor.enable {
vim.globals.tex_flavor = "${cfg.extraOpts.texFlavor.flavor}"; vim.globals.tex_flavor = lib.mkDefault "${cfg.extraOpts.texFlavor.flavor}";
}) })
]); ]);
} }

View file

@ -12,7 +12,13 @@ in {
./texlab.nix ./texlab.nix
]; ];
config = mkIf (cfg.enable && (any (x: x.enable) (attrValues cfg.lsp))) { config =
vim.lsp.lspconfig.enable = true; # Enable lspconfig when any of the lsps are enabled 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
}; };
} }

View file

@ -26,6 +26,9 @@
cfg = config.vim.languages.tex; cfg = config.vim.languages.tex;
texlabCfg = cfg.lsp.texlab; texlabCfg = cfg.lsp.texlab;
builderCfg = cfg.build.builder; builderCfg = cfg.build.builder;
# Get the enabled pdf viewer.
pdfViewer = import ../pdfViewer/getEnabledPdfViewer.nix {inherit lib config;};
in { in {
options.vim.languages.tex.lsp.texlab = { options.vim.languages.tex.lsp.texlab = {
enable = mkBool config.vim.languages.enableLSP '' enable = mkBool config.vim.languages.enableLSP ''
@ -271,7 +274,7 @@ in {
package = mkOption { package = mkOption {
type = package; type = package;
default = cfg.pdfViewer.package; default = pdfViewer.package;
description = '' description = ''
The package to use as your PDF viewer. The package to use as your PDF viewer.
This viewer needs to support Synctex. This viewer needs to support Synctex.
@ -282,7 +285,7 @@ in {
executable = mkOption { executable = mkOption {
type = str; type = str;
default = cfg.pdfViewer.executable; default = pdfViewer.executable;
description = '' description = ''
Defines the executable of the PDF previewer. The previewer needs to Defines the executable of the PDF previewer. The previewer needs to
support SyncTeX. support SyncTeX.
@ -293,7 +296,7 @@ in {
args = mkOption { args = mkOption {
type = listOf str; type = listOf str;
default = cfg.pdfViewer.args; default = pdfViewer.args;
description = '' description = ''
Defines additional arguments that are passed to the configured Defines additional arguments that are passed to the configured
previewer to perform the forward search. previewer to perform the forward search.

View file

@ -1,43 +0,0 @@
{
pkgs,
lib,
...
} @ moduleInheritancePackage: let
# The name of the pdf viewer
name = "custom";
# The viewer template
template = import ./viewerTemplate.nix;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) str listOf;
in (
template {
inherit name moduleInheritancePackage;
options = {
enable = mkEnableOption "enable using a custom pdf viewer.";
package = mkPackageOption pkgs "okular" {
extraDescription = "custom viewer package";
};
executable = mkOption {
type = str;
example = "okular";
description = "The executable name to call the viewer.";
};
args = mkOption {
type = listOf str;
example = [
"--unique"
"file:%p#src:%l%f"
];
description = "Arguments to pass to the viewer.";
};
};
argsFunction = viewerCfg: (viewerCfg.args);
}
)

View file

@ -1,162 +1,104 @@
{ {
config, config,
lib, lib,
pkgs,
... ...
}: let }: let
defaultPdfViewerName = "okular";
inherit
(builtins)
filter
isAttrs
hasAttr
attrNames
length
elemAt
;
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption; inherit (lib.options) mkOption;
inherit (lib.types) str package listOf; inherit (lib.types) str package listOf;
cfg = config.vim.languages.tex; cfg = config.vim.languages.tex;
viewerCfg = cfg.pdfViewer;
enabledPdfViewersInfo = let pdfViewer = {name, ...}: {
# This function will sort through the pdf viewer options and count how many options = {
# pdf viewers have been enabled. enable = lib.mkEnableOption "${builtins.toString name} pdf viewer";
# If no viewers have been enabled, the count will be 0 and the name of the
# enabled viewer will be the default pdf viewer defined above.
getEnabledPdfViewersInfo = {
enabledPdfViewersCount ? 0,
index ? 0,
pdfViewerNamesList ? (
filter (
x: let
y = viewerCfg."${x}";
in (
isAttrs y && hasAttr "enable" y && hasAttr "package" y && hasAttr "executable" y && hasAttr "args" y
)
) (attrNames viewerCfg)
),
currentEnabledPdfViewerName ? defaultPdfViewerName,
}: let
# Get the name of the current pdf viewer being checked if it is enabled
currentPdfViewerName = elemAt pdfViewerNamesList index;
# Get the current pdf viewer object
currentPdfViewer = viewerCfg."${currentPdfViewerName}";
# Get the index that will be used for the next iteration
nextIndex = index + 1;
# Increment the count that is recording the number of enabled pdf viewers
# if this viewer is enabled, otherwise leave it as is.
newEnabledPdfViewersCount =
if currentPdfViewer.enable
then enabledPdfViewersCount + 1
else enabledPdfViewersCount;
# If this pdf viewer is enabled, set is as the enabled viewer.
newEnabledPdfViewerName =
if currentPdfViewer.enable
then currentPdfViewerName
else currentEnabledPdfViewerName;
in
# Check that the end of the list of viewers has not been reached
if length pdfViewerNamesList > nextIndex
# If the end of the viewers list has not been reached, call the next iteration
# of the function to process the next viewer
then
getEnabledPdfViewersInfo {
inherit pdfViewerNamesList;
enabledPdfViewersCount = newEnabledPdfViewersCount;
index = nextIndex;
currentEnabledPdfViewerName = newEnabledPdfViewerName;
}
# If the end of the viewers list has been reached, then return the total number
# of viewers that have been enabled and the name of the last viewer that was enabled.
else {
count = newEnabledPdfViewersCount;
enabledViewerName = newEnabledPdfViewerName;
};
in (getEnabledPdfViewersInfo {});
enabledPdfViewerCfg = viewerCfg."${enabledPdfViewersInfo.enabledViewerName}";
in {
imports = [
./custom.nix
./okular.nix
./qpdfview.nix
./sioyek.nix
./zathura.nix
];
options.vim.languages.tex.pdfViewer = {
name = mkOption { name = mkOption {
type = str; type = str;
default = enabledPdfViewerCfg.name; example = "okular";
description = '' description = ''
The name of the pdf viewer to use. The name of the pdf viewer to use.
This value will be automatically set when any of the viewers are This value will be automatically set when any of the viewers are
enabled. enabled.
Setting this option option manually is not recommended but can be used This value will be automatically set to the value of the parent
for some very technical nix-ing. If you wish to use a custom viewer, attribute set. ex. `...tex.pdfViewer.<name>.name = "$${name}"`
please use the `custom` entry provided under `viewers`. 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 { package = mkOption {
type = package; type = package;
default = enabledPdfViewerCfg.package; example = pkgs.kdePackages.okular;
description = '' description = "The package of the pdf viewer to use.";
The package of the pdf viewer to use.
This value will be automatically set when any of the viewers are
enabled.
Setting this option option manually is not recommended but can be used
for some very technical nix-ing. If you wish to use a custom viewer,
please use the `custom` entry provided under `viewers`.
'';
}; };
executable = mkOption { executable = mkOption {
type = str; type = str;
default = enabledPdfViewerCfg.executable; default = "${builtins.toString name}";
description = '' description = ''
The executable for the pdf viewer to use. The executable for the pdf viewer to use.
This value will be automatically set when any of the viewers are It will be called as `<package_path>/bin/<executable>`.
enabled.
Setting this option option manually is not recommended but can be used By default, the name of the pdf viewer will be used.
for some very technical nix-ing. If you wish to use a custom viewer,
please use the `custom` entry provided under `viewers`.
''; '';
}; };
args = mkOption { args = mkOption {
type = listOf str; type = listOf str;
default = enabledPdfViewerCfg.args; default = [];
description = '' description = ''
The command line arguments to use when calling the pdf viewer command. The command line arguments to use when calling the pdf viewer command.
This value will be automatically set when any of the viewers are These will be called as
enabled. `<package_path>/bin/<executable> <arg1> <arg2> ...`.
Setting this option option manually is not recommended but can be used
for some very technical nix-ing. If you wish to use a custom viewer,
please use the `custom` entry provided under `viewers`.
''; '';
}; };
}; };
config = mkIf (enabledPdfViewersInfo.count > 0) { # 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 = [ assertions = [
{ {
assertion = enabledPdfViewersInfo.count < 2; # Assert that there is only one enabled pdf viewer.
assertion = (countPdfViewers pdfViewers) < 2;
message = '' message = ''
The nvf-tex-language implementation does not support having more than The nvf-tex-language implementation does not support having more than
1 pdf viewers enabled. 1 pdf viewers enabled.

View file

@ -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

View file

@ -1,41 +0,0 @@
{
pkgs,
lib,
...
} @ moduleInheritancePackage: let
# The name of the pdf viewer
name = "okular";
# The viewer template
template = import ./viewerTemplate.nix;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) str listOf;
in (
template {
inherit name moduleInheritancePackage;
options = {
enable = mkEnableOption "enable okular as the pdf file previewer.";
package = mkPackageOption pkgs "okular" {};
executable = mkOption {
type = str;
default = "okular";
description = "The executable name to call the viewer.";
};
args = mkOption {
type = listOf str;
default = [
"--unique"
"file:%p#src:%l%f"
];
description = "Arguments to pass to the viewer.";
};
};
argsFunction = viewerCfg: (viewerCfg.args);
}
)

View file

@ -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"
];
};
};
}

View file

@ -1,41 +0,0 @@
{
pkgs,
lib,
...
} @ moduleInheritancePackage: let
# The name of the pdf viewer
name = "qpdfview";
# The viewer template
template = import ./viewerTemplate.nix;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) str listOf;
in (
template {
inherit name moduleInheritancePackage;
options = {
enable = mkEnableOption "enable qpdfview as the pdf file previewer.";
package = mkPackageOption pkgs "qpdfview" {};
executable = mkOption {
type = str;
default = "qpdfview";
description = "The executable name to call the viewer.";
};
args = mkOption {
type = listOf str;
default = [
"--unique"
"%p#src:%f:%l:1"
];
description = "Arguments to pass to the viewer.";
};
};
argsFunction = viewerCfg: (viewerCfg.args);
}
)

View file

@ -1,55 +0,0 @@
{
pkgs,
lib,
...
} @ moduleInheritancePackage: let
# The name of the pdf viewer
name = "sioyek";
# The viewer template
template = import ./viewerTemplate.nix;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) str listOf;
in (
template {
inherit name moduleInheritancePackage;
options = {
enable = mkEnableOption "sioyek as the pdf file previewer.";
package = mkPackageOption pkgs "sioyek" {};
executable = mkOption {
type = str;
default = "sioyek";
description = "The executable name to call the viewer.";
};
args = mkOption {
type = listOf str;
default = [
"--reuse-window"
"--execute-command"
"toggle_synctex"
"--inverse-search"
"texlab inverse-search -i \"%%1\" -l %%2"
"--forward-search-file"
"%f"
"--forward-search-line"
"%l"
"%p"
];
description = ''
Arguments to pass to the viewer.
By default, this is the only viewer that supports the inverse search
feature by command line arguments and doesn't explicitly require extra
tinkering else where in your config.
'';
};
};
argsFunction = viewerCfg: (viewerCfg.args);
}
)

View file

@ -1,68 +0,0 @@
# This function acts as a template for creating new pdf viewers.
# It enforces providing all the parameters required for creating
# a new pdf viewer for it to be able to work in the existing code.
#
# The first layer requirements are as follows:
{
# This is the name of the pdf viewer, it will only be used internally and
# MUST match the <name>.nix file that the pdf viewer is implemented in.
name,
#
# Module attribute set. This is the attribute set that the module that is
# defining a pdf viewer is passed as its input.
moduleInheritancePackage,
#
# These are the standard options for the pdf viewer 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 view command is called.
# This is a function that will take in the cfg of its own pdf viewer.
# i.e. it will be called as "args cfg.pdfViewer.${name}"
argsFunction,
...
}: 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;
#
# Set the cfg of the viewer itself
viewerCfg = cfg.pdfViewer.${name};
in {
# These are the options for the pdf viewer. It will accept any options
# provided to it but some options are mandatory:
options.vim.languages.tex.pdfViewer.${name} = ({
# The enable option. This one is self explanatory.
enable,
#
# This is the package option for the pdf viewer.
package,
#
# This is the executable that will be used to call the pdf viewer.
# It, along with package will result in:
# "<package_path>/bin/<executable>"
executable,
#
# Any other options provided are accepted.
...
} @ opts:
opts)
options;
# Check that the language and this pdf viewer have been enabled before making
# any config.
config = mkIf (cfg.enable && viewerCfg.enable) {
vim.languages.tex.pdfViewer = {
inherit name;
inherit (viewerCfg) package executable;
args = argsFunction viewerCfg;
};
};
}

View file

@ -1,42 +0,0 @@
{
pkgs,
lib,
...
} @ moduleInheritancePackage: let
# The name of the pdf viewer
name = "zathura";
# The viewer template
template = import ./viewerTemplate.nix;
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.types) str listOf;
in (
template {
inherit name moduleInheritancePackage;
options = {
enable = mkEnableOption "enable zathura as the pdf file previewer.";
package = mkPackageOption pkgs "zathura" {};
executable = mkOption {
type = str;
default = "zathura";
description = "The executable name to call the viewer.";
};
args = mkOption {
type = listOf str;
default = [
"--synctex-forward"
"%l:1:%f"
"%p"
];
description = "Arguments to pass to the viewer.";
};
};
argsFunction = viewerCfg: (viewerCfg.args);
}
)