Highlight keywords differently

This introduces a new variable $fish_color_keyword that will be used
to highlight keywords. If it's not defined, we fall back on
$fish_color_command as before.

An issue here is that most of our keywords have this weird duality of
also being builtins *if* executed without an argument or with
`--help`.

This means that e.g.

    if

is highlighted as a command until you start typing

    if t

and then it turns keyword.
This commit is contained in:
Fabian Homborg 2021-02-04 20:22:32 +01:00
parent 96f2de9d15
commit b3626d48e7
6 changed files with 19 additions and 10 deletions

View file

@ -34,6 +34,7 @@ ROLE_TO_TOKEN = {
"normal": Name.Variable,
"error": Generic.Error,
"command": Name.Function,
"keyword": Keyword,
"statement_terminator": Punctuation,
"param": Name.Constant,
"comment": Comment,

View file

@ -1398,6 +1398,7 @@ Variable Meaning
========================================== =====================================================================
``fish_color_normal`` default color
``fish_color_command`` commands like echo
``fish_color_keyword`` keywords like if - this falls back on command color if unset
``fish_color_quote`` quoted text like "abc"
``fish_color_redirection`` IO redirections like >/dev/null
``fish_color_end`` process separators like ';' and '&'

View file

@ -632,6 +632,7 @@ static const char *highlight_role_to_string(highlight_role_t role) {
TEST_ROLE(normal)
TEST_ROLE(error)
TEST_ROLE(command)
TEST_ROLE(keyword)
TEST_ROLE(statement_terminator)
TEST_ROLE(param)
TEST_ROLE(comment)

View file

@ -4969,7 +4969,7 @@ static void test_highlighting() {
{L"&", highlight_role_t::statement_terminator}});
highlight_tests.push_back({
{L"command", highlight_role_t::command},
{L"command", highlight_role_t::keyword},
{L"echo", highlight_role_t::command},
{L"abc", highlight_role_t::param},
{L"test/fish_highlight_test/foo", param_valid_path},
@ -4977,14 +4977,15 @@ static void test_highlighting() {
});
highlight_tests.push_back({
{L"if command ls", highlight_role_t::command},
{L"if command", highlight_role_t::keyword},
{L"ls", highlight_role_t::command},
{L"; ", highlight_role_t::statement_terminator},
{L"echo", highlight_role_t::command},
{L"abc", highlight_role_t::param},
{L"; ", highlight_role_t::statement_terminator},
{L"/bin/definitely_not_a_command", highlight_role_t::error},
{L"; ", highlight_role_t::statement_terminator},
{L"end", highlight_role_t::command},
{L"end", highlight_role_t::keyword},
});
// Verify that cd shows errors for non-directories.
@ -5067,7 +5068,7 @@ static void test_highlighting() {
highlight_tests.push_back({
{L"end", highlight_role_t::error},
{L";", highlight_role_t::statement_terminator},
{L"if", highlight_role_t::command},
{L"if", highlight_role_t::keyword},
{L"end", highlight_role_t::error},
});
@ -5097,12 +5098,12 @@ static void test_highlighting() {
});
highlight_tests.push_back({
{L"for", highlight_role_t::command},
{L"for", highlight_role_t::keyword},
{L"i", highlight_role_t::param},
{L"in", highlight_role_t::command},
{L"in", highlight_role_t::keyword},
{L"1 2 3", highlight_role_t::param},
{L";", highlight_role_t::statement_terminator},
{L"end", highlight_role_t::command},
{L"end", highlight_role_t::keyword},
});
highlight_tests.push_back({
@ -5125,7 +5126,7 @@ static void test_highlighting() {
});
highlight_tests.push_back({
{L"if", highlight_role_t::command},
{L"if", highlight_role_t::keyword},
{L"true", highlight_role_t::command},
{L"&&", highlight_role_t::operat},
{L"false", highlight_role_t::command},
@ -5140,7 +5141,7 @@ static void test_highlighting() {
{L"!", highlight_role_t::operat},
{L"true", highlight_role_t::command},
{L";", highlight_role_t::statement_terminator},
{L"end", highlight_role_t::command},
{L"end", highlight_role_t::keyword},
});
highlight_tests.push_back({

View file

@ -47,6 +47,8 @@ static const wchar_t *get_highlight_var_name(highlight_role_t role) {
return L"fish_color_error";
case highlight_role_t::command:
return L"fish_color_command";
case highlight_role_t::keyword:
return L"fish_color_keyword";
case highlight_role_t::statement_terminator:
return L"fish_color_end";
case highlight_role_t::param:
@ -107,6 +109,8 @@ static highlight_role_t get_fallback(highlight_role_t role) {
return highlight_role_t::normal;
case highlight_role_t::command:
return highlight_role_t::normal;
case highlight_role_t::keyword:
return highlight_role_t::command;
case highlight_role_t::statement_terminator:
return highlight_role_t::normal;
case highlight_role_t::param:
@ -949,7 +953,7 @@ void highlighter_t::visit(const ast::keyword_base_t &kw) {
case parse_keyword_t::kw_in:
case parse_keyword_t::kw_switch:
case parse_keyword_t::kw_while:
role = highlight_role_t::command;
role = highlight_role_t::keyword;
break;
case parse_keyword_t::kw_and:

View file

@ -17,6 +17,7 @@ enum class highlight_role_t : uint8_t {
normal = 0, // normal text
error, // error
command, // command
keyword,
statement_terminator, // process separator
param, // command parameter (argument)
comment, // comment