アフィリエイト広告を利用しています

2017年07月31日

Emacs: Multi-term で Control-u (universal-argument) を有効にする.

Emacs では multi-term という端末エミュレータープログラムでシェルを起動させて使っている.
現在のところは, プログラムを書いたりデバッグしたりはしていないので, シェルの対話機能を深く使うことはまだない.

今日, 偶然に multi-term のシェル端末バッファー "*terminal<1>*" 上からシェル端末をもう一つ起動しようとしたら Control-u (以下 C-u) が使えないことに気がついた.

自分の Emacs の設定では C-\ でシェル端末の起動または既存のシェル端末バッファーへの移動, C-u C-\ で新しいシェル端末の起動を行う設定にしてある.

実際にシェル端末のバッファー以外では C-u C-\ で新しいシェル端末が起動する.
この場合は C-u が universal-argument という関数に割り当てられていて, 次の C-\ で起動される multi-term-new という自作の関数へ引数が渡されて新しいシェル端末が起動することになる.

端末バッファー上で C-u は term-send-raw という関数に割り当てられている. これは入力されたキーを直接端末エミュレーターに送る関数で, したがってそのキー入力は Emacs には渡らない.

とりあえず, 端末エミュレーター上でも C-u を universal-argument として使いたいので Emacs の設定を次のように変更した.

$HOME/.emacs.d/init.el を次のように編集する.
(1) term-mode におけるキーバインドの設定
C-p: ヒストリーバッファー内の移動 ── 一つ前のコマンドへ.
C-n: ヒストリーバッファー内の移動 ── 一つ後ろのコマンドへ.
C-\: multi-term-new 関数 (後述) の起動.
C-,: 一つ前の端末エミュレーターバッファーに移動.
C-.: 一つ後ろの端末エミュレーターバッファーに移動.
C-u: universal-argument 関数の起動.
C-o: SKK のオン/オフ

;; Key bindings
(add-hook 'term-mode-hook
'(lambda ()
(let* ((key-and-func
`((,(kbd "C-p") term-send-up)
(,(kbd "C-n") term-send-down)
(,(kbd "C-\\") multi-term-new)
(,(kbd "C-\,") multi-term-prev)
(,(kbd "C-\.") multi-term-next)
(,(kbd "C-u") universal-argument)
(,(kbd "C-o") skk-mode)
)))
(loop for (keybind function) in key-and-func do
(define-key term-raw-map keybind function)))))


(2) 端末エミュレーター起動の関数 multi-term-new の書き直し
対話形式 (M-x での起動) で使えるように interactive 関数を使う.
この関数では引数の有無だけが意味を持ち, 評価は必要ないので interactive への引数は "P" とする (引数は raw データとして interactive に渡る).

(interactive "P")

引数の判別を行う cond 節を以下のように変更した:
条件 1: 引数が無く, 端末エミュレーターのリスト multi-term-buffer-list が空リストである.
新しい端末エミュレーターを起動する.
作成されたバッファーの名前は "*terminal<1>*" となり, 端末エミュレーターのリスト multi-term-buffer-list は

multi-term-bufre-list: (#<buffer *terminal<1>*>)

となる.
条件 2 : 引数が無く, 端末エミュレーターのリストが空でない.
端末エミュレーターのリスト multi-term-buffer-list の先頭にあるバッファーに移動し, カーソルをその最後尾に置く.
条件 3: それ以外 (引数がある場合)
新しい端末エミュレーターを起動する.

(defun multi-term-new (&optional arg)
"Switch to the first terminal buffer, that normally has the name
``*terminal<1>*'', if it exists. Otherwise create a new terminal
buffer."
(interactive "P")
(cond ((and (null arg) (null multi-term-buffer-list))
(multi-term))
((and (null arg) multi-term-buffer-list)
(switch-to-buffer (car multi-term-buffer-list))
(goto-char (point-max)))
(t
(multi-term))))


場当たり的なコードだがひとまず動いた.
もし問題があれば (多分あるだろうが) 使っているうちに出てくるだろうと思う (†).

†: 現在の自分程度の Emacs の使い方では複数の端末エミュレーターが必要になるケースはほぼ無い.
シェルのジョブコントロール機能と pushd, popd で足りている.
けれども準備をしておくことは大切だ.
この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

この記事へのトラックバックURL
https://fanblogs.jp/tb/6545888

この記事へのトラックバック
ファン
検索
<< 2024年11月 >>
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
最新記事
最新コメント
眼科の定期検査 〜 散歩 by コトタマ (02/15)
眼科の定期検査 by 三文字寄れば文殊のヒフミヨ (09/21)
本を読んで過ごす by 底彦 (12/13)
本を読んで過ごす by ねこ (12/12)
数学の計算をする by 底彦 (12/04)
タグクラウド
カテゴリアーカイブ
仕事(59)
社会復帰(22)
(44)
コンピューター(211)
(1441)
借金(8)
勉強(13)
(13)
数学(97)
運動(8)
日常生活(1404)
(204)
健康(38)
読書(21)
プロフィール

ブログランキング・にほんブログ村へ
にほんブログ村
にほんブログ村 メンタルヘルスブログ うつ病(鬱病)へ
にほんブログ村
にほんブログ村 科学ブログ 数学へ
にほんブログ村
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
にほんブログ村