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

37
Emacs 2012-10-20 @ Emacs#x06 Emacs 1

Upload: lintaro-ina

Post on 25-Jan-2017

2.055 views

Category:

Software


1 download

TRANSCRIPT

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

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

伊奈林太郎

2012-10-20 @関西Emacs#x06

伊奈林太郎 Emacs 上のターミナルを最強に 1

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

ターミナル使ってますか?

◮ 素のターミナル◮ 標準的なターミナルエミュレータ

xterm, gnome-terminal, Terminal.app, ...

◮ マルチプレクサscreen, tmux, ...

◮ sshといっしょになってるものPuTTY, Tera Term, ...

◮ Emacs上term.el

◮ 使ってないeshell.el, ...

◮ その他伊奈林太郎 Emacs 上のターミナルを最強に 2

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

ターミナル使ってますか?

◮ 素のターミナル◮ 標準的なターミナルエミュレータ

xterm, gnome-terminal, Terminal.app, ...

◮ マルチプレクサscreen, tmux, ...

◮ sshといっしょになってるものPuTTY, Tera Term, ...

◮ Emacs上term.el

◮ 使ってないeshell.el, ...

◮ その他伊奈林太郎 Emacs 上のターミナルを最強に 2

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

ターミナルとEmacs

ターミナルエミュレータを使う理由

◮ ncursesアプリもちゃんと動いてほしい

◮ 素の端末を触るときにパニくらない

Emacsとの共存

◮ Emacsは別窓で◮ ウィンドウが増えてうざい◮ 端末とのコピペが面倒

◮ screenの中でEmacs◮ キーボードだけでコピペ◮ Emacsごと detach

伊奈林太郎 Emacs 上のターミナルを最強に 3

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

screenのままならないところ

◮ 改造しにくい

◮ CJK ambiguous width

◮ 問題の切り分けが難しくなる

◮ (Xなどの)クリップボードとの連携

◮ 面倒なハックが必要

◮ 環境変数の引き渡し

◮ 外部からのコマンド発行で解決 (要開発版)

#この辺は tmuxでも同じですね

伊奈林太郎 Emacs 上のターミナルを最強に 4

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

すべてEmacsでやる

◮ CJK,クリップボードなどもOK

◮ detachもできる(emacs --daemon)

◮ Emacs本体と連携⊚

◮ 操作性を一体に

◮ Lispで改造しまくり

伊奈林太郎 Emacs 上のターミナルを最強に 5

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

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

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

term.elのいけてないところ

◮ キーがほぼすべて端末に持っていかれる◮ M-xとかきかない◮ でも ESCとかどっちで認識すべき?

◮ 端末が 1つしか開けない(内部的には可能だけどインタフェースが無い)

◮ 色が 8色しかない

◮ term-line-modeがちょっと貧弱

◮ コードがレガシーで拡張しにくい◮ 関数がでかい◮ hookも少ない

◮ 遅い

伊奈林太郎 Emacs 上のターミナルを最強に 7

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 8

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

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

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

デモ

伊奈林太郎 Emacs 上のターミナルを最強に 10

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 11

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

256色対応 / xterm互換性(require 'xterm-256color)

256色対応

◮ 256色表示の制御シーケンスの解釈を実装

◮ ついでに斜体 ,取り消し線等にも対応

◮ 原理的には 24bit色に対応可能 (cf. Konsole)(24bit色表示しようとするアプリはあるのか?)

xterm互換性 (TERM=xterm-256color)

◮ TERM=eterm-256colorを定義すればよい?◮ たいていのアプリは terminfoなんか見てない

◮ xtermを騙れば 256色表示しようとしてくれる

◮ 騙るからには xterm制御シーケンスを処理 (不完全)

伊奈林太郎 Emacs 上のターミナルを最強に 12

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 13

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

キーバインド強化 [1/2](require 'term+)

端末に奪わせないキーを定義

◮ term+char-mapに define-key

定義 するだけ(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

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

キーバインド強化 [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

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 16

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

編集機能強化 [1/2](require 'term+)

編集モード (term-line-mode)中は

◮ 入力フィールド外では読取専用

◮ SPCで選択開始もう一度SPCで範囲コピー→編集モード終了

◮ RET, ESCで編集モード終了

◮ 入力フィールド内ではふつうのバッファ

◮ ただし RETで端末に送信◮ ふつうの改行は C-j◮ 別のメジャーモードにもできる

e.g. シェルのプロンプトに sh-modeで入力

伊奈林太郎 Emacs 上のターミナルを最強に 17

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

編集機能強化 [1/2](require 'term+)

編集モード (term-line-mode)中は

◮ 入力フィールド外では読取専用

◮ SPCで選択開始もう一度SPCで範囲コピー→編集モード終了

◮ RET, ESCで編集モード終了

◮ 入力フィールド内ではふつうのバッファ

◮ ただし RETで端末に送信◮ ふつうの改行は C-j◮ 別のメジャーモードにもできる

e.g. シェルのプロンプトに sh-modeで入力

伊奈林太郎 Emacs 上のターミナルを最強に 17

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

編集機能強化 [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

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 19

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

ログ機能(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

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 21

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

マルチプレクサ [1/3](require 'term+mux)

やりたいこと

◮ 複数の端末をタブ表示(tabbar.el, emux.elでもできますね)

◮ 編集モード以外のときはモードラインをタブに

◮ セッション (ユーザ/ホストの別)ごとにグループ化

◮ 同一セッションからは 1つだけバッファ一覧に

◮ セッション内の選択中のタブが代表◮ 一覧中ではバッファ名ではなくセッション名

伊奈林太郎 Emacs 上のターミナルを最強に 22

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

マルチプレクサ [2/3]タブグループ(require 'term+mux)

実装: tab-group.el

◮ https://github.com/tarao/tab-group-el

◮ 車輪の再発明

◮ tabbar.elでできることはだいたいできる

◮ モードラインにも表示できる

◮ バッファをひとまとめにできる

◮ かっこいいタブ選択UI

◮ D&Dでタブ移動

伊奈林太郎 Emacs 上のターミナルを最強に 23

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

マルチプレクサ [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

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

term+.el — term.elを強化する

主な機能

◮ 256色対応 / xterm互換性向上

◮ キーバインド強化

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサ (+マルチセッション)

◮ シェル連携強化

伊奈林太郎 Emacs 上のターミナルを最強に 25

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

シェル連携

できること◮ 編集モード

◮ 編集モードでのメジャーモード指定◮ バッファ内容を引き継いで編集モードへ

◮ ユーザ/ホスト/ディレクトリ通知◮ ファイル転送 (open / view / get / put)◮ シェルコマンド履歴選択◮ マルチプレクサ

◮ タブタイトル設定◮ cdd (別タブの現在ディレクトリを取得)

方法◮ 端末内から特殊な制御コマンドを送る

伊奈林太郎 Emacs 上のターミナルを最強に 26

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

シェル連携 [1/6]編集モード

M-iで sh-modeの編集モードへ (zsh)function switch-to-line-mode-insert () {1

local buf="$BUFFER"2

zle kill-buffer3

zle -R # reset command line4

echo -ne "\e]51;mode;sh-mode\e\\" > /dev/tty5

echo -ne "\e]52;i;$buf\e\\" > /dev/tty6

}7

zle -N switch-to-line-mode-insert8

bindkey '^[i' switch-to-line-mode-insert9

参照 https://raw.github.com/tarao/dotfiles/master/.zsh/eterm.zsh

伊奈林太郎 Emacs 上のターミナルを最強に 27

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

シェル連携 [2/6]セッション情報

ユーザ名/ホスト名を通知host=`hostname` # ホスト名10

echo -ne "\e]51;host;$host\e\\" > /dev/tty11

user=`id -run` # ユーザ名12

echo -ne "\e]51;user;$user\e\\" > /dev/tty13

ディレクトリ通知 (zsh)function precmd_eterm_cwd () {14

local dir; dir=`pwd`15

echo -ne "\e]51;cd;$dir\e\\" > /dev/tty16

}17

typeset -Uga precmd_functions # これは一回だけ18

precmd_functions+=precmd_eterm_cwd19

◮ Emacs側の default-directoryが変更される◮ TRAMPでリモートファイルも開ける

伊奈林太郎 Emacs 上のターミナルを最強に 28

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

シェル連携 [3/6]ファイル転送

function o() { # シェルで見えてるファイルを開く20

echo -ne "\e]51;open;$1\e\\" > /dev/tty }21

function v() { # シェルで見えてるファイルを view-modeで開く22

echo -ne "\e]51;view;$1\e\\" > /dev/tty }23

function get() { # シェルで見えてるファイルを手元にコピー24

echo -ne "\e]51;get;$1\e\\" > /dev/tty }25

function put() { # シェルで見えてる場所に26

# ファイルを選択してコピー27

echo -ne "\e]51;put;\e\\" > /dev/tty }28

◮ セッション情報を通知しておく必要あり◮ get/putはFTPと同じ向き

◮ putするとミニバッファでファイルを訊く◮ diredインタフェースでの複数選択も可

伊奈林太郎 Emacs 上のターミナルを最強に 29

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

シェル連携 [4/6]履歴選択

C-rで履歴選択 (zsh)echo -ne "\e]51;histfile;$HISTFILE\e\\" >/dev/tty #一回だけ29

30

function history-search-eterm () {31

local buf="$BUFFER"32

zle kill-buffer33

echo -ne "\e]52;h;$buf\e\\" > /dev/tty }34

zle -N history-search-eterm35

bindkey '^R' history-search-eterm36

◮ 類似: zshの履歴検索に anything.elを使うhttp://d.hatena.ne.jp/tarao/20100429/1272509893

伊奈林太郎 Emacs 上のターミナルを最強に 30

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

シェル連携 [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

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

シェル連携 [6/6]カスタマイズ

定義済みの特殊制御コマンドを調べる◮ M-x des-fun, term-emulate-terminal

◮ M-x term+control-command-list

新しい特殊制御コマンドを定義する(require 'term+vars)37

(defun my-control-command (text) ...)38

(term+new-control-command39

"START" "END " 'my-control-command)40

例(defun term+open (files &optional find-file) ...)41

(term+new-control-command42

"\033]51;open;" "\033\\" 'term+open)43

伊奈林太郎 Emacs 上のターミナルを最強に 32

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

まとめ

Emacs上でだって端末機能をフルに使いたい!

◮ 256色対応

◮ xterm互換性向上

◮ キーバインド

Emacsなのをいいことに魔改造

◮ 編集機能の強化

◮ ログ機能

◮ マルチプレクサをまるごと実装

◮ シェル連携しまくり

伊奈林太郎 Emacs 上のターミナルを最強に 33

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

参考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

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

おわり