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 171
|
#!/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)
|