diff --git a/po/de.po b/po/de.po index 9e1f1ce66..fbad820f8 100644 --- a/po/de.po +++ b/po/de.po @@ -75,8 +75,9 @@ msgstr "" msgid "$@ is not supported. In fish, please use $argv." msgstr "" -msgid "$status is not valid as a command. See `help conditions`" -msgstr "$status ist kein gültiger Befehl. Siehe `help conditions`" +#, c-format +msgid "$status is not valid as a command. See `help %s`" +msgstr "$status ist kein gültiger Befehl. Siehe `help %s`" #, c-format msgid "%.*s: invalid conversion specification" @@ -135,7 +136,7 @@ msgid "%s and %s are mutually exclusive" msgstr "" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." msgstr "" #, c-format @@ -203,7 +204,7 @@ msgid "%s: %s: invalid mode\n" msgstr "" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" msgstr "" #, c-format @@ -215,7 +216,7 @@ msgid "%s: %s: invalid subcommand\n" msgstr "%s: %s: ungültiger Unterbefehl\n" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" msgstr "" #, c-format @@ -1290,7 +1291,7 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "Kein TTY für interaktive Shell (tcgetpgrp schlug fehl)" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." +msgid "No matches for wildcard '%s'. See `help %s`." msgstr "" msgid "Not a function" diff --git a/po/en.po b/po/en.po index 85486890c..7a1f9e32e 100644 --- a/po/en.po +++ b/po/en.po @@ -73,7 +73,8 @@ msgstr "" msgid "$@ is not supported. In fish, please use $argv." msgstr "" -msgid "$status is not valid as a command. See `help conditions`" +#, c-format +msgid "$status is not valid as a command. See `help %s`" msgstr "" #, c-format @@ -133,7 +134,7 @@ msgid "%s and %s are mutually exclusive" msgstr "" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." msgstr "" #, c-format @@ -201,7 +202,7 @@ msgid "%s: %s: invalid mode\n" msgstr "" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" msgstr "" #, c-format @@ -213,7 +214,7 @@ msgid "%s: %s: invalid subcommand\n" msgstr "" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" msgstr "" #, c-format @@ -1288,7 +1289,7 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "No TTY for interactive shell (tcgetpgrp failed)" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." +msgid "No matches for wildcard '%s'. See `help %s`." msgstr "" msgid "Not a function" diff --git a/po/fr.po b/po/fr.po index 20e44552f..1e6a0edf1 100644 --- a/po/fr.po +++ b/po/fr.po @@ -204,8 +204,9 @@ msgstr "$? n’est pas le code de retour. Dans fish, veuillez utiliser $status." msgid "$@ is not supported. In fish, please use $argv." msgstr "$@ n’est pas supporté. Dans fish, veuillez utiliser $argv." -msgid "$status is not valid as a command. See `help conditions`" -msgstr "$status n’est pas une commande valide. Voir « help conditions »" +#, fuzzy, c-format +msgid "$status is not valid as a command. See `help %s`" +msgstr "$status n’est pas une commande valide. Voir « help %s »" #, c-format msgid "%.*s: invalid conversion specification" @@ -264,8 +265,8 @@ msgid "%s and %s are mutually exclusive" msgstr "" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." -msgstr "%s n’a pas pu lire de réponse à une requête « Primary Device Attribute » après avoir attendu %d secondes. Ceci est souvent dû à une fonctionnalité manquante de votre terminal. Voir « help terminal-compatibility » ou « man fish-terminal-compatibility ». Le processus %s va désormais ignorer les requêtes en attente, ce qui désactive quelques fonctionnalités optionnelles." +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgstr "%s n’a pas pu lire de réponse à une requête « Primary Device Attribute » après avoir attendu %d secondes. Ceci est souvent dû à une fonctionnalité manquante de votre terminal. Voir « help %s » ou « man fish-terminal-compatibility ». Le processus %s va désormais ignorer les requêtes en attente, ce qui désactive quelques fonctionnalités optionnelles." #, c-format msgid "%s is %s\n" @@ -332,8 +333,8 @@ msgid "%s: %s: invalid mode\n" msgstr "%s : %s : mode invalide\n" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" -msgstr "%s : %s : nom de mode invalide. Voir « help identifiers »\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" +msgstr "%s : %s : nom de mode invalide. Voir « help %s »\n" #, c-format msgid "%s: %s: invalid scale\n" @@ -344,8 +345,8 @@ msgid "%s: %s: invalid subcommand\n" msgstr "%s : %s : sous-commande invalide\n" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" -msgstr "%s : %s : nom de variable invalide. Voir « help identifiers »\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" +msgstr "%s : %s : nom de variable invalide. Voir « help %s »\n" #, c-format msgid "%s: %s: option does not take an argument\n" @@ -1419,7 +1420,7 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "Pas de TTY pour shell interactif (tcgetpgrp a échoué)" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." +msgid "No matches for wildcard '%s'. See `help %s`." msgstr "" msgid "Not a function" diff --git a/po/pl.po b/po/pl.po index 7ed31785f..2e218af75 100644 --- a/po/pl.po +++ b/po/pl.po @@ -69,7 +69,8 @@ msgstr "" msgid "$@ is not supported. In fish, please use $argv." msgstr "$@ nie jest obsługiwane. W fish używane jest $argv." -msgid "$status is not valid as a command. See `help conditions`" +#, c-format +msgid "$status is not valid as a command. See `help %s`" msgstr "" #, c-format @@ -129,7 +130,7 @@ msgid "%s and %s are mutually exclusive" msgstr "" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." msgstr "" #, c-format @@ -197,7 +198,7 @@ msgid "%s: %s: invalid mode\n" msgstr "" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" msgstr "" #, c-format @@ -209,7 +210,7 @@ msgid "%s: %s: invalid subcommand\n" msgstr "" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" msgstr "" #, c-format @@ -1284,7 +1285,7 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." +msgid "No matches for wildcard '%s'. See `help %s`." msgstr "" msgid "Not a function" diff --git a/po/pt_BR.po b/po/pt_BR.po index b558aa947..22c74b2f3 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -74,7 +74,8 @@ msgstr "" msgid "$@ is not supported. In fish, please use $argv." msgstr "" -msgid "$status is not valid as a command. See `help conditions`" +#, c-format +msgid "$status is not valid as a command. See `help %s`" msgstr "" #, c-format @@ -134,7 +135,7 @@ msgid "%s and %s are mutually exclusive" msgstr "" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." msgstr "" #, c-format @@ -202,7 +203,7 @@ msgid "%s: %s: invalid mode\n" msgstr "" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" msgstr "" #, c-format @@ -214,7 +215,7 @@ msgid "%s: %s: invalid subcommand\n" msgstr "" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" msgstr "" #, c-format @@ -1289,7 +1290,7 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "Não há TTY para shell interativo (falha em tcgetpgrp)" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." +msgid "No matches for wildcard '%s'. See `help %s`." msgstr "" msgid "Not a function" diff --git a/po/sv.po b/po/sv.po index 79ac08c8c..483b0ac35 100644 --- a/po/sv.po +++ b/po/sv.po @@ -70,7 +70,8 @@ msgstr "" msgid "$@ is not supported. In fish, please use $argv." msgstr "" -msgid "$status is not valid as a command. See `help conditions`" +#, c-format +msgid "$status is not valid as a command. See `help %s`" msgstr "" #, c-format @@ -130,7 +131,7 @@ msgid "%s and %s are mutually exclusive" msgstr "" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." msgstr "" #, c-format @@ -198,7 +199,7 @@ msgid "%s: %s: invalid mode\n" msgstr "" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" msgstr "" #, c-format @@ -210,7 +211,7 @@ msgid "%s: %s: invalid subcommand\n" msgstr "" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" msgstr "" #, c-format @@ -1285,7 +1286,7 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." +msgid "No matches for wildcard '%s'. See `help %s`." msgstr "" msgid "Not a function" diff --git a/po/zh_CN.po b/po/zh_CN.po index 89a3f8cc1..704efe922 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -96,8 +96,9 @@ msgstr "$? 不是退出代码。在 fish 中,请使用 $status。" msgid "$@ is not supported. In fish, please use $argv." msgstr "不支持 $@。在 fish 中,请使用 $argv。" -msgid "$status is not valid as a command. See `help conditions`" -msgstr "$status 不是有效的命令。参见 `help conditions`" +#, c-format +msgid "$status is not valid as a command. See `help %s`" +msgstr "$status 不是有效的命令。参见 `help %s`" #, c-format msgid "%.*s: invalid conversion specification" @@ -156,8 +157,8 @@ msgid "%s and %s are mutually exclusive" msgstr "%s 与 %s 互斥" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." -msgstr "%s 等待 %d 秒后仍无法读取 Primary Device Attribute 查询的响应。这通常是由于终端缺少相应功能所致。参见 'help terminal-compatibility' 或 'man fish-terminal-compatibility'。此 %s 进程将不再等待未处理的查询,这将禁用某些可选功能。" +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgstr "%s 等待 %d 秒后仍无法读取 Primary Device Attribute 查询的响应。这通常是由于终端缺少相应功能所致。参见 'help %s' 或 'man fish-terminal-compatibility'。此 %s 进程将不再等待未处理的查询,这将禁用某些可选功能。" #, c-format msgid "%s is %s\n" @@ -224,8 +225,8 @@ msgid "%s: %s: invalid mode\n" msgstr "%s: %s: 无效舍入模式\n" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" -msgstr "%s: %s: 无效模式名。参见 `help identifiers`\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" +msgstr "%s: %s: 无效模式名。参见 `help %s`\n" #, c-format msgid "%s: %s: invalid scale\n" @@ -236,8 +237,8 @@ msgid "%s: %s: invalid subcommand\n" msgstr "%s: %s: 无效的子命令\n" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" -msgstr "%s: %s: 无效的变量名。参见 `help identifiers`\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" +msgstr "%s: %s: 无效的变量名。参见 `help %s`\n" #, c-format msgid "%s: %s: option does not take an argument\n" @@ -1314,8 +1315,8 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "交互 shell 没有 TTY (tcgetpgrp 失败)" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." -msgstr "未找到通配符 '%s' 的匹配项。参见 `help wildcards-globbing`。" +msgid "No matches for wildcard '%s'. See `help %s`." +msgstr "未找到通配符 '%s' 的匹配项。参见 `help %s`。" msgid "Not a function" msgstr "不是一个函数" diff --git a/po/zh_TW.po b/po/zh_TW.po index dc6f80b16..d1716e4b9 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -69,8 +69,9 @@ msgstr "$? 不是結束代碼。在 fish 中請使用 $status。" msgid "$@ is not supported. In fish, please use $argv." msgstr "不支援 $@。在 fish 中請使用 $argv。" -msgid "$status is not valid as a command. See `help conditions`" -msgstr "$status 不是有效的命令。參見「help conditions」" +#, c-format +msgid "$status is not valid as a command. See `help %s`" +msgstr "$status 不是有效的命令。參見「help %s」" #, c-format msgid "%.*s: invalid conversion specification" @@ -129,8 +130,8 @@ msgid "%s and %s are mutually exclusive" msgstr "%s 和 %s 不能同時使用" #, c-format -msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." -msgstr "%s 在過了 %d 秒後仍無法讀取到查詢主要裝置特性的回應。這通常是由於你的終端機缺少功能,參見「help terminal-compatibility」或「man fish-terminal-compatibility」。此 %s 行程不再會等待未決的查詢,一些非必要的功能將因此停用。" +msgid "%s could not read response to Primary Device Attribute query after waiting for %d seconds. This is often due to a missing feature in your terminal. See 'help %s' or 'man fish-terminal-compatibility'. This %s process will no longer wait for outstanding queries, which disables some optional features." +msgstr "%s 在過了 %d 秒後仍無法讀取到查詢主要裝置特性的回應。這通常是由於你的終端機缺少功能,參見「help %s」或「man fish-terminal-compatibility」。此 %s 行程不再會等待未決的查詢,一些非必要的功能將因此停用。" #, c-format msgid "%s is %s\n" @@ -197,8 +198,8 @@ msgid "%s: %s: invalid mode\n" msgstr "%s:%s:無效的模式\n" #, c-format -msgid "%s: %s: invalid mode name. See `help identifiers`\n" -msgstr "%s:%s:無效的模式名稱。參見「help identifiers」\n" +msgid "%s: %s: invalid mode name. See `help %s`\n" +msgstr "%s:%s:無效的模式名稱。參見「help %s」\n" #, c-format msgid "%s: %s: invalid scale\n" @@ -209,8 +210,8 @@ msgid "%s: %s: invalid subcommand\n" msgstr "%s:%s:無效的子命令\n" #, c-format -msgid "%s: %s: invalid variable name. See `help identifiers`\n" -msgstr "%s:%s:無效的變數名稱。參見「help identifiers」\n" +msgid "%s: %s: invalid variable name. See `help %s`\n" +msgstr "%s:%s:無效的變數名稱。參見「help %s」\n" #, c-format msgid "%s: %s: option does not take an argument\n" @@ -1288,8 +1289,8 @@ msgid "No TTY for interactive shell (tcgetpgrp failed)" msgstr "沒有互動式 shell 所需的 TTY(tcgetpgrp 失敗了)" #, c-format -msgid "No matches for wildcard '%s'. See `help wildcards-globbing`." -msgstr "wildcard「%s」無匹配項目。參見「help wildcards-globbing」。" +msgid "No matches for wildcard '%s'. See `help %s`." +msgstr "wildcard「%s」無匹配項目。參見「help %s」。" msgid "Not a function" msgstr "不是函式" diff --git a/src/builtins/abbr.rs b/src/builtins/abbr.rs index 0a072ca02..816a72d5f 100644 --- a/src/builtins/abbr.rs +++ b/src/builtins/abbr.rs @@ -165,7 +165,10 @@ fn abbr_show(streams: &mut IoStreams) -> BuiltinResult { add_arg(&escape_string(&abbr.replacement, style)); } if abbr.from_universal { - add_arg(L!("# imported from a universal variable, see `help abbr`")); + add_arg(&sprintf!( + "# imported from a universal variable, see `help %s`", + help_section!("cmds/abbr") + )); } result.push('\n'); streams.out.append(&result); diff --git a/src/builtins/bind.rs b/src/builtins/bind.rs index 4fc489632..ec4a10073 100644 --- a/src/builtins/bind.rs +++ b/src/builtins/bind.rs @@ -423,6 +423,19 @@ fn parse_cmd_opts( wopt(L!("user"), NoArgument, 'u'), ]; + let mut check_mode_name = |mode_name: &wstr| -> Result<(), ErrorCode> { + if !valid_var_name(mode_name) { + streams.err.append(wgettext_fmt!( + BUILTIN_ERR_BIND_MODE, + cmd, + mode_name, + help_section!("language#shell-variable-and-function-names") + )); + return Err(STATUS_INVALID_ARGS); + } + Ok(()) + }; + let mut w = WGetopter::new(short_options, long_options, argv); while let Some(c) = w.next_opt() { match c { @@ -443,25 +456,14 @@ fn parse_cmd_opts( return Ok(SUCCESS); } 'M' => { - if !valid_var_name(w.woptarg.unwrap()) { - streams.err.append(wgettext_fmt!( - BUILTIN_ERR_BIND_MODE, - cmd, - w.woptarg.unwrap() - )); - return Err(STATUS_INVALID_ARGS); - } - opts.bind_mode = w.woptarg.unwrap().to_owned(); + let applicable_mode = w.woptarg.unwrap(); + check_mode_name(applicable_mode)?; + opts.bind_mode = applicable_mode.to_owned(); opts.bind_mode_given = true; } 'm' => { let new_mode = w.woptarg.unwrap(); - if !valid_var_name(new_mode) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_BIND_MODE, cmd, new_mode)); - return Err(STATUS_INVALID_ARGS); - } + check_mode_name(new_mode)?; opts.sets_bind_mode = Some(new_mode.to_owned()); } 'p' => { diff --git a/src/builtins/function.rs b/src/builtins/function.rs index 477fcf4cb..190496812 100644 --- a/src/builtins/function.rs +++ b/src/builtins/function.rs @@ -8,6 +8,7 @@ use crate::function; use crate::global_safety::RelaxedAtomicBool; use crate::nix::getpid; +use crate::parse_execution::varname_error; use crate::parse_tree::NodeRef; use crate::parser_keywords::parser_keywords_is_reserved; use crate::proc::Pid; @@ -127,9 +128,7 @@ fn parse_cmd_opts( 'v' => { let name = w.woptarg.unwrap().to_owned(); if !valid_var_name(&name) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, name)); + streams.err.append(varname_error(cmd, &name)); return Err(STATUS_INVALID_ARGS); } opts.events.push(EventDescription::Variable { name }); @@ -197,9 +196,7 @@ fn parse_cmd_opts( 'V' => { let woptarg = w.woptarg.unwrap(); if !valid_var_name(woptarg) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, woptarg)); + streams.err.append(varname_error(cmd, woptarg)); return Err(STATUS_INVALID_ARGS); } opts.inherit_vars.push(woptarg.to_owned()); @@ -303,9 +300,7 @@ pub fn function( // Remaining arguments are named arguments. for &arg in argv[optind..].iter() { if !valid_var_name(arg) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, arg)); + streams.err.append(varname_error(cmd, arg)); return Err(STATUS_INVALID_ARGS); } opts.named_arguments.push(arg.to_owned()); @@ -338,9 +333,7 @@ pub fn function( for named in &opts.named_arguments { if !valid_var_name(named) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, named)); + streams.err.append(varname_error(cmd, named)); return Err(STATUS_INVALID_ARGS); } } diff --git a/src/builtins/read.rs b/src/builtins/read.rs index 437917e1c..e43b86c93 100644 --- a/src/builtins/read.rs +++ b/src/builtins/read.rs @@ -15,6 +15,7 @@ use crate::input_common::InvalidPolicy; use crate::input_common::decode_one_codepoint_utf8; use crate::nix::isatty; +use crate::parse_execution::varname_error; use crate::reader::ReaderConfig; use crate::reader::commandline_set_buffer; use crate::reader::reader_save_screen_state; @@ -559,9 +560,7 @@ fn tokenize_flag(token_mode: TokenOutputMode) -> &'static wstr { // Verify all variable names. for arg in argv { if !valid_var_name(arg) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, arg)); + streams.err.append(varname_error(cmd, arg)); builtin_print_error_trailer(parser, streams.err, cmd); return Err(STATUS_INVALID_ARGS); } diff --git a/src/builtins/set.rs b/src/builtins/set.rs index 8adb1cd38..6c86cad59 100644 --- a/src/builtins/set.rs +++ b/src/builtins/set.rs @@ -15,6 +15,7 @@ use crate::expand::expand_escape_variable; use crate::history::History; use crate::history::history_session_id; +use crate::parse_execution::varname_error; use crate::{ env::{EnvMode, EnvVar, Environment}, wutil::wcstoi::wcstoi_partial, @@ -183,8 +184,9 @@ fn parse( // implicit drop(w); here if args[optind - 1].starts_with("-o") { // TODO: translate this - streams.err.appendln(L!( - "Fish does not have shell options. See `help fish-for-bash-users`." + streams.err.appendln(sprintf!( + "Fish does not have shell options. See `help %s`.", + help_section!("fish_for_bash_users") )); if optind < args.len() { if args[optind] == "vi" { @@ -730,9 +732,7 @@ fn show(cmd: &wstr, parser: &Parser, streams: &mut IoStreams, args: &[&wstr]) -> } else { for arg in args.iter().copied() { if !valid_var_name(arg) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, arg)); + streams.err.append(varname_error(cmd, arg)); builtin_print_error_trailer(parser, streams.err, cmd); return Err(STATUS_INVALID_ARGS); } @@ -788,9 +788,7 @@ fn erase( }; if !valid_var_name(split.varname) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, split.varname)); + streams.err.append(varname_error(cmd, split.varname)); builtin_print_error_trailer(parser, streams.err, cmd); return Err(STATUS_INVALID_ARGS); } @@ -927,9 +925,7 @@ fn set_internal( // Is the variable valid? if !valid_var_name(split.varname) { - streams - .err - .append(wgettext_fmt!(BUILTIN_ERR_VARNAME, cmd, split.varname)); + streams.err.append(varname_error(cmd, split.varname)); if let Some(pos) = split.varname.chars().position(|c| c == '=') { streams.err.append(wgettext_fmt!( "%s: Did you mean `set %s %s`?", diff --git a/src/builtins/shared.rs b/src/builtins/shared.rs index 679332beb..86205b03d 100644 --- a/src/builtins/shared.rs +++ b/src/builtins/shared.rs @@ -50,7 +50,7 @@ /// Error message for invalid bind mode name. pub BUILTIN_ERR_BIND_MODE - "%s: %s: invalid mode name. See `help identifiers`\n" + "%s: %s: invalid mode name. See `help %s`\n" /// Error message when too many arguments are supplied to a builtin. pub BUILTIN_ERR_TOO_MANY_ARGUMENTS @@ -85,7 +85,7 @@ /// Error message for invalid variable name. pub BUILTIN_ERR_VARNAME - "%s: %s: invalid variable name. See `help identifiers`\n" + "%s: %s: invalid variable name. See `help %s`\n" /// Error message on invalid combination of options. pub BUILTIN_ERR_COMBO diff --git a/src/common.rs b/src/common.rs index e2a5d7f68..937bbff13 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1326,6 +1326,42 @@ macro_rules! write_to_output { }}; } +pub const fn help_section_exists(section: &str) -> bool { + let haystack = include_str!("../share/help_sections"); + let needle = section; + + let needle = needle.as_bytes(); + let haystack = haystack.as_bytes(); + let nlen = needle.len(); + let mut line_start = 0; + let mut i = 0; + while i <= haystack.len() { + if i == haystack.len() || haystack[i] == b'\n' { + let line_len = i - line_start; + + if line_len == nlen { + let mut j = 0; + while j < nlen && haystack[line_start + j] == needle[j] { + j += 1; + } + if j == nlen { + return true; + } + } + line_start = i + 1; + } + i += 1; + } + false +} + +macro_rules! help_section { + ($section:expr) => {{ + const _: () = assert!(crate::common::help_section_exists($section)); + $section + }}; +} + /// Write the given paragraph of output, redoing linebreaks to fit `termsize`. pub fn reformat_for_screen(msg: &wstr, termsize: &Termsize) -> WString { let mut buff = WString::new(); diff --git a/src/parse_constants.rs b/src/parse_constants.rs index ed50a20a1..5797a3abb 100644 --- a/src/parse_constants.rs +++ b/src/parse_constants.rs @@ -469,7 +469,7 @@ pub fn parse_error_offset_source_start(errors: &mut ParseErrorList, amt: usize) /// Error message for wildcards with no matches. pub WILDCARD_ERR_MSG - "No matches for wildcard '%s'. See `help wildcards-globbing`." + "No matches for wildcard '%s'. See `help %s`." /// Error when using break outside of loop. pub INVALID_BREAK_ERR_MSG diff --git a/src/parse_execution.rs b/src/parse_execution.rs index c1850d102..578db3bb2 100644 --- a/src/parse_execution.rs +++ b/src/parse_execution.rs @@ -28,7 +28,7 @@ CALL_STACK_LIMIT_EXCEEDED_ERR_MSG, ERROR_TIME_BACKGROUND, FAILED_EXPANSION_VARIABLE_NAME_ERR_MSG, ILLEGAL_FD_ERR_MSG, INFINITE_FUNC_RECURSION_ERR_MSG, ParseError, ParseErrorCode, ParseErrorList, ParseKeyword, ParseTokenType, StatementDecoration, - WILDCARD_ERR_MSG, parse_error_offset_source_start, + parse_error_offset_source_start, }; use crate::parse_tree::{LineCounter, NodeRef, ParsedSourceRef}; use crate::parse_util::{ @@ -114,6 +114,15 @@ macro_rules! report_error_formatted { }}; } +pub fn varname_error(command: &wstr, bad_name: &wstr) -> WString { + wgettext_fmt!( + BUILTIN_ERR_VARNAME, + command, + bad_name, + help_section!("language#shell-variable-and-function-names") + ) +} + impl<'a> ExecutionContext<'a> { /// Construct a context in preparation for evaluating a node in a tree, with the given block_io. /// The execution context may access the parser and parent job group (if any) through ctx. @@ -449,6 +458,22 @@ fn infinite_recursive_statement_in_job_list<'b>( infinite_recursive_statement } + fn report_wildcard_error( + &self, + ctx: &OperationContext<'_>, + node: &dyn ast::Node, + ) -> EndExecutionReason { + report_error!( + self, + ctx, + STATUS_UNMATCHED_WILDCARD, + node, + crate::parse_constants::WILDCARD_ERR_MSG, + self.node_source(node), + help_section!("language#wildcards-globbing") + ) + } + // Expand a command which may contain variables, producing an expand command and possibly // arguments. Prints an error message on error. fn expand_command( @@ -486,14 +511,7 @@ fn expand_command( return self.report_errors(ctx, STATUS_ILLEGAL_CMD, &errors); } ExpandResultCode::wildcard_no_match => { - return report_error!( - self, - ctx, - STATUS_UNMATCHED_WILDCARD, - statement, - WILDCARD_ERR_MSG, - self.node_source(statement) - ); + return self.report_wildcard_error(ctx, statement); } ExpandResultCode::cancel => { return EndExecutionReason::cancelled; @@ -882,9 +900,8 @@ fn run_for_statement( ctx, STATUS_INVALID_ARGS, header.var_name, - BUILTIN_ERR_VARNAME, - "for", - for_var_name + "%s", + varname_error(L!("for"), &for_var_name) ); } @@ -1078,14 +1095,7 @@ fn run_switch_statement( return EndExecutionReason::cancelled; } ExpandResultCode::wildcard_no_match => { - return report_error!( - self, - ctx, - STATUS_UNMATCHED_WILDCARD, - &statement.argument, - WILDCARD_ERR_MSG, - self.node_source(&statement.argument) - ); + return self.report_wildcard_error(ctx, &statement.argument); } ExpandResultCode::ok => { if switch_values_expanded.len() > 1 { @@ -1337,7 +1347,7 @@ fn expand_arguments_from_nodes( // Get all argument nodes underneath the statement. We guess we'll have that many arguments (but // may have more or fewer, if there are wildcards involved). out_arguments.reserve(argument_nodes.len()); - for arg_node in argument_nodes { + for &arg_node in argument_nodes { // Expect all arguments to have source. assert!(arg_node.has_source(), "Argument should have source"); @@ -1345,7 +1355,7 @@ fn expand_arguments_from_nodes( let mut errors = ParseErrorList::new(); let mut arg_expanded = CompletionList::new(); let expand_ret = expand_string( - self.node_source_owned(*arg_node), + self.node_source_owned(arg_node), &mut arg_expanded, ExpandFlags::default(), ctx, @@ -1366,14 +1376,7 @@ fn expand_arguments_from_nodes( return EndExecutionReason::ok; } // Report the unmatched wildcard error and stop processing. - return report_error!( - self, - ctx, - STATUS_UNMATCHED_WILDCARD, - arg_node, - WILDCARD_ERR_MSG, - self.node_source(*arg_node) - ); + return self.report_wildcard_error(ctx, arg_node); } } ExpandResultCode::ok => {} @@ -1465,7 +1468,8 @@ fn determine_redirections( } } { eprintf!( - "If you wish to use process substitution, consider the psub command, see: `help psub`\n" + "If you wish to use process substitution, consider the psub command, see: `help %s`\n", + help_section!("cmds/psub") ); } return error_ret; diff --git a/src/parse_util.rs b/src/parse_util.rs index 015b4cdb6..118fe9def 100644 --- a/src/parse_util.rs +++ b/src/parse_util.rs @@ -1711,7 +1711,8 @@ fn detect_errors_in_decorated_statement( parse_errors, source_start, source_length, - "$status is not valid as a command. See `help conditions`" + "$status is not valid as a command. See `help %s`", + help_section!("language#conditions") ); } diff --git a/src/reader/reader.rs b/src/reader/reader.rs index 02ec7c7c8..2713ff408 100644 --- a/src/reader/reader.rs +++ b/src/reader/reader.rs @@ -293,11 +293,12 @@ pub fn terminal_init(vars: &dyn Environment, inputfd: RawFd) -> InputEventQueue wgettext_fmt!( "%s could not read response to Primary Device Attribute query after waiting for %d seconds. \ This is often due to a missing feature in your terminal. \ - See 'help terminal-compatibility' or 'man fish-terminal-compatibility'. \ + See 'help %s' or 'man fish-terminal-compatibility'. \ This %s process will no longer wait for outstanding queries, \ which disables some optional features.", program, LONG_READ_TIMEOUT.as_secs(), + help_section!("terminal-compatibility"), program ), ); diff --git a/tests/checks/abbr.fish b/tests/checks/abbr.fish index ababb75c4..abedb2ce1 100644 --- a/tests/checks/abbr.fish +++ b/tests/checks/abbr.fish @@ -4,7 +4,7 @@ set -U _fish_abbr_cuckoo somevalue set fish (status fish-path) $fish -c abbr -# CHECK: abbr -a -- cuckoo somevalue # imported from a universal variable, see `help abbr` +# CHECK: abbr -a -- cuckoo somevalue # imported from a universal variable, see `help cmds/abbr` # Test basic add and list of __abbr1 abbr __abbr1 alpha beta gamma diff --git a/tests/checks/bind.fish b/tests/checks/bind.fish index 5d199eb5f..b889abcfc 100644 --- a/tests/checks/bind.fish +++ b/tests/checks/bind.fish @@ -24,11 +24,11 @@ echo >&2 bind output evaluation works # Verify that an invalid bind mode is rejected. bind -m 'bad bind mode' \cX true -# CHECKERR: bind: bad bind mode: invalid mode name. See `help identifiers` +# CHECKERR: bind: bad bind mode: invalid mode name. See `help language#shell-variable-and-function-names` # Verify that an invalid bind mode target is rejected. bind -M bind-mode \cX true -# CHECKERR: bind: bind-mode: invalid mode name. See `help identifiers` +# CHECKERR: bind: bind-mode: invalid mode name. See `help language#shell-variable-and-function-names` # This should succeed and result in a success, zero, status. bind -M bind_mode \cX true diff --git a/tests/checks/function.fish b/tests/checks/function.fish index 3e962e34f..640888740 100644 --- a/tests/checks/function.fish +++ b/tests/checks/function.fish @@ -152,7 +152,7 @@ function foo -p bar; end # CHECKERR: ^~~~~~~~~~~~~~~~~~~^ function foo --argument-names "banana pajama"; end -# CHECKERR: {{.*}}function.fish (line {{\d+}}): function: banana pajama: invalid variable name. See `help identifiers` +# CHECKERR: {{.*}}function.fish (line {{\d+}}): function: banana pajama: invalid variable name. See `help language#shell-variable-and-function-names` # CHECKERR: function foo --argument-names "banana pajama"; end # CHECKERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ diff --git a/tests/checks/psub.fish b/tests/checks/psub.fish index 4d93c2822..3ab68be42 100644 --- a/tests/checks/psub.fish +++ b/tests/checks/psub.fish @@ -77,7 +77,7 @@ echo <(seq 0) # CHECKERR: {{.*}}/psub.fish (line {{\d+}}): Invalid redirection target: # CHECKERR: echo <(seq 0) # CHECKERR: ^~~~~~~^ -# CHECKERR: If you wish to use process substitution, consider the psub command, see: `help psub` +# CHECKERR: If you wish to use process substitution, consider the psub command, see: `help cmds/psub` # To-do: should also mention psub here. echo <(seq 1) @@ -88,4 +88,4 @@ echo <(seq 2) # CHECKERR: {{.*}}/psub.fish (line {{\d+}}): Invalid redirection target: # CHECKERR: echo <(seq 2) # CHECKERR: ^~~~~~~^ -# CHECKERR: If you wish to use process substitution, consider the psub command, see: `help psub` +# CHECKERR: If you wish to use process substitution, consider the psub command, see: `help cmds/psub` diff --git a/tests/checks/set.fish b/tests/checks/set.fish index 277a3cf7e..018a2225c 100644 --- a/tests/checks/set.fish +++ b/tests/checks/set.fish @@ -472,7 +472,7 @@ env | grep __fish_empty_uvar for a,b in y 1 z 3 echo $a,$b end -# CHECKERR: {{.*}} for: a,b: invalid variable name. See `help identifiers` +# CHECKERR: {{.*}} for: a,b: invalid variable name. See `help language#shell-variable-and-function-names` # CHECKERR: for a,b in y 1 z 3 # CHECKERR: ^~^ @@ -531,7 +531,7 @@ sh -c 'EDITOR=vim "$@" -c "set -S EDITOR"' uselessargument $FISH | string match # Verify behavior of `set --show` given an invalid var name set --show 'argle bargle' -#CHECKERR: set: argle bargle: invalid variable name. See `help identifiers` +#CHECKERR: set: argle bargle: invalid variable name. See `help language#shell-variable-and-function-names` #CHECKERR: {{.*}}set.fish (line {{\d+}}): #CHECKERR: set --show 'argle bargle' #CHECKERR: ^ @@ -757,21 +757,21 @@ echo $status true set "" foo -#CHECKERR: set: : invalid variable name. See `help identifiers` +#CHECKERR: set: : invalid variable name. See `help language#shell-variable-and-function-names` #CHECKERR: {{.*}}set.fish (line {{\d+}}): #CHECKERR: set "" foo #CHECKERR: ^ #CHECKERR: (Type 'help set' for related documentation) set --show "" -#CHECKERR: set: : invalid variable name. See `help identifiers` +#CHECKERR: set: : invalid variable name. See `help language#shell-variable-and-function-names` #CHECKERR: {{.*}}set.fish (line {{\d+}}): #CHECKERR: set --show "" #CHECKERR: ^ #CHECKERR: (Type 'help set' for related documentation) set foo="ba nana" -#CHECKERR: set: foo=ba nana: invalid variable name. See `help identifiers` +#CHECKERR: set: foo=ba nana: invalid variable name. See `help language#shell-variable-and-function-names` #CHECKERR: set: Did you mean `set foo 'ba nana'`? #CHECKERR: {{.*}}set.fish (line {{\d+}}): #CHECKERR: set foo="ba nana" diff --git a/tests/checks/switch.fish b/tests/checks/switch.fish index ed5feb38e..c7dea7fc5 100644 --- a/tests/checks/switch.fish +++ b/tests/checks/switch.fish @@ -88,7 +88,7 @@ switch $smurf case "*" echo Test 2 fail end -#CHECKERR: {{.*}}switch.fish (line {{\d+}}): No matches for wildcard '*ee*'. See `help wildcards-globbing`. +#CHECKERR: {{.*}}switch.fish (line {{\d+}}): No matches for wildcard '*ee*'. See `help language#wildcards-globbing`. #CHECKERR: case *ee* #CHECKERR: ^~~^ #CHECK: Test 2 pass diff --git a/tests/checks/syntax-error-location.fish b/tests/checks/syntax-error-location.fish index 371642b8f..5081b43b4 100644 --- a/tests/checks/syntax-error-location.fish +++ b/tests/checks/syntax-error-location.fish @@ -131,7 +131,7 @@ $fish -c 'echo (set -l foo 1 2 3; for $foo in foo; end)' # CHECKERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ $fish -c 'echo (echo *nosuchname*)' -# CHECKERR: fish: No matches for wildcard '*nosuchname*'. See `help wildcards-globbing`. +# CHECKERR: fish: No matches for wildcard '*nosuchname*'. See `help language#wildcards-globbing`. # CHECKERR: echo *nosuchname* # CHECKERR: ^~~~~~~~~~~^ # CHECKERR: in command substitution diff --git a/tests/checks/vars_as_commands.fish b/tests/checks/vars_as_commands.fish index 363cbc0a8..8e5915b78 100644 --- a/tests/checks/vars_as_commands.fish +++ b/tests/checks/vars_as_commands.fish @@ -30,17 +30,17 @@ $CMD3 && echo $PWD # $status specifically is not valid, to avoid a common error # with `if $status` echo 'if $status; echo foo; end' | $fish --no-config -#CHECKERR: fish: $status is not valid as a command. See `help conditions` +#CHECKERR: fish: $status is not valid as a command. See `help language#conditions` #CHECKERR: if $status; echo foo; end #CHECKERR: ^~~~~~^ echo 'not $status' | $fish --no-config -#CHECKERR: fish: $status is not valid as a command. See `help conditions` +#CHECKERR: fish: $status is not valid as a command. See `help language#conditions` #CHECKERR: not $status #CHECKERR: ^~~~~~^ # Script doesn't run at all. echo 'echo foo; and $status' | $fish --no-config -#CHECKERR: fish: $status is not valid as a command. See `help conditions` +#CHECKERR: fish: $status is not valid as a command. See `help language#conditions` #CHECKERR: echo foo; and $status #CHECKERR: ^~~~~~^ diff --git a/tests/checks/wildcard.fish b/tests/checks/wildcard.fish index 9b6494f98..22741bed0 100644 --- a/tests/checks/wildcard.fish +++ b/tests/checks/wildcard.fish @@ -12,7 +12,7 @@ touch ./b/file.txt set dirs ./a ./b echo $dirs/*.txt # CHECK: ./b/file.txt echo */foo/ -# CHECKERR: {{.*}}checks/wildcard.fish (line {{\d+}}): No matches for wildcard '*/foo/'. See `help wildcards-globbing`. +# CHECKERR: {{.*}}checks/wildcard.fish (line {{\d+}}): No matches for wildcard '*/foo/'. See `help language#wildcards-globbing`. # CHECKERR: echo */foo/ # CHECKERR: ^~~~~^