aboutsummaryrefslogtreecommitdiff
path: root/src/arg.lua
blob: de19c7708673f01ba36db9dd6a8d08bec56b5c27 (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
local function help(opts)

	io.write(Path:new(arg[0]):name())
	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

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_name()
			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 and opts.strict then
					print("error: unknown flag '" .. flag .. "'")
					help(opts)
				elseif option == nil then
					option = { name = flag, kind = 'property' }
					params[flag] = option
				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