3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Emacsを使う理由(1): EXWM

Last updated at Posted at 2025-12-10

はじめに

  • 「LLMで記事を書くな」という風潮があると聞きましたが、.emacs(古い)を読んでもらってドラフトを作ってもらいました(Claude Code)
  • 「開発環境(OS)は何使ってるのですか?」と聞かれた時に、「 Emacs(arch)です ドヤァ 」と言って「こいつは何を言っているんだろう」という顔をされるのが生き甲斐です

EXWMとは

EXWMは、EmacsをX11のタイル型ウィンドウマネージャーとして動作させるパッケージです(GNOMEやKDE、Xfce、i3wm、Swayなどとだいたい一緒)。

つまり:

  • ChromeもEmacsのバッファ
  • ターミナルもEmacsのバッファ
  • 画像ビューアもEmacsのバッファ

VimやVS Codeなどのエディタも含めて 全てEmacsの支配下 に置くことができます。

基本設定

(package-install 'exwm)
(package-install 'xelb)
(require 'xelb)
(require 'exwm)
(require 'exwm-systemtray)

;; ワークスペース数
(setq exwm-workspace-number 6)

;; バッファ表示設定
(setq exwm-layout-show-all-buffers nil)
(setq exwm-workspace-show-all-buffers nil)

;; ミニバッファ位置(nilで非表示)
(setq exwm-workspace-minibuffer-position nil)

;; OS再起動的なコマンドは無効化しておきます
(global-unset-key (kbd "C-x C-c"))
(global-unset-key (kbd "C-x C-z"))

ワークスペース6つは、2つの物理ディスプレイのそれぞれ上下に仮想画面を拡張させています。

ワークスペース切り替え

(setq exwm-input-global-keys
      `(
        ;; s-0 ~ s-9 でワークスペース切り替え
        ,@(mapcar (lambda (i)
                    `(,(kbd (format "s-%d" i)) .
                      (lambda ()
                        (interactive)
                        (progn
                          (if (= (% exwm-workspace-current-index 2) 0)
                              (setq my-windmove-last-left-index exwm-workspace-current-index)
                            (setq my-windmove-last-right-index exwm-workspace-current-index))
                          (exwm-workspace-switch-create ,i)))))
                  (number-sequence 0 9))
        ...

;; 上下左右のワークスペースへ
(global-set-key (kbd "C-M-p")  'my-windmove-up)
(global-set-key (kbd "C-M-n")  'my-windmove-down)
(global-set-key (kbd "C-M-b")  'my-windmove-left)
(global-set-key (kbd "C-M-f")  'my-windmove-right)
...

6つのスクリーンをC-M-(方向)で移動するのは快適なんですが、たまにdiredとかで設定がぶつかるのでunsetしておきます。

アプリケーション


;; s-r でコマンド実行
([?\s-r] . (lambda (command)
             (interactive (list (read-shell-command "$ ")))
             (start-process-shell-command command nil command)))
;; s-l でロック
([?\s-l] . (lambda ()
             (interactive)
             (start-process "" nil "xsecurelock")))
;; s-a でスクリーンショット
([?\s-a] . (lambda ()
             (interactive)
             (start-process-shell-command "" nil "flameshot gui")))
;; s-; でターミナル起動
([?\s-;] . (lambda ()
             (interactive)
             (start-process "alacritty" nil "alacritty")))
;; 音量操作
([?\s-m] . desktop-environment-toggle-mute)
([?\s-,] . desktop-environment-volume-increment)
([?\s-.] . desktop-environment-volume-decrement)

音量操作や画面ロックなど、人(OS)として基本的なこともいちいち設定しなくてはいけないのに最初はうんざりするでしょうが、まあ一度やってしまえばずっと使えるので乗り越えるべき壁です。

キーカスタマイズ

(setq exwm-input-simulation-keys
      '(
        ;; 基本移動
        ([?\C-p] . [up])
        ([?\C-n] . [down])
        ([?\C-b] . [left])
        ([?\C-f] . [right])
        ([?\C-a] . [home])
        ([?\C-e] . [end])
        ([?\C-g] . [escape])
        ([?\C-h] . [backspace])
        ([?\C-d] . [delete])

        ;; コピー&ペースト
        ([?\C-w]    . [?\C-x])
        ([?\M-w]    . [?\C-c])
        ([?\C-y]    . [?\C-v])
        ([?\C-\S-y] . [?\C-\S-v]) ;; 値のみ貼り付け
        ([?\C-\M-y] . [?\C-\M-v]) ;; 書式のみ貼り付け

        ;; 選択
        ([?\C-\M-a] . [?\C-a])
        ([?\C-\M-g] . [?\C-g])
        
        ([?\C-\S-p] . [S-up])
        ([?\C-\S-n] . [S-down])
        ([?\C-\S-b] . [S-left])
        ([?\C-\S-f] . [S-right])
        ([?\C-\S-a] . [S-home])
        ([?\C-\S-e] . [S-end])

        ;; kill-line/kill-line-backward
        ([?\C-k] . [S-end ?\C-x])
        ([?\C-u] . [S-home ?\C-x])

        ;; 単語移動
        ([?\M-p] . [C-up])
        ([?\M-n] . [C-down])
        ([?\M-b] . [C-left])
        ([?\M-f] . [C-right])
        ([?\M-P] . [C-S-up])
        ([?\M-N] . [C-S-down])
        ([?\M-B] . [C-S-left])
        ([?\M-F] . [C-S-right])
        ([?\M-d] . [C-delete])
        ([?\M-h] . [C-backspace])

        ;; ページ移動
        ([?\C-v] . [next])
        ([?\M-v] . [prior])
        ([?\M-<] . [C-home])
        ([?\M->] . [C-end])
        ([?\C->] . [C-S-next])
        ([?\C-<] . [C-S-prior])
        
        ;; 保存・破棄
        ([?\C-\M-s] . [?\C-s])
        ([?\C-\\] . [?\C-z])

        ;; ブラウザ履歴
        ([?\C-\M-,] . [M-left])   ;; 戻る
        ([?\C-\M-.] . [M-right])  ;; 進む

        ;; 検索
        ([?\C-s] . [?\C-f])))

Chromeのタブを閉じるのにC-M-wやファイル保存時にC-M-sなど妙なものもありますが、そこそこ破綻せずに使えています。
ちなみに、C-qを打ったあとはそのままのキーコード(例えばC-q C-cで真のC-c)を送ってくれます。

;; C-q で次のキーをそのまま送信
(define-key exwm-mode-map [?\C-q] 'exwm-input-send-next-key)

バッファ名のリネーム

EXWMはデフォルトだとバッファ名が微妙なので:

(defun exwm-rename-buffer ()
  (interactive)
  (exwm-workspace-rename-buffer
   (concat exwm-class-name ":"
           (if (<= (length exwm-title) 50) exwm-title
             (concat (substring exwm-title 0 49) "...")))))

(add-hook 'exwm-update-class-hook 'exwm-rename-buffer)
(add-hook 'exwm-update-title-hook 'exwm-rename-buffer)

としてGoogle-chrome:タイトル名のように表示させます

特殊なウィンドウ管理

(setq exwm-manage-configurations
      '(
        ;; Alacrittyは常にchar-mode
        ((member exwm-class-name '("Alacritty"))
         char-mode t)

        ;; Chromeはモードライン非表示
        (lambda ()
          (when (and exwm-class-name
                     (string= exwm-class-name "Google-chrome"))
            (exwm-layout-hide-mode-line)))))

Alacrittyはchar-mode(キー入力を全てパススルー)、Chromeはモードライン消して普通にアプリのように使います。

LightDMの設定

/usr/share/xsessions/emacs.desktop

[Desktop Entry]
Name=Emacs
Exec=emacs
Type=Application

まとめ

確か思いきってインストールしたのが2019年(5-6年前)ぐらいで、そこからず〜〜っと画面はEmacsであり、 たまに違うOS(Windows, Macなど)を使うと生産性が極端に落ちます が、AI時代といってもあと10年ぐらいは快適だと思っているので、興味を持った方はぜひ試してみてください :bow_tone1:

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?