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
719 switch ( (*p
).GetValue() )
728 // the value is in the next argument
731 // ... but there is none
732 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
740 // ... take it from there
741 p
= m_data
->m_arguments
[n
].begin();
742 end
= m_data
->m_arguments
[n
].end();
747 // the value is right here: this may be legal or
748 // not depending on the option style
749 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
751 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
761 wxString
value(p
, end
);
765 wxFAIL_MSG( _T("unknown option type") );
766 // still fall through
768 case wxCMD_LINE_VAL_STRING
:
769 opt
.SetStrVal(value
);
772 case wxCMD_LINE_VAL_NUMBER
:
775 if ( value
.ToLong(&val
) )
781 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
782 value
.c_str(), name
.c_str())
791 case wxCMD_LINE_VAL_DATE
:
794 // FIXME-UTF8: ParseDate API will need changes
795 const wxChar
*res
= dt
.ParseDate(value
.c_str());
798 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
799 name
.c_str(), value
.c_str())
810 #endif // wxUSE_DATETIME
815 else // not an option, must be a parameter
817 if ( currentParam
< countParam
)
819 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
821 // TODO check the param type
823 m_data
->m_parameters
.push_back(arg
);
825 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
831 wxASSERT_MSG( currentParam
== countParam
- 1,
832 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
834 // remember that we did have this last repeatable parameter
835 hadRepeatableParam
= true;
840 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
848 // verify that all mandatory options were given
851 size_t countOpt
= m_data
->m_options
.GetCount();
852 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
854 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
855 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
860 optName
= opt
.shortName
;
864 if ( AreLongOptionsEnabled() )
866 optName
.Printf( _("%s (or %s)"),
867 opt
.shortName
.c_str(),
868 opt
.longName
.c_str() );
872 optName
.Printf( wxT("%s"),
873 opt
.shortName
.c_str() );
877 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
885 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
887 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
888 if ( (currentParam
== countParam
- 1) &&
889 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
892 // special case: currentParam wasn't incremented, but we did
893 // have it, so don't give error
897 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
899 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
900 param
.description
.c_str())
908 // if there was an error during parsing the command line, show this error
909 // and also the usage message if it had been requested
910 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
912 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
917 usage
= GetUsageString();
919 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
923 wxFAIL_MSG( _T("no wxMessageOutput object?") );
927 return ok
? 0 : helpRequested
? -1 : 1;
930 // ----------------------------------------------------------------------------
931 // give the usage message
932 // ----------------------------------------------------------------------------
934 void wxCmdLineParser::Usage()
936 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
939 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
943 wxFAIL_MSG( _T("no wxMessageOutput object?") );
947 wxString
wxCmdLineParser::GetUsageString()
950 if ( m_data
->m_arguments
.empty() )
953 appname
= wxTheApp
->GetAppName();
957 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
960 // we construct the brief cmd line desc on the fly, but not the detailed
961 // help message below because we want to align the options descriptions
962 // and for this we must first know the longest one of them
964 wxArrayString namesOptions
, descOptions
;
966 if ( !m_data
->m_logo
.empty() )
968 usage
<< m_data
->m_logo
<< _T('\n');
971 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
973 // the switch char is usually '-' but this can be changed with
974 // SetSwitchChars() and then the first one of possible chars is used
975 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
976 : m_data
->m_switchChars
[0u];
978 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
979 size_t n
, count
= m_data
->m_options
.GetCount();
980 for ( n
= 0; n
< count
; n
++ )
982 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
985 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
990 if ( !opt
.shortName
.empty() )
992 usage
<< chSwitch
<< opt
.shortName
;
994 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
996 usage
<< _T("--") << opt
.longName
;
1000 if (!opt
.longName
.empty())
1002 wxFAIL_MSG( wxT("option with only a long name while long ")
1003 wxT("options are disabled") );
1007 wxFAIL_MSG( _T("option without neither short nor long name") );
1013 if ( !opt
.shortName
.empty() )
1015 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1018 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1020 option
<< (option
.empty() ? _T(" ") : _T(", "))
1021 << _T("--") << opt
.longName
;
1024 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1027 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1028 usage
<< _T(' ') << val
;
1029 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1032 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1037 namesOptions
.push_back(option
);
1038 descOptions
.push_back(opt
.description
);
1041 count
= m_data
->m_paramDesc
.GetCount();
1042 for ( n
= 0; n
< count
; n
++ )
1044 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1047 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1052 usage
<< param
.description
;
1054 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1059 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1067 // set to number of our own options, not counting the standard ones
1068 count
= namesOptions
.size();
1070 // get option names & descriptions for standard options, if any:
1071 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1074 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1076 // now construct the detailed help message
1077 size_t len
, lenMax
= 0;
1078 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1080 len
= namesOptions
[n
].length();
1085 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1088 usage
<< _T('\n') << stdDesc
;
1090 len
= namesOptions
[n
].length();
1091 usage
<< namesOptions
[n
]
1092 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1100 // ----------------------------------------------------------------------------
1101 // private functions
1102 // ----------------------------------------------------------------------------
1104 static wxString
GetTypeName(wxCmdLineParamType type
)
1110 wxFAIL_MSG( _T("unknown option type") );
1111 // still fall through
1113 case wxCMD_LINE_VAL_STRING
:
1117 case wxCMD_LINE_VAL_NUMBER
:
1121 case wxCMD_LINE_VAL_DATE
:
1130 Returns a string which is equal to the string pointed to by p, but up to the
1131 point where p contains an character that's not allowed.
1132 Allowable characters are letters and numbers, and characters pointed to by
1133 the parameter allowedChars.
1135 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1136 this function returns "abcde-".
1138 static wxString
GetOptionName(wxString::const_iterator p
,
1139 wxString::const_iterator end
,
1140 const wxChar
*allowedChars
)
1144 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1152 // Besides alphanumeric characters, short and long options can
1153 // have other characters.
1155 // A short option additionally can have these
1156 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1158 // A long option can have the same characters as a short option and a '-'.
1159 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1160 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1162 static wxString
GetShortOptionName(wxString::const_iterator p
,
1163 wxString::const_iterator end
)
1165 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1168 static wxString
GetLongOptionName(wxString::const_iterator p
,
1169 wxString::const_iterator end
)
1171 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1174 #endif // wxUSE_CMDLINE_PARSER
1176 // ----------------------------------------------------------------------------
1178 // ----------------------------------------------------------------------------
1181 This function is mainly used under Windows (as under Unix we always get the
1182 command line arguments as argc/argv anyhow) and so it tries to follow
1183 Windows conventions for the command line handling, not Unix ones. For
1184 instance, backslash is not special except when it precedes double quote when
1189 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
)
1196 bool isInsideQuotes
= false;
1198 wxString::const_iterator p
= cmdline
.begin();
1203 while ( p
!= cmdline
.end() && (*p
== _T(' ') || *p
== _T('\t')) )
1207 if ( p
== cmdline
.end() )
1210 // parse this parameter
1211 bool endParam
= false;
1212 bool lastBS
= false;
1213 for ( arg
.clear(); !endParam
; p
++ )
1215 switch ( (*p
).GetValue() )
1220 isInsideQuotes
= !isInsideQuotes
;
1222 // don't put quote in arg
1225 //else: quote has no special meaning but the backslash
1226 // still remains -- makes no sense but this is what
1232 // backslash does *not* quote the space, only quotes do
1233 if ( isInsideQuotes
)
1235 // skip assignment below
1251 lastBS
= *p
== _T('\\');
1256 args
.push_back(arg
);