From 8223e6f23e17c5d262983a86b75a9f5702f760d7 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Sat, 10 Jul 2021 10:26:58 +0200 Subject: [PATCH] fish_config: Add CLI-based theme selector `fish_config theme`: - `list` to list all available themes (files in the two theme directories - either the web_config/themes one or ~/.config/fish/themes!) - `show` to show select (or all) themes right in the terminal - this starts another fish that reads the theme file and prints the sample text, manually colored - `choose` to load a theme *now*, setting the variables globally - `save` to load a theme and save the variables universally - `dump` to write the current theme in .theme format (to stdout) - `demo` to display the current theme --- doc_src/cmds/fish_config.rst | 14 ++ share/completions/fish_config.fish | 16 ++ share/functions/fish_config.fish | 263 +++++++++++++++++++++-------- 3 files changed, 224 insertions(+), 69 deletions(-) diff --git a/doc_src/cmds/fish_config.rst b/doc_src/cmds/fish_config.rst index 69bb1f023..f11438143 100644 --- a/doc_src/cmds/fish_config.rst +++ b/doc_src/cmds/fish_config.rst @@ -11,6 +11,7 @@ Synopsis fish_config fish_config browse fish_config prompt (choose | list | save | show) + fish_config theme (choose | demo | dump | list | save | show) Description ----------- @@ -30,6 +31,19 @@ Available subcommands for the ``prompt`` command: - ``save`` saves the current prompt to a file (via :ref:`funcsave `). - ``show`` shows what the given sample prompts (or all) would look like. +With the ``theme`` command ``fish_config`` can be used to view and choose a theme (meaning a color scheme) inside the terminal. + +Available subcommands for the ``theme`` command: + +- ``choose`` loads a sample theme in the current session. +- ``demo`` displays some sample text in the current theme. +- ``dump`` prints the current theme in a loadable format. +- ``list`` lists the names of the available sample themes. +- ``save`` saves the current prompt to :ref:`universal variables `. +- ``show`` shows what the given sample theme (or all) would look like. + +The themes are loaded from the theme directory shipped with fish or a ``themes`` directory in the fish configuration directory (typically ``~/.config/fish/themes``). + Example ------- diff --git a/share/completions/fish_config.fish b/share/completions/fish_config.fish index 6db433444..0a254b4e4 100644 --- a/share/completions/fish_config.fish +++ b/share/completions/fish_config.fish @@ -1,5 +1,6 @@ complete fish_config -f set -l prompt_commands choose save show list +set -l theme_commands choose demo dump save show list complete fish_config -n '__fish_use_subcommand' -a prompt -d 'View and pick from the sample prompts' complete fish_config -n "__fish_seen_subcommand_from prompt; and not __fish_seen_subcommand_from $prompt_commands" \ -a choose -d 'View and pick from the sample prompts' @@ -12,3 +13,18 @@ complete fish_config -n "__fish_seen_subcommand_from prompt; and not __fish_seen complete fish_config -n '__fish_seen_subcommand_from prompt; and __fish_seen_subcommand_from choose save show' -a '(fish_config prompt list)' complete fish_config -n '__fish_use_subcommand' -a browse -d 'Open the web-based UI' + +complete fish_config -n '__fish_use_subcommand' -a theme -d 'View and pick from the sample themes' +complete fish_config -n '__fish_seen_subcommand_from theme; and __fish_seen_subcommand_from choose save show' -a '(fish_config theme list)' +complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \ + -a choose -d 'View and pick from the sample themes' +complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \ + -a show -d 'Show what theme would look like' +complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \ + -a list -d 'List all available themes' +complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \ + -a save -d 'Save the given theme as universal variables' +complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \ + -a demo -d 'Show example in the current theme' +complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \ + -a dump -d 'Print the current theme in .theme format' diff --git a/share/functions/fish_config.fish b/share/functions/fish_config.fish index ba3cad69d..f773aae3b 100644 --- a/share/functions/fish_config.fish +++ b/share/functions/fish_config.fish @@ -32,99 +32,224 @@ function fish_config --description "Launch fish's web based configuration" return 0 end - if not contains -- $cmd prompt + if not contains -- $cmd prompt theme echo No such subcommand: $cmd >&2 return 1 end - # prompt - for prompt switching - set -l cmd $argv[1] - set -e argv[1] - - if contains -- $cmd list; and set -q argv[1] - echo "Too many arguments" >&2 - return 1 - end - - set -l prompt_dir $__fish_data_dir/sample_prompts $__fish_data_dir/tools/web_config/sample_prompts switch $cmd - case show - set -l fish (status fish-path) - set -l prompts $prompt_dir/$argv.fish - set -q prompts[1]; or set prompts $prompt_dir/*.fish - for p in $prompts - if not test -e "$p" - continue - end - set -l promptname (string replace -r '.*/([^/]*).fish$' '$1' $p) - echo -s (set_color --underline) $promptname (set_color normal) - $fish -c "functions -e fish_right_prompt; source $p; - false - fish_prompt - echo (set_color normal) - if functions -q fish_right_prompt; - echo right prompt: (false; fish_right_prompt) - end" - echo - end - case list '' - string replace -r '.*/([^/]*).fish$' '$1' $prompt_dir/*.fish - return - case choose - if set -q argv[2] + case prompt + # prompt - for prompt switching + set -l cmd $argv[1] + set -e argv[1] + + if contains -- $cmd list; and set -q argv[1] echo "Too many arguments" >&2 return 1 end - if not set -q argv[1] - echo "Too few arguments" >&2 - return 1 - end - set -l have 0 - for f in $prompt_dir/$argv[1].fish - if test -f $f - source $f - set have 1 - break - end - end - if test $have -eq 0 - echo "No such prompt: '$argv[1]'" >&2 - return 1 - end - case save - read -P"Overwrite prompt? [y/N]" -l yesno - if string match -riq 'y(es)?' -- $yesno - echo Overwriting - cp $__fish_config_dir/functions/fish_prompt.fish{,.bak} + set -l prompt_dir $__fish_data_dir/sample_prompts $__fish_data_dir/tools/web_config/sample_prompts + switch $cmd + case show + set -l fish (status fish-path) + set -l prompts $prompt_dir/$argv.fish + set -q prompts[1]; or set prompts $prompt_dir/*.fish + for p in $prompts + if not test -e "$p" + continue + end + set -l promptname (string replace -r '.*/([^/]*).fish$' '$1' $p) + echo -s (set_color --underline) $promptname (set_color normal) + $fish -c "functions -e fish_right_prompt; source $p; + false + fish_prompt + echo (set_color normal) + if functions -q fish_right_prompt; + echo right prompt: (false; fish_right_prompt) + end" + echo + end + case list '' + string replace -r '.*/([^/]*).fish$' '$1' $prompt_dir/*.fish + return + case choose + if set -q argv[2] + echo "Too many arguments" >&2 + return 1 + end + if not set -q argv[1] + echo "Too few arguments" >&2 + return 1 + end - if set -q argv[1] set -l have 0 for f in $prompt_dir/$argv[1].fish if test -f $f - set have 1 source $f - or return 2 + set have 1 + break end end if test $have -eq 0 echo "No such prompt: '$argv[1]'" >&2 return 1 end - end + case save + read -P"Overwrite prompt? [y/N]" -l yesno + if string match -riq 'y(es)?' -- $yesno + echo Overwriting + cp $__fish_config_dir/functions/fish_prompt.fish{,.bak} - funcsave fish_prompt - or return + if set -q argv[1] + set -l have 0 + for f in $prompt_dir/$argv[1].fish + if test -f $f + set have 1 + source $f + or return 2 + end + end + if test $have -eq 0 + echo "No such prompt: '$argv[1]'" >&2 + return 1 + end + end - functions -q fish_right_prompt - and funcsave fish_right_prompt + funcsave fish_prompt + or return - return - else - echo Not overwriting + functions -q fish_right_prompt + and funcsave fish_right_prompt + + return + else + echo Not overwriting + return 1 + end + end + + return 0 + case theme + # Selecting themes + set -l cmd $argv[1] + set -e argv[1] + + if contains -- $cmd list; and set -q argv[1] + echo "Too many arguments" >&2 return 1 end - end - return 0 + set -l dir $__fish_config_dir/themes $__fish_data_dir/tools/web_config/themes + + switch $cmd + case list '' + string replace -r '.*/([^/]*).theme$' '$1' $dir/*.theme + return + case demo + echo -ns (set_color $fish_color_command) /bright/vixens + echo -ns (set_color normal) ' ' + echo -ns (set_color $fish_color_param) jump + echo -ns (set_color normal) ' ' + echo -ns (set_color $fish_color_redirection) '|' + echo -ns (set_color normal) ' ' + echo -ns (set_color $fish_color_quote) '"fowl"' + echo -ns (set_color normal) ' ' + echo -ns (set_color $fish_color_redirection) '> quack' + echo -ns (set_color normal) ' ' + echo -ns (set_color $fish_color_end) '&' + set_color normal + echo -s (set_color $fish_color_comment) ' # This is a comment' + set_color normal + echo -ns (set_color $fish_color_command) echo + echo -ns (set_color normal) ' ' + echo -s (set_color $fish_color_error) "'Errors are the portal to discovery" + set_color normal + echo -ns (set_color $fish_color_command) Th + set_color normal + set_color $fish_color_autosuggestion + echo is is an autosuggestion + echo + case show + set -l fish (status fish-path) + set -l themes $dir/$argv.theme + set -q themes[1]; or set themes $dir/*.theme + set -l used_themes + + echo -s (set_color normal; set_color --underline) Current (set_color normal) + fish_config theme demo + + for t in $themes + not test -e "$t" + and continue + + set -l themename (string replace -r '.*/([^/]*).theme$' '$1' $t) + contains -- $themename $used_themes + and continue + set -a used_themes $themename + + echo -s (set_color normal; set_color --underline) $themename (set_color normal) + + # Use a new, --no-config, fish to display the theme. + # So we can use this function, explicitly source it before anything else! + functions fish_config | $fish -C "source -" --no-config -c " + fish_config theme choose '$themename' + fish_config theme demo '$themename' + " + end + + case choose save + set -l files $dir/$argv[1].theme + set -l file + + set -l scope -g + if contains -- $cmd save + read -P"Overwrite theme? [y/N]" -l yesno + if not string match -riq 'y(es)?' -- $yesno + echo Not overwriting >&2 + return 1 + end + set scope -U + end + + for f in $files + if test -e "$f" + set file $f + break + end + end + + if not set -q file[1] + echo "No such theme: $argv[1]" >&2 + echo "Dirs: $dir" >&2 + return 1 + end + + set -l have_color 0 + while read -lat toks + # We only allow color variables. + # Not the specific list, but something named *like* a color variable. + # + # This also takes care of empty lines and comment lines. + string match -rq '^fish_(?:pager_)?color.*$' -- $toks[1] + or continue + + # Note: This can warn about global variables shadowing the universal + # versions we create. + # We want that warning to go through, because we *can't* + # permanently remove the globals. + set $scope $toks + set have_color 1 + end < $file + + # Return true if we changed at least one color + test $have_color -eq 1 + return + case dump + # Write the current theme in .theme format, to stdout. + set -L | string match -r '^fish_(?:pager_)?color.*$' + case '*' + echo "No such command: $cmd" >&2 + return 1 + end + end end