Created PDF viewer framework

This commit is contained in:
isaacST08 2025-01-30 17:15:00 -07:00
commit 9524d93bd2
5 changed files with 258 additions and 0 deletions

View file

@ -13,6 +13,7 @@ in {
./treesitter.nix ./treesitter.nix
./lsp ./lsp
./build ./build
./pdfViewer
]; ];
options.vim.languages.tex = { options.vim.languages.tex = {

View file

@ -0,0 +1,141 @@
{
config,
lib,
pkgs,
...
}: let
defaultPdfViewerName = "okular";
inherit (lib) mkOverride;
inherit (lib.options) mkOption;
inherit (lib.modules) mkIf;
inherit (lib.types) str package listOf;
inherit (builtins) filter isAttrs hasAttr attrNames length elemAt;
inherit (lib.nvim.config) mkBool;
cfg = config.vim.languages.tex;
viewersCfg = cfg.pdfViewer.viewers;
enabledPdfViewersInfo = let
# This function will sort through the pdf viewer options and count how many
# pdf viewers have been enabled.
# 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 = viewersCfg.${x};
in (
isAttrs y
&& hasAttr "enable" y
&& hasAttr "package" y
&& hasAttr "executable" y
&& hasAttr "args" y
)
) (attrNames viewersCfg)
),
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 = viewersCfg.${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 = viewersCfg.${enabledPdfViewersInfo.enabledViewerName};
in {
imports = [
./viewers
];
options.vim.languages.tex.pdfViewer = {
enable =
mkBool (
if enabledPdfViewersInfo.count > 1
then throw "nvf-tex-language does not support having more than 1 pdf viewer enabled!"
else (enabledPdfViewersInfo.count == 1)
) ''
Whether to enable configuring the pdf viewer.
By enabling any of the pdfViewers, this option will be automatically set.
If you enable more than one pdf viewer then an error will be thrown.
'';
name = mkOption {
type = str;
default = enabledPdfViewerCfg.name;
description = ''
TODO
'';
};
package = mkOption {
type = package;
default = enabledPdfViewerCfg.package;
description = ''
The package to set to use a custom viewer.
'';
};
executable = mkOption {
type = str;
default = enabledPdfViewerCfg.executable;
description = ''
TODO
'';
};
args = mkOption {
type = listOf str;
default = enabledPdfViewerCfg.args;
description = ''
TODO
'';
};
};
# If the pdf viewer has been enabled, but none of the individual viewers have been enabled,
# then enable the default viewer.
config = mkIf (cfg.enable && cfg.pdfViewer.enable && enabledPdfViewersInfo.count == 0) {
vim.languages.tex.pdfViewer.viewers.${defaultPdfViewerName}.enable = mkOverride 75 true;
};
}

View file

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

View file

@ -0,0 +1,42 @@
{
pkgs,
lib,
...
} @ moduleInheritencePackage: let
# The name of the pdf viewer
name = "okular";
# The viewer template
template = import ./viewerTemplate.nix;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.types) package str listOf;
in (
template {
inherit name moduleInheritencePackage;
options = {
enable = mkEnableOption "enable okular as the pdf file previewer.";
package = mkOption {
type = package;
default = pkgs.okular;
description = "okular package";
};
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.";
};
};
args = viewerCfg: ( viewerCfg.args );
}
)

View file

@ -0,0 +1,68 @@
# 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.
moduleInheritencePackage,
#
# 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.viewers.${name}"
args,
...
}: let
# Inherit the necessary variables available to any module.
inherit (moduleInheritencePackage) 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.viewers.${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.viewers.${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, overall pdf viewing, 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 = args viewerCfg;
};
};
}