mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
Slightly improve bash completion arg parsing
This commit is contained in:
parent
6b90f3db4d
commit
52a0b767c8
79
qpdf/qpdf.cc
79
qpdf/qpdf.cc
@ -1414,30 +1414,85 @@ void
|
||||
ArgParser::handleBashArguments()
|
||||
{
|
||||
// Do a minimal job of parsing bash_line into arguments. This
|
||||
// doesn't do everything the shell does, but it should be good
|
||||
// enough for purposes of handling completion. We can't use
|
||||
// new_argv because this has to interoperate with @file arguments.
|
||||
// doesn't do everything the shell does (e.g. $(...), variable
|
||||
// expansion, arithmetic, globs, etc.), but it should be good
|
||||
// enough for purposes of handling completion. As we build up the
|
||||
// new argv, we can't use this->new_argv because this code has to
|
||||
// interoperate with @file arguments, so memory for both ways of
|
||||
// fabricating argv has to be protected.
|
||||
|
||||
enum { st_top, st_quote } state = st_top;
|
||||
bool last_was_backslash = false;
|
||||
enum { st_top, st_squote, st_dquote } state = st_top;
|
||||
std::string arg;
|
||||
for (std::string::iterator iter = bash_line.begin();
|
||||
iter != bash_line.end(); ++iter)
|
||||
{
|
||||
char ch = (*iter);
|
||||
if ((state == st_top) && QUtil::is_space(ch) && (! arg.empty()))
|
||||
if (last_was_backslash)
|
||||
{
|
||||
bash_argv.push_back(
|
||||
PointerHolder<char>(
|
||||
true, QUtil::copy_string(arg.c_str())));
|
||||
arg.clear();
|
||||
arg.append(1, ch);
|
||||
last_was_backslash = false;
|
||||
}
|
||||
else if (ch == '\\')
|
||||
{
|
||||
last_was_backslash = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ch == '"')
|
||||
bool append = false;
|
||||
switch (state)
|
||||
{
|
||||
state = (state == st_top ? st_quote : st_top);
|
||||
case st_top:
|
||||
if (QUtil::is_space(ch))
|
||||
{
|
||||
if (! arg.empty())
|
||||
{
|
||||
bash_argv.push_back(
|
||||
PointerHolder<char>(
|
||||
true, QUtil::copy_string(arg.c_str())));
|
||||
arg.clear();
|
||||
}
|
||||
}
|
||||
else if (ch == '"')
|
||||
{
|
||||
state = st_dquote;
|
||||
}
|
||||
else if (ch == '\'')
|
||||
{
|
||||
state = st_squote;
|
||||
}
|
||||
else
|
||||
{
|
||||
append = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case st_squote:
|
||||
if (ch == '\'')
|
||||
{
|
||||
state = st_top;
|
||||
}
|
||||
else
|
||||
{
|
||||
append = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case st_dquote:
|
||||
if (ch == '"')
|
||||
{
|
||||
state = st_top;
|
||||
}
|
||||
else
|
||||
{
|
||||
append = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (append)
|
||||
{
|
||||
arg.append(1, ch);
|
||||
}
|
||||
arg.append(1, ch);
|
||||
}
|
||||
}
|
||||
if (bash_argv.empty())
|
||||
|
@ -117,6 +117,12 @@ my @completion_tests = (
|
||||
['qpdf --decode-lzzz', 15, 'decode-l'],
|
||||
['qpdf --decode-level=', undef, 'decode-level'],
|
||||
['qpdf --check -', undef, 'later-arg'],
|
||||
['qpdf infile outfile oops --ch', undef, 'usage-empty'],
|
||||
['qpdf --encrypt \'user " password\' ', undef, 'quoting'],
|
||||
['qpdf --encrypt \'user password\' ', undef, 'quoting'],
|
||||
['qpdf --encrypt "user password" ', undef, 'quoting'],
|
||||
['qpdf --encrypt "user pass\'word" ', undef, 'quoting'],
|
||||
['qpdf --encrypt user\ password ', undef, 'quoting'],
|
||||
);
|
||||
$n_tests += scalar(@completion_tests);
|
||||
foreach my $c (@completion_tests)
|
||||
|
1
qpdf/qtest/qpdf/completion-quoting.out
Normal file
1
qpdf/qtest/qpdf/completion-quoting.out
Normal file
@ -0,0 +1 @@
|
||||
owner-password
|
1
qpdf/qtest/qpdf/completion-usage-empty.out
Normal file
1
qpdf/qtest/qpdf/completion-usage-empty.out
Normal file
@ -0,0 +1 @@
|
||||
!--check
|
Loading…
Reference in New Issue
Block a user