| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 | #!/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 civetwebThe 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 argumentscmd = arg[1] -- typically "./civetweb" or whatever path was usedthis = arg[2] -- characters already typed for the next optionslast = arg[3] -- option before this one-- Environment variablescomp_line = os.getenv("COMP_LINE") -- entire command linecomp_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 existfunction fileexists(name)  local f = io.open(name, "r")  if f then    f:close()    return true  end  return falseend-- Debug loggingdp("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)endis_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)endis_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 argumenthtpasswd_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)endif (last == "-R") and (this == htpasswd_r:sub(1,#this)) then  dp("Fill with option template for -R")  print(htpasswd_r)  os.exit(0)endif (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)endhttp = "https://"if (last == "-C") and (this == http:sub(1,#this)) then  print(http)  print(http.. "localhost/")  os.exit(0)endif (is_c) then  dp("Option -C has just one argument")  os.exit(0)end-- Take options directly from "--help" output of executableoptfile = "/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")endfor 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  endendif keymatch then  -- at least one options matches  os.exit(0)endif valmatch then  -- suggest the default value  print(valmatch)  os.exit(0)end-- No context to determine next argumentdp("no specific option")os.exit(0)
 |