From 9524d93bd2638c4b31256526f25ccdc8fbd41a2e Mon Sep 17 00:00:00 2001 From: isaacST08 Date: Thu, 30 Jan 2025 17:15:00 -0700 Subject: [PATCH] Created PDF viewer framework --- modules/plugins/languages/tex/default.nix | 1 + .../languages/tex/pdfViewer/default.nix | 141 ++++++++++++++++++ .../tex/pdfViewer/viewers/default.nix | 6 + .../tex/pdfViewer/viewers/okular.nix | 42 ++++++ .../tex/pdfViewer/viewers/viewerTemplate.nix | 68 +++++++++ 5 files changed, 258 insertions(+) create mode 100644 modules/plugins/languages/tex/pdfViewer/default.nix create mode 100644 modules/plugins/languages/tex/pdfViewer/viewers/default.nix create mode 100644 modules/plugins/languages/tex/pdfViewer/viewers/okular.nix create mode 100644 modules/plugins/languages/tex/pdfViewer/viewers/viewerTemplate.nix diff --git a/modules/plugins/languages/tex/default.nix b/modules/plugins/languages/tex/default.nix index 98ac5f1c..518361d7 100644 --- a/modules/plugins/languages/tex/default.nix +++ b/modules/plugins/languages/tex/default.nix @@ -13,6 +13,7 @@ in { ./treesitter.nix ./lsp ./build + ./pdfViewer ]; options.vim.languages.tex = { diff --git a/modules/plugins/languages/tex/pdfViewer/default.nix b/modules/plugins/languages/tex/pdfViewer/default.nix new file mode 100644 index 00000000..890031dc --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/default.nix @@ -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; + }; +} diff --git a/modules/plugins/languages/tex/pdfViewer/viewers/default.nix b/modules/plugins/languages/tex/pdfViewer/viewers/default.nix new file mode 100644 index 00000000..8874fc12 --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/viewers/default.nix @@ -0,0 +1,6 @@ +{ ... }: +{ + imports = [ + ./okular.nix + ]; +} diff --git a/modules/plugins/languages/tex/pdfViewer/viewers/okular.nix b/modules/plugins/languages/tex/pdfViewer/viewers/okular.nix new file mode 100644 index 00000000..4d0d90d4 --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/viewers/okular.nix @@ -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 ); + } +) diff --git a/modules/plugins/languages/tex/pdfViewer/viewers/viewerTemplate.nix b/modules/plugins/languages/tex/pdfViewer/viewers/viewerTemplate.nix new file mode 100644 index 00000000..64cb2ca2 --- /dev/null +++ b/modules/plugins/languages/tex/pdfViewer/viewers/viewerTemplate.nix @@ -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 .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: + # "/bin/" + 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; + }; + }; +}