Skip to content

Instantly share code, notes, and snippets.

@MattDiesel
Last active December 18, 2015 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MattDiesel/5759477 to your computer and use it in GitHub Desktop.
Save MattDiesel/5759477 to your computer and use it in GitHub Desktop.
#include <Array.au3>
#include <Math.au3>
Global $__CmdLine_StrictMode = False
Global $__CmdLine_PrefixLong = "--"
Global $__CmdLine_PrefixShort = "-"
Global $__CmdLine_StringChars = "'"""
Global $__CmdLine_SplitChars = " =:" & @TAB
Global $__CmdLine_ProgramName = Default
Global $__CmdLine_ProgramDescr = Default
Global $__CmdLine_ProgramVersion = Default
Global $__CmdLine_ProgramCopyright = Default
Global $_CmdLine_Process = False
Global $__CmdLine_OnError = Default
Global Enum $CLERR_SUCCESS = 0, $CLERR_INVALIDARG, $CLERR_ARGNOPARAM, $CLERR_LITARGNOPARAM, $CLERR_EMPTYSHORT, $__CLERR_COUNT
Global Const $__CLERR_STR[$__CLERR_COUNT] = [ _
"Success.", _
"Invalid argument '%s'.", _
"Argument '%s' expects a parameter.", _
"Literal argument '-- ...' expects a parameter.", _
"Empty short argument: '%s'." _
]
Global Const $CLF_DEFAULT = 0
Global Const $CLF_HIDDEN = 1
Global Const $CLF_DISABLED = 2
Global Const $CLF_MULTI_ARRAY = 4 ; Default is MULTI_OVERRIDE
Global Const $CLF_DEFAULTVALUE = 8
Global Const $CLF_HASPARAM = 16
Global Const $CLF_PARAMOPTIONAL = 32
Global Const $CLF_FORCEPARAM = 64
Global Const $CLF_AUTOADDED = 128
Global Enum $_CLI_LONG = 0, $_CLI_SHORT, $_CLI_FLAGS, $_CLI_DESCR, $_CLI_HELPSTR, $_CLI_ARGNAME, $_CLI_VALUE, $_CLI_DEFAULT, _
$_CLI_CALLBACK, $_CLI_USAGE, $_CLI_SHORTUSAGE, $__CLI_COUNT
Global $__CMDLINE_DB[1][$__CLI_COUNT]
_CmdLine_Register("", "", $CLF_DEFAULTVALUE + $CLF_MULTI_ARRAY + $CLF_HASPARAM)
; #FUNCTION# ====================================================================================================================
; Name ..........: CmdLine
; Description ...: Returns an argument from the command line
; Syntax ........: CmdLine($sName[, $vDefault = Default])
; Parameters ....: $sName - The name of the argument. This can be either the short or the long version (not
; including the prefix.
; $vDefault - [optional] The default value. This overrides any previous default set for the argument.
; Return values .: The value associated with the command line argument. If it is a flag then this will be True or False,
; otherwise it will be the string value associated with it. If the argument was not used then the default value
; is returned.
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......: This is not quite the same as the previous version of the CmdLine() function I released, as it has the
; additional action of checking the database of registered command line options.
;+
; If $CmdLine has not been parsed yet then that is done the first time this function is called.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func CmdLine($sName, $vDefault = Default)
If Not $_CmdLine_Process Then
_CmdLine_Process()
EndIf
Local $i = __CmdLine_Lookup($sName)
If $i < 0 Then
Return SetError(1, 0, $vDefault)
EndIf
Local $vRet = $__CMDLINE_DB[$i][$_CLI_VALUE]
If $vRet = Default Then
If $vDefault = Default Then
$vRet = $__CMDLINE_DB[$i][$_CLI_DEFAULT]
Else
$vRet = $vDefault
EndIf
EndIf
Return $vRet
EndFunc ;==>CmdLine
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_Process
; Description ...: Process the command line
; Syntax ........: _CmdLine_Process([$sCmdLine = Default])
; Parameters ....: $sCmdLine - [optional] The command line. If left as default then it will use the programs command
; line.
; Return values .: None
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......: This does not need to be called explicitly, as it is called when CmdLine() is called for the first time. If
; commands are using callbacks like help and version then it is better to call this function as soon as you have
; finished registering commands.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_Process($sCmdLine = Default)
Local $aCmdLine
$_CmdLine_Process = True
If $sCmdLine = Default Then
$aCmdLine = $CmdLine
Else
$aCmdLine = __CmdLine_Split($sCmdLine)
EndIf
Local $sArg, $n, $vValue, $iType
For $i = 1 To $aCmdLine[0]
If ($__CmdLine_PrefixLong <> "" And _
StringLeft($aCmdLine[$i], StringLen($__CmdLine_PrefixLong)) = $__CmdLine_PrefixLong) Then
$iType = 1
ElseIf ($__CmdLine_PrefixShort <> "" And _
StringLeft($aCmdLine[$i], StringLen($__CmdLine_PrefixShort)) = $__CmdLine_PrefixShort) Then
$iType = 2
Else
$iType = 0
EndIf
If $iType Then
If $iType = 1 Then
$sArg = StringTrimLeft($aCmdLine[$i], StringLen($__CmdLine_PrefixLong))
Else
$sArg = StringTrimLeft($aCmdLine[$i], StringLen($__CmdLine_PrefixShort))
If $sArg = "" Then
__CmdLine_ErrorReport($CLERR_EMPTYSHORT, $__CmdLine_PrefixShort)
ContinueLoop
EndIf
EndIf
If $sArg = "" Then
$n = 0
If $i = $aCmdLine[0] Then
__CmdLine_ErrorReport($CLERR_LITARGNOPARAM, $aCmdLine[$i])
ContinueLoop
Else
$vValue = $aCmdLine[$i + 1]
$i += 1
EndIf
Else
$n = __CmdLine_Lookup($sArg, $iType)
If $n < 0 Then
If $__CmdLine_StrictMode Then
__CmdLine_ErrorReport($CLERR_INVALIDARG, $aCmdLine[$i])
ContinueLoop
Else
$flags = $CLF_AUTOADDED + $CLF_HIDDEN
If $i <> $aCmdLine[0] And $iType = 1 And _
StringLeft($aCmdLine[$i + 1], StringLen($__CmdLine_PrefixLong)) <> $__CmdLine_PrefixLong And _
StringLeft($aCmdLine[$i + 1], StringLen($__CmdLine_PrefixShort)) <> $__CmdLine_PrefixShort Then
$flags += $CLF_HASPARAM
$vValue = $aCmdLine[$i + 1]
$i += 1
Else
$vValue = True
EndIf
$n = _CmdLine_Register($sArg, "", $flags)
$__CMDLINE_DB[$n][$_CLI_VALUE] = $vValue
ContinueLoop
EndIf
EndIf
$vValue = Default
If BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_HASPARAM) Then
If $i = $aCmdLine[0] Or (Not BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_FORCEPARAM) And ( _
StringLeft($aCmdLine[$i + 1], StringLen($__CmdLine_PrefixLong)) = $__CmdLine_PrefixLong Or _
StringLeft($aCmdLine[$i + 1], StringLen($__CmdLine_PrefixShort)) = $__CmdLine_PrefixShort)) Then
If BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_PARAMOPTIONAL) Then
$vValue = True
Else
__CmdLine_ErrorReport($CLERR_ARGNOPARAM, $aCmdLine[$i])
ContinueLoop
EndIf
Else
$vValue = $aCmdLine[$i + 1]
$i += 1
EndIf
If BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_MULTI_ARRAY) Then
_ArrayAdd($__CMDLINE_DB[$n][$_CLI_VALUE], $vValue)
__Array_IncIndex($__CMDLINE_DB[$n][$_CLI_VALUE])
Else
$__CMDLINE_DB[$n][$_CLI_VALUE] = $vValue
EndIf
Else
$__CMDLINE_DB[$n][$_CLI_VALUE] = True
$vValue = True
EndIf
If $__CMDLINE_DB[$n][$_CLI_CALLBACK] <> "" Then
If BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_HASPARAM) Then
;If $vValue = Default Or $vValue = True Then $vValue = $__CMDLINE_DB[$n][$_CLI_DEFAULT]
If Not IsString($vValue) Then $vValue = $__CMDLINE_DB[$n][$_CLI_DEFAULT]
Call($__CMDLINE_DB[$n][$_CLI_CALLBACK], $vValue)
Else
Call($__CMDLINE_DB[$n][$_CLI_CALLBACK])
EndIf
EndIf
EndIf
Else
_ArrayAdd($__CMDLINE_DB[0][$_CLI_VALUE], $aCmdLine[$i])
__Array_IncIndex($__CMDLINE_DB[0][$_CLI_VALUE])
EndIf
Next
EndFunc ;==>_CmdLine_Process
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_Register
; Description ...: Registers a command line parameter
; Syntax ........: _CmdLine_Register($sLong[, $sShort = ""[, $iFlags = $CLF_DEFAULT[, $sDescr = ""[, $sHelp = ""[,
; $sParamName = ""[, $vDefault = Default[, $sCallback = ""]]]]]]])
; Parameters ....: $sLong - The long version of the argument. Not including the prefix.
; $sShort - [optional] The short version of the argument. Not including the prefix.
; $iFlags - [optional] Flags for the argument. This is a BitORed combination of:
; |$CLF_HIDDEN - The command is not shown in the help command listings
; |$CLF_DISABLED - The command cannot be run.
; |$CLF_MULTI_ARRAY - If the same argument is used multiple times, then extra values are
; appended to an array, rather than overriding the old values. The
; return value for the argument is always an array, even if only one
; value is given. The array has the count in the first element.
; |$CLF_DEFAULTVALUE - The argument is an alias for the default element, which means any
; value passed to the program but is not associated with an argument.
; |$CLF_HASPARAM - The argument takes a parameter. The UDF supports the following styles
; of parameter:
; | --ARG PARAMETER
; | --ARG=PARAMETER
; | --ARG:PARAMETER
; |$CLF_PARAMOPTIONAL - The parameter for the argument is optional. If the argument appears
; at the end of the list, or the next item in the command line is
; also an argument (based on its prefix) then the result is TRUE and
; no parameter is required.
; |$CLF_FORCEPARAM - The argument always has a parameter, even if the next item in the
; command line is also an argument. This is dangerous and should only be
; used in special cases.
; $sDescr - [optional] The description for the argument. Ideally this is less than 50 characters.
; It is used in the argument listing and argument specific help messages.
; $sHelp - [optional] A longer help string for the argument. This is only shown for the
; argument specific help message, and can be multiline.
; $sParamName - [optional] The name of the parameter. This replaces "..." in help usage strings.
; $vDefault - [optional] The default value for the argument.
; $sCallback - [optional] A callback function for the argument. This is called when the command line
; argument is processed. It can take a single parameter.
; Return values .: Not Used
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_Register($sLong, $sShort = "", $iFlags = $CLF_DEFAULT, $sDescr = "", $sHelp = "", $sParamName = "", $vDefault = Default, $sCallback = "")
Local $i
If BitAND($iFlags, $CLF_DEFAULTVALUE) Or $sLong = "" Then
; Modify first command line
$i = 0
$iFlags = BitOR($iFlags, $CLF_DEFAULTVALUE, $CLF_HASPARAM) ; Forced flags
Else
$i = UBound($__CMDLINE_DB)
ReDim $__CMDLINE_DB[$i + 1][$__CLI_COUNT]
EndIf
$__CMDLINE_DB[$i][$_CLI_LONG] = $sLong
$__CMDLINE_DB[$i][$_CLI_SHORT] = $sShort
$__CMDLINE_DB[$i][$_CLI_FLAGS] = $iFlags
$__CMDLINE_DB[$i][$_CLI_DESCR] = $sDescr
$__CMDLINE_DB[$i][$_CLI_HELPSTR] = $sHelp
$__CMDLINE_DB[$i][$_CLI_ARGNAME] = $sParamName
If BitAND($iFlags, $CLF_MULTI_ARRAY) Then
Local $a[1] = [0]
$__CMDLINE_DB[$i][$_CLI_VALUE] = $a
Else
$__CMDLINE_DB[$i][$_CLI_VALUE] = Default
EndIf
$__CMDLINE_DB[$i][$_CLI_DEFAULT] = $vDefault
$__CMDLINE_DB[$i][$_CLI_CALLBACK] = $sCallback
If $sLong <> "" Then
Local $s = ""
$s &= $__CmdLine_PrefixLong & $sLong
If BitAND($iFlags, $CLF_HASPARAM) Then
$s &= " "
If BitAND($iFlags, $CLF_PARAMOPTIONAL) Then $s &= "["
If $sParamName = "" Then
$s &= "..."
Else
$s &= $sParamName
EndIf
If BitAND($iFlags, $CLF_PARAMOPTIONAL) Then $s &= "]"
EndIf
$__CMDLINE_DB[$i][$_CLI_USAGE] = $s
EndIf
If $sShort <> "" Then
Local $s = ""
$s &= $__CmdLine_PrefixShort & $sShort
If BitAND($iFlags, $CLF_HASPARAM) Then
$s &= " "
If BitAND($iFlags, $CLF_PARAMOPTIONAL) Then $s &= "["
If $sParamName = "" Then
$s &= "..."
Else
$s &= $sParamName
EndIf
If BitAND($iFlags, $CLF_PARAMOPTIONAL) Then $s &= "]"
EndIf
$__CMDLINE_DB[$i][$_CLI_SHORTUSAGE] = $s
EndIf
Return $i
EndFunc ;==>_CmdLine_Register
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_SetOnError
; Description ...: Sets the error handler callback function
; Syntax ........: _CmdLine_SetOnError([$sFunc = Default])
; Parameters ....: $sFunc - [optional] The new error handler callback function
; Return values .: None
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_SetOnError($sFunc = Default)
$__CmdLine_OnError = $sFunc
EndFunc ;==>_CmdLine_SetOnError
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_SetPrefixes
; Description ...: Sets the prefixes for command line arguments.
; Syntax ........: _CmdLine_SetPrefixes($sLong[, $sShort = ""])
; Parameters ....: $sLong - The new long prefix
; $sShort - [optional] The new short prefix.
; Return values .: None
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......: Commonly used prefixes include:
; |GNU - uses '--' to start arguments. <a href="http://www.gnu.org/prep/standards/
; html_node/Command_002dLine-Interfaces.html">Page</a>. '--' on it's own sets the
; unnamed argument but always uses the next parameter, even if prefixed by '--'.
; E.g. '-- --file' will mean CmdLine() = '--file'.
; |Powershell - uses '-'. Arguments with values are seperated by a colon: ':'. <a
; href="http://technet.microsoft.com/en-us/library/ee156811.aspx">Page</a>.
; |MS - Like AutoIt, uses a forward slash "/" for long or short arguments.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_SetPrefixes($sLong, $sShort = "")
If StringLeft($sShort, StringLen($sLong)) = $sLong Then
Local $sTmp = $sShort
$sShort = $sLong
$sLong = $sTmp
EndIf
$__CmdLine_PrefixLong = $sLong
$__CmdLine_PrefixShort = $sShort
EndFunc ;==>_CmdLine_SetPrefixes
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_SetProgramInfo
; Description ...: Sets program information
; Syntax ........: _CmdLine_SetProgramInfo([$sName = Default[, $sDescr = Default[, $sVersion = Default[, $sCopyright = Default]]]])
; Parameters ....: $sName - [optional] The name of the program.
; $sDescr - [optional] The program description.
; $sVersion - [optional] The program version
; $sCopyright - [optional] The program copyright string.
; Return values .: None
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......: If these are left as defaults, and the script is not compiled, then they are all left as blank apart from
; $sName which is set to @ScriptName. If the script is compiled and the program information is left as default,
; then the UDF attempts to get the information from the exe metadata.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_SetProgramInfo($sName = Default, $sDescr = Default, $sVersion = Default, $sCopyright = Default)
$__CmdLine_ProgramName = $sName
$__CmdLine_ProgramDescr = $sDescr
$__CmdLine_ProgramVersion = $sVersion
$__CmdLine_ProgramCopyright = $sCopyright
EndFunc ;==>_CmdLine_SetProgramInfo
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_StrictMode
; Description ...: Enables/Disables strict mode
; Syntax ........: _CmdLine_StrictMode([$fEnable = Default])
; Parameters ....: $fEnable - [optional] Whether strict mode should be enabled or disabled. If this is default then
; the function returns the current value and does nothing else.
; Return values .: None (unless $fEnable = Default).
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......: Strict mode means that any command line arguments not already added to the database by using _CmdLine_Register
; generate errors on processing. When it is disabled, unrecognised arguments are added to the database.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_StrictMode($fEnable = Default)
If $fEnable = Default Then Return $__CmdLine_StrictMode
$__CmdLine_StrictMode = $fEnable
EndFunc ;==>_CmdLine_StrictMode
; #FUNCTION# ====================================================================================================================
; Name ..........: _CmdLine_UseDefaults
; Description ...: Registers built in command line arguments.
; Syntax ........: _CmdLine_UseDefaults([$fHelp = True[, $fVersion = True]])
; Parameters ....: $fHelp - [optional] If true then a built in help command will be registered.
; $fVersion - [optional] If True then a built in version command will be registered.
; Return values .: None
; Author ........: Matt Diesel (Mat)
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _CmdLine_UseDefaults($fHelp = True, $fVersion = True)
If $fHelp Then _
_CmdLine_Register("help", "?", $CLF_HASPARAM + $CLF_PARAMOPTIONAL + $CLF_FORCEPARAM, _
"Prints help information.", "", "command", "", "__CmdLine_Default_Help")
If $fVersion Then _
_CmdLine_Register("version", "v", 0, _
"Prints the program version", _
"", "", "", "__CmdLine_Default_Version")
EndFunc ;==>_CmdLine_UseDefaults
#region Internal functions
; Sorry, CBA to document.
Func __CmdLine_ErrorHandler($iError, $sArg = "")
ConsoleWrite(StringFormat($__CLERR_STR[$iError], $sArg) & @LF)
Switch $iError
Case $CLERR_INVALIDARG
If StringLeft($sArg, StringLen($__CmdLine_PrefixLong)) = $__CmdLine_PrefixLong Then
Local $aMatches = __CmdLine_ClosestMatches(StringTrimLeft($sArg, StringLen($__CmdLine_PrefixLong)))
If $aMatches[0] Then
ConsoleWrite("Did you mean:" & @CRLF)
For $i = 1 To $aMatches[0]
ConsoleWrite(" --" & $aMatches[$i] & @LF)
Next
EndIf
EndIf
EndSwitch
EndFunc ;==>__CmdLine_ErrorHandler
Func __CmdLine_ErrorReport($iError, $sArg)
If $__CmdLine_OnError = Default Then
__CmdLine_ErrorHandler($iError, $sArg)
ElseIf $__CmdLine_OnError <> "" Then
Call($__CmdLine_OnError, $iError, $sArg)
EndIf
EndFunc ;==>__CmdLine_ErrorReport
; iType:
; 0 - Long or short (long takes priority
; 1 - Long
; 2 - Short
; 3 - Long or Short (allow disabled entries)
; 4 - Long (allow disabled entries)
; 5 - Short (allow disabled entries)
Func __CmdLine_Lookup($sName, $iType = 0)
Local $iLong = -1, $iShort = -1
For $n = 0 To UBound($__CMDLINE_DB) - 1
If $__CMDLINE_DB[$n][$_CLI_LONG] = $sName And _
($iType >= 3 Or Not BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_DISABLED)) Then
$iLong = $n
ExitLoop
ElseIf $__CMDLINE_DB[$n][$_CLI_SHORT] = $sName And _
($iType >= 3 Or Not BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_DISABLED)) Then
$iShort = $n
EndIf
Next
If $iType = 1 Then Return $iLong
If $iType = 2 Then Return $iShort
If $iLong = -1 And $iShort <> -1 Then Return $iShort
Return $iLong
EndFunc ;==>__CmdLine_Lookup
Func __CmdLine_Split($sCmdLine)
Local $aRet[1] = [0]
Local $iStart = 1, $inStr = 0, $sAdd, $c
For $i = 1 To StringLen($sCmdLine) + 1
$c = StringMid($sCmdLine, $i, 1)
If ($inStr And $c = StringMid($__CmdLine_StringChars, $inStr, 1)) Or _
(Not $inStr And StringInStr($__CmdLine_SplitChars, $c)) Or _
$c = "" Then
$sAdd = StringStripWS(StringMid($sCmdLine, $iStart, $i - $iStart), 3)
If $sAdd <> "" Then
_ArrayAdd($aRet, StringMid($sCmdLine, $iStart, $i - $iStart))
$aRet[0] += 1
EndIf
$iStart = $i + 1
$inStr = 0
ElseIf Not $inStr And StringInStr($__CmdLine_StringChars, $c) Then
$inStr = StringInStr($__CmdLine_StringChars, $c)
$iStart = $i + 1
EndIf
Next
Return $aRet
EndFunc ;==>__CmdLine_Split
Func __CmdLine_GetProgramName()
Local $sRet = @ScriptName
If $__CmdLine_ProgramName <> Default Then
$sRet = $__CmdLine_ProgramName
ElseIf @Compiled Then
$sRet = FileGetVersion(@ScriptFullPath, "ProductName")
EndIf
Return $sRet
EndFunc ;==>__CmdLine_GetProgramName
Func __CmdLine_GetProgramVersion()
Local $sRet = ""
If $__CmdLine_ProgramVersion <> Default Then
$sRet = $__CmdLine_ProgramVersion
ElseIf @Compiled Then
$sRet = FileGetVersion(@ScriptFullPath, "ProductVersion")
EndIf
Return $sRet
EndFunc ;==>__CmdLine_GetProgramVersion
Func __CmdLine_GetProgramDescr()
Local $sRet = ""
If $__CmdLine_ProgramName <> Default Then
$sRet = $__CmdLine_ProgramDescr
ElseIf @Compiled Then
$sRet = FileGetVersion(@ScriptFullPath, "FileDescription")
EndIf
Return $sRet
EndFunc ;==>__CmdLine_GetProgramDescr
Func __CmdLine_GetProgramCopyright()
Local $sRet = ""
If $__CmdLine_ProgramName <> Default Then
$sRet = $__CmdLine_ProgramCopyright
ElseIf @Compiled Then
$sRet = FileGetVersion(@ScriptFullPath, "LegalCopyright")
EndIf
Return $sRet
EndFunc ;==>__CmdLine_GetProgramCopyright
Func __CmdLine_PrintProgramHeader()
ConsoleWrite(__CmdLine_GetProgramName())
Local $s = __CmdLine_GetProgramVersion()
If $s = "" Then
ConsoleWrite(@LF)
Else
ConsoleWrite(" v" & $s & @LF)
EndIf
$s = __CmdLine_GetProgramDescr()
If $s <> "" Then ConsoleWrite(" " & $s & @LF)
$s = __CmdLine_GetProgramCopyright()
If $s <> "" Then ConsoleWrite(" " & $s & @LF)
ConsoleWrite(@LF)
EndFunc ;==>__CmdLine_PrintProgramHeader
Func __CmdLine_Default_Help($sCommand = "")
__CmdLine_PrintProgramHeader()
If $sCommand = "" Or $sCommand = Default Then
ConsoleWrite("Available Commands: " & @LF)
Local $iCmdLen = 0, $l
Local $w = __Console_GetScreenBufferSize()
If @error Or $w[0] = 0 Then
$w = 80
Else
$w = $w[0]
EndIf
For $i = 0 To UBound($__CMDLINE_DB) - 1
$l = StringLen($__CMDLINE_DB[$i][$_CLI_USAGE])
If $__CMDLINE_DB[$i][$_CLI_SHORT] <> "" Then
$l += 2 + StringLen($__CMDLINE_DB[$i][$_CLI_SHORTUSAGE])
EndIf
$iCmdLen = _Max($iCmdLen, $l)
Next
; Columns: 4 margin, $iCmdLen, 4 margin, "- ", Description
For $i = 0 To UBound($__CMDLINE_DB) - 1
$l = $__CMDLINE_DB[$i][$_CLI_USAGE]
If $__CMDLINE_DB[$i][$_CLI_SHORT] <> "" Then
$l &= ", " & $__CMDLINE_DB[$i][$_CLI_SHORTUSAGE]
EndIf
ConsoleWrite(StringFormat(" %-" & $iCmdLen & "s", $l))
If $__CMDLINE_DB[$i][$_CLI_DESCR] = "" Then
ConsoleWrite(@LF)
Else
ConsoleWrite(" - ")
Local $l2
$l = $__CMDLINE_DB[$i][$_CLI_DESCR]
While 1
$l2 = __String_CharInStr($l & " ", " .,-?!", 2, -1, $w - 10 - $iCmdLen, $w - 10 - $iCmdLen)
If $l2 = 0 Then $l2 = $w - 10 - $iCmdLen
ConsoleWrite(StringStripWS(StringLeft($l, $l2), 3) & @LF)
$l = StringStripWS(StringTrimLeft($l, $l2), 1)
If $l = "" Then ExitLoop
ConsoleWrite(StringFormat("%" & 10 + $iCmdLen & "s", ""))
WEnd
EndIf
Next
Else
; Print help information for $sCommand
Local $sArg = $sCommand, $iType = 0
If StringLeft($sArg, StringLen($__CmdLine_PrefixLong)) = $__CmdLine_PrefixLong Then
$sArg = StringTrimLeft($sArg, StringLen($__CmdLine_PrefixLong))
ElseIf StringLeft($sArg, StringLen($__CmdLine_PrefixShort)) = $__CmdLine_PrefixShort Then
$sArg = StringTrimLeft($sArg, StringLen($__CmdLine_PrefixShort))
EndIf
Local $n = __CmdLine_Lookup($sArg, $iType + 3)
If $n < 0 Then
__CmdLine_ErrorReport($CLERR_INVALIDARG, $sCommand)
ElseIf BitAND($__CMDLINE_DB[$n][$_CLI_FLAGS], $CLF_DISABLED) Then
ConsoleWrite(StringFormat("Command '%s' is currently disabled.\n", $sCommand))
Else
If $__CMDLINE_DB[$n][$_CLI_DESCR] <> "" Then ConsoleWrite($__CMDLINE_DB[$n][$_CLI_DESCR] & @LF)
ConsoleWrite("Usage: " & @LF)
If $__CMDLINE_DB[$n][$_CLI_LONG] <> "" Then
ConsoleWrite(@TAB & $__CMDLINE_DB[$n][$_CLI_USAGE] & @LF)
EndIf
If $__CMDLINE_DB[$n][$_CLI_SHORT] <> "" Then
ConsoleWrite(@TAB & $__CMDLINE_DB[$n][$_CLI_SHORTUSAGE] & @LF)
EndIf
ConsoleWrite(@LF)
If $__CMDLINE_DB[$n][$_CLI_HELPSTR] Then
ConsoleWrite($__CMDLINE_DB[$n][$_CLI_HELPSTR] & @LF)
EndIf
EndIf
EndIf
Exit
EndFunc ;==>__CmdLine_Default_Help
Func __CmdLine_Default_Version()
__CmdLine_PrintProgramHeader()
Exit
EndFunc ;==>__CmdLine_Default_Version
Func __CmdLine_ClosestMatches($sName)
Local $asRet[1] = [0], $aiMinDists[1] = [0], $d, $n
For $i = 0 To UBound($__CMDLINE_DB) - 1
$d = __String_Distance($sName, $__CMDLINE_DB[$i][$_CLI_LONG])
If $d * 2 <= StringLen($sName) Then
For $n = 1 To $aiMinDists[0]
If $d > $aiMinDists[$n] Then ContinueLoop
Next
_ArrayInsert($aiMinDists, $n, $d)
_ArrayInsert($asRet, $n, $__CMDLINE_DB[$i][$_CLI_LONG])
$aiMinDists[0] += 1
$asRet[0] += 1
EndIf
Next
Return $asRet
EndFunc ;==>__CmdLine_ClosestMatches
#endregion Internal functions
#region Other funcs
; All these are taken from other non-standard UDFs
; All of them are written by me
Func __Array_IncIndex(ByRef $a)
$a[0] += 1
EndFunc ;==>__Array_IncIndex
; http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance#Algorithm
Func __String_Distance($s, $t)
Local $m = StringLen($s)
Local $n = StringLen($t)
Local $d[$m + 1][$n + 1]
For $i = 0 To $m
$d[$i][0] = $i
Next
For $j = 0 To $n
$d[0][$j] = $j
Next
Local $cost = 0
For $j = 1 To $n
For $i = 1 To $m
$cost = 1 - Number(StringMid($s, $i, 1) = StringMid($t, $j, 1))
$d[$i][$j] = _Min($d[$i][$j - 1] + 1, _ ; Insertion
_Min($d[$i - 1][$j] + 1, _ ; Deletion
$d[$i - 1][$j - 1] + $cost)) ; Substitution
If $i > 1 And $j > 1 And _
StringMid($s, $i, 1) = StringMid($t, $j - 1, 1) And _
StringMid($s, $i - 1, 1) = StringMid($t, $j, 1) Then
$d[$i][$j] = _Min($d[$i][$j], $d[$i - 1][$j - 1] + $cost)
EndIf
Next
Next
Return $d[$m][$n]
EndFunc ;==>__String_Distance
; Same as StringInStr, but searches for any character within $sChars.
; Returns the index of the actual character in @extended
Func __String_CharInStr($sString, $sChars, $iCaseSense = 0, $iOccurence = 1, $iStart = Default, $iCount = Default)
Local $iRet = -1, $i
If $iCount = Default Then $iCount = StringLen($sString)
If $iStart = Default Then
If $iOccurence < 0 Then
$iStart = StringLen($sString)
Else
$iStart = 1
EndIf
EndIf
Local $iEnd = $iStart + $iCount, $iStep = 1
If $iOccurence < 0 Then
$iEnd = $iStart - $iCount
$iStep = -1
EndIf
Local $n = 0, $j
For $c = $iStart To $iEnd Step $iStep
$j = StringInStr($sChars, StringMid($sString, $c, 1), $iCaseSense)
If $j Then
$n += $iStep
If $n = $iOccurence Then Return SetExtended($j, $c)
EndIf
Next
If $iRet < 0 Then Return 0
Return $iRet
EndFunc ;==>__String_CharInStr
Func __Console_GetScreenBufferSize($hConsoleOutput = -1, $hDll = -1)
Local $tConsoleScreenBufferInfo, $aRet[2]
$tConsoleScreenBufferInfo = __Console_GetScreenBufferInfo($hConsoleOutput, $hDll)
If @error Then Return SetError(@error, @extended, 0)
$aRet[0] = DllStructGetData($tConsoleScreenBufferInfo, "SizeX")
$aRet[1] = DllStructGetData($tConsoleScreenBufferInfo, "SizeY")
Return $aRet
EndFunc ;==>__Console_GetScreenBufferSize
Func __Console_GetScreenBufferInfo($hConsoleOutput = -1, $hDll = -1)
Local Const $tagCONSOLE_SCREEN_BUFFER_INFO = "SHORT SizeX; SHORT SizeY; SHORT CursorPositionX;" & _
"SHORT CursorPositionY; SHORT Attributes; SHORT Left; SHORT Top; SHORT Right; SHORT Bottom;" & _
"SHORT MaximumWindowSizeX; SHORT MaximumWindowSizeY"
Local $tConsoleScreenBufferInfo, $aResult
If $hDll = -1 Then $hDll = "kernel32.dll"
If $hConsoleOutput = -1 Then $hConsoleOutput = __Console_GetStdHandle(-11, $hDll)
$tConsoleScreenBufferInfo = DllStructCreate($tagCONSOLE_SCREEN_BUFFER_INFO)
$aResult = DllCall($hDll, "bool", "GetConsoleScreenBufferInfo", _
"handle", $hConsoleOutput, _
"ptr", DllStructGetPtr($tConsoleScreenBufferInfo))
If @error Or (Not $aResult[0]) Then Return SetError(@error, @extended, 0)
Return $tConsoleScreenBufferInfo
EndFunc ;==>__Console_GetScreenBufferInfo
Func __Console_GetStdHandle($nStdHandle = -11, $hDll = -1)
Local $aResult
If $hDll = -1 Then $hDll = "kernel32.dll"
$aResult = DllCall($hDll, "handle", "GetStdHandle", _
"dword", $nStdHandle)
If @error Then Return SetError(@error, @extended, 0)
Return $aResult[0]
EndFunc ;==>__Console_GetStdHandle
#endregion Other funcs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment