From d73c487d609154753fa0b243f7f46958e8aaa416 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 10 Oct 2018 14:26:29 -0700 Subject: [PATCH 1/2] Restore %self to refer to the fish pid This brings back the %self argument. Like the original %self it only expands if the argument is literally %self. --- src/common.cpp | 12 ++++++++++++ src/env.cpp | 2 +- src/expand.cpp | 16 ++++++++++++---- src/expand.h | 5 +++++ src/highlight.cpp | 1 + tests/expansion.err | 3 +++ tests/expansion.in | 5 +++++ tests/expansion.out | 5 +++++ 8 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index a9037ca8f..b4063df79 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1040,6 +1040,7 @@ static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring case L'|': case L';': case L'"': + case L'%': case L'~': { bool char_is_normal = (c == L'~' && no_tilde) || (c == L'^' && no_caret) || (c == L'?' && no_qmark); @@ -1398,6 +1399,17 @@ static bool unescape_string_internal(const wchar_t *const input, const size_t in } break; } + case L'%': { + // Note that this only recognizes %self if the string is literally %self. + // %self/foo will NOT match this. + if (unescape_special && input_position == 0 && + !wcscmp(input, PROCESS_EXPAND_SELF_STR)) { + to_append_or_none = PROCESS_EXPAND_SELF; + input_position += + wcslen(PROCESS_EXPAND_SELF_STR) - 1; // skip over 'self' part. + } + break; + } case L'*': { if (unescape_special) { // In general, this is ANY_STRING. But as a hack, if the last appended char diff --git a/src/env.cpp b/src/env.cpp index 69e9d8a03..9c35b9ba4 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -924,7 +924,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) { wcstring version = str2wcstring(get_fish_version()); env_set_one(L"version", ENV_GLOBAL, version); - // Set the $fish_pid variable (%self replacement) + // Set the $fish_pid variable. env_set_one(L"fish_pid", ENV_GLOBAL, to_string(getpid())); // Set the $hostname variable diff --git a/src/expand.cpp b/src/expand.cpp index a0e2dd7ef..d4bc6e553 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -56,7 +56,7 @@ /// Characters which make a string unclean if they are the first character of the string. See \c /// expand_is_clean(). -#define UNCLEAN_FIRST L"~" +#define UNCLEAN_FIRST L"~%" /// Unclean characters. See \c expand_is_clean(). #define UNCLEAN L"$*?\\\"'({})" @@ -784,6 +784,13 @@ static void expand_home_directory(wcstring &input) { } } +/// Expand the %self escape. Note this can only come at the beginning of the string. +static void expand_percent_self(wcstring &input) { + if (!input.empty() && input.front() == PROCESS_EXPAND_SELF) { + input.replace(0, 1, to_string(getpid())); + } +} + void expand_tilde(wcstring &input) { // Avoid needless COW behavior by ensuring we use const at. const wcstring &tmp = input; @@ -934,12 +941,13 @@ static expand_error_t expand_stage_braces(wcstring input, std::vector *out, - expand_flags_t flags, parse_error_list_t *errors) { +static expand_error_t expand_stage_home_and_self(wcstring input, std::vector *out, + expand_flags_t flags, parse_error_list_t *errors) { (void)errors; if (!(EXPAND_SKIP_HOME_DIRECTORIES & flags)) { expand_home_directory(input); } + expand_percent_self(input); append_completion(out, std::move(input)); return EXPAND_OK; } @@ -1047,7 +1055,7 @@ expand_error_t expand_string(wcstring input, std::vector *out_comp // Our expansion stages. const expand_stage_t stages[] = {expand_stage_cmdsubst, expand_stage_variables, - expand_stage_braces, expand_stage_home, + expand_stage_braces, expand_stage_home_and_self, expand_stage_wildcards}; // Load up our single initial completion. diff --git a/src/expand.h b/src/expand.h index f92350a1c..b6fac9364 100644 --- a/src/expand.h +++ b/src/expand.h @@ -61,6 +61,8 @@ class completion_t; enum { /// Character representing a home directory. HOME_DIRECTORY = EXPAND_RESERVED_BASE, + /// Character representing process expansion for %self. + PROCESS_EXPAND_SELF, /// Character representing variable expansion. VARIABLE_EXPAND, /// Character representing variable expansion into a single element. @@ -95,6 +97,9 @@ enum expand_error_t { EXPAND_WILDCARD_MATCH }; +/// The string represented by PROCESS_EXPAND_SELF +#define PROCESS_EXPAND_SELF_STR L"%self" + /// Perform various forms of expansion on in, such as tilde expansion (\~USER becomes the users home /// directory), variable expansion (\$VAR_NAME becomes the value of the environment variable /// VAR_NAME), cmdsubst expansion and wildcard expansion. The results are inserted into the list diff --git a/src/highlight.cpp b/src/highlight.cpp index b620f6d3d..ac988d42b 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -121,6 +121,7 @@ bool is_potential_path(const wcstring &potential_path_fragment, const wcstring_l for (size_t i = 0; i < path_with_magic.size(); i++) { wchar_t c = path_with_magic.at(i); switch (c) { + case PROCESS_EXPAND_SELF: case VARIABLE_EXPAND: case VARIABLE_EXPAND_SINGLE: case BRACE_BEGIN: diff --git a/tests/expansion.err b/tests/expansion.err index d75619e07..65ffe2e28 100644 --- a/tests/expansion.err +++ b/tests/expansion.err @@ -8,6 +8,9 @@ fish: Invalid index value echo ()[d] ^ +#################### +# Percent self + #################### # Catch your breath fish: $) is not a valid variable in fish. diff --git a/tests/expansion.in b/tests/expansion.in index f0f594bbd..a0fdd2138 100644 --- a/tests/expansion.in +++ b/tests/expansion.in @@ -101,6 +101,11 @@ echo $foo[d] echo ()[1] echo ()[d] +logmsg Percent self +echo %selfNOT NOT%self \%self "%self" '%self' +echo %self | string match -qr '^\\d+$' +echo "All digits: $status" + logmsg Catch your breath set paren ')' echo $$paren diff --git a/tests/expansion.out b/tests/expansion.out index 82f3b9ee7..ca7596395 100644 --- a/tests/expansion.out +++ b/tests/expansion.out @@ -63,6 +63,11 @@ 0 +#################### +# Percent self +%selfNOT NOT%self %self %self %self +All digits: 0 + #################### # Catch your breath From 5fa4e0d2eeaba11fd933c10dcabf9138ef213b9f Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 10 Oct 2018 16:25:21 -0700 Subject: [PATCH 2/2] Highlight %self as an operator --- src/fish_tests.cpp | 8 +++++++- src/highlight.cpp | 10 ++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 80e997e8e..91d9e0554 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -2472,7 +2472,6 @@ static void test_complete() { do_test(completions.at(1).completion == L"zero"); do_test((completions.at(1).flags & COMPLETE_NO_SPACE) != 0); - // Test wraps. do_test(comma_join(complete_get_wrap_targets(L"wrapper1")) == L""); complete_add_wrapper(L"wrapper1", L"wrapper2"); @@ -4086,6 +4085,13 @@ static void test_highlighting() { {L"end", highlight_spec_command}, }); + highlight_tests.push_back({ + {L"echo", highlight_spec_command}, + {L"%self", highlight_spec_operator}, + {L"not%self", highlight_spec_param}, + {L"self%not", highlight_spec_param}, + }); + // Verify variables and wildcards in commands using /bin/cat. env_set(L"VARIABLE_IN_COMMAND", ENV_LOCAL, {L"a"}); env_set(L"VARIABLE_IN_COMMAND2", ENV_LOCAL, {L"at"}); diff --git a/src/highlight.cpp b/src/highlight.cpp index ac988d42b..321ce9874 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -444,6 +444,12 @@ static void color_string_internal(const wcstring &buffstr, highlight_spec_t base const size_t buff_len = buffstr.size(); std::fill(colors, colors + buff_len, base_color); + // Hacky support for %self which must be an unquoted literal argument. + if (buffstr == PROCESS_EXPAND_SELF_STR) { + std::fill_n(colors, wcslen(PROCESS_EXPAND_SELF_STR), highlight_spec_operator); + return; + } + enum { e_unquoted, e_single_quoted, e_double_quoted } mode = e_unquoted; int bracket_count = 0; for (size_t in_pos = 0; in_pos < buff_len; in_pos++) { @@ -692,8 +698,8 @@ class highlighter_t { public: // Constructor - highlighter_t(const wcstring &str, size_t pos, const env_vars_snapshot_t &ev, - wcstring wd, bool can_do_io) + highlighter_t(const wcstring &str, size_t pos, const env_vars_snapshot_t &ev, wcstring wd, + bool can_do_io) : buff(str), cursor_pos(pos), vars(ev),