wmtools/nimbledeps/pkgs2/argparse-4.0.1-e9c2ebe3f74b1dfc4df773686ae6dab7638a8662/argparse/filler.nim
2023-11-23 20:10:04 +00:00

113 lines
2.9 KiB
Nim

import tables
type
SlotKind* = enum
Required
Optional
Wildcard
Slot = object
name: string
case kind*: SlotKind
of Required:
nargs: int
else:
discard
ArgFiller* = object
slots: seq[Slot]
counts: CountTableRef[SlotKind]
FillChannel* = tuple
idx: Slice[int]
dest: string
kind: SlotKind
proc newArgFiller*(): ref ArgFiller =
new(result)
result.counts = newCountTable[SlotKind]()
using
filler: ref ArgFiller
proc required*(filler; argname: string, nargs = 1) =
filler.slots.add(Slot(kind: Required, name: argname, nargs: nargs))
filler.counts.inc(Required, nargs)
proc optional*(filler; argname: string) =
filler.slots.add(Slot(kind: Optional, name: argname))
filler.counts.inc(Optional)
proc wildcard*(filler; argname: string) =
if filler.counts[Wildcard] > 0:
raise ValueError.newException("More than one wildcard argument not allowed")
filler.slots.add(Slot(kind: Wildcard, name: argname))
filler.counts.inc(Wildcard)
proc minArgs*(filler): int =
for slot in filler.slots:
if slot.kind == Required:
result.inc(slot.nargs)
proc numArgsAfterWildcard*(filler): int =
var afterWildcard = false
for slot in filler.slots:
if slot.kind == Wildcard:
afterWildcard = true
elif afterWildcard:
case slot.kind
of Required:
result.inc(slot.nargs)
of Optional:
result.inc(1)
of Wildcard:
discard
proc hasVariableArgs*(filler): bool =
filler.counts[Optional] > 0 or filler.counts[Wildcard] > 0
proc hasWildcard*(filler): bool =
filler.counts[Wildcard] > 0
proc upperBreakpoint*(filler): int =
filler.counts[Required] + filler.counts[Optional] + filler.counts[Wildcard]
proc channels*(filler; nargs: int): seq[FillChannel] =
## Given the number of arguments, show where those arguments will go
var toget = newCountTable[SlotKind]()
var left = nargs
for kind in [Required, Optional, Wildcard]:
var kind_left = filler.counts[kind]
let totake = min(kind_left, left)
if totake > 0:
left.dec(totake)
kind_left.dec(totake)
toget.inc(kind, totake)
var idx = 0
for slot in filler.slots:
if toget[slot.kind] > 0:
case slot.kind
of Required:
result.add (idx..(idx+slot.nargs - 1), slot.name, slot.kind)
of Optional:
result.add (idx..idx, slot.name, slot.kind)
of Wildcard:
result.add (idx..(idx + left), slot.name, slot.kind)
{.push assertions: off.}
toget[slot.kind] = max(toget[slot.kind] - result[^1][0].len, 0)
{.pop.}
idx.inc(result[^1][0].len)
proc missing*(filler; nargs: int): seq[string] =
## Given the number of arguments, which required arguments will
## not get a value?
var left = nargs
for slot in filler.slots:
if slot.kind == Required:
for c in 0..<slot.nargs:
left.dec()
if left < 0:
result.add slot.name
proc generate*(filler; containerName: string): NimNode =
discard