Skip to content

Commit

Permalink
Fix #175; update ssh and ping completions.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisant996 committed Jun 1, 2023
1 parent 61bbdcd commit 7a6e055
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 48 deletions.
68 changes: 46 additions & 22 deletions completions/ping.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require('arghelper')
local w = require('tables').wrap
local clink_version = require('clink_version')

-- Hosts from the .ssh/config file use `color.alias`.
-- Hosts from the .ssh/known_hosts use `color.cmd`.
Expand All @@ -24,41 +25,64 @@ local function read_lines (filename)
return lines
end

local function extract_address(pattern, match_type, portflag)
if not pattern then
return nil
end

local addr, port = pattern:match('%[([^%]]+)%]:(%d+)')
if not addr then
addr = pattern:match('%[([^%]]+)%]')
end
if not addr then
addr = pattern
end

local match
if portflag and port then
match = addr .. portflag .. port
else
match = addr
end
if clink_version.supports_display_filter_description then
return { match=match, type=match_type }
else
return match
end
end

-- read all Host entries in the user's ssh config file
local function list_ssh_hosts()
return read_lines(os.getenv("userprofile") .. "/.ssh/config")
:map(function (line)
local host = line:match('^Host%s+(.*)$')
if host then
for pattern in host:gmatch('([^%s]+)') do
if not pattern:match('[%*|%?|/|!]') then
return pattern
end
local function list_ssh_hosts(portflag)
local matches = w({})
local lines = read_lines(clink.get_env("userprofile") .. "/.ssh/config")
for _, line in ipairs(lines) do
line = line:gsub('(#.*)$', '')
local host = line:match('^Host%s+(.*)$')
if host then
for pattern in host:gmatch('([^%s]+)') do
if not pattern:match('[%*%?/!]') then
table.insert(matches, extract_address(pattern, 'alias', portflag))
end
end
return nil
end)
:filter()
:map(function(line)
return { match=line, type="alias" }
end)
end
end
return matches:filter()
end

local function list_known_hosts()
return read_lines(os.getenv("userprofile") .. "/.ssh/known_hosts")
local function list_known_hosts(portflag)
return read_lines(clink.get_env("userprofile") .. "/.ssh/known_hosts")
:map(function (line)
return line:match('^([^%s,]*).*')
line = line:gsub('(#.*)$', '')
return extract_address(line:match('^([^%s,]*).*'), 'cmd', portflag)
end)
:filter()
:map(function (line)
return { match=line, type="cmd" }
end)
end

local function list_hosts_file()
local t = w({})
local lines = read_lines(os.getenv("systemroot") .. "/system32/drivers/etc/hosts")
for _, line in ipairs(lines) do
line = line:gsub('(#.*)$', '')
local ip, hosts = line:match('^%s*([0-9.:]+)%s(.*)$')
if ip then
table.insert(t, ip)
Expand All @@ -70,7 +94,7 @@ local function list_hosts_file()
return t:filter()
end

local hosts = function (token) -- luacheck: no unused args
local function hosts(token) -- luacheck: no unused args
return list_ssh_hosts()
:concat(list_known_hosts())
:concat(list_hosts_file())
Expand Down
151 changes: 125 additions & 26 deletions ssh.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
-- Some modifications added based on:
-- https://github.com/dodmi/Clink-Addons

local clink_version = require('clink_version')

local w = require('tables').wrap
local parser = clink.arg.new_parser

Expand All @@ -19,32 +21,96 @@ local function read_lines (filename)
return lines
end

local function extract_address(pattern, match_type, portflag)
if not pattern then
return nil
end

local addr, port = pattern:match('%[([^%]]+)%]:(%d+)')
if not addr then
addr = pattern:match('%[([^%]]+)%]')
end
if not addr then
addr = pattern
end

local match
if portflag and port then
match = addr .. portflag .. port
else
match = addr
end
if clink_version.supports_display_filter_description then
return { match=match, type=match_type }
else
return match
end
end

-- read all Host entries in the user's ssh config file
local function list_ssh_hosts()
return read_lines(clink.get_env("userprofile") .. "/.ssh/config")
:map(function (line)
local host = line:match('^Host%s+(.*)$')
if host then
for pattern in host:gmatch('([^%s]+)') do
if not pattern:match('[%*|%?|/|!]') then
return pattern
end
local function list_ssh_hosts(portflag)
local matches = w({})
local lines = read_lines(clink.get_env("userprofile") .. "/.ssh/config")
for _, line in ipairs(lines) do
line = line:gsub('(#.*)$', '')
local host = line:match('^Host%s+(.*)$')
if host then
for pattern in host:gmatch('([^%s]+)') do
if not pattern:match('[%*%?/!]') then
table.insert(matches, extract_address(pattern, 'alias', portflag))
end
end
return nil
end)
:filter()
end
end
return matches:filter()
end

local function list_known_hosts()
local function list_known_hosts(portflag)
return read_lines(clink.get_env("userprofile") .. "/.ssh/known_hosts")
:map(function (line)
return line:match('^([^%s,]*).*')
line = line:gsub('(#.*)$', '')
return extract_address(line:match('^([^%s,]*).*'), 'cmd', portflag)
end)
:filter()
end

local hosts = function (token) -- luacheck: no unused args
local function match_display_filter(matches)
for i, v in ipairs(matches) do
matches[i] = v:gsub('( %-p )', '\027[39m%1')
end
return matches
end

local function ondisplaymatches(matches)
local new_matches = {}
for _,m in ipairs(matches) do
m.display = m.match:gsub('( %-p )', '\027[39m%1')
table.insert(new_matches, m)
end
return new_matches
end

local function hosts_with_port_flag(token) -- luacheck: no unused args
if clink_version.supports_display_filter_description then
clink.ondisplaymatches(ondisplaymatches)
else
clink.match_display_filter = match_display_filter
end
return list_ssh_hosts(' -p ')
:concat(list_known_hosts(' -p '))
end

local function hosts_with_port(token) -- luacheck: no unused args
if clink_version.supports_display_filter_description then
clink.ondisplaymatches(ondisplaymatches)
else
clink.match_display_filter = match_display_filter
end
return list_ssh_hosts(':')
:concat(list_known_hosts(':'))
end

local function hosts(token) -- luacheck: no unused args, no unused
return list_ssh_hosts()
:concat(list_known_hosts())
end
Expand Down Expand Up @@ -94,21 +160,54 @@ local function supportedMACs(token) -- luacheck: no unused args
return macs
end

local ssh_parser = parser({hosts},
"-4", "-6", "-A", "-a", "-C", "-f", "-G", "-g", "-K", "-k",
"-M", "-N", "-n", "-q", "-s", "-T", "-t", "-V", "-v", "-X",
"-x", "-Y", "-y", "-I", "-L", "-l", "-m", "-O", "-o", "-p",
"-R", "-w", "-B", "-c", "-D", "-e", "-S",
"-Q" .. parser({"cipher", "cipher_auth", "help", "mac", "kex", "kex-gss", "key", "key-cert", "key-plain", "key-sig", "protocol-version", "sig"}), -- luacheck: no max line length
"-J" .. parser({hosts}),
"-W" .. parser({hosts}),
local ssh_parser = parser({hosts_with_port_flag},
"-4", "-6", "-A", "-a", "-C", "-f", "-G", "-g", "-K", "-k", "-M",
"-N", "-n", "-q", "-s", "-T", "-t", "-V", "-v", "-X", "-x", "-Y", "-y",
"-B" .. parser({fromhistory=true}), -- How to find available bind_interface's?
"-b" .. parser({localIPs}),
"-c" .. parser({supportedCiphers}),
"-D" .. parser({fromhistory=true, localIPs}),
"-E" .. parser({clink.filematches}),
"-e" .. parser({fromhistory=true}),
"-F" .. parser({clink.filematches}),
"-I" .. parser({fromhistory=true}),
"-i" .. parser({clink.filematches}),
"-b" .. parser({localIPs}),
"-c" .. parser({supportedCiphers}),
"-m" .. parser({supportedMACs})
"-J" .. parser({hosts_with_port}),
"-L" .. parser({fromhistory=true}),
"-l" .. parser({fromhistory=true}),
"-m" .. parser({supportedMACs}),
"-O" .. parser({fromhistory=true}),
"-o" .. parser({fromhistory=true}),
"-p" .. parser({fromhistory=true}),
"-Q" .. parser({"cipher", "cipher_auth", "help", "mac", "kex", "kex-gss", "key", "key-cert", "key-plain", "key-sig", "protocol-version", "sig"}), -- luacheck: no max line length
"-R" .. parser({fromhistory=true}),
"-S" .. parser({fromhistory=true}),
"-W" .. parser({hosts_with_port}),
"-w" .. parser({fromhistory=true})
)
:adddescriptions({
["-B"] = { " bind_interface", "" },
["-b"] = { " bind_address", "" },
["-c"] = { " cipher_spec", "" },
["-D"] = { " [bind_address:]port", "" },
["-E"] = { " log_file", "" },
["-e"] = { " escape_char", "" },
["-F"] = { " configfile", "" },
["-I"] = { " pkcs11", "" },
["-i"] = { " identity_file", "" },
["-J"] = { " [user@]host[:port]", "" },
["-L"] = { " address", "" },
["-l"] = { " login_name", "" },
["-m"] = { " mac_spec", "" },
["-O"] = { " ctl_cmd", "" },
["-o"] = { " option", "" },
["-p"] = { " port", "" },
["-Q"] = { " query_option", "" },
["-R"] = { " address", "" },
["-S"] = { " ctl_path", "" },
["-W"] = { " host:port", "" },
["-w"] = { " local_tun[:remote_tun]", "" },
})

clink.arg.register_parser("ssh", ssh_parser)

0 comments on commit 7a6e055

Please sign in to comment.