Add clickable menu and prompt settings

This commit is contained in:
2026-07-17 00:49:11 +09:00
parent 124c99bef8
commit 0f9632a678

View File

@@ -96,12 +96,14 @@ local pane_start_times = {}
wezterm.on("update-right-status", function(window, pane)
window:set_left_status(wezterm.format({
{ Hyperlink = { uri = "wezterm://main-menu" } },
{ Background = { Color = "#89b4fa" } },
{ Foreground = { Color = "#1e1e2e" } },
{ Text = "" },
{ Text = " Menu " },
{ Hyperlink = { uri = "" } },
{ Background = { Color = "#313244" } },
{ Foreground = { Color = "#cdd6f4" } },
{ Text = " Menu: Ctrl+a m " },
{ Text = " Ctrl+a m " },
}))
local pane_id = pane:pane_id()
@@ -150,41 +152,225 @@ config.unix_domains = {
local is_windows = wezterm.target_triple:find("windows") ~= nil
local config_file = is_windows and (wezterm.home_dir .. "\\.wezterm.lua") or "/mnt/storage/wezterm.lua"
local function open_config_section(window, pane, line)
local args
if is_windows then
args = {
"powershell.exe",
"-NoLogo",
"-NoExit",
"-Command",
string.format(
'$file = %q; $line = %d; '
.. '$code = Get-Command code.cmd,code -ErrorAction SilentlyContinue | Select-Object -First 1; '
.. 'if ($code) { & $code.Source -g "${file}:${line}" } '
.. 'else { Write-Host "VS Code not found. Opening Notepad without line jump."; notepad.exe $file }',
config_file,
line
),
}
local function notify(window, message)
if window.toast_notification then
window:toast_notification("WezTerm", message, nil, 4000)
else
args = {
"sh",
"-lc",
string.format(
'file=%q; line=%d; editor="${VISUAL:-${EDITOR:-}}"; '
.. 'if [ -z "$editor" ]; then for candidate in nvim vim vi nano; do command -v "$candidate" >/dev/null 2>&1 && editor="$candidate" && break; done; fi; '
.. 'if [ -z "$editor" ]; then echo "No terminal editor found. Set EDITOR or install vim/nano."; exec "${SHELL:-sh}"; fi; '
.. '"$editor" +"$line" "$file"; status=$?; '
.. 'if [ $status -ne 0 ]; then echo; echo "Editor exited with status $status. Press Enter to close, or type commands below."; exec "${SHELL:-sh}"; fi',
config_file,
line
),
}
wezterm.log_info(message)
end
end
local function read_config_text()
local file = io.open(config_file, "r")
if not file then
return nil, "설정 파일을 열 수 없습니다: " .. config_file
end
local text = file:read("*a")
file:close()
return text
end
local function write_config_text(text)
local file = io.open(config_file, "w")
if not file then
return false, "설정 파일에 쓸 수 없습니다: " .. config_file
end
file:write(text)
file:close()
return true
end
local function set_config_value(window, pane, key, value)
local text, err = read_config_text()
if not text then
notify(window, err)
return
end
local pattern = "(config%." .. key .. "%s*=%s*)[^\n]+"
local updated, count = text:gsub(pattern, function(prefix)
return prefix .. value
end, 1)
if count == 0 then
notify(window, "설정 항목을 찾지 못했습니다: config." .. key)
return
end
local ok, write_err = write_config_text(updated)
if not ok then
notify(window, write_err)
return
end
notify(window, "저장됨: config." .. key .. " = " .. value)
window:perform_action(act.ReloadConfiguration, pane)
end
local function prompt_config_value(window, pane, title, key, initial_value, quote_string)
window:perform_action(
act.SpawnCommandInNewTab({ args = args }),
act.PromptInputLine({
description = title,
initial_value = tostring(initial_value),
action = wezterm.action_callback(function(inner_window, inner_pane, line)
if not line or line == "" then
return
end
local value = quote_string and string.format("%q", line) or line
set_config_value(inner_window, inner_pane, key, value)
end),
}),
pane
)
end
local function show_font_settings(window, pane)
window:perform_action(
act.InputSelector({
title = "폰트 설정",
fuzzy = true,
choices = {
{ label = "폰트 크기", id = "font_size" },
{ label = "줄 높이", id = "line_height" },
{ label = "색상 테마", id = "color_scheme" },
{ label = "창 투명도", id = "opacity" },
},
action = wezterm.action_callback(function(inner_window, inner_pane, id)
if id == "font_size" then
prompt_config_value(inner_window, inner_pane, "폰트 크기", "font_size", config.font_size, false)
elseif id == "line_height" then
prompt_config_value(inner_window, inner_pane, "줄 높이", "line_height", config.line_height, false)
elseif id == "color_scheme" then
prompt_config_value(inner_window, inner_pane, "색상 테마", "color_scheme", config.color_scheme, true)
elseif id == "opacity" then
prompt_config_value(inner_window, inner_pane, "창 투명도", "window_background_opacity", config.window_background_opacity, false)
end
end),
}),
pane
)
end
local function append_ssh_domain(window, pane, name, remote_address, username)
local text, err = read_config_text()
if not text then
notify(window, err)
return
end
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 updated, count = text:gsub("(config%.ssh_domains%s*=%s*{%s*\n)", function(prefix)
return prefix .. entry
end, 1)
if count == 0 then
notify(window, "config.ssh_domains 블록을 찾지 못했습니다")
return
end
local ok, write_err = write_config_text(updated)
if not ok then
notify(window, write_err)
return
end
notify(window, "SSH 도메인 추가됨: " .. name)
window:perform_action(act.ReloadConfiguration, pane)
end
local function prompt_ssh_domain(window, pane)
local draft = {}
window:perform_action(
act.PromptInputLine({
description = "SSH 이름",
action = wezterm.action_callback(function(w1, p1, name)
if not name or name == "" then
return
end
draft.name = name
w1:perform_action(
act.PromptInputLine({
description = "SSH 주소",
action = wezterm.action_callback(function(w2, p2, address)
if not address or address == "" then
return
end
draft.remote_address = address
w2:perform_action(
act.PromptInputLine({
description = "SSH 사용자명",
action = wezterm.action_callback(function(w3, p3, username)
if not username or username == "" then
return
end
append_ssh_domain(w3, p3, draft.name, draft.remote_address, username)
end),
}),
p2
)
end),
}),
p1
)
end),
}),
pane
)
end
local function show_connection_settings(window, pane)
window:perform_action(
act.InputSelector({
title = "연결 설정",
fuzzy = true,
choices = {
{ label = "SSH 도메인 추가", id = "add_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 == "domains" then
inner_window:perform_action(act.ShowLauncherArgs({ flags = "DOMAINS" }), inner_pane)
elseif id == "launcher" then
inner_window:perform_action(act.ShowLauncherArgs({ flags = "FUZZY|TABS|DOMAINS|WORKSPACES|LAUNCH_MENU_ITEMS" }), inner_pane)
end
end),
}),
pane
)
end
local function show_other_settings(window, pane)
window:perform_action(
act.InputSelector({
title = "기타 설정",
fuzzy = true,
choices = {
{ label = "스크롤백 줄 수", id = "scrollback" },
{ label = "최대 FPS", id = "max_fps" },
{ label = "탭바 위치: 상단", id = "tab_top" },
{ label = "탭바 위치: 하단", id = "tab_bottom" },
{ label = "창 닫기 확인 켜기", id = "close_prompt" },
{ label = "창 닫기 확인 끄기", id = "close_no_prompt" },
},
action = wezterm.action_callback(function(inner_window, inner_pane, id)
if id == "scrollback" then
prompt_config_value(inner_window, inner_pane, "스크롤백 줄 수", "scrollback_lines", config.scrollback_lines, false)
elseif id == "max_fps" then
prompt_config_value(inner_window, inner_pane, "최대 FPS", "max_fps", config.max_fps, false)
elseif id == "tab_top" then
set_config_value(inner_window, inner_pane, "tab_bar_at_bottom", "false")
elseif id == "tab_bottom" then
set_config_value(inner_window, inner_pane, "tab_bar_at_bottom", "true")
elseif id == "close_prompt" then
set_config_value(inner_window, inner_pane, "window_close_confirmation", string.format("%q", "AlwaysPrompt"))
elseif id == "close_no_prompt" then
set_config_value(inner_window, inner_pane, "window_close_confirmation", string.format("%q", "NeverPrompt"))
end
end),
}),
pane
)
end
@@ -207,11 +393,11 @@ local function show_main_menu(window, pane)
end
if id == "font" then
open_config_section(inner_window, inner_pane, 6)
show_font_settings(inner_window, inner_pane)
elseif id == "connection" then
open_config_section(inner_window, inner_pane, 123)
show_connection_settings(inner_window, inner_pane)
elseif id == "other" then
open_config_section(inner_window, inner_pane, 339)
show_other_settings(inner_window, inner_pane)
elseif id == "launcher" then
inner_window:perform_action(
act.ShowLauncherArgs({ flags = "FUZZY|TABS|DOMAINS|WORKSPACES|LAUNCH_MENU_ITEMS" }),
@@ -230,6 +416,13 @@ wezterm.on("show-main-menu", function(window, pane)
show_main_menu(window, pane)
end)
wezterm.on("open-uri", function(window, pane, uri)
if uri == "wezterm://main-menu" then
show_main_menu(window, pane)
return false
end
end)
-- 시작 시 첫 화면으로 메인 메뉴를 띄워 설정과 연결 메뉴에 바로 접근합니다.
wezterm.on("gui-startup", function(cmd)
local tab, pane, window = wezterm.mux.spawn_window(cmd or {})