Support FOO=bar syntax for passing variables to individual commands

This adds initial support for statements with prefixed variable assignments.
Statments like this are supported:

a=1 b=$a echo $b        # outputs 1

Just like in other shells, the left-hand side of each assignment must
be a valid variable identifier (no quoting/escaping).  Array indexing
(PATH[1]=/bin ls $PATH) is *not* yet supported, but can be added fairly
easily.

The right hand side may be any valid string token, like a command
substitution, or a brace expansion.

Since `a=* foo` is equivalent to `begin set -lx a *; foo; end`,
the assignment, like `set`, uses nullglob behavior, e.g. below command
can safely be used to check if a directory is empty.

x=/nothing/{,.}* test (count $x) -eq 0

Generic file completion is done after the equal sign, so for example
pressing tab after something like `HOME=/` completes files in the
root directory
Subcommand completion works, so something like
`GIT_DIR=repo.git and command git ` correctly calls git completions
(but the git completion does not use the variable as of now).

The variable assignment is highlighted like an argument.

Closes #6048
This commit is contained in:
Johannes Altmanninger
2019-10-23 03:13:29 +02:00
parent 3b0f642de9
commit 7d5b44e828
21 changed files with 335 additions and 93 deletions

View File

@@ -41,6 +41,9 @@ class io_chain_t;
/// Breakpoint block.
#define BREAKPOINT_BLOCK N_(L"block created by breakpoint")
/// Variable assignment block.
#define VARIABLE_ASSIGNMENT_BLOCK N_(L"block created by variable assignment prefixing a command")
/// If block description.
#define IF_BLOCK N_(L"'if' conditional block")
@@ -95,6 +98,7 @@ static const struct block_lookup_entry block_lookup[] = {
{SOURCE, L"source", SOURCE_BLOCK},
{EVENT, 0, EVENT_BLOCK},
{BREAKPOINT, L"breakpoint", BREAKPOINT_BLOCK},
{VARIABLE_ASSIGNMENT, L"variable assignment", VARIABLE_ASSIGNMENT_BLOCK},
{(block_type_t)0, 0, 0}};
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
@@ -789,6 +793,10 @@ wcstring block_t::description() const {
result.append(L"breakpoint");
break;
}
case VARIABLE_ASSIGNMENT: {
result.append(L"variable_assignment");
break;
}
}
if (this->src_lineno >= 0) {
@@ -831,3 +839,4 @@ block_t block_t::scope_block(block_type_t type) {
return block_t(type);
}
block_t block_t::breakpoint_block() { return block_t(BREAKPOINT); }
block_t block_t::variable_assignment_block() { return block_t(VARIABLE_ASSIGNMENT); }