Compare commits
No commits in common. "refactor/derive-enums-from-man" and "main" have entirely different histories.
refactor/d
...
main
2 changed files with 61 additions and 143 deletions
|
|
@ -18,131 +18,60 @@ function M.enabled()
|
|||
return vim.bo.filetype == 'sshconfig'
|
||||
end
|
||||
|
||||
---@param fragment string
|
||||
---@return string[]?
|
||||
local function parse_value_list(fragment)
|
||||
fragment = fragment:gsub('%b()', '')
|
||||
fragment = fragment:gsub('"', '')
|
||||
fragment = fragment:gsub(' or ', ', ')
|
||||
fragment = fragment:gsub(' and ', ', ')
|
||||
local vals = {}
|
||||
local seen = {}
|
||||
for piece in (fragment .. ','):gmatch('%s*(.-),%s*') do
|
||||
piece = vim.trim(piece)
|
||||
if piece ~= '' and not piece:find('%s') then
|
||||
local val = piece:match('^([%a][%a%d-]+)$')
|
||||
if val then
|
||||
if not seen[val] then
|
||||
seen[val] = true
|
||||
vals[#vals + 1] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return #vals >= 2 and vals or nil
|
||||
end
|
||||
|
||||
---@param man_stdout string
|
||||
---@return table<string, string[]>
|
||||
local function extract_enums_from_man(man_stdout)
|
||||
local lines = {}
|
||||
for line in (man_stdout .. '\n'):gmatch('(.-)\n') do
|
||||
lines[#lines + 1] = line
|
||||
end
|
||||
|
||||
local defs = {}
|
||||
for i, line in ipairs(lines) do
|
||||
local kw = line:match('^ (%u[%a%d]+)%s*$')
|
||||
or line:match('^ (%u[%a%d]+) ')
|
||||
or line:match('^ (%u[%a%d]+) %u')
|
||||
if kw then
|
||||
defs[#defs + 1] = { line = i, keyword = kw }
|
||||
end
|
||||
end
|
||||
|
||||
local enums = {}
|
||||
for idx, def in ipairs(defs) do
|
||||
local block_end = (defs[idx + 1] and defs[idx + 1].line or #lines) - 1
|
||||
local parts = {}
|
||||
for k = def.line + 1, block_end do
|
||||
parts[#parts + 1] = lines[k]
|
||||
end
|
||||
local text = table.concat(parts, ' ')
|
||||
text = text:gsub(string.char(0xe2, 0x80, 0x90) .. '%s+', '')
|
||||
text = text:gsub('%s+', ' ')
|
||||
|
||||
local list = text:match('[Tt]he argument must be (.-)%.')
|
||||
or text:match('[Tt]he argument to this keyword must be (.-)%.')
|
||||
or text:match('[Tt]he argument may be one of:? (.-)%.')
|
||||
or text:match('[Tt]he argument may be (.-)%.')
|
||||
or text:match('[Tt]he possible values are:? (.-)%.')
|
||||
or text:match('[Vv]alid arguments are (.-)%.')
|
||||
or text:match('[Vv]alid options are:? (.-)%.')
|
||||
or text:match('[Aa]ccepted values are (.-)%.')
|
||||
local vals = list and parse_value_list(list)
|
||||
|
||||
if not vals then
|
||||
local fvals = {}
|
||||
local fseen = {}
|
||||
local function add(v)
|
||||
if v and #v >= 2 and not fseen[v] then
|
||||
fseen[v] = true
|
||||
fvals[#fvals + 1] = v
|
||||
end
|
||||
end
|
||||
for v1, v2 in text:gmatch(' is set to "?([%a][%a%d-]+)"? or "?([%a][%a%d-]+)"?') do
|
||||
add(v1)
|
||||
add(v2)
|
||||
end
|
||||
for v in text:gmatch(' is set to "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
for v in text:gmatch('%u[%a%d]+ set to "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
for v in text:gmatch('When set to "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
for v in text:gmatch('[Ss]etting %S+ to "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
for v in text:gmatch('value %S+ be set to "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
local these = text:match('[Tt]hese options are:? (.-)%.')
|
||||
if these then
|
||||
local tv = parse_value_list(these)
|
||||
if tv then
|
||||
for _, v in ipairs(tv) do
|
||||
add(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
for v in text:gmatch('[Tt]he default is "?([%a][%a%d-]+)"?') do
|
||||
if v ~= 'to' then
|
||||
add(v)
|
||||
end
|
||||
end
|
||||
for v in text:gmatch('[Tt]he default, "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
for v in text:gmatch('[Aa]n argument of "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
for v in text:gmatch('[Aa] value of "?([%a][%a%d-]+)"?') do
|
||||
add(v)
|
||||
end
|
||||
if #fvals >= 2 then
|
||||
vals = fvals
|
||||
end
|
||||
end
|
||||
|
||||
if vals then
|
||||
enums[def.keyword:lower()] = vals
|
||||
end
|
||||
end
|
||||
return enums
|
||||
end
|
||||
---@type table<string, string[]>
|
||||
local static_enums = {
|
||||
AddKeysToAgent = { 'yes', 'no', 'ask', 'confirm' },
|
||||
AddressFamily = { 'any', 'inet', 'inet6' },
|
||||
BatchMode = { 'yes', 'no' },
|
||||
CanonicalizeHostname = { 'yes', 'no', 'always' },
|
||||
CanonicalizeFallbackLocal = { 'yes', 'no' },
|
||||
CheckHostIP = { 'yes', 'no' },
|
||||
ClearAllForwardings = { 'yes', 'no' },
|
||||
Compression = { 'yes', 'no' },
|
||||
ControlMaster = { 'yes', 'no', 'ask', 'auto', 'autoask' },
|
||||
EnableEscapeCommandline = { 'yes', 'no' },
|
||||
EnableSSHKeysign = { 'yes', 'no' },
|
||||
ExitOnForwardFailure = { 'yes', 'no' },
|
||||
FingerprintHash = { 'md5', 'sha256' },
|
||||
ForkAfterAuthentication = { 'yes', 'no' },
|
||||
ForwardAgent = { 'yes', 'no' },
|
||||
ForwardX11 = { 'yes', 'no' },
|
||||
ForwardX11Trusted = { 'yes', 'no' },
|
||||
GatewayPorts = { 'yes', 'no' },
|
||||
GSSAPIAuthentication = { 'yes', 'no' },
|
||||
GSSAPIDelegateCredentials = { 'yes', 'no' },
|
||||
HashKnownHosts = { 'yes', 'no' },
|
||||
HostbasedAuthentication = { 'yes', 'no' },
|
||||
IdentitiesOnly = { 'yes', 'no' },
|
||||
KbdInteractiveAuthentication = { 'yes', 'no' },
|
||||
LogLevel = {
|
||||
'QUIET',
|
||||
'FATAL',
|
||||
'ERROR',
|
||||
'INFO',
|
||||
'VERBOSE',
|
||||
'DEBUG',
|
||||
'DEBUG1',
|
||||
'DEBUG2',
|
||||
'DEBUG3',
|
||||
},
|
||||
NoHostAuthenticationForLocalhost = { 'yes', 'no' },
|
||||
PasswordAuthentication = { 'yes', 'no' },
|
||||
PermitLocalCommand = { 'yes', 'no' },
|
||||
PermitRemoteOpen = { 'any', 'none' },
|
||||
ProxyUseFdpass = { 'yes', 'no' },
|
||||
PubkeyAuthentication = { 'yes', 'no', 'unbound', 'host-bound' },
|
||||
RequestTTY = { 'yes', 'no', 'force', 'auto' },
|
||||
SessionType = { 'none', 'subsystem', 'default' },
|
||||
StdinNull = { 'yes', 'no' },
|
||||
StreamLocalBindUnlink = { 'yes', 'no' },
|
||||
StrictHostKeyChecking = { 'yes', 'no', 'ask', 'accept-new', 'off' },
|
||||
TCPKeepAlive = { 'yes', 'no' },
|
||||
Tunnel = { 'yes', 'no', 'point-to-point', 'ethernet' },
|
||||
UpdateHostKeys = { 'yes', 'no', 'ask' },
|
||||
VerifyHostKeyDNS = { 'yes', 'no', 'ask' },
|
||||
VisualHostKey = { 'yes', 'no' },
|
||||
}
|
||||
|
||||
---@type table<string, string[]>
|
||||
local query_to_keywords = {
|
||||
|
|
@ -165,11 +94,9 @@ local function parse_keywords(stdout)
|
|||
|
||||
local defs = {}
|
||||
for i, line in ipairs(lines) do
|
||||
local kw = line:match('^ (%u[%a%d]+)%s*$')
|
||||
or line:match('^ (%u[%a%d]+) ')
|
||||
or line:match('^ (%u[%a%d]+) %u')
|
||||
local kw = line:match('^ (%u%a+)%s*$') or line:match('^ (%u%a+) ')
|
||||
if kw then
|
||||
local inline = line:match('^ %u[%a%d]+%s%s+(.+)')
|
||||
local inline = line:match('^ %u%a+%s%s%s+(.+)')
|
||||
defs[#defs + 1] = { line = i, keyword = kw, inline = inline }
|
||||
end
|
||||
end
|
||||
|
|
@ -220,12 +147,11 @@ local function parse_keywords(stdout)
|
|||
end
|
||||
|
||||
---@param stdout string
|
||||
---@param man_enums table<string, string[]>
|
||||
---@return table<string, string[]>
|
||||
local function parse_enums(stdout, man_enums)
|
||||
local function parse_enums(stdout)
|
||||
local enums = {}
|
||||
for k, v in pairs(man_enums) do
|
||||
enums[k] = v
|
||||
for k, v in pairs(static_enums) do
|
||||
enums[k:lower()] = v
|
||||
end
|
||||
|
||||
local current_query = nil
|
||||
|
|
@ -323,11 +249,7 @@ function M:get_completions(ctx, callback)
|
|||
kw = {}
|
||||
end
|
||||
keywords_cache = kw
|
||||
local ok_me, me = pcall(extract_enums_from_man, man_out)
|
||||
if not ok_me then
|
||||
me = {}
|
||||
end
|
||||
local ok_en, en = pcall(parse_enums, enums_out, me)
|
||||
local ok_en, en = pcall(parse_enums, enums_out)
|
||||
if not ok_en then
|
||||
en = {}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,11 +12,7 @@ local MAN_PAGE = table.concat({
|
|||
' StrictHostKeyChecking',
|
||||
' If this flag is set to yes, ssh(1) will never automatically add',
|
||||
' host keys to the ~/.ssh/known_hosts file, and refuses to connect',
|
||||
' to hosts whose host key has changed. If this flag is set to',
|
||||
' accept-new then ssh will automatically add new host keys. If',
|
||||
' this flag is set to no or off, ssh will automatically add new',
|
||||
' host keys. If this flag is set to ask (the default), new host',
|
||||
' keys will be added only after the user has confirmed.',
|
||||
' to hosts whose host key has changed.',
|
||||
'',
|
||||
' Hostname',
|
||||
' Specifies the real host name to log into.',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue