1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/cmdline.cpp
3 // Purpose: wxCmdLineParser implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/dynarray.h"
29 #include "wx/string.h"
35 #include "wx/cmdline.h"
37 #if wxUSE_CMDLINE_PARSER
41 #include "wx/datetime.h"
42 #include "wx/msgout.h"
43 #include "wx/filename.h"
44 #include "wx/apptrait.h"
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 static wxString
GetTypeName(wxCmdLineParamType type
);
52 static wxString
GetOptionName(wxString::const_iterator p
,
53 wxString::const_iterator end
,
54 const wxChar
*allowedChars
);
56 static wxString
GetShortOptionName(wxString::const_iterator p
,
57 wxString::const_iterator end
);
59 static wxString
GetLongOptionName(wxString::const_iterator p
,
60 wxString::const_iterator end
);
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 // an internal representation of an option
67 struct wxCmdLineOption
69 wxCmdLineOption(wxCmdLineEntryType k
,
73 wxCmdLineParamType typ
,
76 wxASSERT_MSG( !shrt
.empty() || !lng
.empty(),
77 _T("option should have at least one name") );
81 GetShortOptionName(shrt
.begin(), shrt
.end()).Len() == shrt
.Len(),
82 wxT("Short option contains invalid characters")
87 GetLongOptionName(lng
.begin(), lng
.end()).Len() == lng
.Len(),
88 wxT("Long option contains invalid characters")
104 // can't use union easily here, so just store all possible data fields, we
105 // don't waste much (might still use union later if the number of supported
106 // types increases, so always use the accessor functions and don't access
107 // the fields directly!)
109 void Check(wxCmdLineParamType
WXUNUSED_UNLESS_DEBUG(typ
)) const
111 wxASSERT_MSG( type
== typ
, _T("type mismatch in wxCmdLineOption") );
114 long GetLongVal() const
115 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
116 const wxString
& GetStrVal() const
117 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
119 const wxDateTime
& GetDateVal() const
120 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
121 #endif // wxUSE_DATETIME
123 void SetLongVal(long val
)
124 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
125 void SetStrVal(const wxString
& val
)
126 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
128 void SetDateVal(const wxDateTime
& val
)
129 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
130 #endif // wxUSE_DATETIME
132 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
133 bool HasValue() const { return m_hasVal
; }
136 wxCmdLineEntryType kind
;
140 wxCmdLineParamType type
;
149 wxDateTime m_dateVal
;
150 #endif // wxUSE_DATETIME
153 struct wxCmdLineParam
155 wxCmdLineParam(const wxString
& desc
,
156 wxCmdLineParamType typ
,
164 wxString description
;
165 wxCmdLineParamType type
;
169 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
170 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
172 #include "wx/arrimpl.cpp"
174 WX_DEFINE_OBJARRAY(wxArrayOptions
)
175 WX_DEFINE_OBJARRAY(wxArrayParams
)
177 // the parser internal state
178 struct wxCmdLineParserData
181 wxString m_switchChars
; // characters which may start an option
182 bool m_enableLongOptions
; // true if long options are enabled
183 wxString m_logo
; // some extra text to show in Usage()
186 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
187 wxArrayOptions m_options
; // all possible options and switches
188 wxArrayParams m_paramDesc
; // description of all possible params
189 wxArrayString m_parameters
; // all params found
192 wxCmdLineParserData();
193 void SetArguments(int argc
, char **argv
);
195 void SetArguments(int argc
, wxChar
**argv
);
196 #endif // wxUSE_UNICODE
197 void SetArguments(const wxString
& cmdline
);
199 int FindOption(const wxString
& name
);
200 int FindOptionByLongName(const wxString
& name
);
203 // ============================================================================
205 // ============================================================================
207 // ----------------------------------------------------------------------------
208 // wxCmdLineParserData
209 // ----------------------------------------------------------------------------
211 wxCmdLineParserData::wxCmdLineParserData()
213 m_enableLongOptions
= true;
215 m_switchChars
= _T("-");
217 m_switchChars
= _T("/-");
221 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
225 for ( int n
= 0; n
< argc
; n
++ )
227 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
233 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
237 for ( int n
= 0; n
< argc
; n
++ )
239 m_arguments
.push_back(argv
[n
]);
243 #endif // wxUSE_UNICODE
245 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
249 if(wxTheApp
&& wxTheApp
->argc
> 0)
250 m_arguments
.push_back(wxTheApp
->argv
[0]);
252 m_arguments
.push_back(wxEmptyString
);
254 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
256 WX_APPEND_ARRAY(m_arguments
, args
);
259 int wxCmdLineParserData::FindOption(const wxString
& name
)
263 size_t count
= m_options
.GetCount();
264 for ( size_t n
= 0; n
< count
; n
++ )
266 if ( m_options
[n
].shortName
== name
)
277 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
279 size_t count
= m_options
.GetCount();
280 for ( size_t n
= 0; n
< count
; n
++ )
282 if ( m_options
[n
].longName
== name
)
292 // ----------------------------------------------------------------------------
293 // construction and destruction
294 // ----------------------------------------------------------------------------
296 void wxCmdLineParser::Init()
298 m_data
= new wxCmdLineParserData
;
301 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
303 m_data
->SetArguments(argc
, argv
);
308 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
310 m_data
->SetArguments(argc
, argv
);
313 #endif // wxUSE_UNICODE
315 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
317 m_data
->SetArguments(cmdline
);
320 wxCmdLineParser::~wxCmdLineParser()
325 // ----------------------------------------------------------------------------
327 // ----------------------------------------------------------------------------
329 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
331 m_data
->m_switchChars
= switchChars
;
334 void wxCmdLineParser::EnableLongOptions(bool enable
)
336 m_data
->m_enableLongOptions
= enable
;
339 bool wxCmdLineParser::AreLongOptionsEnabled()
341 return m_data
->m_enableLongOptions
;
344 void wxCmdLineParser::SetLogo(const wxString
& logo
)
346 m_data
->m_logo
= logo
;
349 // ----------------------------------------------------------------------------
350 // command line construction
351 // ----------------------------------------------------------------------------
353 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
357 switch ( desc
->kind
)
359 case wxCMD_LINE_SWITCH
:
360 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
364 case wxCMD_LINE_OPTION
:
365 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
366 desc
->type
, desc
->flags
);
369 case wxCMD_LINE_PARAM
:
370 AddParam(desc
->description
, desc
->type
, desc
->flags
);
374 wxFAIL_MSG( _T("unknown command line entry type") );
375 // still fall through
377 case wxCMD_LINE_NONE
:
383 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
384 const wxString
& longName
,
385 const wxString
& desc
,
388 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
389 _T("duplicate switch") );
391 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
392 shortName
, longName
, desc
,
393 wxCMD_LINE_VAL_NONE
, flags
);
395 m_data
->m_options
.Add(option
);
398 void wxCmdLineParser::AddOption(const wxString
& shortName
,
399 const wxString
& longName
,
400 const wxString
& desc
,
401 wxCmdLineParamType type
,
404 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
405 _T("duplicate option") );
407 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
408 shortName
, longName
, desc
,
411 m_data
->m_options
.Add(option
);
414 void wxCmdLineParser::AddParam(const wxString
& desc
,
415 wxCmdLineParamType type
,
418 // do some consistency checks: a required parameter can't follow an
419 // optional one and nothing should follow a parameter with MULTIPLE flag
421 if ( !m_data
->m_paramDesc
.IsEmpty() )
423 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
425 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
426 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
428 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
430 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
431 _T("a required parameter can't follow an optional one") );
436 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
438 m_data
->m_paramDesc
.Add(param
);
441 // ----------------------------------------------------------------------------
442 // access to parse command line
443 // ----------------------------------------------------------------------------
445 bool wxCmdLineParser::Found(const wxString
& name
) const
447 int i
= m_data
->FindOption(name
);
448 if ( i
== wxNOT_FOUND
)
449 i
= m_data
->FindOptionByLongName(name
);
451 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
453 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
454 if ( !opt
.HasValue() )
460 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
462 int i
= m_data
->FindOption(name
);
463 if ( i
== wxNOT_FOUND
)
464 i
= m_data
->FindOptionByLongName(name
);
466 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
468 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
469 if ( !opt
.HasValue() )
472 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
474 *value
= opt
.GetStrVal();
479 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
481 int i
= m_data
->FindOption(name
);
482 if ( i
== wxNOT_FOUND
)
483 i
= m_data
->FindOptionByLongName(name
);
485 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
487 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
488 if ( !opt
.HasValue() )
491 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
493 *value
= opt
.GetLongVal();
499 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
501 int i
= m_data
->FindOption(name
);
502 if ( i
== wxNOT_FOUND
)
503 i
= m_data
->FindOptionByLongName(name
);
505 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
507 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
508 if ( !opt
.HasValue() )
511 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
513 *value
= opt
.GetDateVal();
517 #endif // wxUSE_DATETIME
519 size_t wxCmdLineParser::GetParamCount() const
521 return m_data
->m_parameters
.size();
524 wxString
wxCmdLineParser::GetParam(size_t n
) const
526 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
528 return m_data
->m_parameters
[n
];
531 // Resets switches and options
532 void wxCmdLineParser::Reset()
534 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
536 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
537 opt
.SetHasValue(false);
542 // ----------------------------------------------------------------------------
543 // the real work is done here
544 // ----------------------------------------------------------------------------
546 int wxCmdLineParser::Parse(bool showUsage
)
548 bool maybeOption
= true; // can the following arg be an option?
549 bool ok
= true; // true until an error is detected
550 bool helpRequested
= false; // true if "-h" was given
551 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
553 size_t currentParam
= 0; // the index in m_paramDesc
555 size_t countParam
= m_data
->m_paramDesc
.GetCount();
562 size_t count
= m_data
->m_arguments
.size();
563 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
565 arg
= m_data
->m_arguments
[n
];
567 // special case: "--" should be discarded and all following arguments
568 // should be considered as parameters, even if they start with '-' and
569 // not like options (this is POSIX-like)
570 if ( arg
== _T("--") )
577 // empty argument or just '-' is not an option but a parameter
578 if ( maybeOption
&& arg
.length() > 1 &&
579 // FIXME-UTF8: use wc_str() after removing ANSI build
580 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) )
584 int optInd
= wxNOT_FOUND
; // init to suppress warnings
586 // an option or a switch: find whether it's a long or a short one
587 if ( arg
.length() >= 3 && arg
[0u] == _T('-') && arg
[1u] == _T('-') )
593 wxString::const_iterator p
= arg
.begin() + 2;
595 bool longOptionsEnabled
= AreLongOptionsEnabled();
597 name
= GetLongOptionName(p
, arg
.end());
599 if (longOptionsEnabled
)
601 optInd
= m_data
->FindOptionByLongName(name
);
602 if ( optInd
== wxNOT_FOUND
)
604 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
610 optInd
= wxNOT_FOUND
; // Sanity check
612 // Print the argument including leading "--"
613 name
.Prepend( wxT("--") );
614 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
619 else // not a long option
623 // a short one: as they can be cumulated, we try to find the
624 // longest substring which is a valid option
625 wxString::const_iterator p
= arg
.begin() + 1;
627 name
= GetShortOptionName(p
, arg
.end());
629 size_t len
= name
.length();
634 // we couldn't find a valid option name in the
635 // beginning of this string
636 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
643 optInd
= m_data
->FindOption(name
.Left(len
));
645 // will try with one character less the next time
649 while ( optInd
== wxNOT_FOUND
);
651 len
++; // compensates extra len-- above
652 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
654 // first of all, the option name is only part of this
656 name
= name
.Left(len
);
658 // our option is only part of this argument, there is
659 // something else in it - it is either the value of this
660 // option or other switches if it is a switch
661 if ( m_data
->m_options
[(size_t)optInd
].kind
662 == wxCMD_LINE_SWITCH
)
664 // pretend that all the rest of the argument is the
665 // next argument, in fact
666 wxString arg2
= arg
[0u];
667 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
669 m_data
->m_arguments
.insert
670 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
673 //else: it's our value, we'll deal with it below
677 if ( optInd
== wxNOT_FOUND
)
681 continue; // will break, in fact
684 // look at what follows:
686 // +1 for leading '-'
687 wxString::const_iterator p
= arg
.begin() + 1 + name
.length();
688 wxString::const_iterator end
= arg
.end();
691 ++p
; // for another leading '-'
693 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
694 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
696 // we must check that there is no value following the switch
697 if ( p
!= arg
.end() )
699 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
703 else // no value, as expected
705 // nothing more to do
708 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
710 helpRequested
= true;
712 // it's not an error, but we still stop here
717 else // it's an option. not a switch
722 if ( *p
++ != _T('=') )
724 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str())
732 switch ( (*p
).GetValue() )
741 // the value is in the next argument
744 // ... but there is none
745 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
753 // ... take it from there
754 p
= m_data
->m_arguments
[n
].begin();
755 end
= m_data
->m_arguments
[n
].end();
760 // the value is right here: this may be legal or
761 // not depending on the option style
762 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
764 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
775 wxString
value(p
, end
);
779 wxFAIL_MSG( _T("unknown option type") );
780 // still fall through
782 case wxCMD_LINE_VAL_STRING
:
783 opt
.SetStrVal(value
);
786 case wxCMD_LINE_VAL_NUMBER
:
789 if ( value
.ToLong(&val
) )
795 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
796 value
.c_str(), name
.c_str())
805 case wxCMD_LINE_VAL_DATE
:
808 // FIXME-UTF8: ParseDate API will need changes
809 const wxChar
*res
= dt
.ParseDate(value
.c_str());
812 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
813 name
.c_str(), value
.c_str())
824 #endif // wxUSE_DATETIME
829 else // not an option, must be a parameter
831 if ( currentParam
< countParam
)
833 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
835 // TODO check the param type
837 m_data
->m_parameters
.push_back(arg
);
839 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
845 wxASSERT_MSG( currentParam
== countParam
- 1,
846 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
848 // remember that we did have this last repeatable parameter
849 hadRepeatableParam
= true;
854 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
862 // verify that all mandatory options were given
865 size_t countOpt
= m_data
->m_options
.GetCount();
866 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
868 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
869 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
874 optName
= opt
.shortName
;
878 if ( AreLongOptionsEnabled() )
880 optName
.Printf( _("%s (or %s)"),
881 opt
.shortName
.c_str(),
882 opt
.longName
.c_str() );
886 optName
.Printf( wxT("%s"),
887 opt
.shortName
.c_str() );
891 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
899 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
901 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
902 if ( (currentParam
== countParam
- 1) &&
903 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
906 // special case: currentParam wasn't incremented, but we did
907 // have it, so don't give error
911 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
913 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
914 param
.description
.c_str())
922 // if there was an error during parsing the command line, show this error
923 // and also the usage message if it had been requested
924 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
926 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
931 usage
= GetUsageString();
933 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
937 wxFAIL_MSG( _T("no wxMessageOutput object?") );
941 return ok
? 0 : helpRequested
? -1 : 1;
944 // ----------------------------------------------------------------------------
945 // give the usage message
946 // ----------------------------------------------------------------------------
948 void wxCmdLineParser::Usage()
950 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
953 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
957 wxFAIL_MSG( _T("no wxMessageOutput object?") );
961 wxString
wxCmdLineParser::GetUsageString()
964 if ( m_data
->m_arguments
.empty() )
967 appname
= wxTheApp
->GetAppName();
971 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
974 // we construct the brief cmd line desc on the fly, but not the detailed
975 // help message below because we want to align the options descriptions
976 // and for this we must first know the longest one of them
978 wxArrayString namesOptions
, descOptions
;
980 if ( !m_data
->m_logo
.empty() )
982 usage
<< m_data
->m_logo
<< _T('\n');
985 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
987 // the switch char is usually '-' but this can be changed with
988 // SetSwitchChars() and then the first one of possible chars is used
989 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
990 : m_data
->m_switchChars
[0u];
992 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
993 size_t n
, count
= m_data
->m_options
.GetCount();
994 for ( n
= 0; n
< count
; n
++ )
996 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
999 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1004 if ( !opt
.shortName
.empty() )
1006 usage
<< chSwitch
<< opt
.shortName
;
1008 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1010 usage
<< _T("--") << opt
.longName
;
1014 if (!opt
.longName
.empty())
1016 wxFAIL_MSG( wxT("option with only a long name while long ")
1017 wxT("options are disabled") );
1021 wxFAIL_MSG( _T("option without neither short nor long name") );
1027 if ( !opt
.shortName
.empty() )
1029 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1032 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1034 option
<< (option
.empty() ? _T(" ") : _T(", "))
1035 << _T("--") << opt
.longName
;
1038 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1041 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1042 usage
<< _T(' ') << val
;
1043 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1046 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1051 namesOptions
.push_back(option
);
1052 descOptions
.push_back(opt
.description
);
1055 count
= m_data
->m_paramDesc
.GetCount();
1056 for ( n
= 0; n
< count
; n
++ )
1058 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1061 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1066 usage
<< param
.description
;
1068 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1073 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1081 // set to number of our own options, not counting the standard ones
1082 count
= namesOptions
.size();
1084 // get option names & descriptions for standard options, if any:
1085 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1088 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1090 // now construct the detailed help message
1091 size_t len
, lenMax
= 0;
1092 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1094 len
= namesOptions
[n
].length();
1099 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1102 usage
<< _T('\n') << stdDesc
;
1104 len
= namesOptions
[n
].length();
1105 usage
<< namesOptions
[n
]
1106 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1114 // ----------------------------------------------------------------------------
1115 // private functions
1116 // ----------------------------------------------------------------------------
1118 static wxString
GetTypeName(wxCmdLineParamType type
)
1124 wxFAIL_MSG( _T("unknown option type") );
1125 // still fall through
1127 case wxCMD_LINE_VAL_STRING
:
1131 case wxCMD_LINE_VAL_NUMBER
:
1135 case wxCMD_LINE_VAL_DATE
:
1144 Returns a string which is equal to the string pointed to by p, but up to the
1145 point where p contains an character that's not allowed.
1146 Allowable characters are letters and numbers, and characters pointed to by
1147 the parameter allowedChars.
1149 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1150 this function returns "abcde-".
1152 static wxString
GetOptionName(wxString::const_iterator p
,
1153 wxString::const_iterator end
,
1154 const wxChar
*allowedChars
)
1158 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1166 // Besides alphanumeric characters, short and long options can
1167 // have other characters.
1169 // A short option additionally can have these
1170 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1172 // A long option can have the same characters as a short option and a '-'.
1173 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1174 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1176 static wxString
GetShortOptionName(wxString::const_iterator p
,
1177 wxString::const_iterator end
)
1179 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1182 static wxString
GetLongOptionName(wxString::const_iterator p
,
1183 wxString::const_iterator end
)
1185 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1188 #endif // wxUSE_CMDLINE_PARSER
1190 // ----------------------------------------------------------------------------
1192 // ----------------------------------------------------------------------------
1195 This function is mainly used under Windows (as under Unix we always get the
1196 command line arguments as argc/argv anyhow) and so it tries to follow
1197 Windows conventions for the command line handling, not Unix ones. For
1198 instance, backslash is not special except when it precedes double quote when
1203 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
)
1210 bool isInsideQuotes
= false;
1212 wxString::const_iterator p
= cmdline
.begin();
1217 while ( p
!= cmdline
.end() && (*p
== _T(' ') || *p
== _T('\t')) )
1221 if ( p
== cmdline
.end() )
1224 // parse this parameter
1225 bool endParam
= false;
1226 bool lastBS
= false;
1227 for ( arg
.clear(); !endParam
; p
++ )
1229 switch ( (*p
).GetValue() )
1234 isInsideQuotes
= !isInsideQuotes
;
1236 // don't put quote in arg
1239 //else: quote has no special meaning but the backslash
1240 // still remains -- makes no sense but this is what
1246 // backslash does *not* quote the space, only quotes do
1247 if ( isInsideQuotes
)
1249 // skip assignment below
1265 lastBS
= *p
== _T('\\');
1270 args
.push_back(arg
);