Commit 53ba65eb59d0bced37e73d8bf96a0d7a7285f662

Authored by Jay Berkenbilt
1 parent a301cc53

QPDFArgParser: handle optional choices including help

Handle optional choices in addition to required choices. Refactor the
way help options are added to completion to make it work with optional
help choices.
generate_auto_job
@@ -119,7 +119,7 @@ class Main: @@ -119,7 +119,7 @@ class Main:
119 self.check_keys('top', o, set( 119 self.check_keys('top', o, set(
120 ['table', 'prefix', 'bare', 'positional', 120 ['table', 'prefix', 'bare', 'positional',
121 'optional_parameter', 'required_parameter', 121 'optional_parameter', 'required_parameter',
122 - 'required_choices', 'from_table'])) 122 + 'required_choices', 'optional_choices', 'from_table']))
123 123
124 def to_identifier(self, label, prefix, const): 124 def to_identifier(self, label, prefix, const):
125 identifier = re.sub(r'[^a-zA-Z0-9]', '_', label) 125 identifier = re.sub(r'[^a-zA-Z0-9]', '_', label)
@@ -157,6 +157,9 @@ class Main: @@ -157,6 +157,9 @@ class Main:
157 for i in o.get('required_choices', {}): 157 for i in o.get('required_choices', {}):
158 identifier = self.to_identifier(i, prefix, False) 158 identifier = self.to_identifier(i, prefix, False)
159 print(f'void {identifier}(char *);', file=f) 159 print(f'void {identifier}(char *);', file=f)
  160 + for i in o.get('optional_choices', {}):
  161 + identifier = self.to_identifier(i, prefix, False)
  162 + print(f'void {identifier}(char *);', file=f)
160 if table not in ('main', 'help'): 163 if table not in ('main', 'help'):
161 identifier = self.to_identifier(table, 'argEnd', False) 164 identifier = self.to_identifier(table, 'argEnd', False)
162 print(f'void {identifier}();', file=f) 165 print(f'void {identifier}();', file=f)
@@ -204,9 +207,14 @@ class Main: @@ -204,9 +207,14 @@ class Main:
204 f', "{v}");', file=f) 207 f', "{v}");', file=f)
205 for k, v in o.get('required_choices', {}).items(): 208 for k, v in o.get('required_choices', {}).items():
206 identifier = self.to_identifier(k, prefix, False) 209 identifier = self.to_identifier(k, prefix, False)
207 - print(f'this->ap.addRequiredChoices("{k}", ' 210 + print(f'this->ap.addChoices("{k}", '
  211 + f'p(&ArgParser::{identifier})'
  212 + f', true, {v}_choices);', file=f)
  213 + for k, v in o.get('optional_choices', {}).items():
  214 + identifier = self.to_identifier(k, prefix, False)
  215 + print(f'this->ap.addChoices("{k}", '
208 f'p(&ArgParser::{identifier})' 216 f'p(&ArgParser::{identifier})'
209 - f', {v}_choices);', file=f) 217 + f', false, {v}_choices);', file=f)
210 for o in data['options']: 218 for o in data['options']:
211 table = o['table'] 219 table = o['table']
212 if 'from_table' not in o: 220 if 'from_table' not in o:
include/qpdf/QPDFArgParser.hh
@@ -115,13 +115,14 @@ class QPDFArgParser @@ -115,13 +115,14 @@ class QPDFArgParser
115 QPDF_DLL 115 QPDF_DLL
116 void addOptionalParameter(std::string const& arg, param_arg_handler_t); 116 void addOptionalParameter(std::string const& arg, param_arg_handler_t);
117 QPDF_DLL 117 QPDF_DLL
118 - void addRequiredChoices(  
119 - std::string const& arg, param_arg_handler_t, char const** choices);  
120 - QPDF_DLL 118 + void addChoices(
  119 + std::string const& arg, param_arg_handler_t,
  120 + bool required, char const** choices);
121 121
122 // If an option is shared among multiple tables and uses identical 122 // If an option is shared among multiple tables and uses identical
123 // handlers, you can just copy it instead of repeating the 123 // handlers, you can just copy it instead of repeating the
124 // registration call. 124 // registration call.
  125 + QPDF_DLL
125 void copyFromOtherTable(std::string const& arg, 126 void copyFromOtherTable(std::string const& arg,
126 std::string const& other_table); 127 std::string const& other_table);
127 128
@@ -179,7 +180,7 @@ class QPDFArgParser @@ -179,7 +180,7 @@ class QPDFArgParser
179 bare_arg_handler_t bare_arg_handler; 180 bare_arg_handler_t bare_arg_handler;
180 param_arg_handler_t param_arg_handler; 181 param_arg_handler_t param_arg_handler;
181 }; 182 };
182 - friend struct OptionEntry; 183 + typedef std::map<std::string, OptionEntry> option_table_t;
183 184
184 OptionEntry& registerArg(std::string const& arg); 185 OptionEntry& registerArg(std::string const& arg);
185 186
@@ -187,18 +188,20 @@ class QPDFArgParser @@ -187,18 +188,20 @@ class QPDFArgParser
187 188
188 void argCompletionBash(); 189 void argCompletionBash();
189 void argCompletionZsh(); 190 void argCompletionZsh();
  191 + void argHelp(char*);
190 192
191 void checkCompletion(); 193 void checkCompletion();
192 void handleArgFileArguments(); 194 void handleArgFileArguments();
193 void handleBashArguments(); 195 void handleBashArguments();
194 void readArgsFromFile(char const* filename); 196 void readArgsFromFile(char const* filename);
195 void doFinalChecks(); 197 void doFinalChecks();
196 - void addOptionsToCompletions();  
197 - void addChoicesToCompletions(std::string const&, std::string const&); 198 + void addOptionsToCompletions(option_table_t&);
  199 + void addChoicesToCompletions(
  200 + option_table_t&, std::string const&, std::string const&);
  201 + void insertCompletions(
  202 + option_table_t&, std::string const&, std::string const&);
198 void handleCompletion(); 203 void handleCompletion();
199 204
200 - typedef std::map<std::string, OptionEntry> option_table_t;  
201 -  
202 class Members 205 class Members
203 { 206 {
204 friend class QPDFArgParser; 207 friend class QPDFArgParser;
job.sums
1 # Generated by generate_auto_job 1 # Generated by generate_auto_job
2 -generate_auto_job 575569edf2ab0036ed7f810bf506968c73c9209a64ec0ae2ed959f0426291447  
3 -job.yml 5de5f1cd3f998274ed4aafa234e61b726a8f96157148ad463970439a96e897bd  
4 -libqpdf/qpdf/auto_job_decl.hh fca37543c1a2b7f675374e23b1ab34b30a7f5f2d843c53d4bc7e9a12bf4c3615  
5 -libqpdf/qpdf/auto_job_init.hh 7d7dfe96d4da765b8defb646058027584ea8924c604c558402aa7f2d2e61a005 2 +generate_auto_job 019081046f1bc19f498134eae00344ecfc65b4e52442ee5f1bc80bff99689443
  3 +job.yml 8e5b3fe5a6abea64a5a33977c440a7ac9ecc4516d2a131ed38fd4bc1a73445d7
  4 +libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a
  5 +libqpdf/qpdf/auto_job_init.hh 465bf46769559ceb77110d1b9d3293ba9b3595850b49848c31aeabd10aadb4ad
@@ -51,7 +51,6 @@ choices: @@ -51,7 +51,6 @@ choices:
51 options: 51 options:
52 - table: help 52 - table: help
53 bare: 53 bare:
54 - - help  
55 - version 54 - version
56 - copyright 55 - copyright
57 - json-help 56 - json-help
libqpdf/QPDFArgParser.cc
@@ -35,6 +35,9 @@ QPDFArgParser::QPDFArgParser(int argc, char* argv[], char const* progname_env) : @@ -35,6 +35,9 @@ QPDFArgParser::QPDFArgParser(int argc, char* argv[], char const* progname_env) :
35 m(new Members(argc, argv, progname_env)) 35 m(new Members(argc, argv, progname_env))
36 { 36 {
37 selectHelpOptionTable(); 37 selectHelpOptionTable();
  38 + char const* help_choices[] = {"all", 0};
  39 + addChoices(
  40 + "help", bindParam(&QPDFArgParser::argHelp, this), false, help_choices);
38 addBare("completion-bash", 41 addBare("completion-bash",
39 std::bind(std::mem_fn(&QPDFArgParser::argCompletionBash), this)); 42 std::bind(std::mem_fn(&QPDFArgParser::argCompletionBash), this));
40 addBare("completion-zsh", 43 addBare("completion-zsh",
@@ -139,13 +142,14 @@ QPDFArgParser::addOptionalParameter( @@ -139,13 +142,14 @@ QPDFArgParser::addOptionalParameter(
139 } 142 }
140 143
141 void 144 void
142 -QPDFArgParser::addRequiredChoices( 145 +QPDFArgParser::addChoices(
143 std::string const& arg, 146 std::string const& arg,
144 param_arg_handler_t handler, 147 param_arg_handler_t handler,
  148 + bool required,
145 char const** choices) 149 char const** choices)
146 { 150 {
147 OptionEntry& oe = registerArg(arg); 151 OptionEntry& oe = registerArg(arg);
148 - oe.parameter_needed = true; 152 + oe.parameter_needed = required;
149 oe.param_arg_handler = handler; 153 oe.param_arg_handler = handler;
150 for (char const** i = choices; *i; ++i) 154 for (char const** i = choices; *i; ++i)
151 { 155 {
@@ -254,6 +258,12 @@ QPDFArgParser::argCompletionZsh() @@ -254,6 +258,12 @@ QPDFArgParser::argCompletionZsh()
254 } 258 }
255 259
256 void 260 void
  261 +QPDFArgParser::argHelp(char*)
  262 +{
  263 + // QXXXQ
  264 +}
  265 +
  266 +void
257 QPDFArgParser::handleArgFileArguments() 267 QPDFArgParser::handleArgFileArguments()
258 { 268 {
259 // Support reading arguments from files. Create a new argv. Ensure 269 // Support reading arguments from files. Create a new argv. Ensure
@@ -624,10 +634,9 @@ QPDFArgParser::parseArgs() @@ -624,10 +634,9 @@ QPDFArgParser::parseArgs()
624 } 634 }
625 635
626 OptionEntry& oe = oep->second; 636 OptionEntry& oe = oep->second;
627 - if ((oe.parameter_needed && (0 == parameter)) ||  
628 - ((! oe.choices.empty() &&  
629 - ((0 == parameter) ||  
630 - (0 == oe.choices.count(parameter)))))) 637 + if ((oe.parameter_needed && (nullptr == parameter)) ||
  638 + ((! oe.choices.empty() && (nullptr != parameter) &&
  639 + (0 == oe.choices.count(parameter)))))
631 { 640 {
632 std::string message = 641 std::string message =
633 "--" + arg_s + " must be given as --" + arg_s + "="; 642 "--" + arg_s + " must be given as --" + arg_s + "=";
@@ -708,12 +717,13 @@ QPDFArgParser::doFinalChecks() @@ -708,12 +717,13 @@ QPDFArgParser::doFinalChecks()
708 } 717 }
709 718
710 void 719 void
711 -QPDFArgParser::addChoicesToCompletions(std::string const& option, 720 +QPDFArgParser::addChoicesToCompletions(option_table_t& option_table,
  721 + std::string const& option,
712 std::string const& extra_prefix) 722 std::string const& extra_prefix)
713 { 723 {
714 - if (this->m->option_table->count(option) != 0) 724 + if (option_table.count(option) != 0)
715 { 725 {
716 - OptionEntry& oe = (*this->m->option_table)[option]; 726 + OptionEntry& oe = option_table[option];
717 for (std::set<std::string>::iterator iter = oe.choices.begin(); 727 for (std::set<std::string>::iterator iter = oe.choices.begin();
718 iter != oe.choices.end(); ++iter) 728 iter != oe.choices.end(); ++iter)
719 { 729 {
@@ -724,18 +734,16 @@ QPDFArgParser::addChoicesToCompletions(std::string const&amp; option, @@ -724,18 +734,16 @@ QPDFArgParser::addChoicesToCompletions(std::string const&amp; option,
724 } 734 }
725 735
726 void 736 void
727 -QPDFArgParser::addOptionsToCompletions() 737 +QPDFArgParser::addOptionsToCompletions(option_table_t& option_table)
728 { 738 {
729 - for (std::map<std::string, OptionEntry>::iterator iter =  
730 - this->m->option_table->begin();  
731 - iter != this->m->option_table->end(); ++iter) 739 + for (auto& iter: option_table)
732 { 740 {
733 - std::string const& arg = (*iter).first; 741 + std::string const& arg = iter.first;
734 if (arg == "--") 742 if (arg == "--")
735 { 743 {
736 continue; 744 continue;
737 } 745 }
738 - OptionEntry& oe = (*iter).second; 746 + OptionEntry& oe = iter.second;
739 std::string base = "--" + arg; 747 std::string base = "--" + arg;
740 if (oe.param_arg_handler) 748 if (oe.param_arg_handler)
741 { 749 {
@@ -743,7 +751,7 @@ QPDFArgParser::addOptionsToCompletions() @@ -743,7 +751,7 @@ QPDFArgParser::addOptionsToCompletions()
743 { 751 {
744 // zsh doesn't treat = as a word separator, so add all 752 // zsh doesn't treat = as a word separator, so add all
745 // the options so we don't get a space after the =. 753 // the options so we don't get a space after the =.
746 - addChoicesToCompletions(arg, base + "="); 754 + addChoicesToCompletions(option_table, arg, base + "=");
747 } 755 }
748 this->m->completions.insert(base + "="); 756 this->m->completions.insert(base + "=");
749 } 757 }
@@ -755,6 +763,22 @@ QPDFArgParser::addOptionsToCompletions() @@ -755,6 +763,22 @@ QPDFArgParser::addOptionsToCompletions()
755 } 763 }
756 764
757 void 765 void
  766 +QPDFArgParser::insertCompletions(option_table_t& option_table,
  767 + std::string const& choice_option,
  768 + std::string const& extra_prefix)
  769 +{
  770 + if (! choice_option.empty())
  771 + {
  772 + addChoicesToCompletions(option_table, choice_option, extra_prefix);
  773 + }
  774 + else if ((! this->m->bash_cur.empty()) &&
  775 + (this->m->bash_cur.at(0) == '-'))
  776 + {
  777 + addOptionsToCompletions(option_table);
  778 + }
  779 +}
  780 +
  781 +void
758 QPDFArgParser::handleCompletion() 782 QPDFArgParser::handleCompletion()
759 { 783 {
760 std::string extra_prefix; 784 std::string extra_prefix;
@@ -795,29 +819,17 @@ QPDFArgParser::handleCompletion() @@ -795,29 +819,17 @@ QPDFArgParser::handleCompletion()
795 } 819 }
796 } 820 }
797 } 821 }
798 - if (! choice_option.empty()) 822 + if (this->m->zsh_completion && (! choice_option.empty()))
799 { 823 {
800 - if (this->m->zsh_completion)  
801 - {  
802 - // zsh wants --option=choice rather than just choice  
803 - extra_prefix = "--" + choice_option + "=";  
804 - }  
805 - addChoicesToCompletions(choice_option, extra_prefix); 824 + // zsh wants --option=choice rather than just choice
  825 + extra_prefix = "--" + choice_option + "=";
806 } 826 }
807 - else if ((! this->m->bash_cur.empty()) &&  
808 - (this->m->bash_cur.at(0) == '-')) 827 + insertCompletions(*this->m->option_table, choice_option, extra_prefix);
  828 + if (this->m->argc == 1)
809 { 829 {
810 - addOptionsToCompletions();  
811 - if (this->m->argc == 1)  
812 - {  
813 - // Help options are valid only by themselves.  
814 - for (std::map<std::string, OptionEntry>::iterator iter =  
815 - this->m->help_option_table.begin();  
816 - iter != this->m->help_option_table.end(); ++iter)  
817 - {  
818 - this->m->completions.insert("--" + (*iter).first);  
819 - }  
820 - } 830 + // Help options are valid only by themselves.
  831 + insertCompletions(
  832 + this->m->help_option_table, choice_option, extra_prefix);
821 } 833 }
822 } 834 }
823 std::string prefix = extra_prefix + this->m->bash_cur; 835 std::string prefix = extra_prefix + this->m->bash_cur;
libqpdf/QPDFJob_argv.cc
@@ -127,9 +127,11 @@ ArgParser::argCopyright() @@ -127,9 +127,11 @@ ArgParser::argCopyright()
127 << std::endl; 127 << std::endl;
128 } 128 }
129 129
  130 +#if 0
130 void 131 void
131 ArgParser::argHelp() 132 ArgParser::argHelp()
132 { 133 {
  134 + // QXXXQ
133 std::cout 135 std::cout
134 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 136 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
135 << "Usage: qpdf [options] {infile | --empty} [page_selection_options] outfile\n" 137 << "Usage: qpdf [options] {infile | --empty} [page_selection_options] outfile\n"
@@ -630,6 +632,7 @@ ArgParser::argHelp() @@ -630,6 +632,7 @@ ArgParser::argHelp()
630 << "qpdf to completely ignore warnings. qpdf does not use exit status 1,\n" 632 << "qpdf to completely ignore warnings. qpdf does not use exit status 1,\n"
631 << "since that is used by the shell if it can't execute qpdf.\n"; 633 << "since that is used by the shell if it can't execute qpdf.\n";
632 } 634 }
  635 +#endif
633 636
634 void 637 void
635 ArgParser::argJsonHelp() 638 ArgParser::argJsonHelp()
libqpdf/qpdf/auto_job_decl.hh
@@ -12,7 +12,6 @@ static constexpr char const* O_UNDERLAY_OVERLAY = &quot;underlay/overlay&quot;; @@ -12,7 +12,6 @@ static constexpr char const* O_UNDERLAY_OVERLAY = &quot;underlay/overlay&quot;;
12 static constexpr char const* O_ATTACHMENT = "attachment"; 12 static constexpr char const* O_ATTACHMENT = "attachment";
13 static constexpr char const* O_COPY_ATTACHMENT = "copy attachment"; 13 static constexpr char const* O_COPY_ATTACHMENT = "copy attachment";
14 14
15 -void argHelp();  
16 void argVersion(); 15 void argVersion();
17 void argCopyright(); 16 void argCopyright();
18 void argJsonHelp(); 17 void argJsonHelp();
libqpdf/qpdf/auto_job_init.hh
@@ -22,7 +22,6 @@ char const* print128_choices[] = {&quot;full&quot;, &quot;low&quot;, &quot;none&quot;, 0}; @@ -22,7 +22,6 @@ char const* print128_choices[] = {&quot;full&quot;, &quot;low&quot;, &quot;none&quot;, 0};
22 char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0}; 22 char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0};
23 23
24 this->ap.selectHelpOptionTable(); 24 this->ap.selectHelpOptionTable();
25 -this->ap.addBare("help", b(&ArgParser::argHelp));  
26 this->ap.addBare("version", b(&ArgParser::argVersion)); 25 this->ap.addBare("version", b(&ArgParser::argVersion));
27 this->ap.addBare("copyright", b(&ArgParser::argCopyright)); 26 this->ap.addBare("copyright", b(&ArgParser::argCopyright));
28 this->ap.addBare("json-help", b(&ArgParser::argJsonHelp)); 27 this->ap.addBare("json-help", b(&ArgParser::argJsonHelp));
@@ -99,38 +98,38 @@ this-&gt;ap.addRequiredParameter(&quot;remove-attachment&quot;, p(&amp;ArgParser::argRemoveAttach @@ -99,38 +98,38 @@ this-&gt;ap.addRequiredParameter(&quot;remove-attachment&quot;, p(&amp;ArgParser::argRemoveAttach
99 this->ap.addRequiredParameter("rotate", p(&ArgParser::argRotate), "[+|-]angle"); 98 this->ap.addRequiredParameter("rotate", p(&ArgParser::argRotate), "[+|-]angle");
100 this->ap.addRequiredParameter("show-attachment", p(&ArgParser::argShowAttachment), "attachment"); 99 this->ap.addRequiredParameter("show-attachment", p(&ArgParser::argShowAttachment), "attachment");
101 this->ap.addRequiredParameter("show-object", p(&ArgParser::argShowObject), "trailer"); 100 this->ap.addRequiredParameter("show-object", p(&ArgParser::argShowObject), "trailer");
102 -this->ap.addRequiredChoices("compress-streams", p(&ArgParser::argCompressStreams), yn_choices);  
103 -this->ap.addRequiredChoices("decode-level", p(&ArgParser::argDecodeLevel), decode_level_choices);  
104 -this->ap.addRequiredChoices("flatten-annotations", p(&ArgParser::argFlattenAnnotations), flatten_choices);  
105 -this->ap.addRequiredChoices("json-key", p(&ArgParser::argJsonKey), json_key_choices);  
106 -this->ap.addRequiredChoices("keep-files-open", p(&ArgParser::argKeepFilesOpen), yn_choices);  
107 -this->ap.addRequiredChoices("normalize-content", p(&ArgParser::argNormalizeContent), yn_choices);  
108 -this->ap.addRequiredChoices("object-streams", p(&ArgParser::argObjectStreams), object_streams_choices);  
109 -this->ap.addRequiredChoices("password-mode", p(&ArgParser::argPasswordMode), password_mode_choices);  
110 -this->ap.addRequiredChoices("remove-unreferenced-resources", p(&ArgParser::argRemoveUnreferencedResources), remove_unref_choices);  
111 -this->ap.addRequiredChoices("stream-data", p(&ArgParser::argStreamData), stream_data_choices); 101 +this->ap.addChoices("compress-streams", p(&ArgParser::argCompressStreams), true, yn_choices);
  102 +this->ap.addChoices("decode-level", p(&ArgParser::argDecodeLevel), true, decode_level_choices);
  103 +this->ap.addChoices("flatten-annotations", p(&ArgParser::argFlattenAnnotations), true, flatten_choices);
  104 +this->ap.addChoices("json-key", p(&ArgParser::argJsonKey), true, json_key_choices);
  105 +this->ap.addChoices("keep-files-open", p(&ArgParser::argKeepFilesOpen), true, yn_choices);
  106 +this->ap.addChoices("normalize-content", p(&ArgParser::argNormalizeContent), true, yn_choices);
  107 +this->ap.addChoices("object-streams", p(&ArgParser::argObjectStreams), true, object_streams_choices);
  108 +this->ap.addChoices("password-mode", p(&ArgParser::argPasswordMode), true, password_mode_choices);
  109 +this->ap.addChoices("remove-unreferenced-resources", p(&ArgParser::argRemoveUnreferencedResources), true, remove_unref_choices);
  110 +this->ap.addChoices("stream-data", p(&ArgParser::argStreamData), true, stream_data_choices);
112 this->ap.registerOptionTable("pages", b(&ArgParser::argEndPages)); 111 this->ap.registerOptionTable("pages", b(&ArgParser::argEndPages));
113 this->ap.addPositional(p(&ArgParser::argPagesPositional)); 112 this->ap.addPositional(p(&ArgParser::argPagesPositional));
114 this->ap.addRequiredParameter("password", p(&ArgParser::argPagesPassword), "password"); 113 this->ap.addRequiredParameter("password", p(&ArgParser::argPagesPassword), "password");
115 this->ap.registerOptionTable("encryption", b(&ArgParser::argEndEncryption)); 114 this->ap.registerOptionTable("encryption", b(&ArgParser::argEndEncryption));
116 this->ap.addPositional(p(&ArgParser::argEncPositional)); 115 this->ap.addPositional(p(&ArgParser::argEncPositional));
117 this->ap.registerOptionTable("40-bit encryption", b(&ArgParser::argEnd40BitEncryption)); 116 this->ap.registerOptionTable("40-bit encryption", b(&ArgParser::argEnd40BitEncryption));
118 -this->ap.addRequiredChoices("extract", p(&ArgParser::argEnc40Extract), yn_choices);  
119 -this->ap.addRequiredChoices("annotate", p(&ArgParser::argEnc40Annotate), yn_choices);  
120 -this->ap.addRequiredChoices("print", p(&ArgParser::argEnc40Print), yn_choices);  
121 -this->ap.addRequiredChoices("modify", p(&ArgParser::argEnc40Modify), yn_choices); 117 +this->ap.addChoices("extract", p(&ArgParser::argEnc40Extract), true, yn_choices);
  118 +this->ap.addChoices("annotate", p(&ArgParser::argEnc40Annotate), true, yn_choices);
  119 +this->ap.addChoices("print", p(&ArgParser::argEnc40Print), true, yn_choices);
  120 +this->ap.addChoices("modify", p(&ArgParser::argEnc40Modify), true, yn_choices);
122 this->ap.registerOptionTable("128-bit encryption", b(&ArgParser::argEnd128BitEncryption)); 121 this->ap.registerOptionTable("128-bit encryption", b(&ArgParser::argEnd128BitEncryption));
123 this->ap.addBare("cleartext-metadata", b(&ArgParser::argEnc128CleartextMetadata)); 122 this->ap.addBare("cleartext-metadata", b(&ArgParser::argEnc128CleartextMetadata));
124 this->ap.addBare("force-V4", b(&ArgParser::argEnc128ForceV4)); 123 this->ap.addBare("force-V4", b(&ArgParser::argEnc128ForceV4));
125 -this->ap.addRequiredChoices("accessibility", p(&ArgParser::argEnc128Accessibility), yn_choices);  
126 -this->ap.addRequiredChoices("extract", p(&ArgParser::argEnc128Extract), yn_choices);  
127 -this->ap.addRequiredChoices("print", p(&ArgParser::argEnc128Print), print128_choices);  
128 -this->ap.addRequiredChoices("assemble", p(&ArgParser::argEnc128Assemble), yn_choices);  
129 -this->ap.addRequiredChoices("annotate", p(&ArgParser::argEnc128Annotate), yn_choices);  
130 -this->ap.addRequiredChoices("form", p(&ArgParser::argEnc128Form), yn_choices);  
131 -this->ap.addRequiredChoices("modify-other", p(&ArgParser::argEnc128ModifyOther), yn_choices);  
132 -this->ap.addRequiredChoices("modify", p(&ArgParser::argEnc128Modify), modify128_choices);  
133 -this->ap.addRequiredChoices("use-aes", p(&ArgParser::argEnc128UseAes), yn_choices); 124 +this->ap.addChoices("accessibility", p(&ArgParser::argEnc128Accessibility), true, yn_choices);
  125 +this->ap.addChoices("extract", p(&ArgParser::argEnc128Extract), true, yn_choices);
  126 +this->ap.addChoices("print", p(&ArgParser::argEnc128Print), true, print128_choices);
  127 +this->ap.addChoices("assemble", p(&ArgParser::argEnc128Assemble), true, yn_choices);
  128 +this->ap.addChoices("annotate", p(&ArgParser::argEnc128Annotate), true, yn_choices);
  129 +this->ap.addChoices("form", p(&ArgParser::argEnc128Form), true, yn_choices);
  130 +this->ap.addChoices("modify-other", p(&ArgParser::argEnc128ModifyOther), true, yn_choices);
  131 +this->ap.addChoices("modify", p(&ArgParser::argEnc128Modify), true, modify128_choices);
  132 +this->ap.addChoices("use-aes", p(&ArgParser::argEnc128UseAes), true, yn_choices);
134 this->ap.registerOptionTable("256-bit encryption", b(&ArgParser::argEnd256BitEncryption)); 133 this->ap.registerOptionTable("256-bit encryption", b(&ArgParser::argEnd256BitEncryption));
135 this->ap.addBare("force-R5", b(&ArgParser::argEnc256ForceR5)); 134 this->ap.addBare("force-R5", b(&ArgParser::argEnc256ForceR5));
136 this->ap.addBare("allow-insecure", b(&ArgParser::argEnc256AllowInsecure)); 135 this->ap.addBare("allow-insecure", b(&ArgParser::argEnc256AllowInsecure));
libtests/arg_parser.cc
@@ -51,7 +51,7 @@ ArgParser::initOptions() @@ -51,7 +51,7 @@ ArgParser::initOptions()
51 ap.addRequiredParameter("salad", p(&ArgParser::handleSalad), "tossed"); 51 ap.addRequiredParameter("salad", p(&ArgParser::handleSalad), "tossed");
52 ap.addOptionalParameter("moo", p(&ArgParser::handleMoo)); 52 ap.addOptionalParameter("moo", p(&ArgParser::handleMoo));
53 char const* choices[] = {"pig", "boar", "sow", 0}; 53 char const* choices[] = {"pig", "boar", "sow", 0};
54 - ap.addRequiredChoices("oink", p(&ArgParser::handleOink), choices); 54 + ap.addChoices("oink", p(&ArgParser::handleOink), true, choices);
55 ap.selectHelpOptionTable(); 55 ap.selectHelpOptionTable();
56 ap.addBare("version", [this](){ output("3.14159"); }); 56 ap.addBare("version", [this](){ output("3.14159"); });
57 ap.selectMainOptionTable(); 57 ap.selectMainOptionTable();
libtests/qtest/arg_parser/completion-top-arg-zsh.out
1 --baaa 1 --baaa
2 --completion-zsh 2 --completion-zsh
  3 +--help
  4 +--help=
  5 +--help=all
3 --moo 6 --moo
4 --moo= 7 --moo=
5 --oink= 8 --oink=