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 // FIXME-UTF8: ParseDate API will need changes
810 const wxChar
*res
= dt
.ParseDate(value
.c_str());
813 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
814 name
.c_str(), value
.c_str())
825 #endif // wxUSE_DATETIME
830 else // not an option, must be a parameter
832 if ( currentParam
< countParam
)
834 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
836 // TODO check the param type
838 m_data
->m_parameters
.push_back(arg
);
840 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
846 wxASSERT_MSG( currentParam
== countParam
- 1,
847 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
849 // remember that we did have this last repeatable parameter
850 hadRepeatableParam
= true;
855 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
863 // verify that all mandatory options were given
866 size_t countOpt
= m_data
->m_options
.GetCount();
867 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
869 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
870 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
875 optName
= opt
.shortName
;
879 if ( AreLongOptionsEnabled() )
881 optName
.Printf( _("%s (or %s)"),
882 opt
.shortName
.c_str(),
883 opt
.longName
.c_str() );
887 optName
.Printf( wxT("%s"),
888 opt
.shortName
.c_str() );
892 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
900 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
902 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
903 if ( (currentParam
== countParam
- 1) &&
904 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
907 // special case: currentParam wasn't incremented, but we did
908 // have it, so don't give error
912 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
914 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
915 param
.description
.c_str())
923 // if there was an error during parsing the command line, show this error
924 // and also the usage message if it had been requested
925 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
927 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
932 usage
= GetUsageString();
934 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
938 wxFAIL_MSG( _T("no wxMessageOutput object?") );
942 return ok
? 0 : helpRequested
? -1 : 1;
945 // ----------------------------------------------------------------------------
946 // give the usage message
947 // ----------------------------------------------------------------------------
949 void wxCmdLineParser::Usage()
951 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
954 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
958 wxFAIL_MSG( _T("no wxMessageOutput object?") );
962 wxString
wxCmdLineParser::GetUsageString()
965 if ( m_data
->m_arguments
.empty() )
968 appname
= wxTheApp
->GetAppName();
972 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
975 // we construct the brief cmd line desc on the fly, but not the detailed
976 // help message below because we want to align the options descriptions
977 // and for this we must first know the longest one of them
979 wxArrayString namesOptions
, descOptions
;
981 if ( !m_data
->m_logo
.empty() )
983 usage
<< m_data
->m_logo
<< _T('\n');
986 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
988 // the switch char is usually '-' but this can be changed with
989 // SetSwitchChars() and then the first one of possible chars is used
990 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
991 : m_data
->m_switchChars
[0u];
993 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
994 size_t n
, count
= m_data
->m_options
.GetCount();
995 for ( n
= 0; n
< count
; n
++ )
997 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
1000 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1005 if ( !opt
.shortName
.empty() )
1007 usage
<< chSwitch
<< opt
.shortName
;
1009 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1011 usage
<< _T("--") << opt
.longName
;
1015 if (!opt
.longName
.empty())
1017 wxFAIL_MSG( wxT("option with only a long name while long ")
1018 wxT("options are disabled") );
1022 wxFAIL_MSG( _T("option without neither short nor long name") );
1028 if ( !opt
.shortName
.empty() )
1030 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1033 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1035 option
<< (option
.empty() ? _T(" ") : _T(", "))
1036 << _T("--") << opt
.longName
;
1039 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1042 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1043 usage
<< _T(' ') << val
;
1044 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1047 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1052 namesOptions
.push_back(option
);
1053 descOptions
.push_back(opt
.description
);
1056 count
= m_data
->m_paramDesc
.GetCount();
1057 for ( n
= 0; n
< count
; n
++ )
1059 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1062 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1067 usage
<< param
.description
;
1069 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1074 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1082 // set to number of our own options, not counting the standard ones
1083 count
= namesOptions
.size();
1085 // get option names & descriptions for standard options, if any:
1086 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1089 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1091 // now construct the detailed help message
1092 size_t len
, lenMax
= 0;
1093 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1095 len
= namesOptions
[n
].length();
1100 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1103 usage
<< _T('\n') << stdDesc
;
1105 len
= namesOptions
[n
].length();
1106 usage
<< namesOptions
[n
]
1107 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1115 // ----------------------------------------------------------------------------
1116 // private functions
1117 // ----------------------------------------------------------------------------
1119 static wxString
GetTypeName(wxCmdLineParamType type
)
1125 wxFAIL_MSG( _T("unknown option type") );
1126 // still fall through
1128 case wxCMD_LINE_VAL_STRING
:
1132 case wxCMD_LINE_VAL_NUMBER
:
1136 case wxCMD_LINE_VAL_DATE
:
1145 Returns a string which is equal to the string pointed to by p, but up to the
1146 point where p contains an character that's not allowed.
1147 Allowable characters are letters and numbers, and characters pointed to by
1148 the parameter allowedChars.
1150 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1151 this function returns "abcde-".
1153 static wxString
GetOptionName(wxString::const_iterator p
,
1154 wxString::const_iterator end
,
1155 const wxChar
*allowedChars
)
1159 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1167 // Besides alphanumeric characters, short and long options can
1168 // have other characters.
1170 // A short option additionally can have these
1171 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1173 // A long option can have the same characters as a short option and a '-'.
1174 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1175 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1177 static wxString
GetShortOptionName(wxString::const_iterator p
,
1178 wxString::const_iterator end
)
1180 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1183 static wxString
GetLongOptionName(wxString::const_iterator p
,
1184 wxString::const_iterator end
)
1186 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1189 #endif // wxUSE_CMDLINE_PARSER
1191 // ----------------------------------------------------------------------------
1193 // ----------------------------------------------------------------------------
1196 This function is mainly used under Windows (as under Unix we always get the
1197 command line arguments as argc/argv anyhow) and so it tries to follow
1198 Windows conventions for the command line handling, not Unix ones. For
1199 instance, backslash is not special except when it precedes double quote when
1204 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
)
1211 bool isInsideQuotes
= false;
1213 wxString::const_iterator p
= cmdline
.begin();
1218 while ( p
!= cmdline
.end() && (*p
== _T(' ') || *p
== _T('\t')) )
1222 if ( p
== cmdline
.end() )
1225 // parse this parameter
1226 bool endParam
= false;
1227 bool lastBS
= false;
1228 for ( arg
.clear(); !endParam
; p
++ )
1230 switch ( (*p
).GetValue() )
1235 isInsideQuotes
= !isInsideQuotes
;
1237 // don't put quote in arg
1240 //else: quote has no special meaning but the backslash
1241 // still remains -- makes no sense but this is what
1247 // backslash does *not* quote the space, only quotes do
1248 if ( isInsideQuotes
)
1250 // skip assignment below
1266 lastBS
= *p
== _T('\\');
1271 args
.push_back(arg
);