aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtin_complete.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2014-08-15 18:14:36 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2014-08-15 18:14:36 -0700
commit06400b83b188156f31ed92216ec27122d29f88cd (patch)
tree2f9cec409aba50449638c8d4361b4dafe530f3ec /builtin_complete.cpp
parentfe68d30be97853865b24ad5f5998d3e50769f860 (diff)
Support for command wrapping ("aliases")
Add the --wraps option to 'complete' and 'function'. This allows a command to (recursively) inherit the completions of a wrapped command. Fixes #393. When evaluating a completion, we inspect the entire "wrap chain" for a command, i.e. we follow the sequence of wrapping until we either hit a loop (which we silently ignore) or the end of the chain. We then evaluate completions as if the wrapping command were substituted with the wrapped command. Currently this only works for commands, i.e. 'complete --command gco --wraps git\ checkout' won't work (that would seem to encroaching on abbreviations anyways). It might be useful to show an error message for that case. The commandline builtin reflects the commandline with the wrapped command substituted in, so e.g. git completions (which inspect the command line) will just work. This sort of command line munging is also performed by 'complete -C' so it's not totally without precedent. 'alias will also now mark its generated function as wrapping the 'target.
Diffstat (limited to 'builtin_complete.cpp')
-rw-r--r--builtin_complete.cpp44
1 files changed, 23 insertions, 21 deletions
diff --git a/builtin_complete.cpp b/builtin_complete.cpp
index 3b7a13a2..f0eb6e1b 100644
--- a/builtin_complete.cpp
+++ b/builtin_complete.cpp
@@ -24,12 +24,6 @@ Functions used for implementing the complete builtin.
#include "parser.h"
#include "reader.h"
-
-/**
- Internal storage for the builtin_complete_get_temporary_buffer() function.
-*/
-static const wchar_t *temporary_buffer;
-
/*
builtin_complete_* are a set of rather silly looping functions that
make sure that all the proper combinations of complete_add or
@@ -270,13 +264,6 @@ static void builtin_complete_remove(const wcstring_list_t &cmd,
}
-
-const wchar_t *builtin_complete_get_temporary_buffer()
-{
- ASSERT_IS_MAIN_THREAD();
- return temporary_buffer;
-}
-
/**
The complete builtin. Used for specifying programmable
tab-completions. Calls the functions in complete.c for any heavy
@@ -300,6 +287,7 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
wcstring_list_t cmd;
wcstring_list_t path;
+ wcstring_list_t wrap_targets;
static int recursion_level=0;
@@ -326,6 +314,7 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
{ L"unauthoritative", no_argument, 0, 'u' },
{ L"authoritative", no_argument, 0, 'A' },
{ L"condition", required_argument, 0, 'n' },
+ { L"wraps", required_argument, 0, 'w' },
{ L"do-complete", optional_argument, 0, 'C' },
{ L"help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
@@ -422,6 +411,10 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
case 'n':
condition = woptarg;
break;
+
+ case 'w':
+ wrap_targets.push_back(woptarg);
+ break;
case 'C':
do_complete = true;
@@ -495,9 +488,9 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
const wchar_t *token;
parse_util_token_extent(do_complete_param.c_str(), do_complete_param.size(), &token, 0, 0, 0);
-
- const wchar_t *prev_temporary_buffer = temporary_buffer;
- temporary_buffer = do_complete_param.c_str();
+
+ /* Create a scoped transient command line, so that bulitin_commandline will see our argument, not the reader buffer */
+ builtin_commandline_scoped_transient_t temp_buffer(do_complete_param);
if (recursion_level < 1)
{
@@ -536,9 +529,6 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
recursion_level--;
}
-
- temporary_buffer = prev_temporary_buffer;
-
}
else if (woptind != argc)
{
@@ -558,7 +548,7 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
else
{
int flags = COMPLETE_AUTO_SPACE;
-
+
if (remove)
{
builtin_complete_remove(cmd,
@@ -566,6 +556,7 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
short_opt.c_str(),
gnu_opt,
old_opt);
+
}
else
{
@@ -581,7 +572,18 @@ static int builtin_complete(parser_t &parser, wchar_t **argv)
desc,
flags);
}
-
+
+ // Handle wrap targets (probably empty)
+ // We only wrap commands, not paths
+ for (size_t w=0; w < wrap_targets.size(); w++)
+ {
+ const wcstring &wrap_target = wrap_targets.at(w);
+ for (size_t i=0; i < cmd.size(); i++)
+ {
+
+ (remove ? complete_remove_wrapper : complete_add_wrapper)(cmd.at(i), wrap_target);
+ }
+ }
}
}