mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-04-19 14:51:13 -03:00
Compare commits
1 Commits
Integratio
...
update-def
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb2b1c6621 |
@@ -10,7 +10,7 @@ Synopsis
|
||||
|
||||
fish_config [browse]
|
||||
fish_config prompt (choose | list | save | show)
|
||||
fish_config theme (choose | demo | dump | list | save | show)
|
||||
fish_config theme (choose | demo | dump | list | save | show | update)
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -40,6 +40,9 @@ Available subcommands for the ``theme`` command:
|
||||
- ``list`` lists the names of the available sample themes.
|
||||
- ``save`` saves the given theme to :ref:`universal variables <variables-universal>`.
|
||||
- ``show`` shows what the given sample theme (or all) would look like.
|
||||
- ``update`` updates any ``fish_color_*`` and ``fish_pager_color_*`` variables whose value contains
|
||||
"--track=THEME". They are set to the latest version of that theme, and the tracking
|
||||
option is preserved. Note that ``fish_config theme update`` is run at fish startup.
|
||||
|
||||
The **-h** or **--help** option displays help about using this command.
|
||||
|
||||
|
||||
@@ -59,6 +59,12 @@ The following options are available:
|
||||
**-u** or **--underline**, or **-uSTYLE** or **--underline=STYLE**
|
||||
Set the underline mode; supported styles are **single** (default) and **curly**.
|
||||
|
||||
**--track=THEME**
|
||||
Ignored. Included by default in universally-scoped color variables to tell fish to update
|
||||
them as the associated theme changes.
|
||||
This flag can be set for all variables when loading a theme with the `--track`` option, that is
|
||||
:doc:`fish_config theme save THEME --track <fish_config>`.
|
||||
|
||||
**-h** or **--help**
|
||||
Displays help about using this command.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
complete fish_config -f
|
||||
set -l prompt_commands choose save show list
|
||||
set -l theme_commands choose demo dump save show list
|
||||
set -l theme_commands choose demo dump save show list update
|
||||
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'
|
||||
@@ -16,6 +16,7 @@ complete fish_config -n __fish_use_subcommand -a browse -d 'Open the web-based U
|
||||
|
||||
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 __fish_seen_subcommand_from save' -l track -d 'Add --track to color variables to apply future theme updates'
|
||||
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" \
|
||||
@@ -28,3 +29,5 @@ complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_
|
||||
-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'
|
||||
complete fish_config -n "__fish_seen_subcommand_from theme; and not __fish_seen_subcommand_from $theme_commands" \
|
||||
-a update -d "Update universal colors that have the tracking flag set"
|
||||
|
||||
@@ -8,3 +8,4 @@ complete -c set_color -s r -l reverse -d 'Reverse color text'
|
||||
complete -c set_color -s u -l underline -d 'Underline style' -a 'single curly'
|
||||
complete -c set_color -s h -l help -d 'Display help and exit'
|
||||
complete -c set_color -s c -l print-colors -d 'Print a list of all accepted color names'
|
||||
complete -c set_color -l track -xa '(fish_config theme list)' -d 'Ignored. Used in color variables to follow theme changes'
|
||||
|
||||
@@ -30,12 +30,13 @@ if status is-interactive
|
||||
# Commands to run in interactive sessions can go here
|
||||
end" >$__fish_config_dir/config.fish
|
||||
|
||||
echo yes | fish_config theme save "fish default"
|
||||
echo yes | fish_config theme save "fish default" --track
|
||||
set -Ue fish_color_keyword fish_color_option
|
||||
end
|
||||
if test $__fish_initialized -lt 3800 && test "$fish_color_search_match[1]" = bryellow
|
||||
set --universal fish_color_search_match[1] white
|
||||
end
|
||||
fish_config theme update
|
||||
|
||||
#
|
||||
# Generate man page completions if not present.
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
function fish_config --description "Launch fish's web based configuration"
|
||||
argparse h/help -- $argv
|
||||
# Variables a theme is allowed to set
|
||||
set -l theme_var_filter '^fish_(?:pager_)?color.*$'
|
||||
|
||||
function fish_config --description "Launch fish's web based configuration" \
|
||||
--inherit-variable theme_var_filter
|
||||
|
||||
set -l _flag_track
|
||||
argparse h/help track -- $argv
|
||||
or return
|
||||
|
||||
if set -q _flag_help
|
||||
@@ -10,6 +16,11 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
set -l cmd $argv[1]
|
||||
set -e argv[1]
|
||||
|
||||
if set -q _flag_track[1] && not { test "$cmd" = theme && test "$argv[1]" = save }
|
||||
echo >&2 fish_config: --track: unknown option
|
||||
return 1
|
||||
end
|
||||
|
||||
set -q cmd[1]
|
||||
or set cmd browse
|
||||
|
||||
@@ -65,9 +76,6 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
return 1
|
||||
end
|
||||
|
||||
# Variables a theme is allowed to set
|
||||
set -l theme_var_filter '^fish_(?:pager_)?color.*$'
|
||||
|
||||
switch $cmd
|
||||
case prompt
|
||||
# prompt - for prompt switching
|
||||
@@ -292,34 +300,7 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
# If we are choosing a theme or saving from a named theme, load the theme now.
|
||||
# Otherwise, we'll persist the currently loaded/themed variables (in case of `theme save`).
|
||||
if set -q argv[1]
|
||||
set -l files $dirs/$argv[1].theme
|
||||
set -l file
|
||||
|
||||
for f in $files
|
||||
if test -e "$f"
|
||||
set file $f
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not set -q file[1]
|
||||
if status list-files tools/web_config/themes/$argv[1].theme &>/dev/null
|
||||
set file tools/web_config/themes/$argv[1].theme
|
||||
else
|
||||
echo "No such theme: $argv[1]" >&2
|
||||
echo "Searched directories: $dirs" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
set -l content
|
||||
if string match -qr '^tools/' -- $file
|
||||
set content (status get-file $file)
|
||||
else
|
||||
read -z content < $file
|
||||
end
|
||||
|
||||
printf %s\n $content | while read -lat toks
|
||||
__fish_config_theme_get $argv[1] | while read -lat toks
|
||||
# The whitelist allows only color variables.
|
||||
# Not the specific list, but something named *like* a color variable.
|
||||
# This also takes care of empty lines and comment lines.
|
||||
@@ -331,7 +312,7 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
if test x"$scope" = x-U; and set -qg $toks[1]
|
||||
set -eg $toks[1]
|
||||
end
|
||||
set $scope $toks
|
||||
set $scope $toks $_flag_track=$argv[1]
|
||||
set -a have_colors $toks[1]
|
||||
end
|
||||
|
||||
@@ -343,7 +324,7 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
# Erase conflicting global variables so we don't get a warning and
|
||||
# so changes are observed immediately.
|
||||
set -eg $c
|
||||
set $scope $c
|
||||
set $scope $c $_flag_track=$argv[1]
|
||||
end
|
||||
else
|
||||
# We're persisting whatever current colors are loaded (maybe in the global scope)
|
||||
@@ -365,6 +346,8 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
# If we've made it this far, we've either found a theme file or persisted the current
|
||||
# state (if any). In all cases we haven't failed, so return 0.
|
||||
return 0
|
||||
case update
|
||||
__fish_config_theme_update $argv
|
||||
case dump
|
||||
# Write the current theme in .theme format, to stdout.
|
||||
set -L | string match -r $theme_var_filter
|
||||
@@ -374,3 +357,88 @@ function fish_config --description "Launch fish's web based configuration"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function __fish_config_theme_get
|
||||
set -l dirs $__fish_config_dir/themes $__fish_data_dir/tools/web_config/themes
|
||||
set -l files $dirs/$argv[1].theme
|
||||
set -l file
|
||||
|
||||
for f in $files
|
||||
if test -e "$f"
|
||||
set file $f
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not set -q file[1]
|
||||
if status list-files tools/web_config/themes/$argv[1].theme &>/dev/null
|
||||
set file tools/web_config/themes/$argv[1].theme
|
||||
else
|
||||
echo "No such theme: $argv[1]" >&2
|
||||
echo "Searched directories: $dirs" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
if string match -qr '^tools/' -- $file
|
||||
status get-file $file
|
||||
else
|
||||
string join \n <$file
|
||||
end
|
||||
end
|
||||
|
||||
function __fish_config_show_tracked_color_vars
|
||||
set -l color_var $argv[1]
|
||||
set -l _flag_track
|
||||
argparse --ignore-unknown track= -- _set_color $argv[2..]
|
||||
or return $status
|
||||
if not set -q _flag_track[1]
|
||||
return
|
||||
end
|
||||
if set -q _flag_track[2]
|
||||
echo >&2 "fish_config: $color_var: --track option can only be specified once"
|
||||
exit 1
|
||||
end
|
||||
if test (printf %s $_flag_track | count) -ne 0
|
||||
echo >&2 "fish_config: $color_var: error: tracking theme name must not contain newlines"
|
||||
exit 1
|
||||
end
|
||||
printf %s\n $color_var $_flag_track
|
||||
end
|
||||
|
||||
function __fish_config_theme_update --inherit-variable theme_var_filter
|
||||
if set -q argv[1]
|
||||
echo "fish_config: too many arguments" >&2
|
||||
return 1
|
||||
end
|
||||
set -l themes
|
||||
|
||||
set -l tracking_variables (
|
||||
set --universal --long |
|
||||
string match -r '^fish_(?:pager_)?color.*$' |
|
||||
string replace -r '.*' '__fish_config_show_tracked_color_vars $0' |
|
||||
source
|
||||
)
|
||||
or return $status
|
||||
string join \n $tracking_variables |
|
||||
while read --line _colorvar theme
|
||||
if not contains -- $theme $themes
|
||||
set -a themes $theme
|
||||
end
|
||||
end
|
||||
|
||||
for theme in $themes
|
||||
set -l colorvars
|
||||
string join \n $tracking_variables |
|
||||
while read --line color_var t
|
||||
if test $t = $theme
|
||||
set -a colorvars $color_var
|
||||
end
|
||||
end
|
||||
set -l theme_escaped (string escape -- $theme)
|
||||
__fish_config_theme_get $theme |
|
||||
string match -r -- "^(?:$(string join '|' $colorvars))\b .*" |
|
||||
string replace -r '.*' "set -U \$0 --track=$theme_escaped" |
|
||||
source
|
||||
end
|
||||
end
|
||||
|
||||
@@ -86,6 +86,13 @@ pub fn set_color(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -
|
||||
// In future we change both to actually print an error.
|
||||
return Err(STATUS_INVALID_ARGS);
|
||||
}
|
||||
Err(MultipleTracking) => {
|
||||
streams.err.append(wgettext_fmt!(
|
||||
"%ls: --track option can only be specified once\n",
|
||||
argv[0]
|
||||
));
|
||||
return Err(STATUS_INVALID_ARGS);
|
||||
}
|
||||
Err(UnknownColor(arg)) => {
|
||||
streams
|
||||
.err
|
||||
@@ -124,7 +131,7 @@ pub fn set_color(parser: &Parser, streams: &mut IoStreams, argv: &mut [&wstr]) -
|
||||
specified_face.fg.unwrap_or(Color::None),
|
||||
specified_face.bg.unwrap_or(Color::None),
|
||||
specified_face.underline_color.unwrap_or(Color::None),
|
||||
specified_face.style,
|
||||
specified_face.style.unwrap_or_default(),
|
||||
));
|
||||
|
||||
if specified_face.fg.is_some() && outp.contents().is_empty() {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
};
|
||||
use crate::path::{path_as_implicit_cd, path_get_cdpath, path_get_path, paths_are_same_file};
|
||||
use crate::terminal::Outputter;
|
||||
use crate::text_face::{parse_text_face, TextFace, UnderlineStyle};
|
||||
use crate::text_face::{parse_text_face, SpecifiedTextFace, TextFace, UnderlineStyle};
|
||||
use crate::threads::assert_is_background_thread;
|
||||
use crate::tokenizer::{variable_assignment_equals_pos, PipeOrRedir};
|
||||
use crate::wchar::{wstr, WString, L};
|
||||
@@ -140,12 +140,16 @@ pub(crate) fn resolve_spec_uncached(
|
||||
vars: &dyn Environment,
|
||||
) -> TextFace {
|
||||
let resolve_role = |role| {
|
||||
vars.get_unless_empty(get_highlight_var_name(role))
|
||||
.or_else(|| vars.get_unless_empty(get_highlight_var_name(get_fallback(role))))
|
||||
.or_else(|| vars.get_unless_empty(get_highlight_var_name(HighlightRole::normal)))
|
||||
.as_ref()
|
||||
.map(parse_text_face_for_highlight)
|
||||
.unwrap_or_else(TextFace::default)
|
||||
for role in [role, get_fallback(role), HighlightRole::normal] {
|
||||
if let Some(face) = vars
|
||||
.get_unless_empty(get_highlight_var_name(role))
|
||||
.as_ref()
|
||||
.and_then(parse_text_face_for_highlight)
|
||||
{
|
||||
return face;
|
||||
}
|
||||
}
|
||||
TextFace::default()
|
||||
};
|
||||
let mut face = resolve_role(highlight.foreground);
|
||||
|
||||
@@ -162,7 +166,8 @@ pub(crate) fn resolve_spec_uncached(
|
||||
if highlight.valid_path {
|
||||
if let Some(valid_path_var) = vars.get(L!("fish_color_valid_path")) {
|
||||
// Historical behavior is to not apply background.
|
||||
let valid_path_face = parse_text_face_for_highlight(&valid_path_var);
|
||||
let valid_path_face =
|
||||
parse_text_face_for_highlight(&valid_path_var).unwrap_or_default();
|
||||
// Apply the foreground, except if it's normal. The intention here is likely
|
||||
// to only override foreground if the valid path color has an explicit foreground.
|
||||
if !valid_path_face.fg.is_normal() {
|
||||
@@ -181,19 +186,21 @@ pub(crate) fn resolve_spec_uncached(
|
||||
}
|
||||
|
||||
/// Return the internal color code representing the specified color.
|
||||
pub(crate) fn parse_text_face_for_highlight(var: &EnvVar) -> TextFace {
|
||||
pub(crate) fn parse_text_face_for_highlight(var: &EnvVar) -> Option<TextFace> {
|
||||
let face = parse_text_face(var.as_list());
|
||||
let default = TextFace::default();
|
||||
let fg = face.fg.unwrap_or(default.fg);
|
||||
let bg = face.bg.unwrap_or(default.bg);
|
||||
let underline_color = face.underline_color.unwrap_or(default.underline_color);
|
||||
let style = face.style;
|
||||
TextFace {
|
||||
fg,
|
||||
bg,
|
||||
underline_color,
|
||||
style,
|
||||
}
|
||||
(face != SpecifiedTextFace::default()).then(|| {
|
||||
let default = TextFace::default();
|
||||
let fg = face.fg.unwrap_or(default.fg);
|
||||
let bg = face.bg.unwrap_or(default.bg);
|
||||
let underline_color = face.underline_color.unwrap_or(default.underline_color);
|
||||
let style = face.style.unwrap_or_default();
|
||||
TextFace {
|
||||
fg,
|
||||
bg,
|
||||
underline_color,
|
||||
style,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn command_is_valid(
|
||||
|
||||
@@ -2688,7 +2688,9 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) {
|
||||
|
||||
let mut outp = Outputter::stdoutput().borrow_mut();
|
||||
if let Some(fish_color_cancel) = self.vars().get(L!("fish_color_cancel")) {
|
||||
outp.set_text_face(parse_text_face_for_highlight(&fish_color_cancel));
|
||||
outp.set_text_face(
|
||||
parse_text_face_for_highlight(&fish_color_cancel).unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
outp.write_wstr(L!("^C"));
|
||||
outp.reset_text_face();
|
||||
|
||||
@@ -111,6 +111,12 @@ pub(crate) struct TextFace {
|
||||
pub(crate) style: TextStyling,
|
||||
}
|
||||
|
||||
impl Default for TextFace {
|
||||
fn default() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl TextFace {
|
||||
pub const fn default() -> Self {
|
||||
Self {
|
||||
@@ -131,12 +137,12 @@ pub fn new(fg: Color, bg: Color, underline_color: Color, style: TextStyling) ->
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Eq, PartialEq)]
|
||||
pub(crate) struct SpecifiedTextFace {
|
||||
pub(crate) fg: Option<Color>,
|
||||
pub(crate) bg: Option<Color>,
|
||||
pub(crate) underline_color: Option<Color>,
|
||||
pub(crate) style: TextStyling,
|
||||
pub(crate) style: Option<TextStyling>,
|
||||
}
|
||||
|
||||
pub(crate) fn parse_text_face(arguments: &[WString]) -> SpecifiedTextFace {
|
||||
@@ -167,6 +173,7 @@ pub(crate) enum ParsedArgs<'argarray, 'args> {
|
||||
|
||||
pub(crate) enum ParseError<'args> {
|
||||
MissingOptArg,
|
||||
MultipleTracking,
|
||||
UnknownColor(&'args wstr),
|
||||
UnknownUnderlineStyle(&'args wstr),
|
||||
UnknownOption(usize),
|
||||
@@ -189,6 +196,7 @@ pub(crate) fn parse_text_face_and_options<'argarray, 'args>(
|
||||
wopt(L!("reverse"), ArgType::NoArgument, 'r'),
|
||||
wopt(L!("help"), ArgType::NoArgument, 'h'),
|
||||
wopt(L!("print-colors"), ArgType::NoArgument, 'c'),
|
||||
wopt(L!("track"), ArgType::RequiredArgument, '\x01'),
|
||||
];
|
||||
let long_options = &long_options[..long_options.len() - builtin_extra_args];
|
||||
|
||||
@@ -210,6 +218,7 @@ pub(crate) fn parse_text_face_and_options<'argarray, 'args>(
|
||||
let mut underline_colors = vec![];
|
||||
let mut style = TextStyling::default();
|
||||
let mut print_color_mode = false;
|
||||
let mut tracking = false;
|
||||
|
||||
let mut w = WGetopter::new(short_options, long_options, argv);
|
||||
while let Some(c) = w.next_opt() {
|
||||
@@ -219,6 +228,12 @@ pub(crate) fn parse_text_face_and_options<'argarray, 'args>(
|
||||
bg_colors.push(bg);
|
||||
}
|
||||
}
|
||||
'\x01' => {
|
||||
if is_builtin && tracking {
|
||||
return Err(MultipleTracking);
|
||||
}
|
||||
tracking = true;
|
||||
}
|
||||
'\x02' => {
|
||||
if let Some(underline_color) = parse_color(w.woptarg.unwrap())? {
|
||||
underline_colors.push(underline_color);
|
||||
@@ -297,6 +312,6 @@ pub(crate) fn parse_text_face_and_options<'argarray, 'args>(
|
||||
fg,
|
||||
bg,
|
||||
underline_color,
|
||||
style,
|
||||
style: (style != TextStyling::default()).then_some(style),
|
||||
}))
|
||||
}
|
||||
|
||||
40
tests/checks/fish_config.fish
Normal file
40
tests/checks/fish_config.fish
Normal file
@@ -0,0 +1,40 @@
|
||||
#RUN: %fish %s
|
||||
|
||||
mkdir $__fish_config_dir/themes
|
||||
echo >$__fish_config_dir/themes/foo.theme 'fish_color_normal cyan'
|
||||
|
||||
set -g fish_pager_color_secondary_background custom-value
|
||||
fish_config theme choose foo
|
||||
|
||||
set -S fish_color_normal
|
||||
# CHECK: $fish_color_normal: set in global scope, unexported, with 1 elements
|
||||
# CHECK: $fish_color_normal[1]: |cyan|
|
||||
set -S fish_pager_color_secondary_background
|
||||
# CHECK: $fish_pager_color_secondary_background: set in global scope, unexported, with 0 elements
|
||||
|
||||
function change-theme
|
||||
echo >$__fish_config_dir/themes/fake-default.theme 'fish_color_command' $argv
|
||||
end
|
||||
|
||||
change-theme 'green'
|
||||
echo yes | fish_config theme save --track fake-default
|
||||
echo $fish_color_command
|
||||
# CHECK: green --track=fake-default
|
||||
|
||||
change-theme 'green --bold'
|
||||
fish_config theme update
|
||||
|
||||
echo $fish_color_command
|
||||
# CHECK: green --bold --track=fake-default
|
||||
|
||||
# Test that we silently update when there is a shadowing global.
|
||||
change-theme 'green --italics'
|
||||
set -g fish_color_command normal
|
||||
fish_config theme update
|
||||
set -S fish_color_command
|
||||
# CHECK: $fish_color_command: set in global scope, unexported, with 1 elements
|
||||
# CHECK: $fish_color_command[1]: |normal|
|
||||
# CHECK: $fish_color_command: set in universal scope, unexported, with 3 elements
|
||||
# CHECK: $fish_color_command[1]: |green|
|
||||
# CHECK: $fish_color_command[2]: |--italics|
|
||||
# CHECK: $fish_color_command[3]: |--track=fake-default|
|
||||
Reference in New Issue
Block a user