mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-28 08:20:56 +01:00
[Wilds] Shell complete files with spaces in them correctly
Summary: Fixes T9116. Ref T13098. Fix shell completion handling of filenames with spaces in them. This is a big mess -- see T9116 for discussion and I'll walk through things below. Test Plan: These all now seem to do the right thing: ``` arc we<tab> -> arc weld (+space) arc weld fo<tab> -> arc weld foo\ bar (+space) arc weld 'fo<tab> -> arc weld 'foo bar' (+space) arc weld src<tab> -> arc weld src/ (no space) arc weld src/w<tab> -> arc weld src/work (no space) arc weld src/work<tab><tab> -> suggests "workflow/", "workingcopy/" arc shell-complete --gen<tab> -> arc shell-complete --generate ``` These also work, which I think is nice-to-have: ``` arc WEL<tab> -> arc weld arc shell-complete --GEN<tab> -> arc shell-complete --generate ``` Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13098, T9116 Differential Revision: https://secure.phabricator.com/D19705
This commit is contained in:
parent
50dfc9cc41
commit
afcaeea9c3
2 changed files with 51 additions and 37 deletions
|
@ -506,18 +506,8 @@ EOTEXT
|
|||
$complete[] = $alias->getTrigger();
|
||||
}
|
||||
|
||||
// Remove invalid possibilities. For example, if the user has typed
|
||||
// "skun<tab>", it obviously can't complete to "zebra". We don't really
|
||||
// need to do this filtering ourselves: the shell completion will
|
||||
// automatically match things for us even if we emit impossible results.
|
||||
// However, it's a little easier to debug the raw output if we clean it
|
||||
// up here before printing it out.
|
||||
$partial = $argv[$pos];
|
||||
foreach ($complete as $key => $candidate) {
|
||||
if (strncmp($partial, $candidate, strlen($partial))) {
|
||||
unset($complete[$key]);
|
||||
}
|
||||
}
|
||||
$complete = $this->getMatches($complete, $partial);
|
||||
|
||||
if ($complete) {
|
||||
return $this->suggestStrings($complete);
|
||||
|
@ -540,6 +530,7 @@ EOTEXT
|
|||
|
||||
$arguments = $workflow->getWorkflowArguments();
|
||||
$arguments = mpull($arguments, null, 'getKey');
|
||||
$current = idx($argv, $pos, '');
|
||||
|
||||
$argument = null;
|
||||
$prev = idx($argv, $pos - 1, null);
|
||||
|
@ -554,7 +545,7 @@ EOTEXT
|
|||
|
||||
if ($argument && strlen($argument->getParameter())) {
|
||||
if ($argument->getIsPathArgument()) {
|
||||
return $this->suggestPaths();
|
||||
return $this->suggestPaths($current);
|
||||
} else {
|
||||
return $this->suggestNothing();
|
||||
}
|
||||
|
@ -575,15 +566,7 @@ EOTEXT
|
|||
$flags[] = '--'.$argument->getKey();
|
||||
}
|
||||
|
||||
$current = idx($argv, $pos, '');
|
||||
$matches = array();
|
||||
if (strlen($current)) {
|
||||
foreach ($flags as $possible) {
|
||||
if (!strncmp($possible, $current, strlen($current))) {
|
||||
$matches[] = $possible;
|
||||
}
|
||||
}
|
||||
}
|
||||
$matches = $this->getMatches($flags, $current);
|
||||
|
||||
// If whatever the user is completing does not match the prefix of any
|
||||
// flag, try to autcomplete a wildcard argument if it has some kind of
|
||||
|
@ -597,7 +580,7 @@ EOTEXT
|
|||
// and Workflows.
|
||||
|
||||
if ($wildcard->getIsPathArgument()) {
|
||||
return $this->suggestPaths();
|
||||
return $this->suggestPaths($current);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,19 +588,51 @@ EOTEXT
|
|||
}
|
||||
}
|
||||
|
||||
private function suggestPaths() {
|
||||
echo "FILE\n";
|
||||
private function suggestPaths($prefix) {
|
||||
// NOTE: We are returning a directive to the bash script to run "compgen"
|
||||
// for us rather than running it ourselves. If we run:
|
||||
//
|
||||
// compgen -A file -- %s
|
||||
//
|
||||
// ...from this context, it fails (exits with error code 1 and no output)
|
||||
// if the prefix is "foo\ ", on my machine. See T9116 for some dicussion.
|
||||
echo "<compgen:file>";
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function suggestNothing() {
|
||||
echo "ARGUMENT\n";
|
||||
return 0;
|
||||
return $this->suggestStrings(array());
|
||||
}
|
||||
|
||||
private function suggestStrings(array $strings) {
|
||||
echo implode(' ', $strings)."\n";
|
||||
sort($strings);
|
||||
echo implode("\n", $strings);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function getMatches(array $candidates, $prefix) {
|
||||
$matches = array();
|
||||
|
||||
if (strlen($prefix)) {
|
||||
foreach ($candidates as $possible) {
|
||||
if (!strncmp($possible, $prefix, strlen($prefix))) {
|
||||
$matches[] = $possible;
|
||||
}
|
||||
}
|
||||
|
||||
// If we matched nothing, try a case-insensitive match.
|
||||
if (!$matches) {
|
||||
foreach ($candidates as $possible) {
|
||||
if (!strncasecmp($possible, $prefix, strlen($prefix))) {
|
||||
$matches[] = $possible;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$matches = $candidates;
|
||||
}
|
||||
|
||||
return $matches;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,22 +2,21 @@ _arcanist_complete_{{{BIN}}} ()
|
|||
{
|
||||
COMPREPLY=()
|
||||
|
||||
CUR="${COMP_WORDS[COMP_CWORD]}"
|
||||
OPTS=$(echo | {{{BIN}}} shell-complete --current ${COMP_CWORD} -- ${COMP_WORDS[@]} 2>/dev/null)
|
||||
RESULT=$(echo | {{{BIN}}} shell-complete \
|
||||
--current ${COMP_CWORD} \
|
||||
-- \
|
||||
"${COMP_WORDS[@]}" \
|
||||
2>/dev/null)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [ "$OPTS" = "FILE" ]; then
|
||||
COMPREPLY=( $(compgen -f -- ${CUR}) )
|
||||
return 0
|
||||
if [ "$RESULT" == "<compgen:file>" ]; then
|
||||
RESULT=$( compgen -A file -- ${COMP_WORDS[COMP_CWORD]} )
|
||||
fi
|
||||
|
||||
if [ "$OPTS" = "ARGUMENT" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W "${OPTS}" -- ${CUR}) )
|
||||
local IFS=$'\n'
|
||||
COMPREPLY=( $RESULT )
|
||||
}
|
||||
complete -F _arcanist_complete_{{{BIN}}} -o filenames {{{BIN}}}
|
||||
|
|
Loading…
Reference in a new issue