wip
This commit is contained in:
parent
60d71e8029
commit
5ec8d0d623
|
@ -8,6 +8,11 @@ type
|
|||
cmdLongOption, ## A long option such as --option
|
||||
cmdShortOption ## A short option such as -c
|
||||
|
||||
TriBool* = enum
|
||||
Yes,
|
||||
No,
|
||||
Maybe
|
||||
|
||||
OptParser* = object of RootObj ## Implementation of the command line parser.
|
||||
pos*: int
|
||||
inShortState: bool
|
||||
|
@ -21,6 +26,59 @@ type
|
|||
## or the argument, and the value is not "" if
|
||||
## the option was given a value
|
||||
|
||||
type
|
||||
FieldReader*[ConfigType] = proc (conf: var ConfigType, val: TaintedString)
|
||||
{.gcsafe, raises: [Defect, CatchableError].}
|
||||
|
||||
Transition = object
|
||||
nextState: uint16
|
||||
fieldReaderState: FieldReaderState
|
||||
|
||||
CliDFA*[ConfigType] = object
|
||||
flagNames: Table[string, int] # TODO replace this with perfect hashing
|
||||
|
||||
fieldReaders: seq[FieldReader[configType]]
|
||||
##
|
||||
|
||||
FieldReaderState = distinct uint16
|
||||
# 15 bits for the field reader index
|
||||
# 1 bits to determine the type of the field reader (optional or not)
|
||||
# The special value `noFieldReader` indicates that there is no
|
||||
# current field Reader
|
||||
|
||||
numStates: int
|
||||
|
||||
stateTransitions: seq[Transition]
|
||||
## You can think of this as a two dimentional array where we specify
|
||||
## how each flag index is handled in each state.
|
||||
##
|
||||
## The flags that are invalid in a particular state are marked with
|
||||
## the `invalidTransition` value. Otherwise, the transition indicates
|
||||
## how the state
|
||||
|
||||
CliParserState = object
|
||||
currentState: uint16
|
||||
fieldReaderState: FieldReaderState
|
||||
|
||||
const
|
||||
fieldNotExpected* = FieldReaderState max(uint16)
|
||||
invalidTransition* = Transition(nextState: -1, fieldReaderState: fieldNotExpected)
|
||||
|
||||
template isFieldExpected(stateParam: FieldReaderState): TriBool =
|
||||
let state = uint16(stateParam)
|
||||
if state == uint16(fieldNotExpected):
|
||||
No
|
||||
elif (state and 1) != 0:
|
||||
Yes:
|
||||
else:
|
||||
Maybe
|
||||
|
||||
template readerIdx(state: FieldReaderState) =
|
||||
uint16(state) shr 1
|
||||
|
||||
template init(T: type FieldReaderState, idx: uint16, valueOptional: bool): T =
|
||||
T((idx shl 1) or uint16(valueOptional))
|
||||
|
||||
proc parseWord(s: string, i: int, w: var string,
|
||||
delim: set[char] = {'\t', ' '}): int =
|
||||
result = i
|
||||
|
|
|
@ -17,9 +17,6 @@ type
|
|||
OutDir* = distinct string
|
||||
OutFile* = distinct string
|
||||
|
||||
RestOfCmdLine* = distinct string
|
||||
SubCommandArgs* = distinct string
|
||||
|
||||
Flag* = object
|
||||
name*: TaintedString
|
||||
|
||||
|
@ -46,16 +43,17 @@ template desc*(v: string) {.pragma.}
|
|||
template longDesc*(v: string) {.pragma.}
|
||||
template name*(v: string) {.pragma.}
|
||||
template abbr*(v: string) {.pragma.}
|
||||
template separator*(v: string) {.pragma.}
|
||||
template defaultValue*(v: untyped) {.pragma.}
|
||||
template defaultValueDesc*(v: string) {.pragma.}
|
||||
template separator*(v: string) {.pragma.}
|
||||
template required* {.pragma.}
|
||||
template command* {.pragma.}
|
||||
template argument* {.pragma.}
|
||||
template arguments* {.pragma.}
|
||||
template hidden* {.pragma.}
|
||||
template ignore* {.pragma.}
|
||||
template inlineConfiguration* {.pragma.}
|
||||
|
||||
template forwardedCmdArgs*(separator: string = "--")* {.pragma.}
|
||||
template implicitlySelectable* {.pragma.}
|
||||
## This can be applied to a case object discriminator
|
||||
## to allow the value of the discriminator to be determined
|
||||
|
|
Loading…
Reference in New Issue