Rename abbreviation cursor "sentinel" to "marker"

Also default the marker to '%'. So you may write:

    abbr -a L --position anywhere --set-cursor "% | less"

or set an explicit marker:

   abbr -a L --position anywhere --set-cursor=! "! | less"
This commit is contained in:
ridiculousfish 2022-11-27 14:33:35 -08:00
parent 01039537b0
commit e08f4db1f9
5 changed files with 45 additions and 37 deletions

View file

@ -9,7 +9,7 @@ Synopsis
.. synopsis:: .. synopsis::
abbr --add NAME [--position command | anywhere] [--regex PATTERN] abbr --add NAME [--position command | anywhere] [--regex PATTERN]
[--set-cursor SENTINEL] [--set-cursor[=MARKER]]
[-f | --function] EXPANSION [-f | --function] EXPANSION
abbr --erase NAME ... abbr --erase NAME ...
abbr --rename OLD_WORD NEW_WORD abbr --rename OLD_WORD NEW_WORD
@ -38,7 +38,7 @@ Abbreviations may be added to :ref:`config.fish <configuration>`. Abbreviations
.. synopsis:: .. synopsis::
abbr [-a | --add] NAME [--position command | anywhere] [--regex PATTERN] abbr [-a | --add] NAME [--position command | anywhere] [--regex PATTERN]
[--set-cursor SENTINEL] [--set-cursor[=MARKER]]
[-f | --function] EXPANSION [-f | --function] EXPANSION
``abbr --add`` creates a new abbreviation. With no other options, the string **NAME** is replaced by **EXPANSION**. ``abbr --add`` creates a new abbreviation. With no other options, the string **NAME** is replaced by **EXPANSION**.
@ -47,7 +47,7 @@ With **--position command**, the abbreviation will only expand when it is positi
With **--regex**, the abbreviation matches using the regular expression given by **PATTERN**, instead of the literal **NAME**. The pattern is interpreted using PCRE2 syntax and must match the entire token. If multiple abbreviations match the same token, the last abbreviation added is used. With **--regex**, the abbreviation matches using the regular expression given by **PATTERN**, instead of the literal **NAME**. The pattern is interpreted using PCRE2 syntax and must match the entire token. If multiple abbreviations match the same token, the last abbreviation added is used.
With **--set-cursor**, the cursor is moved to the first occurrence of **SENTINEL** in the expansion. That **SENTINEL** value is erased. With **--set-cursor=MARKER**, the cursor is moved to the first occurrence of **MARKER** in the expansion. The **MARKER** value is erased. The **MARKER** may be omitted (i.e. simply ``--set-cursor``), in which case it defaults to ``%``.
With **-f** or **--function**, **EXPANSION** is treated as the name of a fish function instead of a literal replacement. When the abbreviation matches, the function will be called with the matching token as an argument. If the function's exit status is 0 (success), the token will be replaced by the function's output; otherwise the token will be left unchanged. With **-f** or **--function**, **EXPANSION** is treated as the name of a fish function instead of a literal replacement. When the abbreviation matches, the function will be called with the matching token as an argument. If the function's exit status is 0 (success), the token will be replaced by the function's output; otherwise the token will be left unchanged.
@ -69,7 +69,7 @@ Add a new abbreviation where ``-C`` will be replaced with ``--color``. The ``--`
:: ::
abbr -a L --position anywhere --set-cursor ! "! | less" abbr -a L --position anywhere --set-cursor "% | less"
Add a new abbreviation where ``L`` will be replaced with ``| less``, placing the cursor before the pipe. Add a new abbreviation where ``L`` will be replaced with ``| less``, placing the cursor before the pipe.

View file

@ -41,7 +41,7 @@ abbrs_replacer_list_t abbrs_set_t::match(const wcstring &token, abbrs_position_t
const abbreviation_t &abbr = *it; const abbreviation_t &abbr = *it;
if (abbr.matches(token, position)) { if (abbr.matches(token, position)) {
result.push_back(abbrs_replacer_t{abbr.replacement, abbr.replacement_is_function, result.push_back(abbrs_replacer_t{abbr.replacement, abbr.replacement_is_function,
abbr.set_cursor_indicator}); abbr.set_cursor_marker});
} }
} }
return result; return result;
@ -123,10 +123,10 @@ abbrs_replacement_t abbrs_replacement_t::from(source_range_t range, wcstring tex
abbrs_replacement_t result{}; abbrs_replacement_t result{};
result.range = range; result.range = range;
result.text = std::move(text); result.text = std::move(text);
if (replacer.set_cursor_indicator.has_value()) { if (replacer.set_cursor_marker.has_value()) {
size_t pos = result.text.find(*replacer.set_cursor_indicator); size_t pos = result.text.find(*replacer.set_cursor_marker);
if (pos != wcstring::npos) { if (pos != wcstring::npos) {
result.text.erase(pos, replacer.set_cursor_indicator->size()); result.text.erase(pos, replacer.set_cursor_marker->size());
result.cursor = pos + range.start; result.cursor = pos + range.start;
} }
} }

View file

@ -43,7 +43,7 @@ struct abbreviation_t {
abbrs_position_t position{abbrs_position_t::command}; abbrs_position_t position{abbrs_position_t::command};
/// If set, then move the cursor to the first instance of this string in the expansion. /// If set, then move the cursor to the first instance of this string in the expansion.
maybe_t<wcstring> set_cursor_indicator{}; maybe_t<wcstring> set_cursor_marker{};
/// Mark if we came from a universal variable. /// Mark if we came from a universal variable.
bool from_universal{}; bool from_universal{};
@ -76,7 +76,7 @@ struct abbrs_replacer_t {
bool is_function; bool is_function;
/// If set, the cursor should be moved to the first instance of this string in the expansion. /// If set, the cursor should be moved to the first instance of this string in the expansion.
maybe_t<wcstring> set_cursor_indicator; maybe_t<wcstring> set_cursor_marker;
}; };
using abbrs_replacer_list_t = std::vector<abbrs_replacer_t>; using abbrs_replacer_list_t = std::vector<abbrs_replacer_t>;

View file

@ -41,7 +41,7 @@ struct abbr_options_t {
bool function{}; bool function{};
maybe_t<wcstring> regex_pattern; maybe_t<wcstring> regex_pattern;
maybe_t<abbrs_position_t> position{}; maybe_t<abbrs_position_t> position{};
maybe_t<wcstring> set_cursor_indicator{}; maybe_t<wcstring> set_cursor_marker{};
wcstring_list_t args; wcstring_list_t args;
@ -78,11 +78,11 @@ struct abbr_options_t {
streams.err.append_format(_(L"%ls: --function option requires --add\n"), CMD); streams.err.append_format(_(L"%ls: --function option requires --add\n"), CMD);
return false; return false;
} }
if (!add && set_cursor_indicator.has_value()) { if (!add && set_cursor_marker.has_value()) {
streams.err.append_format(_(L"%ls: --set-cursor option requires --add\n"), CMD); streams.err.append_format(_(L"%ls: --set-cursor option requires --add\n"), CMD);
return false; return false;
} }
if (set_cursor_indicator.has_value() && set_cursor_indicator->empty()) { if (set_cursor_marker.has_value() && set_cursor_marker->empty()) {
streams.err.append_format(_(L"%ls: --set-cursor argument cannot be empty\n"), CMD); streams.err.append_format(_(L"%ls: --set-cursor argument cannot be empty\n"), CMD);
return false; return false;
} }
@ -107,9 +107,8 @@ static int abbr_show(const abbr_options_t &, io_streams_t &streams) {
comps.push_back(L"--regex"); comps.push_back(L"--regex");
comps.push_back(escape_string(abbr.key)); comps.push_back(escape_string(abbr.key));
} }
if (abbr.set_cursor_indicator.has_value()) { if (abbr.set_cursor_marker.has_value()) {
comps.push_back(L"--set-cursor"); comps.push_back(L"--set-cursor=" + escape_string(*abbr.set_cursor_marker));
comps.push_back(escape_string(*abbr.set_cursor_indicator));
} }
if (abbr.replacement_is_function) { if (abbr.replacement_is_function) {
comps.push_back(L"--function"); comps.push_back(L"--function");
@ -249,7 +248,7 @@ static int abbr_add(const abbr_options_t &opts, io_streams_t &streams) {
abbreviation_t abbr{std::move(name), std::move(key), std::move(replacement), position}; abbreviation_t abbr{std::move(name), std::move(key), std::move(replacement), position};
abbr.regex = std::move(regex); abbr.regex = std::move(regex);
abbr.replacement_is_function = opts.function; abbr.replacement_is_function = opts.function;
abbr.set_cursor_indicator = opts.set_cursor_indicator; abbr.set_cursor_marker = opts.set_cursor_marker;
abbrs_get_set()->add(std::move(abbr)); abbrs_get_set()->add(std::move(abbr));
return STATUS_CMD_OK; return STATUS_CMD_OK;
} }
@ -278,26 +277,27 @@ maybe_t<int> builtin_abbr(parser_t &parser, io_streams_t &streams, const wchar_t
const wchar_t *cmd = argv[0]; const wchar_t *cmd = argv[0];
abbr_options_t opts; abbr_options_t opts;
// Note 1 is returned by wgetopt to indicate a non-option argument. // Note 1 is returned by wgetopt to indicate a non-option argument.
enum { NON_OPTION_ARGUMENT = 1, REGEX_SHORT }; enum { NON_OPTION_ARGUMENT = 1, REGEX_SHORT, SET_CURSOR_SHORT };
// Note the leading '-' causes wgetopter to return arguments in order, instead of permuting // Note the leading '-' causes wgetopter to return arguments in order, instead of permuting
// them. We need this behavior for compatibility with pre-builtin abbreviations where options // them. We need this behavior for compatibility with pre-builtin abbreviations where options
// could be given literally, for example `abbr e emacs -nw`. // could be given literally, for example `abbr e emacs -nw`.
static const wchar_t *const short_options = L"-afrseqgUh"; static const wchar_t *const short_options = L"-afrseqgUh";
static const struct woption long_options[] = {{L"add", no_argument, 'a'}, static const struct woption long_options[] = {
{L"position", required_argument, 'p'}, {L"add", no_argument, 'a'},
{L"regex", required_argument, REGEX_SHORT}, {L"position", required_argument, 'p'},
{L"set-cursor", required_argument, 'C'}, {L"regex", required_argument, REGEX_SHORT},
{L"function", no_argument, 'f'}, {L"set-cursor", optional_argument, SET_CURSOR_SHORT},
{L"rename", no_argument, 'r'}, {L"function", no_argument, 'f'},
{L"erase", no_argument, 'e'}, {L"rename", no_argument, 'r'},
{L"query", no_argument, 'q'}, {L"erase", no_argument, 'e'},
{L"show", no_argument, 's'}, {L"query", no_argument, 'q'},
{L"list", no_argument, 'l'}, {L"show", no_argument, 's'},
{L"global", no_argument, 'g'}, {L"list", no_argument, 'l'},
{L"universal", no_argument, 'U'}, {L"global", no_argument, 'g'},
{L"help", no_argument, 'h'}, {L"universal", no_argument, 'U'},
{}}; {L"help", no_argument, 'h'},
{}};
int argc = builtin_count_args(argv); int argc = builtin_count_args(argv);
int opt; int opt;
@ -346,13 +346,14 @@ maybe_t<int> builtin_abbr(parser_t &parser, io_streams_t &streams, const wchar_t
opts.regex_pattern = w.woptarg; opts.regex_pattern = w.woptarg;
break; break;
} }
case 'C': { case SET_CURSOR_SHORT: {
if (opts.set_cursor_indicator.has_value()) { if (opts.set_cursor_marker.has_value()) {
streams.err.append_format( streams.err.append_format(
_(L"%ls: Cannot specify multiple set-cursor options\n"), CMD); _(L"%ls: Cannot specify multiple set-cursor options\n"), CMD);
return STATUS_INVALID_ARGS; return STATUS_INVALID_ARGS;
} }
opts.set_cursor_indicator = w.woptarg; // The default set-cursor indicator is '%'.
opts.set_cursor_marker = w.woptarg ? w.woptarg : L"%";
break; break;
} }
case 'f': case 'f':

View file

@ -143,7 +143,14 @@ expect_prompt(r"6 : @abc@ ")
# Test cursor positioning. # Test cursor positioning.
sendline(r"""abbr --erase (abbr --list) """) sendline(r"""abbr --erase (abbr --list) """)
expect_prompt() expect_prompt()
sendline(r"""abbr LLL --position anywhere --set-cursor !HERE! '!HERE! | less'""") sendline(r"""abbr LLL --position anywhere --set-cursor 'abc%ghi'""")
expect_prompt()
send(r"""echo LLL def?""")
expect_str(r"<echo abcdefghi >")
sendline(r"""abbr --erase (abbr --list) """)
expect_prompt()
sendline(r"""abbr LLL --position anywhere --set-cursor=!HERE! '!HERE! | less'""")
expect_prompt() expect_prompt()
send(r"""echo LLL derp?""") send(r"""echo LLL derp?""")
expect_str(r"echo derp | less ") expect_str(r"<echo derp | less >")