...

Emacs上のターミナルを最強に

by user

on
Category: Documents
21

views

Report

Comments

Transcript

Emacs上のターミナルを最強に
Emacs 上のターミナルを最強に
伊奈 林太郎
2012-10-20 @ 関西 Emacs#x06
伊奈 林太郎
Emacs 上のターミナルを最強に
1
ターミナル使ってますか?
◮
◮
素のターミナル
標準的なターミナルエミュレータ
xterm, gnome-terminal, Terminal.app, ...
◮
マルチプレクサ
screen, tmux, ...
◮
ssh といっしょになってるもの
PuTTY, Tera Term, ...
◮
Emacs 上
term.el
◮
使ってない
eshell.el, ...
◮
その他
伊奈 林太郎
Emacs 上のターミナルを最強に
2
ターミナル使ってますか?
◮
◮
素のターミナル
標準的なターミナルエミュレータ
xterm, gnome-terminal, Terminal.app, ...
◮
マルチプレクサ
screen, tmux, ...
◮
ssh といっしょになってるもの
PuTTY, Tera Term, ...
◮
Emacs 上
term.el
◮
使ってない
eshell.el, ...
◮
その他
伊奈 林太郎
Emacs 上のターミナルを最強に
2
ターミナルと Emacs
ターミナルエミュレータを使う理由
◮
◮
ncurses アプリもちゃんと動いてほしい
素の端末を触るときにパニくらない
Emacs との共存
◮ Emacs は別窓で
◮ ウィンドウが増えてうざい
◮ 端末とのコピペが面倒
◮ screen の中で Emacs
◮ キーボードだけでコピペ
◮ Emacs ごと detach
伊奈 林太郎
Emacs 上のターミナルを最強に
3
screen のままならないところ
◮
◮
◮
◮
改造しにくい
CJK ambiguous width
◮ 問題の切り分けが難しくなる
(X などの) クリップボードとの連携
◮ 面倒なハックが必要
環境変数の引き渡し
◮ 外部からのコマンド発行で解決 (要開発版)
# この辺は tmux でも同じですね
伊奈 林太郎
Emacs 上のターミナルを最強に
4
すべて Emacs でやる
◮
◮
◮
◮
伊奈 林太郎
CJK, クリップボード
なども OK
detach もできる
(emacs --daemon)
Emacs 本体と連携 ⊚
◮ 操作性を一体に
Lisp で改造しまくり
Emacs 上のターミナルを最強に
5
Emacs 内端末エミュレータ term.el
使い方
M-x term, M-x ansi-term
特徴 — 2 つのモード
◮ term-char-mode
◮ 打ったものがそのまま端末へ
◮
term-line-mode
◮ Emacs のバッファに近い編集
しくみ
◮ process-filter で制御シーケンスを解釈
◮ バッファに put-text-property しながら表示
伊奈 林太郎
Emacs 上のターミナルを最強に
6
term.el のいけてないところ
◮
◮
◮
◮
◮
◮
キーがほぼすべて端末に持っていかれる
◮ M-x とかきかない
◮ でも ESC とかどっちで認識すべき?
端末が 1 つしか開けない
(内部的には可能だけどインタフェースが無い)
色が 8 色しかない
term-line-mode がちょっと貧弱
コードがレガシーで拡張しにくい
◮ 関数がでかい
◮ hook も少ない
遅い
伊奈 林太郎
Emacs 上のターミナルを最強に
7
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
8
term+.el をとりあえず使ってみる
ダウンロード → 真っ新な状態でのお試し
$
$
$
$
git clone git://github.com/tarao/term-plus-all.git
cd term-plus-all
git submodule update --init
make emacs # or make term
# or make EMACS=emacs-snapshot term
注意点
◮
Emacs 24.1.50 で開発してます
◮ 22 はサポートしません
◮ 23 は細かいところが不安定かも
◮ 24.2 はおそらく OK
◮ 24.3 (24.2.50) の term.el の変更には未対応
伊奈 林太郎
Emacs 上のターミナルを最強に
9
デモ
伊奈 林太郎
Emacs 上のターミナルを最強に
10
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
11
256 色対応 / xterm 互換性
(require 'xterm-256color)
256 色対応
◮ 256 色表示の制御シーケンスの解釈を実装
◮ ついでに斜体 , 取り消し線等にも対応
◮ 原理的には 24bit 色に対応可能 (cf. Konsole)
(24bit 色表示しようとするアプリはあるのか?)
xterm 互換性 (TERM=xterm-256color)
◮ TERM=eterm-256color を定義すればよい?
◮ たいていのアプリは terminfo なんか見てない
◮ xterm を騙れば 256 色表示しようとしてくれる
◮ 騙るからには xterm 制御シーケンスを処理 (不完全)
伊奈 林太郎
Emacs 上のターミナルを最強に
12
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
13
キーバインド強化 [1/2]
(require 'term+)
端末に奪わせないキーを定義
define-key
term+char-map に 定義
するだけ
(multi-term.el でもできますね)
◮ 定義済みのキー (M-x des-fun, term-char-mode)
C-q 後続のキーをそのまま端末に渡す
C-y 端末へ貼り付け
M-RET 編集モード (term-line-mode) へスイッチ
ESC 端末へ ESC を送る
C-c 0.5 秒間何も入力がなければ端末へ C-c
直後に何か入力すればプレフィックスキー
◮ Emacs 本体で実行 (nil をマップ): M-x, M-:, C-x
◮
伊奈 林太郎
Emacs 上のターミナルを最強に
14
キーバインド強化 [2/2]
(require 'key-intercept)
後続のキーがあるかどうかで意味が違う!
ESC 端末へ ESC を送る
M-x ふつうの M-x
C-c 0.5 秒間何も入力がなければ端末へ C-c
直後に何か入力すればプレフィックスキー
実装: key-intercept.el
◮
https://github.com/tarao/key-intercept-el
◮
プレフィックスキーにもコマンドを割り当てる
http://d.hatena.ne.jp/tarao/20120427/1335527960
伊奈 林太郎
Emacs 上のターミナルを最強に
15
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
16
編集機能強化 [1/2]
(require 'term+)
編集モード (term-line-mode) 中は
◮
◮
入力フィールド外では読取専用
◮ SPC で選択開始
もう一度 SPC で範囲コピー → 編集モード終了
◮ RET, ESC で編集モード終了
入力フィールド内ではふつうのバッファ
◮ ただし RET で端末に送信
◮ ふつうの改行は C-j
◮ 別のメジャーモードにもできる
e.g. シェルのプロンプトに sh-mode で入力
伊奈 林太郎
Emacs 上のターミナルを最強に
17
編集機能強化 [1/2]
(require 'term+)
編集モード (term-line-mode) 中は
◮
◮
入力フィールド外では読取専用
◮ SPC で選択開始
もう一度 SPC で範囲コピー → 編集モード終了
◮ RET, ESC で編集モード終了
入力フィールド内ではふつうのバッファ
◮ ただし RET で端末に送信
◮ ふつうの改行は C-j
◮ 別のメジャーモードにもできる
e.g. シェルのプロンプトに sh-mode で入力
伊奈 林太郎
Emacs 上のターミナルを最強に
17
編集機能強化 [2/2]
(require 'multi-mode-util)
入力フィールドだけ別モード
◮
あらかじめどのモードにするか指定 (後述)
indirect buffer
◮
◮
編集モードに入ると 間接バッファ
を作成
multi-mode.el
http://www.loveshack.ukfsn.org/emacs/multi-mode.el
◮
multi-mode-util.el
https://github.com/tarao/multi-mode-util
伊奈 林太郎
Emacs 上のターミナルを最強に
18
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
19
ログ機能
(require 'term+)
term-start-output-log
◮ term.el に元からある (ほぼデバッグ用)
term+hardcopy (C-c h)
◮ 一画面だけテキスト保存 (追記可)
◮ screen の:hardcopy 相当
term+start-buffer-log (C-c l)
◮ いままでの累積テキストを保存
◮ 表示限界 (2048 行) を超えた分も保存
term+start-record (C-c r)
◮ 端末の制御シーケンスを時系列で保存
◮ ttyrec 互換 (ttyplay で再生可)
伊奈 林太郎
Emacs 上のターミナルを最強に
20
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
21
マルチプレクサ [1/3]
(require 'term+mux)
やりたいこと
◮
◮
◮
◮
複数の端末をタブ表示
(tabbar.el, emux.el でもできますね)
編集モード以外のときはモードラインをタブに
セッション (ユーザ/ホストの別) ごとにグループ化
同一セッションからは 1 つだけバッファ一覧に
◮ セッション内の選択中のタブが代表
◮ 一覧中ではバッファ名ではなくセッション名
伊奈 林太郎
Emacs 上のターミナルを最強に
22
マルチプレクサ [2/3] タブグループ
(require 'term+mux)
実装: tab-group.el
◮
◮
◮
◮
◮
◮
https://github.com/tarao/tab-group-el
車輪の再発明
◮ tabbar.el でできることはだいたいできる
モードラインにも表示できる
バッファをひとまとめにできる
かっこいいタブ選択 UI
D&D でタブ移動
伊奈 林太郎
Emacs 上のターミナルを最強に
23
マルチプレクサ [3/3] セッション管理
(require 'term+mux)
M-x term+mux-new
◮ 現在のセッションで (or 選択して) 端末を開く
M-x term+mux-new-command
◮ 現在のセッションで指定のコマンドを実行
M-x term+mux-remote-session
◮ ユーザ/ホストを指定してセッションを作成
◮ シェル端末も 1 つ開く
◮ ローカルで root なら sudo する
◮ リモートなら ssh する
伊奈 林太郎
Emacs 上のターミナルを最強に
24
term+.el — term.el を強化する
主な機能
◮
◮
◮
◮
◮
◮
256 色対応 / xterm 互換性向上
キーバインド強化
編集機能の強化
ログ機能
マルチプレクサ (+ マルチセッション)
シェル連携強化
伊奈 林太郎
Emacs 上のターミナルを最強に
25
シェル連携
できること
◮ 編集モード
◮ 編集モードでのメジャーモード指定
◮ バッファ内容を引き継いで編集モードへ
◮ ユーザ/ホスト/ディレクトリ通知
◮ ファイル転送 (open / view / get / put)
◮ シェルコマンド履歴選択
◮ マルチプレクサ
◮ タブタイトル設定
◮ cdd (別タブの現在ディレクトリを取得)
方法
◮ 端末内から特殊な制御コマンドを送る
伊奈 林太郎
Emacs 上のターミナルを最強に
26
シェル連携 [1/6] 編集モード
M-i で sh-mode の編集モードへ (zsh)
1
2
3
4
5
6
7
8
9
function switch-to-line-mode-insert () {
local buf="$BUFFER"
zle kill-buffer
zle -R # reset command line
echo -ne "\e]51;mode;sh-mode\e\\" > /dev/tty
echo -ne "\e]52;i;$buf\e\\" > /dev/tty
}
zle -N switch-to-line-mode-insert
bindkey '^[i' switch-to-line-mode-insert
参照
https://raw.github.com/tarao/dotfiles/master/.zsh/eterm.zsh
伊奈 林太郎
Emacs 上のターミナルを最強に
27
シェル連携 [2/6] セッション情報
ユーザ名/ホスト名を通知
10
11
12
13
host=`hostname` # ホスト名
echo -ne "\e]51;host;$host\e\\" > /dev/tty
user=`id -run` # ユーザ名
echo -ne "\e]51;user;$user\e\\" > /dev/tty
ディレクトリ通知 (zsh)
14
15
16
17
18
19
function precmd_eterm_cwd () {
local dir; dir=`pwd`
echo -ne "\e]51;cd;$dir\e\\" > /dev/tty
}
typeset -Uga precmd_functions # これは一回だけ
precmd_functions+=precmd_eterm_cwd
◮
Emacs 側の default-directory が変更される
◮ TRAMP でリモートファイルも開ける
伊奈 林太郎
Emacs 上のターミナルを最強に
28
シェル連携 [3/6] ファイル転送
20
21
22
23
24
25
26
o() { # シェルで見えてるファイルを開く
-ne "\e]51;open;$1\e\\" > /dev/tty }
v() { # シェルで見えてるファイルを view-mode で開く
-ne "\e]51;view;$1\e\\" > /dev/tty }
get() { # シェルで見えてるファイルを手元にコピー
-ne "\e]51;get;$1\e\\" > /dev/tty }
put() { # シェルで見えてる場所に
# ファイルを選択してコピー
echo -ne "\e]51;put;\e\\" > /dev/tty }
function
echo
function
echo
function
echo
function
27
28
◮
◮
セッション情報を通知しておく必要あり
get/put は FTP と同じ向き
◮ put するとミニバッファでファイルを訊く
◮ dired インタフェースでの複数選択も可
伊奈 林太郎
Emacs 上のターミナルを最強に
29
シェル連携 [4/6] 履歴選択
C-r で履歴選択 (zsh)
29
echo -ne "\e]51;histfile;$HISTFILE\e\\" >/dev/tty #一回だけ
30
31
32
33
34
35
36
function history-search-eterm () {
local buf="$BUFFER"
zle kill-buffer
echo -ne "\e]52;h;$buf\e\\" > /dev/tty }
zle -N history-search-eterm
bindkey '^R' history-search-eterm
◮
類似: zsh の履歴検索に anything.el を使う
http://d.hatena.ne.jp/tarao/20100429/1272509893
伊奈 林太郎
Emacs 上のターミナルを最強に
30
シェル連携 [5/6] マルチプレクサ
タブタイトル変更
◮
◮
参考
screen の \ekSTR \e\\ 形式
tmux の \e]2;STR \e\\ 形式
https://raw.github.com/tarao/dotfiles/master/.zsh/screen-title.zsh
cdd
◮ 他のタブの `pwd`に移動する
◮ オリジナルは id:secondlife さん (screen 用)
http://d.hatena.ne.jp/secondlife/20080218/1203303528
参照
https://raw.github.com/tarao/dotfiles/master/.zsh/eterm.zsh
伊奈 林太郎
Emacs 上のターミナルを最強に
31
シェル連携 [6/6] カスタマイズ
定義済みの特殊制御コマンドを調べる
◮
M-x des-fun, term-emulate-terminal
◮
M-x term+control-command-list
新しい特殊制御コマンドを定義する
37
38
39
40
(require 'term+vars)
(defun my-control-command (text) ...)
(term+new-control-command
"START " "END " 'my-control-command )
例
41
42
43
(defun term+open (files &optional find-file) ...)
(term+new-control-command
"\033]51;open;" "\033\\" 'term+open)
伊奈 林太郎
Emacs 上のターミナルを最強に
32
まとめ
Emacs 上でだって端末機能をフルに使いたい!
◮
◮
◮
256 色対応
xterm 互換性向上
キーバインド
Emacs なのをいいことに魔改造
◮
◮
◮
◮
編集機能の強化
ログ機能
マルチプレクサをまるごと実装
シェル連携しまくり
伊奈 林太郎
Emacs 上のターミナルを最強に
33
参考 URL
伊奈林太郎.
このスライド.
http://up.orezdnu.org/papers/kansai-emacs/%23x06/slide/slide.pdf .
INA Lintaro.
term+.el のソースリポジトリ.
https://github.com/tarao/term-plus-el .
INA Lintaro.
term+.el の emacs 側設定例.
https://github.com/tarao/dotfiles/blob/master/.emacs.d/init/term.el
https://github.com/tarao/dotfiles/blob/master/.emacs.d/init/tarao/term.el .
INA Lintaro.
term+.el のシェル側設定例.
https://github.com/tarao/dotfiles/blob/master/.zsh/eterm.zsh .
伊奈 林太郎
Emacs 上のターミナルを最強に
34
おわり
Fly UP