Actually, I'm tring to parse command line params by universal types.
Sample Code is below:
import os
import system
import strutils
import strformat
import typeinfo
import macros
type
CmdParam*[T] = object
keyword: string
parseProc: proc (p: string): T
default: T
defaultFlag: bool
res: seq[T]
macro getAnyType(x: typed): auto =
parseStmt($x.getTypeInst.toStrLit)
proc newCmdParam*(keyword: string, default: auto, parseProc: proc): auto =
proc newCmdParamTypedesc[T](keyword: string, default: T, parseProc: proc
(p: string): T): CmdParam[T] =
result.keyword = keyword
result.default = default
result.parseProc = parseProc
result.defaultFlag = false
result = newCmdParamTypedesc[getAnyType(default)](keyword, default,
parseProc)
macro len(t: tuple): int =
len(t)
macro extractObjectElementInTuple(definedTpl: typed, objectElementName:
static[string]): auto =
var length = len(definedTpl.getTypeInst)
var elemStrSeq: seq[string]
for itr in 0..<length:
elemStrSeq.add($definedTpl.toStrLit & "[" & $itr & "]." &
objectElementName)
var command = "(" & elemStrSeq.join(",") & ")"
parseStmt(command)
proc parseCmdLineParamsImpl(cmdParamSeq: seq[string], pre: string, sep:
string, params: var tuple): auto =
let length = len(params)
var itr: int
var fixedCmd: string
for cmdParam in cmdParamSeq:
# I feel doubt that
# rewritable tuple members will be yeilded
# in the following for-loop.
for prm in params.fields:
fixedCmd = pre & prm.keyword & sep
if cmdParam.startsWith(fixedCmd):
try:
prm.res.add(prm.parseProc(cmdParam.replace(fixedCmd, "")))
except:
echo "convert error"
for prm in params.fields:
if len(prm.res) == 0:
if prm.defaultFlag:
prm.res = @[prm.default]
result = extractObjectElementInTuple(params, "res")
proc parseCmdLineParams*(cmdParamSeq: seq[string], pre="--", sep=":",
cmdParamTuple: var tuple): auto =
parseCmdLineParamsImpl(cmdParamSeq, pre, sep, cmdParamTuple)
## An example from here ##
type
MyType[T] = object
value: T
proc toMyType(p: string): MyType[string] =
result.value = p
proc passString(p: string): string =
p
if isMainModule:
var commandLineParamsSample: seq[string] = "--arg1:999 --arg2:9.99
--arg3:abc --arg4:test".split(" ")
var settings = (newCmdParam("arg1", 0, parseInt),
newCmdParam("arg2", 0.0, parseFloat),
newCmdParam("arg3", "", passString),
newCmdParam("arg4", MyType[string](value:"default"),
toMyType)
)
var val =
commandLineParamsSample.parseCmdLineParams(cmdParamTuple=settings)
# show
for x in val.fields:
echo x
# @[999]
# @[9.99]
# @["abc"]
# @[(value: "test")]
Run
In my expectation, the yielded value is a copy of the tuple member.
And even if rewrite the value, it will not affect the original tuple.
There is no written description in the document.