aboutsummaryrefslogtreecommitdiff
path: root/src/arg.lua
blob: a0acd9c6e4a465b8e8bbd2b6f8f4fc6b24865f4e (plain)
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
116
117
118
119
120
121
122
123
124
125
126
local function help(opts)

	io.write(arg[0])
	io.write(" ")

	for _, v in ipairs(opts) do
		if v.kind == nil then
			io.write("[" .. v.name .. "] ")
		end
	end
	io.write("\n")

	local max_width = 0

	for _, v in ipairs(opts) do
		if v.kind ~= nil then
			max_width = math.max(v.name:len(), max_width)
		end
	end

	for _, v in ipairs(opts) do
		if v.kind == nil then
			goto next
		end

		if v.kind == 'property' then
			io.write("\t" .. "--" .. v.name .. " <value>")
		elseif v.kind == 'flag' then
			io.write("\t" .. "--" .. v.name .. "        ")
		end

		if v.description ~= nil then
			io.write(string.rep(" ", max_width - v.name:len()) .. "  " .. "--  ")

			if v.required then
				io.write("(required) ")
			end

			io.write(v.description)
		end

		io.write("\n")

		::next::
	end

	os.exit()
end

function string:flag()
	if self:sub(1, 2) ~= "--" then
		return nil
	end

	return self:sub(3)
end

return function (opts)
	local args = {}

	local current_index = 1
	local current_flag = nil

	local params = {}

	for _, v in ipairs(opts) do
		if v.kind ~= nil then
			params[v.name] = v
			args[v.name] = v.default
		else
			params[#params + 1] = v
		end
	end

	for _, value in ipairs(arg) do
		local key = nil
		if current_flag == nil then
			local flag = value:flag()
			if flag == nil then
				local option = params[current_index]
				current_index = current_index + 1

				if option == nil then
					print("error: too many arguments")
					help(opts)
				end

				key = option.name
			else
				local option = params[flag]

				if option == nil then
					print("error: unknown flag '" .. flag .. "'")
					help(opts)
				end

				if option.kind == 'flag' then
					key = flag
					value = true
				else
					current_flag = flag
					goto next
				end
			end
		else
				local option = params[current_flag]

				key = option.name
				current_flag = nil
		end

		args[key] = value

		::next::
	end

	for _, option in ipairs(opts) do
		if (option.kind == nil or option.required) and args[option.name] == nil then
			print("error: missing argument '" .. option.name .. "'")
			help(opts)
		end
	end

	return args
end