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 void SetArguments(int argc
, const wxCmdLineArgsArray
& argv
);
197 #endif // wxUSE_UNICODE
198 void SetArguments(const wxString
& cmdline
);
200 int FindOption(const wxString
& name
);
201 int FindOptionByLongName(const wxString
& name
);
204 // ============================================================================
206 // ============================================================================
208 // ----------------------------------------------------------------------------
209 // wxCmdLineParserData
210 // ----------------------------------------------------------------------------
212 wxCmdLineParserData::wxCmdLineParserData()
214 m_enableLongOptions
= true;
216 m_switchChars
= _T("-");
218 m_switchChars
= _T("/-");
222 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
226 for ( int n
= 0; n
< argc
; n
++ )
228 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
234 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
238 for ( int n
= 0; n
< argc
; n
++ )
240 m_arguments
.push_back(argv
[n
]);
244 void wxCmdLineParserData::SetArguments(int WXUNUSED(argc
),
245 const wxCmdLineArgsArray
& argv
)
247 m_arguments
= argv
.GetArguments();
250 #endif // wxUSE_UNICODE
252 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
256 if(wxTheApp
&& wxTheApp
->argc
> 0)
257 m_arguments
.push_back(wxTheApp
->argv
[0]);
259 m_arguments
.push_back(wxEmptyString
);
261 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
263 WX_APPEND_ARRAY(m_arguments
, args
);
266 int wxCmdLineParserData::FindOption(const wxString
& name
)
270 size_t count
= m_options
.GetCount();
271 for ( size_t n
= 0; n
< count
; n
++ )
273 if ( m_options
[n
].shortName
== name
)
284 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
286 size_t count
= m_options
.GetCount();
287 for ( size_t n
= 0; n
< count
; n
++ )
289 if ( m_options
[n
].longName
== name
)
299 // ----------------------------------------------------------------------------
300 // construction and destruction
301 // ----------------------------------------------------------------------------
303 void wxCmdLineParser::Init()
305 m_data
= new wxCmdLineParserData
;
308 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
310 m_data
->SetArguments(argc
, argv
);
315 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
317 m_data
->SetArguments(argc
, argv
);
320 void wxCmdLineParser::SetCmdLine(int argc
, const wxCmdLineArgsArray
& argv
)
322 m_data
->SetArguments(argc
, argv
);
325 #endif // wxUSE_UNICODE
327 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
329 m_data
->SetArguments(cmdline
);
332 wxCmdLineParser::~wxCmdLineParser()
337 // ----------------------------------------------------------------------------
339 // ----------------------------------------------------------------------------
341 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
343 m_data
->m_switchChars
= switchChars
;
346 void wxCmdLineParser::EnableLongOptions(bool enable
)
348 m_data
->m_enableLongOptions
= enable
;
351 bool wxCmdLineParser::AreLongOptionsEnabled()
353 return m_data
->m_enableLongOptions
;
356 void wxCmdLineParser::SetLogo(const wxString
& logo
)
358 m_data
->m_logo
= logo
;
361 // ----------------------------------------------------------------------------
362 // command line construction
363 // ----------------------------------------------------------------------------
365 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
369 switch ( desc
->kind
)
371 case wxCMD_LINE_SWITCH
:
372 AddSwitch(desc
->shortName
, desc
->longName
,
373 wxGetTranslation(desc
->description
),
377 case wxCMD_LINE_OPTION
:
378 AddOption(desc
->shortName
, desc
->longName
,
379 wxGetTranslation(desc
->description
),
380 desc
->type
, desc
->flags
);
383 case wxCMD_LINE_PARAM
:
384 AddParam(wxGetTranslation(desc
->description
),
385 desc
->type
, desc
->flags
);
389 wxFAIL_MSG( _T("unknown command line entry type") );
390 // still fall through
392 case wxCMD_LINE_NONE
:
398 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
399 const wxString
& longName
,
400 const wxString
& desc
,
403 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
404 _T("duplicate switch") );
406 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
407 shortName
, longName
, desc
,
408 wxCMD_LINE_VAL_NONE
, flags
);
410 m_data
->m_options
.Add(option
);
413 void wxCmdLineParser::AddOption(const wxString
& shortName
,
414 const wxString
& longName
,
415 const wxString
& desc
,
416 wxCmdLineParamType type
,
419 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
420 _T("duplicate option") );
422 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
423 shortName
, longName
, desc
,
426 m_data
->m_options
.Add(option
);
429 void wxCmdLineParser::AddParam(const wxString
& desc
,
430 wxCmdLineParamType type
,
433 // do some consistency checks: a required parameter can't follow an
434 // optional one and nothing should follow a parameter with MULTIPLE flag
436 if ( !m_data
->m_paramDesc
.IsEmpty() )
438 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
440 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
441 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
443 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
445 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
446 _T("a required parameter can't follow an optional one") );
451 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
453 m_data
->m_paramDesc
.Add(param
);
456 // ----------------------------------------------------------------------------
457 // access to parse command line
458 // ----------------------------------------------------------------------------
460 bool wxCmdLineParser::Found(const wxString
& name
) 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 switch") );
468 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
469 if ( !opt
.HasValue() )
475 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
477 int i
= m_data
->FindOption(name
);
478 if ( i
== wxNOT_FOUND
)
479 i
= m_data
->FindOptionByLongName(name
);
481 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
483 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
484 if ( !opt
.HasValue() )
487 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
489 *value
= opt
.GetStrVal();
494 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
496 int i
= m_data
->FindOption(name
);
497 if ( i
== wxNOT_FOUND
)
498 i
= m_data
->FindOptionByLongName(name
);
500 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
502 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
503 if ( !opt
.HasValue() )
506 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
508 *value
= opt
.GetLongVal();
514 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
516 int i
= m_data
->FindOption(name
);
517 if ( i
== wxNOT_FOUND
)
518 i
= m_data
->FindOptionByLongName(name
);
520 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
522 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
523 if ( !opt
.HasValue() )
526 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
528 *value
= opt
.GetDateVal();
532 #endif // wxUSE_DATETIME
534 size_t wxCmdLineParser::GetParamCount() const
536 return m_data
->m_parameters
.size();
539 wxString
wxCmdLineParser::GetParam(size_t n
) const
541 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
543 return m_data
->m_parameters
[n
];
546 // Resets switches and options
547 void wxCmdLineParser::Reset()
549 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
551 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
552 opt
.SetHasValue(false);
557 // ----------------------------------------------------------------------------
558 // the real work is done here
559 // ----------------------------------------------------------------------------
561 int wxCmdLineParser::Parse(bool showUsage
)
563 bool maybeOption
= true; // can the following arg be an option?
564 bool ok
= true; // true until an error is detected
565 bool helpRequested
= false; // true if "-h" was given
566 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
568 size_t currentParam
= 0; // the index in m_paramDesc
570 size_t countParam
= m_data
->m_paramDesc
.GetCount();
577 size_t count
= m_data
->m_arguments
.size();
578 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
580 arg
= m_data
->m_arguments
[n
];
582 // special case: "--" should be discarded and all following arguments
583 // should be considered as parameters, even if they start with '-' and
584 // not like options (this is POSIX-like)
585 if ( arg
== _T("--") )
592 // empty argument or just '-' is not an option but a parameter
593 if ( maybeOption
&& arg
.length() > 1 &&
594 // FIXME-UTF8: use wc_str() after removing ANSI build
595 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) )
599 int optInd
= wxNOT_FOUND
; // init to suppress warnings
601 // an option or a switch: find whether it's a long or a short one
602 if ( arg
.length() >= 3 && arg
[0u] == _T('-') && arg
[1u] == _T('-') )
608 wxString::const_iterator p
= arg
.begin() + 2;
610 bool longOptionsEnabled
= AreLongOptionsEnabled();
612 name
= GetLongOptionName(p
, arg
.end());
614 if (longOptionsEnabled
)
616 optInd
= m_data
->FindOptionByLongName(name
);
617 if ( optInd
== wxNOT_FOUND
)
619 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
625 optInd
= wxNOT_FOUND
; // Sanity check
627 // Print the argument including leading "--"
628 name
.Prepend( wxT("--") );
629 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
634 else // not a long option
638 // a short one: as they can be cumulated, we try to find the
639 // longest substring which is a valid option
640 wxString::const_iterator p
= arg
.begin() + 1;
642 name
= GetShortOptionName(p
, arg
.end());
644 size_t len
= name
.length();
649 // we couldn't find a valid option name in the
650 // beginning of this string
651 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
658 optInd
= m_data
->FindOption(name
.Left(len
));
660 // will try with one character less the next time
664 while ( optInd
== wxNOT_FOUND
);
666 len
++; // compensates extra len-- above
667 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
669 // first of all, the option name is only part of this
671 name
= name
.Left(len
);
673 // our option is only part of this argument, there is
674 // something else in it - it is either the value of this
675 // option or other switches if it is a switch
676 if ( m_data
->m_options
[(size_t)optInd
].kind
677 == wxCMD_LINE_SWITCH
)
679 // pretend that all the rest of the argument is the
680 // next argument, in fact
681 wxString arg2
= arg
[0u];
682 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
684 m_data
->m_arguments
.insert
685 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
688 //else: it's our value, we'll deal with it below
692 if ( optInd
== wxNOT_FOUND
)
696 continue; // will break, in fact
699 // look at what follows:
701 // +1 for leading '-'
702 wxString::const_iterator p
= arg
.begin() + 1 + name
.length();
703 wxString::const_iterator end
= arg
.end();
706 ++p
; // for another leading '-'
708 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
709 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
711 // we must check that there is no value following the switch
712 if ( p
!= arg
.end() )
714 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
718 else // no value, as expected
720 // nothing more to do
723 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
725 helpRequested
= true;
727 // it's not an error, but we still stop here
732 else // it's an option. not a switch
734 switch ( (*p
).GetValue() )
743 // the value is in the next argument
746 // ... but there is none
747 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
755 // ... take it from there
756 p
= m_data
->m_arguments
[n
].begin();
757 end
= m_data
->m_arguments
[n
].end();
762 // the value is right here: this may be legal or
763 // not depending on the option style
764 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
766 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
776 wxString
value(p
, end
);
780 wxFAIL_MSG( _T("unknown option type") );
781 // still fall through
783 case wxCMD_LINE_VAL_STRING
:
784 opt
.SetStrVal(value
);
787 case wxCMD_LINE_VAL_NUMBER
:
790 if ( value
.ToLong(&val
) )
796 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
797 value
.c_str(), name
.c_str())
806 case wxCMD_LINE_VAL_DATE
:
809 const char *res
= dt
.ParseDate(value
);
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
);