1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# A command line parser; the Nimrod version of this file
# will become part of the standard library.
import
os, strutils
type
TCmdLineKind* = enum
cmdEnd, # end of command line reached
cmdArgument, # argument detected
cmdLongoption, # a long option ``--option`` detected
cmdShortOption # a short option ``-c`` detected
TOptParser* = object of TObject
cmd*: string
pos*: int
inShortState*: bool
kind*: TCmdLineKind
key*, val*: string
proc init*(cmdline: string = ""): TOptParser
proc next*(p: var TOptParser)
proc getRestOfCommandLine*(p: TOptParser): string
# implementation
proc init(cmdline: string = ""): TOptParser =
result.pos = 0
result.inShortState = false
if cmdline != "":
result.cmd = cmdline
else:
result.cmd = ""
for i in countup(1, ParamCount()):
result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i)) & ' '
result.kind = cmdEnd
result.key = ""
result.val = ""
proc parseWord(s: string, i: int, w: var string,
delim: TCharSet = {'\x09', ' ', '\0'}): int =
result = i
if s[result] == '\"':
inc(result)
while not (s[result] in {'\0', '\"'}):
add(w, s[result])
inc(result)
if s[result] == '\"': inc(result)
else:
while not (s[result] in delim):
add(w, s[result])
inc(result)
proc handleShortOption(p: var TOptParser) =
var i: int
i = p.pos
p.kind = cmdShortOption
add(p.key, p.cmd[i])
inc(i)
p.inShortState = true
while p.cmd[i] in {'\x09', ' '}:
inc(i)
p.inShortState = false
if p.cmd[i] in {':', '='}:
inc(i)
p.inShortState = false
while p.cmd[i] in {'\x09', ' '}: inc(i)
i = parseWord(p.cmd, i, p.val)
if p.cmd[i] == '\0': p.inShortState = false
p.pos = i
proc next(p: var TOptParser) =
var i: int
i = p.pos
while p.cmd[i] in {'\x09', ' '}: inc(i)
p.pos = i
setlen(p.key, 0)
setlen(p.val, 0)
if p.inShortState:
handleShortOption(p)
return
case p.cmd[i]
of '\0':
p.kind = cmdEnd
of '-':
inc(i)
if p.cmd[i] == '-':
p.kind = cmdLongOption
inc(i)
i = parseWord(p.cmd, i, p.key, {'\0', ' ', '\x09', ':', '='})
while p.cmd[i] in {'\x09', ' '}: inc(i)
if p.cmd[i] in {':', '='}:
inc(i)
while p.cmd[i] in {'\x09', ' '}: inc(i)
p.pos = parseWord(p.cmd, i, p.val)
else:
p.pos = i
else:
p.pos = i
handleShortOption(p)
else:
p.kind = cmdArgument
p.pos = parseWord(p.cmd, i, p.key)
proc getRestOfCommandLine(p: TOptParser): string =
result = strip(copy(p.cmd, p.pos + 0, len(p.cmd) - 1)) # always -1, because Pascal version uses a trailing zero here
|