Add SSH port field and an edit flow for existing SSH domains
- SSH domain add flow gains a 4th, optional "port" step; a non-empty port is appended to remote_address as "host:port" (WezTerm's native way to specify a non-default SSH port), matching how existing entries are parsed back out via the new split_remote_address helper. - New "SSH 도메인 수정" entry in connection settings lists existing config.ssh_domains entries; picking one re-prompts each field (name/address/port/username) with the current value shown in the description, where leaving a field blank keeps the old value instead of cancelling (unlike the add flow, where blank cancels). - update_ssh_domain locates the exact entry block by its original name (pattern built from append_ssh_domain's fixed write format, escaped for Lua pattern safety) and replaces it wholesale, so a rename is just "old name matched, new block written". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
153
wezterm.lua
153
wezterm.lua
@@ -248,6 +248,19 @@ local function show_font_settings(window, pane)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function escape_pattern(s)
|
||||||
|
return (s:gsub("[%^%$%(%)%.%[%]%*%+%-%?%%]", "%%%1"))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- "host:port" 형태의 remote_address를 host, port로 분리 (port 없으면 port는 nil)
|
||||||
|
local function split_remote_address(remote_address)
|
||||||
|
local host, port = remote_address:match("^(.-):(%d+)$")
|
||||||
|
if host then
|
||||||
|
return host, port
|
||||||
|
end
|
||||||
|
return remote_address, nil
|
||||||
|
end
|
||||||
|
|
||||||
local function append_ssh_domain(window, pane, name, remote_address, username)
|
local function append_ssh_domain(window, pane, name, remote_address, username)
|
||||||
local text, err = read_config_text()
|
local text, err = read_config_text()
|
||||||
if not text then
|
if not text then
|
||||||
@@ -273,13 +286,42 @@ local function append_ssh_domain(window, pane, name, remote_address, username)
|
|||||||
window:perform_action(act.ReloadConfiguration, pane)
|
window:perform_action(act.ReloadConfiguration, pane)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- SSH 도메인 등록을 이름 -> 주소 -> 사용자명 순서로 한 칸씩 물어봄
|
local function update_ssh_domain(window, pane, old_name, name, remote_address, username)
|
||||||
|
local text, err = read_config_text()
|
||||||
|
if not text then
|
||||||
|
notify(window, err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local quoted_old_name = escape_pattern(string.format("%q", old_name))
|
||||||
|
local pattern = "\t{\n\t\tname = " .. quoted_old_name .. ",\n\t\tremote_address = %b\"\",\n\t\tusername = %b\"\",\n\t},\n"
|
||||||
|
local entry = string.format('\t{\n\t\tname = %q,\n\t\tremote_address = %q,\n\t\tusername = %q,\n\t},\n', name, remote_address, username)
|
||||||
|
local safe_entry = entry:gsub("%%", "%%%%")
|
||||||
|
|
||||||
|
local updated, count = text:gsub(pattern, safe_entry, 1)
|
||||||
|
if count == 0 then
|
||||||
|
notify(window, "SSH 도메인 항목을 찾지 못했습니다: " .. old_name)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, write_err = write_config_text(updated)
|
||||||
|
if not ok then
|
||||||
|
notify(window, write_err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
notify(window, "SSH 도메인 수정됨: " .. name .. " -> " .. remote_address .. " (WezTerm을 완전히 재시작해야 반영됩니다)")
|
||||||
|
window:perform_action(act.ReloadConfiguration, pane)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SSH 도메인 등록을 이름 -> 주소 -> 포트 -> 사용자명 순서로 한 칸씩 물어봄
|
||||||
-- (WezTerm에는 입력칸을 여러 개 한 화면에 배치하는 폼 위젯이 없어, 한 줄짜리
|
-- (WezTerm에는 입력칸을 여러 개 한 화면에 배치하는 폼 위젯이 없어, 한 줄짜리
|
||||||
-- PromptInputLine을 단계별로 이어서 띄우는 방식으로 흉내낸다)
|
-- PromptInputLine을 단계별로 이어서 띄우는 방식으로 흉내낸다)
|
||||||
local ssh_domain_steps = {
|
local ssh_domain_steps = {
|
||||||
{ field = "name", title = "SSH 이름 (1/3, 예: prod)" },
|
{ field = "name", title = "SSH 이름 (1/4, 예: prod)" },
|
||||||
{ field = "remote_address", title = "SSH 주소 (2/3, 예: myserver.example.com)" },
|
{ field = "host", title = "SSH 주소 (2/4, 예: myserver.example.com)" },
|
||||||
{ field = "username", title = "SSH 사용자명 (3/3, 예: ubuntu)" },
|
{ field = "port", title = "SSH 포트 (3/4, 비워두면 기본값 22)", optional = true },
|
||||||
|
{ field = "username", title = "SSH 사용자명 (4/4, 예: ubuntu)" },
|
||||||
}
|
}
|
||||||
|
|
||||||
local function prompt_ssh_domain_step(window, pane, step_index, data)
|
local function prompt_ssh_domain_step(window, pane, step_index, data)
|
||||||
@@ -289,17 +331,21 @@ local function prompt_ssh_domain_step(window, pane, step_index, data)
|
|||||||
act.PromptInputLine({
|
act.PromptInputLine({
|
||||||
description = step.title,
|
description = step.title,
|
||||||
action = wezterm.action_callback(function(cb_window, cb_pane, line)
|
action = wezterm.action_callback(function(cb_window, cb_pane, line)
|
||||||
if not line or line == "" then
|
if (not line or line == "") and not step.optional then
|
||||||
notify(cb_window, "SSH 도메인 추가를 취소했습니다")
|
notify(cb_window, "SSH 도메인 추가를 취소했습니다")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
data[step.field] = line
|
data[step.field] = line or ""
|
||||||
|
|
||||||
if step_index < #ssh_domain_steps then
|
if step_index < #ssh_domain_steps then
|
||||||
prompt_ssh_domain_step(cb_window, cb_pane, step_index + 1, data)
|
prompt_ssh_domain_step(cb_window, cb_pane, step_index + 1, data)
|
||||||
else
|
else
|
||||||
append_ssh_domain(cb_window, cb_pane, data.name, data.remote_address, data.username)
|
local remote_address = data.host
|
||||||
|
if data.port ~= "" then
|
||||||
|
remote_address = remote_address .. ":" .. data.port
|
||||||
|
end
|
||||||
|
append_ssh_domain(cb_window, cb_pane, data.name, remote_address, data.username)
|
||||||
end
|
end
|
||||||
end),
|
end),
|
||||||
}),
|
}),
|
||||||
@@ -311,6 +357,96 @@ local function prompt_ssh_domain(window, pane)
|
|||||||
prompt_ssh_domain_step(window, pane, 1, {})
|
prompt_ssh_domain_step(window, pane, 1, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- SSH 도메인 수정: 기존 값은 비워두면 그대로 유지, 입력하면 해당 항목만 교체
|
||||||
|
local edit_ssh_domain_steps = {
|
||||||
|
{ field = "name", label = "SSH 이름" },
|
||||||
|
{ field = "host", label = "SSH 주소" },
|
||||||
|
{ field = "port", label = "SSH 포트" },
|
||||||
|
{ field = "username", label = "SSH 사용자명" },
|
||||||
|
}
|
||||||
|
|
||||||
|
local function prompt_edit_ssh_domain_step(window, pane, step_index, data)
|
||||||
|
local step = edit_ssh_domain_steps[step_index]
|
||||||
|
local current_display = data[step.field]
|
||||||
|
if step.field == "port" and current_display == "" then
|
||||||
|
current_display = "기본값 22"
|
||||||
|
end
|
||||||
|
|
||||||
|
window:perform_action(
|
||||||
|
act.PromptInputLine({
|
||||||
|
description = string.format(
|
||||||
|
"%s (%d/%d, 현재: %s, 비워두면 유지)",
|
||||||
|
step.label,
|
||||||
|
step_index,
|
||||||
|
#edit_ssh_domain_steps,
|
||||||
|
current_display
|
||||||
|
),
|
||||||
|
action = wezterm.action_callback(function(cb_window, cb_pane, line)
|
||||||
|
if line and line ~= "" then
|
||||||
|
data[step.field] = line
|
||||||
|
end
|
||||||
|
|
||||||
|
if step_index < #edit_ssh_domain_steps then
|
||||||
|
prompt_edit_ssh_domain_step(cb_window, cb_pane, step_index + 1, data)
|
||||||
|
else
|
||||||
|
local remote_address = data.host
|
||||||
|
if data.port ~= "" then
|
||||||
|
remote_address = remote_address .. ":" .. data.port
|
||||||
|
end
|
||||||
|
update_ssh_domain(cb_window, cb_pane, data.original_name, data.name, remote_address, data.username)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
}),
|
||||||
|
pane
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function prompt_edit_ssh_domain(window, pane, domain)
|
||||||
|
local host, port = split_remote_address(domain.remote_address)
|
||||||
|
prompt_edit_ssh_domain_step(window, pane, 1, {
|
||||||
|
original_name = domain.name,
|
||||||
|
name = domain.name,
|
||||||
|
host = host,
|
||||||
|
port = port or "",
|
||||||
|
username = domain.username,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function show_edit_ssh_domain_list(window, pane)
|
||||||
|
local choices = {}
|
||||||
|
for _, domain in ipairs(config.ssh_domains or {}) do
|
||||||
|
table.insert(choices, {
|
||||||
|
label = domain.name .. " (" .. domain.remote_address .. ")",
|
||||||
|
id = domain.name,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if #choices == 0 then
|
||||||
|
notify(window, "등록된 SSH 도메인이 없습니다")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
window:perform_action(
|
||||||
|
act.InputSelector({
|
||||||
|
title = "SSH 도메인 수정",
|
||||||
|
fuzzy = true,
|
||||||
|
choices = choices,
|
||||||
|
action = wezterm.action_callback(function(inner_window, inner_pane, id)
|
||||||
|
if not id then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for _, domain in ipairs(config.ssh_domains or {}) do
|
||||||
|
if domain.name == id then
|
||||||
|
prompt_edit_ssh_domain(inner_window, inner_pane, domain)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
}),
|
||||||
|
pane
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
local function show_connection_settings(window, pane)
|
local function show_connection_settings(window, pane)
|
||||||
window:perform_action(
|
window:perform_action(
|
||||||
act.InputSelector({
|
act.InputSelector({
|
||||||
@@ -318,12 +454,15 @@ local function show_connection_settings(window, pane)
|
|||||||
fuzzy = true,
|
fuzzy = true,
|
||||||
choices = {
|
choices = {
|
||||||
{ label = "SSH 도메인 추가", id = "add_ssh" },
|
{ label = "SSH 도메인 추가", id = "add_ssh" },
|
||||||
|
{ label = "SSH 도메인 수정", id = "edit_ssh" },
|
||||||
{ label = "SSH 도메인 목록", id = "domains" },
|
{ label = "SSH 도메인 목록", id = "domains" },
|
||||||
{ label = "통합 런처", id = "launcher" },
|
{ label = "통합 런처", id = "launcher" },
|
||||||
},
|
},
|
||||||
action = wezterm.action_callback(function(inner_window, inner_pane, id)
|
action = wezterm.action_callback(function(inner_window, inner_pane, id)
|
||||||
if id == "add_ssh" then
|
if id == "add_ssh" then
|
||||||
prompt_ssh_domain(inner_window, inner_pane)
|
prompt_ssh_domain(inner_window, inner_pane)
|
||||||
|
elseif id == "edit_ssh" then
|
||||||
|
show_edit_ssh_domain_list(inner_window, inner_pane)
|
||||||
elseif id == "domains" then
|
elseif id == "domains" then
|
||||||
inner_window:perform_action(act.ShowLauncherArgs({ flags = "DOMAINS" }), inner_pane)
|
inner_window:perform_action(act.ShowLauncherArgs({ flags = "DOMAINS" }), inner_pane)
|
||||||
elseif id == "launcher" then
|
elseif id == "launcher" then
|
||||||
|
|||||||
Reference in New Issue
Block a user