]> git.saurik.com Git - wxWidgets.git/blame - src/common/cmdline.cpp
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / common / cmdline.cpp
CommitLineData
9f83044f
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: common/cmdline.cpp
3// Purpose: wxCmdLineParser implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 05.01.00
7// RCS-ID: $Id$
8// Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "cmdline.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/string.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
2822ee33 35 #include "wx/app.h"
9f83044f 36 #include "wx/dynarray.h"
2822ee33 37 #include "wx/filefn.h"
9f83044f
VZ
38#endif //WX_PRECOMP
39
ff0ea71c
GT
40#include <ctype.h>
41
9f83044f
VZ
42#include "wx/datetime.h"
43#include "wx/cmdline.h"
44
45// ----------------------------------------------------------------------------
46// private functions
47// ----------------------------------------------------------------------------
48
49static wxString GetTypeName(wxCmdLineParamType type);
50
51// ----------------------------------------------------------------------------
52// private classes
53// ----------------------------------------------------------------------------
54
55// an internal representation of an option
56struct wxCmdLineOption
57{
58 wxCmdLineOption(wxCmdLineEntryType k,
59 const wxString& shrt,
60 const wxString& lng,
61 const wxString& desc,
62 wxCmdLineParamType typ,
63 int fl)
64 {
65 kind = k;
66
67 shortName = shrt;
68 longName = lng;
69 description = desc;
70
71 type = typ;
72 flags = fl;
73
74 m_hasVal = FALSE;
75 }
76
77 // can't use union easily here, so just store all possible data fields, we
78 // don't waste much (might still use union later if the number of supported
79 // types increases, so always use the accessor functions and don't access
80 // the fields directly!)
81
6f2a55e3 82 void Check(wxCmdLineParamType WXUNUSED_UNLESS_DEBUG(typ)) const
9f83044f
VZ
83 {
84 wxASSERT_MSG( type == typ, _T("type mismatch in wxCmdLineOption") );
85 }
86
87 long GetLongVal() const
88 { Check(wxCMD_LINE_VAL_NUMBER); return m_longVal; }
89 const wxString& GetStrVal() const
90 { Check(wxCMD_LINE_VAL_STRING); return m_strVal; }
91 const wxDateTime& GetDateVal() const
92 { Check(wxCMD_LINE_VAL_DATE); return m_dateVal; }
93
94 void SetLongVal(long val)
95 { Check(wxCMD_LINE_VAL_NUMBER); m_longVal = val; m_hasVal = TRUE; }
96 void SetStrVal(const wxString& val)
97 { Check(wxCMD_LINE_VAL_STRING); m_strVal = val; m_hasVal = TRUE; }
98 void SetDateVal(const wxDateTime val)
99 { Check(wxCMD_LINE_VAL_DATE); m_dateVal = val; m_hasVal = TRUE; }
100
101 void SetHasValue() { m_hasVal = TRUE; }
102 bool HasValue() const { return m_hasVal; }
103
104public:
105 wxCmdLineEntryType kind;
106 wxString shortName, longName, description;
107 wxCmdLineParamType type;
108 int flags;
109
110private:
111 bool m_hasVal;
112
113 long m_longVal;
114 wxString m_strVal;
115 wxDateTime m_dateVal;
116};
117
118struct wxCmdLineParam
119{
120 wxCmdLineParam(const wxString& desc,
121 wxCmdLineParamType typ,
122 int fl)
123 : description(desc)
124 {
125 type = typ;
126 flags = fl;
127 }
128
129 wxString description;
130 wxCmdLineParamType type;
131 int flags;
132};
133
134WX_DECLARE_OBJARRAY(wxCmdLineOption, wxArrayOptions);
135WX_DECLARE_OBJARRAY(wxCmdLineParam, wxArrayParams);
136
137#include "wx/arrimpl.cpp"
138
139WX_DEFINE_OBJARRAY(wxArrayOptions);
140WX_DEFINE_OBJARRAY(wxArrayParams);
141
142// the parser internal state
143struct wxCmdLineParserData
144{
145 // options
146 wxString m_switchChars; // characters which may start an option
9f83044f 147 bool m_enableLongOptions; // TRUE if long options are enabled
e612f101 148 wxString m_logo; // some extra text to show in Usage()
9f83044f
VZ
149
150 // cmd line data
151 wxArrayString m_arguments; // == argv, argc == m_arguments.GetCount()
152 wxArrayOptions m_options; // all possible options and switchrs
153 wxArrayParams m_paramDesc; // description of all possible params
154 wxArrayString m_parameters; // all params found
155
156 // methods
157 wxCmdLineParserData();
158 void SetArguments(int argc, char **argv);
159 void SetArguments(const wxString& cmdline);
160
161 int FindOption(const wxString& name);
162 int FindOptionByLongName(const wxString& name);
163};
164
165// ============================================================================
166// implementation
167// ============================================================================
168
169// ----------------------------------------------------------------------------
170// wxCmdLineParserData
171// ----------------------------------------------------------------------------
172
173wxCmdLineParserData::wxCmdLineParserData()
174{
175 m_enableLongOptions = TRUE;
176#ifdef __UNIX_LIKE__
177 m_switchChars = _T("-");
178#else // !Unix
179 m_switchChars = _T("/-");
180#endif
181}
182
183void wxCmdLineParserData::SetArguments(int argc, char **argv)
184{
185 m_arguments.Empty();
186
187 for ( int n = 0; n < argc; n++ )
188 {
189 m_arguments.Add(argv[n]);
190 }
191}
192
6f2a55e3 193void wxCmdLineParserData::SetArguments(const wxString& WXUNUSED(cmdline))
9f83044f
VZ
194{
195 // either use wxMSW wxApp::ConvertToStandardCommandArgs() or move its logic
196 // here and use this method from it - but don't duplicate the code
197
198 wxFAIL_MSG(_T("TODO"));
199}
200
201int wxCmdLineParserData::FindOption(const wxString& name)
202{
203 size_t count = m_options.GetCount();
204 for ( size_t n = 0; n < count; n++ )
205 {
206 if ( m_options[n].shortName == name )
207 {
208 // found
209 return n;
210 }
211 }
212
213 return wxNOT_FOUND;
214}
215
216int wxCmdLineParserData::FindOptionByLongName(const wxString& name)
217{
218 size_t count = m_options.GetCount();
219 for ( size_t n = 0; n < count; n++ )
220 {
221 if ( m_options[n].longName == name )
222 {
223 // found
224 return n;
225 }
226 }
227
228 return wxNOT_FOUND;
229}
230
231// ----------------------------------------------------------------------------
232// construction and destruction
233// ----------------------------------------------------------------------------
234
235void wxCmdLineParser::Init()
236{
237 m_data = new wxCmdLineParserData;
238}
239
240void wxCmdLineParser::SetCmdLine(int argc, char **argv)
241{
242 m_data->SetArguments(argc, argv);
243}
244
245void wxCmdLineParser::SetCmdLine(const wxString& cmdline)
246{
247 m_data->SetArguments(cmdline);
248}
249
250wxCmdLineParser::~wxCmdLineParser()
251{
252 delete m_data;
253}
254
255// ----------------------------------------------------------------------------
256// options
257// ----------------------------------------------------------------------------
258
259void wxCmdLineParser::SetSwitchChars(const wxString& switchChars)
260{
261 m_data->m_switchChars = switchChars;
262}
263
264void wxCmdLineParser::EnableLongOptions(bool enable)
265{
266 m_data->m_enableLongOptions = enable;
267}
268
e612f101
VZ
269void wxCmdLineParser::SetLogo(const wxString& logo)
270{
271 m_data->m_logo = logo;
272}
273
9f83044f
VZ
274// ----------------------------------------------------------------------------
275// command line construction
276// ----------------------------------------------------------------------------
277
278void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc *desc)
279{
280 for ( ;; desc++ )
281 {
282 switch ( desc->kind )
283 {
284 case wxCMD_LINE_SWITCH:
e612f101
VZ
285 AddSwitch(desc->shortName, desc->longName, desc->description,
286 desc->flags);
9f83044f
VZ
287 break;
288
289 case wxCMD_LINE_OPTION:
290 AddOption(desc->shortName, desc->longName, desc->description,
291 desc->type, desc->flags);
292 break;
293
294 case wxCMD_LINE_PARAM:
295 AddParam(desc->description, desc->type, desc->flags);
296 break;
297
298 default:
299 wxFAIL_MSG( _T("unknown command line entry type") );
300 // still fall through
301
302 case wxCMD_LINE_NONE:
303 return;
304 }
305 }
306}
307
308void wxCmdLineParser::AddSwitch(const wxString& shortName,
309 const wxString& longName,
310 const wxString& desc,
311 int flags)
312{
313 wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
314 _T("duplicate switch") );
315
316 wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_SWITCH,
317 shortName, longName, desc,
318 wxCMD_LINE_VAL_NONE, flags);
319
320 m_data->m_options.Add(option);
321}
322
323void wxCmdLineParser::AddOption(const wxString& shortName,
324 const wxString& longName,
325 const wxString& desc,
326 wxCmdLineParamType type,
327 int flags)
328{
329 wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
330 _T("duplicate option") );
331
332 wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_OPTION,
333 shortName, longName, desc,
334 type, flags);
335
336 m_data->m_options.Add(option);
337}
338
339void wxCmdLineParser::AddParam(const wxString& desc,
340 wxCmdLineParamType type,
341 int flags)
342{
343 // do some consistency checks: a required parameter can't follow an
344 // optional one and nothing should follow a parameter with MULTIPLE flag
345#ifdef __WXDEBUG__
346 if ( !m_data->m_paramDesc.IsEmpty() )
347 {
348 wxCmdLineParam& param = m_data->m_paramDesc.Last();
349
350 wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE),
fbdcff4a 351 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
9f83044f
VZ
352
353 if ( !(flags & wxCMD_LINE_PARAM_OPTIONAL) )
354 {
355 wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL),
fbdcff4a 356 _T("a required parameter can't follow an optional one") );
9f83044f
VZ
357 }
358 }
359#endif // Debug
360
361 wxCmdLineParam *param = new wxCmdLineParam(desc, type, flags);
362
363 m_data->m_paramDesc.Add(param);
364}
365
366// ----------------------------------------------------------------------------
367// access to parse command line
368// ----------------------------------------------------------------------------
369
370bool wxCmdLineParser::Found(const wxString& name) const
371{
372 int i = m_data->FindOption(name);
373 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown switch") );
374
375 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
376 if ( !opt.HasValue() )
377 return FALSE;
378
379 return TRUE;
380}
381
382bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
383{
384 int i = m_data->FindOption(name);
385 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown option") );
386
387 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
388 if ( !opt.HasValue() )
389 return FALSE;
390
391 wxCHECK_MSG( value, FALSE, _T("NULL pointer in wxCmdLineOption::Found") );
392
393 *value = opt.GetStrVal();
394
395 return TRUE;
396}
397
398bool wxCmdLineParser::Found(const wxString& name, long *value) const
399{
400 int i = m_data->FindOption(name);
401 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown option") );
402
403 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
404 if ( !opt.HasValue() )
405 return FALSE;
406
407 wxCHECK_MSG( value, FALSE, _T("NULL pointer in wxCmdLineOption::Found") );
408
409 *value = opt.GetLongVal();
410
411 return TRUE;
412}
413
414bool wxCmdLineParser::Found(const wxString& name, wxDateTime *value) const
415{
416 int i = m_data->FindOption(name);
417 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown option") );
418
419 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
420 if ( !opt.HasValue() )
421 return FALSE;
422
423 wxCHECK_MSG( value, FALSE, _T("NULL pointer in wxCmdLineOption::Found") );
424
425 *value = opt.GetDateVal();
426
427 return TRUE;
428}
429
430size_t wxCmdLineParser::GetParamCount() const
431{
432 return m_data->m_parameters.GetCount();
433}
434
435wxString wxCmdLineParser::GetParam(size_t n) const
436{
437 return m_data->m_parameters[n];
438}
439
440// ----------------------------------------------------------------------------
441// the real work is done here
442// ----------------------------------------------------------------------------
443
444int wxCmdLineParser::Parse()
445{
446 bool maybeOption = TRUE; // can the following arg be an option?
447 bool ok = TRUE; // TRUE until an error is detected
448 bool helpRequested = FALSE; // TRUE if "-h" was given
449 bool hadRepeatableParam = FALSE; // TRUE if found param with MULTIPLE flag
450
451 size_t currentParam = 0; // the index in m_paramDesc
452
453 size_t countParam = m_data->m_paramDesc.GetCount();
454
455 // parse everything
456 wxString arg;
457 size_t count = m_data->m_arguments.GetCount();
458 for ( size_t n = 1; ok && (n < count); n++ ) // 0 is program name
459 {
460 arg = m_data->m_arguments[n];
461
462 // special case: "--" should be discarded and all following arguments
463 // should be considered as parameters, even if they start with '-' and
464 // not like options (this is POSIX-like)
465 if ( arg == _T("--") )
466 {
467 maybeOption = FALSE;
468
469 continue;
470 }
471
472 // empty argument or just '-' is not an option but a parameter
473 if ( maybeOption && arg.length() > 1 &&
474 wxStrchr(m_data->m_switchChars, arg[0u]) )
475 {
476 bool isLong;
477 wxString name;
478 int optInd = wxNOT_FOUND; // init to suppress warnings
479
480 // an option or a switch: find whether it's a long or a short one
481 if ( m_data->m_enableLongOptions &&
482 arg[0u] == _T('-') && arg[1u] == _T('-') )
483 {
484 // a long one
485 isLong = TRUE;
486
487 const wxChar *p = arg.c_str() + 2;
f6bcfd97 488 while ( wxIsalnum(*p) || (*p == _T('_')) || (*p == _T('-')) )
9f83044f
VZ
489 {
490 name += *p++;
491 }
492
493 optInd = m_data->FindOptionByLongName(name);
494 if ( optInd == wxNOT_FOUND )
495 {
496 wxLogError(_("Unknown long option '%s'"), name.c_str());
497 }
498 }
499 else
500 {
501 isLong = FALSE;
502
503 // a short one: as they can be cumulated, we try to find the
504 // longest substring which is a valid option
505 const wxChar *p = arg.c_str() + 1;
f6bcfd97 506 while ( wxIsalnum(*p) || (*p == _T('_')) )
9f83044f
VZ
507 {
508 name += *p++;
509 }
510
511 size_t len = name.length();
512 do
513 {
514 if ( len == 0 )
515 {
516 // we couldn't find a valid option name in the
517 // beginning of this string
518 wxLogError(_("Unknown option '%s'"), name.c_str());
519
520 break;
521 }
522 else
523 {
524 optInd = m_data->FindOption(name.Left(len));
525
526 // will try with one character less the next time
527 len--;
528 }
529 }
530 while ( optInd == wxNOT_FOUND );
531
2822ee33 532 len++; // compensates extra len-- above
4f40f5e3 533 if ( (optInd != wxNOT_FOUND) && (len != name.length()) )
9f83044f 534 {
2822ee33
VZ
535 // first of all, the option name is only part of this
536 // string
537 name = name.Left(len);
538
9f83044f
VZ
539 // our option is only part of this argument, there is
540 // something else in it - it is either the value of this
541 // option or other switches if it is a switch
542 if ( m_data->m_options[(size_t)optInd].kind
543 == wxCMD_LINE_SWITCH )
544 {
545 // pretend that all the rest of the argument is the
546 // next argument, in fact
547 wxString arg2 = arg[0u];
2822ee33 548 arg2 += arg.Mid(len + 1); // +1 for leading '-'
9f83044f
VZ
549
550 m_data->m_arguments.Insert(arg2, n + 1);
4f40f5e3 551 count++;
9f83044f
VZ
552 }
553 //else: it's our value, we'll deal with it below
554 }
555 }
556
557 if ( optInd == wxNOT_FOUND )
558 {
559 ok = FALSE;
560
561 continue; // will break, in fact
562 }
563
564 wxCmdLineOption& opt = m_data->m_options[(size_t)optInd];
565 if ( opt.kind == wxCMD_LINE_SWITCH )
566 {
567 // nothing more to do
568 opt.SetHasValue();
569
570 if ( opt.flags & wxCMD_LINE_OPTION_HELP )
571 {
572 helpRequested = TRUE;
573
574 // it's not an error, but we still stop here
575 ok = FALSE;
576 }
577 }
578 else
579 {
580 // get the value
581
582 // +1 for leading '-'
583 const wxChar *p = arg.c_str() + 1 + name.length();
584 if ( isLong )
585 {
586 p++; // for another leading '-'
587
588 if ( *p++ != _T('=') )
589 {
fbdcff4a 590 wxLogError(_("Option '%s' requires a value, '=' expected."), name.c_str());
9f83044f
VZ
591
592 ok = FALSE;
593 }
594 }
595 else
596 {
597 switch ( *p )
598 {
f6bcfd97 599 case _T('='):
9f83044f
VZ
600 case _T(':'):
601 // the value follows
602 p++;
603 break;
604
605 case 0:
606 // the value is in the next argument
607 if ( ++n == count )
608 {
609 // ... but there is none
610 wxLogError(_("Option '%s' requires a value."),
611 name.c_str());
612
613 ok = FALSE;
614 }
615 else
616 {
617 // ... take it from there
618 p = m_data->m_arguments[n].c_str();
619 }
620 break;
621
622 default:
f6bcfd97
BP
623 // the value is right here: this may be legal or
624 // not depending on the option style
625 if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR )
626 {
627 wxLogError(_("Separator expected after the option '%s'."),
628 name.c_str());
629
630 ok = FALSE;
631 }
9f83044f
VZ
632 }
633 }
634
635 if ( ok )
636 {
637 wxString value = p;
638 switch ( opt.type )
639 {
640 default:
641 wxFAIL_MSG( _T("unknown option type") );
642 // still fall through
643
644 case wxCMD_LINE_VAL_STRING:
645 opt.SetStrVal(value);
646 break;
647
648 case wxCMD_LINE_VAL_NUMBER:
649 {
650 long val;
651 if ( value.ToLong(&val) )
652 {
653 opt.SetLongVal(val);
654 }
655 else
656 {
fbdcff4a 657 wxLogError(_("'%s' is not a correct numeric value for option '%s'."),
9f83044f
VZ
658 value.c_str(), name.c_str());
659
660 ok = FALSE;
661 }
662 }
663 break;
664
665 case wxCMD_LINE_VAL_DATE:
666 {
667 wxDateTime dt;
668 const wxChar *res = dt.ParseDate(value);
669 if ( !res || *res )
670 {
fbdcff4a 671 wxLogError(_("Option '%s': '%s' cannot be converted to a date."),
9f83044f
VZ
672 name.c_str(), value.c_str());
673
674 ok = FALSE;
675 }
676 else
677 {
678 opt.SetDateVal(dt);
679 }
680 }
681 break;
682 }
683 }
684 }
685 }
686 else
687 {
688 // a parameter
689 if ( currentParam < countParam )
690 {
691 wxCmdLineParam& param = m_data->m_paramDesc[currentParam];
692
693 // TODO check the param type
694
695 m_data->m_parameters.Add(arg);
696
697 if ( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE) )
698 {
699 currentParam++;
700 }
701 else
702 {
703 wxASSERT_MSG( currentParam == countParam - 1,
fbdcff4a 704 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
9f83044f
VZ
705
706 // remember that we did have this last repeatable parameter
707 hadRepeatableParam = TRUE;
708 }
709 }
710 else
711 {
712 wxLogError(_("Unexpected parameter '%s'"), arg.c_str());
713
714 ok = FALSE;
715 }
716 }
717 }
718
719 // verify that all mandatory options were given
720 if ( ok )
721 {
722 size_t countOpt = m_data->m_options.GetCount();
723 for ( size_t n = 0; ok && (n < countOpt); n++ )
724 {
725 wxCmdLineOption& opt = m_data->m_options[n];
726 if ( (opt.flags & wxCMD_LINE_OPTION_MANDATORY) && !opt.HasValue() )
727 {
728 wxString optName;
729 if ( !opt.longName )
730 {
731 optName = opt.shortName;
732 }
733 else
734 {
735 optName.Printf(_("%s (or %s)"),
736 opt.shortName.c_str(),
737 opt.longName.c_str());
738 }
739
740 wxLogError(_("The value for the option '%s' must be specified."),
741 optName.c_str());
742
743 ok = FALSE;
744 }
745 }
746
747 for ( ; ok && (currentParam < countParam); currentParam++ )
748 {
749 wxCmdLineParam& param = m_data->m_paramDesc[currentParam];
750 if ( (currentParam == countParam - 1) &&
751 (param.flags & wxCMD_LINE_PARAM_MULTIPLE) &&
752 hadRepeatableParam )
753 {
754 // special case: currentParam wasn't incremented, but we did
755 // have it, so don't give error
756 continue;
757 }
758
759 if ( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL) )
760 {
761 wxLogError(_("The required parameter '%s' was not specified."),
762 param.description.c_str());
763
764 ok = FALSE;
765 }
766 }
767 }
768
769 if ( !ok )
770 {
771 Usage();
772 }
773
774 return ok ? 0 : helpRequested ? -1 : 1;
775}
776
777// ----------------------------------------------------------------------------
778// give the usage message
779// ----------------------------------------------------------------------------
780
781void wxCmdLineParser::Usage()
782{
2822ee33
VZ
783 wxString appname = wxTheApp->GetAppName();
784 if ( !appname )
785 {
786 wxCHECK_RET( !m_data->m_arguments.IsEmpty(), _T("no program name") );
787
788 appname = wxFileNameFromPath(m_data->m_arguments[0]);
789 wxStripExtension(appname);
790 }
791
f6bcfd97
BP
792 // we construct the brief cmd line desc on the fly, but not the detailed
793 // help message below because we want to align the options descriptions
794 // and for this we must first know the longest one of them
795 wxString brief;
796 wxArrayString namesOptions, descOptions;
2822ee33 797 brief.Printf(_("Usage: %s"), appname.c_str());
9f83044f 798
f6bcfd97
BP
799 // the switch char is usually '-' but this can be changed with
800 // SetSwitchChars() and then the first one of possible chars is used
801 wxChar chSwitch = !m_data->m_switchChars ? _T('-')
802 : m_data->m_switchChars[0u];
803
9f83044f
VZ
804 size_t n, count = m_data->m_options.GetCount();
805 for ( n = 0; n < count; n++ )
806 {
807 wxCmdLineOption& opt = m_data->m_options[n];
808
809 brief << _T(' ');
810 if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
811 {
812 brief << _T('[');
813 }
814
f6bcfd97
BP
815 brief << chSwitch << opt.shortName;
816
817 wxString option;
818 option << _T(" ") << chSwitch << opt.shortName;
9f83044f
VZ
819 if ( !!opt.longName )
820 {
f6bcfd97 821 option << _T(" --") << opt.longName;
9f83044f
VZ
822 }
823
824 if ( opt.kind != wxCMD_LINE_SWITCH )
825 {
826 wxString val;
827 val << _T('<') << GetTypeName(opt.type) << _T('>');
828 brief << _T(' ') << val;
f6bcfd97 829 option << (!opt.longName ? _T(':') : _T('=')) << val;
9f83044f
VZ
830 }
831
832 if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
833 {
834 brief << _T(']');
835 }
836
f6bcfd97
BP
837 namesOptions.Add(option);
838 descOptions.Add(opt.description);
9f83044f
VZ
839 }
840
841 count = m_data->m_paramDesc.GetCount();
842 for ( n = 0; n < count; n++ )
843 {
844 wxCmdLineParam& param = m_data->m_paramDesc[n];
845
846 brief << _T(' ');
847 if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
848 {
849 brief << _T('[');
850 }
851
852 brief << param.description;
853
854 if ( param.flags & wxCMD_LINE_PARAM_MULTIPLE )
855 {
856 brief << _T("...");
857 }
858
859 if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
860 {
861 brief << _T(']');
862 }
863 }
864
e612f101
VZ
865 if ( !!m_data->m_logo )
866 {
867 wxLogMessage(m_data->m_logo);
868 }
869
9f83044f 870 wxLogMessage(brief);
f6bcfd97
BP
871
872 // now construct the detailed help message
873 size_t len, lenMax = 0;
874 count = namesOptions.GetCount();
875 for ( n = 0; n < count; n++ )
876 {
877 len = namesOptions[n].length();
878 if ( len > lenMax )
879 lenMax = len;
880 }
881
882 wxString detailed;
883 for ( n = 0; n < count; n++ )
884 {
885 len = namesOptions[n].length();
886 detailed << namesOptions[n]
887 << wxString(_T(' '), lenMax - len) << _T('\t')
888 << descOptions[n]
889 << _T('\n');
890 }
891
9f83044f
VZ
892 wxLogMessage(detailed);
893}
894
895// ----------------------------------------------------------------------------
896// global functions
897// ----------------------------------------------------------------------------
898
899static wxString GetTypeName(wxCmdLineParamType type)
900{
901 wxString s;
902 switch ( type )
903 {
904 default:
905 wxFAIL_MSG( _T("unknown option type") );
906 // still fall through
907
908 case wxCMD_LINE_VAL_STRING: s = _("str"); break;
909 case wxCMD_LINE_VAL_NUMBER: s = _("num"); break;
910 case wxCMD_LINE_VAL_DATE: s = _("date"); break;
911 }
912
913 return s;
914}