月1回くらいの頻度で,~/.emacsなどの手直しをしています.
ただし~/.emacsは数行の内容で,Emacsのバージョンに応じて読み出すinit.elを切り替えるだけです.init.elが主な見直し対象です.設定ごとに空行を設け,不要な設定は「;」でコメントにしたり取り除いたりしていますが,かなり複雑怪奇です.
M-x package-list-packagesでパッケージの一覧を見て,更新します.Emacsを終了させて起動して,エラーがないことを確認し,終了させてから,パッケージの古いバージョンのファイルやディレクトリと,auto-saveで作られる不要なファイルを取り除きます.user-emacs-directoryを丸ごと7z化して,他のWindows PCでも参照できるように,ファイルをクラウド領域に置くと,手直し完了です.
なお,Linuxでの~/.emacsの更新頻度は年1回くらいです.Windows版に話を戻すと,GNU Emacs download - GNU Projectで紹介されているnearby GNU mirrorを使用して,emacs-28.1-installer.exeをインストールし,C:\Program Files\Emacs\emacs-28.1\bin\runemacs.exeをランチャアプリに入れるかショートカットを作ってデスクトップに置いています.もっぱらGUIでの使用です(WSL2などでemacsコマンドは使用しません).
先月,何だったかEmacsでこういうことができるという紹介ページの中で,elscreenではうまく動かないという説明がありました.
自分自身,elscreenを愛用してきました.ブラウザのタブを,Emacsでも利用可能というものです.キー操作で,左右や特定の位置のタブに移動できますし,タブの作成や消去も容易です.
なのですが,M-x package-list-packagesで見ることのできるelscreenのバージョンは20181009.451で,新しいわけではなく,またhttps://github.com/knu/elscreenの各ファイルも最も新しい更新が「4 years ago」です.より新しい,同等の機能に置き換えたほうがいいのかと,思うようになりました.
「同等の機能」について,tab-bar-modeとtab-line-modeを知り,試してみました.Emacs 27.1で追加されたとのことです.
elscreenと共存できるのも,興味深かったのですが,この機会に移行するとしましょう.動かしてみると,tab-bar-modeの設定に手を加えるのがよさそうです---と思いながら,1か月が経過してしまいました.
手を動かして,追加した設定は,次の3つに分かれます.
- 主要な操作を,elscreenと同じキーストロークで行える.
- デスクトップなどからのファイルのShift+ドラッグにより,新しいタブでファイルを開く.
- 閲覧中のタブが分かるように表示する.
キー操作に関して,次のことができればよいとわかりました.
コマンド名 | 意味 | tab-bar-modeのキーバインド | elscreenのキーバインド |
---|---|---|---|
tab-new | タブの新規作成 | C-x t 2 | C-z cまたはC-z C-c |
tab-next | 次のタブへ移動 | C-x t o | C-z nまたはC-z C-n |
tab-previous | 前のタブへ移動 | C-x t O | C-z pまたはC-z C-p |
iconify-or-deiconify-frame | Emacsを最小化 | (なし) | C-z C-z*1 |
elscreenのプレフィクスキー,C-zは,elscreen.elを読み出さないことで,無効化されます.そして独自に,C-zをプレフィクスキーとし*2,そのあと,上記の表の「elscreenのキーバインド」を設定しました.コードは以下の通りです.
(defvar my-c-z-prefix (kbd "C-z")) (setq my-c-z-map (make-keymap)) (define-key global-map my-c-z-prefix my-c-z-map) (defun my-set-key-c-z-map () (local-set-key my-c-z-prefix my-c-z-map)) (define-key my-c-z-map "c" 'tab-new) (define-key my-c-z-map (kbd "C-c") 'tab-new) (define-key my-c-z-map "n" 'tab-next) (define-key my-c-z-map (kbd "C-n") 'tab-next) (define-key my-c-z-map "p" 'tab-previous) (define-key my-c-z-map (kbd "C-p") 'tab-previous) (define-key my-c-z-map (kbd "C-z") 'iconify-or-deiconify-frame)
次に,「Shift+ドラッグで,新しいタブでファイルを開く」ためには,elscreen.elをしっかり読まないといけないのかと思ったらハズレで,自分のinit.elに,次のように書いていました.
(when (require 'elscreen nil t) (elscreen-start) (if window-system (progn (defun w32-drag-n-drop-elscreen-onefile (event) "Edit the file using ElScreen" (interactive "e") (elscreen-create) (find-file event)) (defun w32-drag-n-drop-elscreen (event) "Edit the files using ElScreen" (interactive "e") (mapcar 'w32-drag-n-drop-elscreen-onefile (car (cdr (cdr event))))) (global-set-key [S-drag-n-drop] 'w32-drag-n-drop-elscreen) (define-key elscreen-map (kbd "C-z") 'iconify-or-deiconify-frame))))
[S-drag-n-drop]を,w32-drag-n-drop-elscreenにバインドしています.この関数は,Shift+ドラッグのイベント(event)からファイル名を取り出して,w32-drag-n-drop-elscreen-onefileに渡し,elscreen-create(タブ新設)のあとfind-fileで開いています.
これと同様のことを,tab-modeで行えばいいのですが…
find-file-other-tabが「ファイルを新しいタブで開く」で,そのとおりに動作しました.elscreen-createに対応する指示は不要ということです.それから,fileを開く関数の引数がeventというのはおかしいので,filenameに変更しました.
最終的に出来上がったコードは以下の通りです.
(defun w32-drag-n-drop-tab-mode-onefile (filename) "Edit the file using tab-mode" (interactive "e") (find-file-other-tab filename)) (defun w32-drag-n-drop-tab-mode (event) "Edit the files using tab-mode" (interactive "e") (mapcar 'w32-drag-n-drop-tab-mode-onefile (car (cdr (cdr event))))) (global-set-key [S-drag-n-drop] 'w32-drag-n-drop-tab-mode)
最後は,「閲覧中のタブの表示」です.tab-bar-modeを素のままで使用して,戸惑ったのは,閲覧中の(アクティブな)タブの表示が,そうでないタブよりも薄く見えることです.tab-bar-modeを探検するでは,「見た目については、アクティブなタブは tab-bar-tab 、 非アクティブなタブは tab-bar-tab-inactive のfaceを変更すれば変えられる」と説明されています.faceの変更方法は,別途調査しまして,以下のページを参考にしました.
M-x list-faces-displayを実行し,表示されるFacesバッファで,tab-barから始まる6行分を見ていきました.tab-bar-tabとtab-bar-tab-inactiveの行でEnterを押して設定変更を行い,「Apply and Save」のボタンを押すと,~/.emacsに追記されます.該当コードを取り出してinit.elにコピーしました(~/.emacsへの追記は,Emacsを終了させてから他のテキストエディタで除去しました).以下のコードとなりました.
(custom-set-faces '(tab-bar-tab ((t (:inherit tab-bar :background "LightSkyBlue1" :foreground "black" :box (:line-width (1 . 1) :color "navy" :style released-button))))) '(tab-bar-tab-inactive ((t (:inherit tab-bar-tab :background "gray93" :foreground "gray50")))))
Emacsを起動し直すと,タブが表示されません.デフォルトで起動する設定を,書き忘れていました.
(tab-bar-mode +1)
Emacsのスクリーンショットはこんな感じです(実際の利用では,行数はもっと多いです).
*1:elscreen.elではなく自分のinit.elでの設定です.
*2:http://yohshiy.blog.fc2.com/blog-entry-323.htmlの「(defvar my-atkey-prefix」から始まるコードを参考にしました.