Win11でWezTermの設定をした話

普段は業務でWindows 11を使って開発している。最近GitHub Copilot CLIなどのツール群を活用するにあたり、改めてターミナル環境を見直した。

これまではWindows Terminalを使用していたが、「マルチプラットフォームで動作し、カスタマイズ性が高く、かつ軽量なターミナルエミュレーター」への移行を検討し、WezTerm を採用した。

なぜWezTermを選んだのか?

ターミナル環境は常時稼働させるインフラであるため、以下の要件を満たす必要があった。

  • 動作が軽量で軽快であること: 毎日起動し、タブやペインを大量に開いても描画にもたつきがないこと。
  • Luaによる拡張性の高さ: JSONの単なるキーバリュー設定ではなく、プログラマブルな言語(Lua)でUIやキーバインドを自分の状況に合わせて制御できること。
  • コミュニティの活発さ: トラブルシューティングや先人のDotfiles(設定例)が容易に見つかること。

Win11への導入手順

Windows 11環境へ導入し、設定していく手順を解説する。

1. インストール手順

Windowsの場合、パッケージマネージャーである winget を使うのが最もシンプルだ。管理者権限のPowerShellやコマンドプロンプトで以下を実行する。

winget install wez.wezterm

インストール後、スタートメニューから「WezTerm」を起動する。デフォルト状態では非常にプレーンな画面が立ち上がる。

2. 設定ファイルの構成

設定ファイルを作成する。Windowsの場合、ユーザーディレクトリの直下に .config/wezterm/wezterm.lua を作成して配置する構造が管理しやすい。

現在、設定ファイルは以下の2つのファイルにモジュール分割して管理している。
1. wezterm.lua: 基本設定、UI、描画エンジンの指定
2. keybinds.lua: キーバインド、ペイン操作、コピーモード定義

基本設定(wezterm.lua)

描画エンジンの明示的な指定(OpenGL)や、日本語IMEとの相性問題を回避する設定、フォント(PlemolJP)のヒンティング調整などを含めている。

-- ~/.config/wezterm/wezterm.lua
local wezterm = require("wezterm")
local config = wezterm.config_builder()

----------------------------------------------------
-- 【1. IME・描画トラブルシューティング設定】
----------------------------------------------------
-- 描画エンジンを明示的に指定
config.front_end = "OpenGL"
config.ime_preedit_rendering = "Builtin"

-- フォント描画エンジンを固定
config.font_shaper = "Harfbuzz"

-- タイトルバーを表示(標準)
config.window_decorations = "TITLE | RESIZE"

-- 下部の余白をゼロにする(Neovimの表示を優先)
config.window_padding = { left = 0, right = 0, top = 0, bottom = 0 }

-- アプリ側でカーソルを隠されても、IMEのために位置情報を強制維持する
config.cursor_blink_rate = 0

----------------------------------------------------
-- 【2. 基本システム設定】
----------------------------------------------------
config.automatically_reload_config = true
config.font = wezterm.font("PlemolJP Console NF", { weight = "DemiBold" })
config.font_size = 11.0
config.line_height = 1.15

config.font_rules = {
    { intensity = "Bold", font = wezterm.font("PlemolJP Console NF", { weight = "Bold" }) },
    { intensity = "Bold", italic = true, font = wezterm.font("PlemolJP Console NF", { weight = "Bold", style = "Italic" }) },
}

-- アンチエイリアス・ヒンティング設定
config.freetype_load_target = "Light"
config.freetype_render_target = "HorizontalLcd"

config.use_ime = true
config.default_prog = { "pwsh.exe", "-NoLogo" }
config.scrollback_lines = 10000
config.hyperlink_rules = wezterm.default_hyperlink_rules()

-- 背景設定
config.window_background_opacity = 0.85
config.macos_window_background_blur = 20

-- 非アクティブなペインの明度と彩度を下げて薄く表示する
config.inactive_pane_hsb = {
    saturation = 0.5,
    brightness = 0.6,
}

-- タブバーを背景色に合わせる
config.window_background_gradient = { colors = { "#000000" } }

----------------------------------------------------
-- 【3. タブ・UIカスタマイズ】
----------------------------------------------------
config.show_tabs_in_tab_bar = true
config.hide_tab_bar_if_only_one_tab = true
config.show_new_tab_button_in_tab_bar = true

config.window_frame = {
    inactive_titlebar_bg = "none",
    active_titlebar_bg = "none",
}

config.colors = {
    tab_bar = { inactive_tab_edge = "none" },
}

-- タブの装飾設定
local SOLID_LEFT_ARROW = wezterm.nerdfonts.ple_lower_right_triangle
local SOLID_RIGHT_ARROW = wezterm.nerdfonts.ple_upper_left_triangle

wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover, max_width)
    local background = "#5c6d74"
    local foreground = "#FFFFFF"
    local edge_background = "none"
    if tab.is_active then
        background = "#ae8b2d"
        foreground = "#FFFFFF"
    end
    local edge_foreground = background
    local title = "    " .. wezterm.truncate_right(tab.active_pane.title, max_width - 1) .. "    "
    return {
        { Background = { Color = edge_background } },
        { Foreground = { Color = edge_foreground } },
        { Text = SOLID_LEFT_ARROW },
        { Background = { Color = background } },
        { Foreground = { Color = foreground } },
        { Text = title },
        { Background = { Color = edge_background } },
        { Foreground = { Color = edge_foreground } },
        { Text = SOLID_RIGHT_ARROW },
    }
end)

----------------------------------------------------
-- 【4. キーバインド設定(外部モジュール化)】
----------------------------------------------------
config.disable_default_key_bindings = true
config.keys = require("keybinds").keys
config.key_tables = require("keybinds").key_tables
config.leader = { key = "Space", mods = "CTRL", timeout_milliseconds = 2000 }

return config

キーバインド設定(keybinds.lua)

ターミナル内でのマウス操作を極力減らすため、キーバインドは外部ファイルに切り出している。
CTRL + Space をLeaderキーとして設定し、タブ移動やペイン分割、コピーモードなどをVimライクに実行できるように構成している。

-- ~/.config/wezterm/keybinds.lua
local wezterm = require("wezterm")
local act = wezterm.action

-- 選択中のキーテーブルを右下に表示
wezterm.on("update-right-status", function(window, pane)
    local name = window:active_key_table()
    if name then name = "TABLE: " .. name end
    window:set_right_status(name or "")
end)

return {
    keys = {
        { key = "Space", mods = "LEADER|CTRL", action = act.SendKey({ key = "Space", mods = "CTRL" }) },

        -- ワークスペース管理
        { key = "w", mods = "LEADER", action = act.ShowLauncherArgs({ flags = "WORKSPACES", title = "Select workspace" }) },

        -- コマンドパレット
        { key = "p", mods = "SUPER", action = act.ActivateCommandPalette },

        -- Tab移動・管理
        { key = "Tab", mods = "CTRL", action = act.ActivateTabRelative(1) },
        { key = "Tab", mods = "SHIFT|CTRL", action = act.ActivateTabRelative(-1) },
        { key = "t", mods = "LEADER", action = act({ SpawnTab = "CurrentPaneDomain" }) },

        -- ペイン管理 (Leader + r or d)
        { key = "d", mods = "LEADER", action = act.SplitVertical({ domain = "CurrentPaneDomain" }) },
        { key = "r", mods = "LEADER", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) },
        { key = "x", mods = "LEADER", action = act({ CloseCurrentPane = { confirm = true } }) },

        -- ペイン移動 (Leader + hlkj)
        { key = "h", mods = "LEADER", action = act.ActivatePaneDirection("Left") },
        { key = "l", mods = "LEADER", action = act.ActivatePaneDirection("Right") },
        { key = "k", mods = "LEADER", action = act.ActivatePaneDirection("Up") },
        { key = "j", mods = "LEADER", action = act.ActivatePaneDirection("Down") },

        -- ペインズーム切替
        { key = "z", mods = "LEADER", action = act.TogglePaneZoomState },

        -- コピーモード起動
        { key = "[", mods = "LEADER", action = act.ActivateCopyMode },

        -- キーテーブル起動
        { key = "s", mods = "LEADER", action = act.ActivateKeyTable({ name = "resize_pane", one_shot = false }) },
        { key = "a", mods = "LEADER", action = act.ActivateKeyTable({ name = "activate_pane", timeout_milliseconds = 1000 }) },
    },

    key_tables = {
        -- ペインリサイズ (Leader + s の後)
        resize_pane = {
            { key = "h", action = act.AdjustPaneSize({ "Left", 1 }) },
            { key = "l", action = act.AdjustPaneSize({ "Right", 1 }) },
            { key = "k", action = act.AdjustPaneSize({ "Up", 1 }) },
            { key = "j", action = act.AdjustPaneSize({ "Down", 1 }) },
            { key = "Enter", action = "PopKeyTable" },
        },
        activate_pane = {
            { key = "h", action = act.ActivatePaneDirection("Left") },
            { key = "l", action = act.ActivatePaneDirection("Right") },
            { key = "k", action = act.ActivatePaneDirection("Up") },
            { key = "j", action = act.ActivatePaneDirection("Down") },
        },
        copy_mode = {
            { key = "h", mods = "NONE", action = act.CopyMode("MoveLeft") },
            { key = "j", mods = "NONE", action = act.CopyMode("MoveDown") },
            { key = "k", mods = "NONE", action = act.CopyMode("MoveUp") },
            { key = "l", mods = "NONE", action = act.CopyMode("MoveRight") },
            { key = "y", mods = "NONE", action = act.CopyTo("Clipboard") },
            { key = "Enter", mods = "NONE", action = act.Multiple({ { CopyTo = "ClipboardAndPrimarySelection" }, { CopyMode = "Close" } }) },
            { key = "Escape", mods = "NONE", action = act.CopyMode("Close") },
        },
    },
}

※一部抜粋

3. 見た目の拡張 (Starshipの導入)

ターミナルのプロンプト表示をリッチにするため、Starshipも併せて導入している。

winget install Starship.Starship

インストール後、PowerShellのプロファイル ($PROFILE) に以下を追記する。

Invoke-Expression (&starship init powershell)

これでWezTermを再起動すると、Gitのブランチ情報などが付与されたプロンプトが有効化される。

まとめ

WezTermに移行し、Luaで設定をモジュール化・整理したことで、複数プロジェクトをまたいだ並列作業や、キーボード操作完結のペイン管理が非常に快適になった。特に、設定をコードとして管理できるため、環境移行の再現性が高い点も優れたツールだと感じている。

付録:現在のキーボードショートカットチートシート

設定ファイル(keybinds.lua)に基づく、主要な操作のチートシートをまとめておく。
基点となる Leader キーは CTRL + Space に設定している。

操作カテゴリ キー操作 概要
Leader起動 Ctrl + Space 以下の操作の起点(Leader)となる
ワークスペース Leaderw ワークスペースの切り替え(ランチャー表示)
Leader + ShiftW 新規ワークスペースの作成
タブ管理 Leadert 新しいタブの作成
Ctrl + Tab / Ctrl + Shift + Tab 次のタブ / 前のタブへ移動
Super + w 現在のタブを閉じる
ペイン管理 Leaderd ペインを縦に分割
Leaderr ペインを横に分割
Leaderx 現在のペインを閉じる
Leaderh, j, k, l ペインのフォーカス移動(左、下、上、右)
Leaderz 選択中のペインをズーム(最大化)トグル
Leaders ペインのリサイズモード起動(h,j,k,lで調整、Enterで終了)
コピーモード Leader[ コピーモード(Vimライクなカーソル移動)起動
v / Ctrl + v / V 文字選択 / 矩形選択 / 行選択(コピーモード中)
y または Enter 選択範囲をコピーして終了(コピーモード中)
クリップボード Ctrl + Shift + c 選択したテキストをコピー(標準)
Ctrl + Shift + v クリップボードのテキストをペースト
その他 Super + p コマンドパレットの表示

参考記事

本設定ファイル(特にUIやキーバインド構成)は、以下の記事を大いに参考にさせていただいた。
WezTermをモテるターミナルにカスタマイズする

コメント

タイトルとURLをコピーしました