diff --git a/wezterm.lua b/wezterm.lua index c2f81bf..7a97206 100644 --- a/wezterm.lua +++ b/wezterm.lua @@ -248,6 +248,19 @@ local function show_font_settings(window, pane) ) 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 text, err = read_config_text() 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) 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에는 입력칸을 여러 개 한 화면에 배치하는 폼 위젯이 없어, 한 줄짜리 -- PromptInputLine을 단계별로 이어서 띄우는 방식으로 흉내낸다) local ssh_domain_steps = { - { field = "name", title = "SSH 이름 (1/3, 예: prod)" }, - { field = "remote_address", title = "SSH 주소 (2/3, 예: myserver.example.com)" }, - { field = "username", title = "SSH 사용자명 (3/3, 예: ubuntu)" }, + { field = "name", title = "SSH 이름 (1/4, 예: prod)" }, + { field = "host", title = "SSH 주소 (2/4, 예: myserver.example.com)" }, + { 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) @@ -289,17 +331,21 @@ local function prompt_ssh_domain_step(window, pane, step_index, data) act.PromptInputLine({ description = step.title, 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 도메인 추가를 취소했습니다") return end - data[step.field] = line + data[step.field] = line or "" if step_index < #ssh_domain_steps then prompt_ssh_domain_step(cb_window, cb_pane, step_index + 1, data) 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), }), @@ -311,6 +357,96 @@ local function prompt_ssh_domain(window, pane) prompt_ssh_domain_step(window, pane, 1, {}) 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) window:perform_action( act.InputSelector({ @@ -318,12 +454,15 @@ local function show_connection_settings(window, pane) fuzzy = true, choices = { { label = "SSH 도메인 추가", id = "add_ssh" }, + { label = "SSH 도메인 수정", id = "edit_ssh" }, { label = "SSH 도메인 목록", id = "domains" }, { label = "통합 런처", id = "launcher" }, }, action = wezterm.action_callback(function(inner_window, inner_pane, id) if id == "add_ssh" then 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 inner_window:perform_action(act.ShowLauncherArgs({ flags = "DOMAINS" }), inner_pane) elseif id == "launcher" then