WezTermのworkspace管理をいい感じにする
#はじめに
こんにちは, @kazuです.
weztermでのworkspaceをいい感じに管理する方法について, 自分の中で満足できる設定を作れたので共有です.
背景
前提
前提として, 自分の作業スタイルを記載しておきます.
- 大体の開発作業はWezTerm上で行っている.
- なんとなくの作業内容ごとに, 適切にworkspaceを切り替えながら作業したい.
- WezTermのwindowは常にひとつだけにしたい.
- workspace中のlayoutなどは特に気にしない.
実現したいこと
いい感じにworkspaceを管理するために, 以下が実現したいことです.
- 任意のcwdから, そこを起点とするworkspaceが楽に作れること.
- そこを起点とするworkspaceがすでに存在する場合は, 新規作成せずに切り替えのみを行うこと.
- ショートカットでworkspace切り替え画面が呼び出せること.
- workspace切り替え画面では, 以下のworkspaceが選択できること.
- すでに存在するworkspace
- 事前定義したworkspace
成果物
先に成果物をお見せします.

一番上のcurrent:として表示されているものは, 現在アクティブな(フォーカスしている)workspaceです.
二番のdefault:として表示されているものは, home directoryを起点とするworkspaceです.
それ以降の, 背景色がない部分(ここでは1のみ)は, 現在存在するworkspceです(currentは除外ずみ.).
背景色が青い部分は, 事前定義してある かつ まだ存在していないworkspaceです.
これらの選択肢をfuzzyに選択し, 任意のworkspaceに切り替えることができます.
設定内容
workspaceを作成する設定
まず, workspaceを作成する部分のコードをお見せします.
M.create_or_switch_new = function(win, pane)
-- 現在の作業ディレクトリを取得
local cwd = pane:get_current_working_dir()
local workspace_name = cwd.file_path
win:perform_action(wezterm.action.SwitchToWorkspace { name = workspace_name,
spawn = {
cwd = workspace_name
}
}, pane)
end
ここでやってることは,
- 現在のpaneで
cwdを取得 - その
cwdを名前としてworkspaceを切り替える.
だけです.
SwitchToWorkspaceが以下のような挙動をするため, 設定上ではそのworkspaceがすでに存在するか否かを気にする必要はありません.
-
nameで指定されたworkspaceがすでに存在すれば, そのworkspaceに切り替える. - 存在しない場合,
spawnで指定した設定で新規workspaceを作成し,そのworkspaceに切り替える.
ref:
workspaceを選択する設定
続いて, workspaceを選択する部分のコードをお見せします.
メインの部分はこちら.
M.switch_to_workspace = function(win, pane)
local current_workspace = wezterm.mux.get_active_workspace()
-- workspace のリストを作成
local workspaces = {}
if current_workspace ~= "" then
table.insert(workspaces, {
id = current_workspace,
label = wezterm.format {
{ Background = { Color = "#80d4ff" } },
{ Foreground = { Color = '#383a42' } },
{ Text = "current: " },
{ Text = current_workspace }
},
})
end
if current_workspace ~= 'default' then
table.insert(workspaces, {
id = "default",
label = wezterm.format {
{ Background = { Color = "#ffff99" } },
{ Foreground = { Color = '#383a42' } },
{ Text = "default: " },
{ Text = wezterm.home_dir }
},
})
end
local count = 1;
local workspace_names = wezterm.mux.get_workspace_names()
for _, name in pairs(workspace_names) do
if name == current_workspace or name == "default" then
goto continue
end
table.insert(workspaces, {
id = name,
label = string.format("%7d: %s", count, name),
})
count = count + 1
::continue::
end
-- 別途定義してあるworkspaceを読み込む.後述
local local_workspaces = load_local_workspaces()
for _, workspace in pairs(local_workspaces) do
if not utils.table_contains(workspace_names, workspace) then
table.insert(workspaces, {
id = workspace,
label = wezterm.format {
{ Background = { Color = "#79a6d2" } },
{ Foreground = { Color = '#383a42' } },
{ Text = string.format("%7d: %s", count, workspace) }
},
})
count = count + 1
end
end
-- 選択メニューを起動
win:perform_action(wezterm.action.InputSelector {
action = wezterm.action_callback(function(_, _, id, label)
if not id and not label then
wezterm.log_info "Workspace selection canceled"
else
win:perform_action(wezterm.action.SwitchToWorkspace { name = id,
spawn = { cwd = id }
}, pane)
end
end),
title = "Select workspace",
choices = workspaces,
fuzzy = true,
}, pane)
end
事前定義のworkspaceを読み込む設定はこちら.
local function load_local_workspaces()
if utils.file_exists("local_workspaces") then
return require("local_workspaces")
end
return {}
end
utilsはこちら.
M.file_exists = function(name)
local full_path = package.searchpath(name, package.path)
if not full_path then
return false
end
local f = io.open(full_path, 'r')
if f then
io.close(f)
return true
else
return false
end
end
M.table_contains = function(table, element)
for _, value in pairs(table) do
if value == element then
return true
end
end
return false
end
事前定義してあるworkspaceの設定例がこちら
return {
"/home/kazu914/dotfiles",
"/home/kazu914/Downloads",
"/home/kazu914/Desktop",
}
普通にworkspaceの起点にしたいpathを羅列しているだけです.
PCごとに異なるworkspaceを事前定義したかったので, あえてlocal_workspacesとして分離してますが, そのような要望がない場合は普通にベタ書きで良いと思います.
全体としてやっていることは,
-
wezterm.mux.get_workspace_names()で既存のworkspace一覧を取得-
currentとdefalutを特別扱いしつつ, 後述するInputSelectorに渡せる形式に変換する
-
-
load_local_workspaces事前定義したworkspace一覧を取得- 既存のworkspace一覧と重複しないように気をつけながら同様に
InputSelectorに渡せる形式に変換する
- 既存のworkspace一覧と重複しないように気をつけながら同様に
- 作成したworkspace一覧を,
InputSelectorに渡し, 選ばれたものに切り替える.- labelには色々装飾ができるので, 特別な選択肢を目立つようにしてます.
ref:
keybindings設定
あとはお好みのkeybindingとして設定するだけです.
例
{
key = "n",
mods = "LEADER",
action = wezterm.action_callback(workspace_management.create_or_switch_new),
},
{
mods = 'LEADER',
key = 's',
action = wezterm.action_callback(workspace_management.switch_to_workspace),
},
ref:
参考記事
日本語情報だと, 以下の記事が大変参考になりました.
My dotfiles Repository
自分のdofilesのrepositoryは以下です.参考までにどうぞ.
あとがき
バシバシworkspaceを切り替えながら作業するのは大変楽しいです.
Discussion