/
complete.lua
171 lines (141 loc) · 4.74 KB
/
complete.lua
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/lua5.2
-- CivetWeb command line completion for bash
--[[ INSTALLING:
To use auto-completion for bash, you need to define a command for the bash built-in
[*complete*](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html).
Create a file called "civetweb" in the completion folder.
Depending on Linux distribution and version, this might be
/usr/share/bash-completion/completions/, /etc/bash_completion or another folder.
The file has to contain just one line:
complete -C /path/to/civetweb/resources/complete.lua civetweb
The complete command script is implemented in this file.
It needs Lua 5.2 to be installed (for Debian based systems: "sudo apt-get install lua5.2").
In case lua5.2 is not located in /usr/bin/lua5.2 (see "which lua5.2"),
the first line (#!) needs to be adapted accordingly.
--]]
---------------------------------------------------------------------------------------------------
-- The bash "complete -C" has an awkward interface:
-- see https://unix.stackexchange.com/questions/250262/how-to-use-bashs-complete-or-compgen-c-command-option
-- Command line arguments
cmd = arg[1] -- typically "./civetweb" or whatever path was used
this = arg[2] -- characters already typed for the next options
last = arg[3] -- option before this one
-- Environment variables
comp_line = os.getenv("COMP_LINE") -- entire command line
comp_point = os.getenv("COMP_POINT") -- position of cursor (index)
comp_type = os.getenv("COMP_TYPE") -- type:
-- 9 for normal completion
-- 33 when listing alternatives on ambiguous completions
-- 37 for menu completion
-- 63 when tabbing between ambiguous completions
-- 64 to list completions after a partial completion
-- Debug-Print function (must use absolute path for log file)
function dp(txt)
--[[ comment / uncomment to enable debugging
local f = io.open("/tmp/complete.log", "a");
f:write(txt .. "\n")
f:close()
--]]
end
-- Helper function: Check if files exist
function fileexists(name)
local f = io.open(name, "r")
if f then
f:close()
return true
end
return false
end
-- Debug logging
dp("complete: cmd=" .. cmd .. ", this=" .. this .. ", last=" .. last .. ", type=" .. comp_type)
-- Trim command line (remove spaces)
trim_comp_line = string.match(comp_line, "^%s*(.-)%s*$")
if (trim_comp_line == cmd) then
-- this is the first option
dp("Suggest --help argument")
print("--help ")
os.exit(0)
end
is_h = string.find(comp_line, "^%s*" .. cmd .. "%s+%-h%s")
is_h = is_h or string.find(comp_line, "^%s*" .. cmd .. "%s+%--help%s")
is_h = is_h or string.find(comp_line, "^%s*" .. cmd .. "%s+%-H%s")
if (is_h) then
dp("If --help is used, no additional argument is allowed")
os.exit(0)
end
is_a = string.find(comp_line, "^%s*" .. cmd .. "%s+%-A%s")
is_c = string.find(comp_line, "^%s*" .. cmd .. "%s+%-C%s")
is_i = string.find(comp_line, "^%s*" .. cmd .. "%s+%-I%s")
is_r = string.find(comp_line, "^%s*" .. cmd .. "%s+%-R%s")
if (is_i) then
dp("If --I is used, no additional argument is allowed")
os.exit(0)
end
-- -A and -R require the password file as second argument
htpasswd_r = ".htpasswd <mydomain.com> <username>"
htpasswd_a = htpasswd_r .. " <password>"
if (last == "-A") and (this == htpasswd_a:sub(1,#this)) then
dp("Fill with option template for -A")
print(htpasswd_a)
os.exit(0)
end
if (last == "-R") and (this == htpasswd_r:sub(1,#this)) then
dp("Fill with option template for -R")
print(htpasswd_r)
os.exit(0)
end
if (is_a or is_r) then
dp("Options -A and -R have a fixed number of arguments")
os.exit(0)
end
-- -C requires an URL, usually starting with http:// or https://
http = "http://"
if (last == "-C") and (this == http:sub(1,#this)) then
print(http)
print(http.. "localhost/")
os.exit(0)
end
http = "https://"
if (last == "-C") and (this == http:sub(1,#this)) then
print(http)
print(http.. "localhost/")
os.exit(0)
end
if (is_c) then
dp("Option -C has just one argument")
os.exit(0)
end
-- Take options directly from "--help" output of executable
optfile = "/tmp/civetweb.options"
if not fileexists(optfile) then
dp("options file " .. optfile .. " missing")
os.execute(cmd .. " --help > " .. optfile .. " 2>&1")
else
dp("options file " .. optfile .. " found")
end
for l in io.lines(optfile) do
local lkey, lval = l:match("^%s+(%-[^%s]*)%s*([^%s]*)%s*$")
if lkey then
local thislen = string.len(this)
if (thislen>0) and (this == lkey:sub(1,thislen)) then
print(lkey)
dp("match: " .. lkey)
keymatch = true
end
if last == lkey then
valmatch = lval
end
end
end
if keymatch then
-- at least one options matches
os.exit(0)
end
if valmatch then
-- suggest the default value
print(valmatch)
os.exit(0)
end
-- No context to determine next argument
dp("no specific option")
os.exit(0)