From ca3e27ec770bf3d3f980a7ff41718c528fd43ef1 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sat, 26 Nov 2022 06:35:58 +0100 Subject: [PATCH] nix-option-search: Init --- README.md | 18 +++- flake.nix | 4 + searchers/nix-option-search.nix | 185 +++++++++++++++++++++++++++++++- 3 files changed, 203 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3eb1e80..e3c72c2 100644 --- a/README.md +++ b/README.md @@ -18,17 +18,29 @@ TODO: ### Nix Options -TODO: +**NOTE:** This is mostly a copypaste of `home-manager-search`. +The documentation structure for `home-manager-search` and `nix-option-search` differ slightly, but they are similar enough that the copypaste version is kind of usable. +I will fix up this in the future, but for now I am focusing on squashing the bugs within `home-manager-search`. + +```console +nix run github:h7x4/nix-attr-search#nix-option-search +``` + +Or a more advanced version: + +```console +nix run github:h7x4/nix-attr-search#nix-option-search -- --flake="github:NixOS/nixpkgs" --ref="nixos-22.05" +``` ### Homemanager -``` +```console nix run github:h7x4/nix-attr-search#home-manager-search ``` Or a more advanced version: -``` +```console nix run github:h7x4/nix-attr-search#home-manager-search -- --flake="github:nix-community/home-manager" --ref="release-22.05" ``` diff --git a/flake.nix b/flake.nix index 7b76b64..cbdd7d1 100644 --- a/flake.nix +++ b/flake.nix @@ -45,6 +45,10 @@ }; nix-option-search = pkgs.callPackage ./searchers/nix-option-search.nix { inherit nixpkgs; + inherit (self.packages.${system}) json2nix; + defaultManualPath = + let pkg = self.packages.${system}.nix-options-json; + in "${pkg}/share/doc/nixos/options.json"; }; nix-package-search = pkgs.callPackage ./searchers/nix-package-search.nix { }; diff --git a/searchers/nix-option-search.nix b/searchers/nix-option-search.nix index 01856f4..b3daf7f 100644 --- a/searchers/nix-option-search.nix +++ b/searchers/nix-option-search.nix @@ -1,2 +1,185 @@ # TODO: -{ pkgs, ... }: pkgs.emptyFile \ No newline at end of file +{ pkgs, lib, nixpkgs, defaultManualPath, system, json2nix, ... }: +let + usage = pkgs.writeText "nix-option-search-usage" '' + Usage: + nix-option-search [ -j | -n ] [-f= [-r=]] + + Options: + -h | --help Display this message. + -j | --json Display raw data in json format. + -np | --no-preview Don't display a preview. + -nc | --no-color Turn off ANSI colors. + -f=* | --flake=* Use a flake url to an instance (e.g. a fork) of nixpkgs, + generate its options, and use those instead of the global ones. + -r=* | --ref=* If a flake url is specified, this option might be used to choose + a specific reference (branch, tag, commit, etc.) to use for + generating the docs. + + Example usage: + nix-option-search + nix-option-search -j + nix-option-search --flake="github:NixOS/nixpkgs" + nix-option-search --flake="github:NixOS/nixpkgs" --ref="nixos-22.05" + ''; + + inherit (pkgs.callPackage ../internals/lib.nix { }) + jq fzf gomplate nixfmt bat perl blinkred bold red green yellow blue magenta + clear flatten; + + # TODO: Preprocess all XML tags in description. + substitutionsColor = let s = "\\s*"; + in { + "([^>]*)" = "${bold}`$1`${clear}"; + "([^>]*)" = "${bold}`$1`${clear}"; + "([^>]*)" = "${yellow}$1${clear}"; + "([^>]*)" = "${bold}$1${clear}"; + "([^>]*)" = "${red}$1${clear}"; + "([^>]*)" = "${red}$1${clear}"; + "" = "\\n"; + "]*)\"${s}/>" = "${blue}$1${clear}"; + "]*)\"${s}>([^<]*)" = + "${bold}$2 ${clear}(${blue}$1${clear})"; + "]*)\"${s}/>" = "${blue}$1${clear}"; + }; + + substitutions = let s = "\\s*"; + in { + "([^>]*)" = "`$1`"; + "([^>]*)" = "`$1`"; + "([^>]*)" = "`$1`"; + "([^>]*)" = "`$1`"; + "([^>]*)" = "`$1`"; + "([^>]*)" = "`$1`"; + "" = "\\n"; + "]*)\"${s}/>" = "`$1`"; + "]*)\"${s}>([^<]*)" = "`$2 ($1)`"; + "]*)\"${s}/>" = "`$1`"; + }; + + perlArgsColor = with lib; + pipe substitutionsColor [ + (mapAttrsToList (name: value: "s|${name}|${value}|gm")) + (concatStringsSep ";") + (x: "-pe '${x}'") + ]; + + perlArgs = with lib; + pipe substitutions [ + (mapAttrsToList (name: value: "s|${name}|${value}|gm")) + (concatStringsSep ";") + (x: "-pe '${x}'") + ]; + + optionTemplateColor = + pkgs.callPackage ../templates/option-preview-template-color.nix { }; + + optionTemplate = + pkgs.callPackage ../templates/option-preview-template.nix { }; + + # TODO: This preview does not respect the color option... + previewJson = pkgs.writers.writeBash "preview-nix-option-attrs-json" '' + OPTION_KEY=$1 + JSON_MANUAL_PATH=$2 + + ${jq} -C ".\"$OPTION_KEY\"" $JSON_MANUAL_PATH + ''; + + previewGomplate = isColorized: + let + # TODO: Color management here needs a refactoring badly... + pArgs = if isColorized then perlArgsColor else perlArgs; + colorSuffix = if isColorized then "-color" else ""; + batColorArg = if isColorized then "--color=always " else ""; + template = if isColorized then optionTemplateColor else optionTemplate; + in pkgs.writers.writeBash + "preview-nix-option-attrs-gomplate${colorSuffix}" '' + OPTION_KEY=$1 + JSON_MANUAL_PATH=$2 + + JSON_DATA=$(${jq} ".\"$OPTION_KEY\"" $JSON_MANUAL_PATH) + export DESCRIPTION=$(echo $JSON_DATA | ${jq} -r ".description" | ${perl} ${pArgs}) + + EXAMPLE_DATA=$(echo $JSON_DATA | ${jq} -r ".example.text" 2>/dev/null) + if [ $? != 0 ]; then + EXAMPLE_DATA=$(echo $JSON_DATA | ${jq} -r ".example" | ${json2nix}/bin/json2nix) + fi + export EXAMPLE=$(echo $EXAMPLE_DATA | ${nixfmt} | ${bat} ${batColorArg}--style=numbers) + + export DEFAULT=$(echo $JSON_DATA | ${jq} -r ".default" | ${json2nix}/bin/json2nix | ${nixfmt} | ${bat} ${batColorArg}--style=numbers) + echo $JSON_DATA | ${gomplate} --datasource opt=stdin:?type=application/json --file ${template} + ''; + +in pkgs.writers.writeBash "search-nix-option-attrs" '' + JSON_MANUAL_PATH="${defaultManualPath}" + + for i in "$@"; do + case $i in + -h|--help) + cat ${usage} + exit 0 + ;; + -j|--json) + PRINT_JSON=1 + shift + ;; + -np|--no-preview) + NO_PREVIEW=1 + shift + ;; + -nc|--no-color) + NO_COLOR=1 + shift + ;; + -f=*|--flake=*) + FLAKE="''${i#*=}" + shift + ;; + -r=*|--ref=*) + REF="''${i#*=}" + shift + ;; + *|-*|--*) + echo "Unknown option $i" + cat ${usage} + exit 1 + ;; + esac + done + + if [ -v PRINT_JSON ] && [ -v NO_PREVIEW ]; then + echo "Cannot preview as json with no-preview enabled" + cat ${usage} + exit 1 + fi + + if [ -v FLAKE ]; then + FLAKE_URL="''${FLAKE}" + + if [ -v REF ]; then + FLAKE_URL="''${FLAKE_URL}?ref=$REF" + fi + + echo "Building docs from $FLAKE_URL" + + OUT_PATH=$(${pkgs.nix}/bin/nix build --impure --no-link --print-out-paths --no-write-lock-file --expr "let nixpkgs=(builtins.getFlake \"$FLAKE_URL\"); in (import \"\''${nixpkgs}/nixos/release.nix\" { inherit nixpkgs; }).options") + echo $OUT_PATH + JSON_MANUAL_PATH="$OUT_PATH/share/doc/nixos/options.json" + echo "Using docs located at $JSON_MANUAL_PATH" + fi + + if [ -v NO_PREVIEW ]; then + ${jq} -r 'keys | .[] | .' $JSON_MANUAL_PATH | ${fzf} + elif [ -v PRINT_JSON ]; then + ${jq} -r 'keys | .[] | .' $JSON_MANUAL_PATH | ${fzf} --preview "${previewJson} {} $JSON_MANUAL_PATH" + elif [ -v NO_COLOR ]; then + ${jq} -r 'keys | .[] | .' $JSON_MANUAL_PATH | ${fzf} --preview "${ + previewGomplate false + } {} $JSON_MANUAL_PATH" + else + ${jq} -r 'keys | .[] | .' $JSON_MANUAL_PATH | ${fzf} --preview "${ + previewGomplate true + } {} $JSON_MANUAL_PATH" + fi +'' +