概要
検証環境
この文章は主に以下の環境でテストした結果を記述しています。
- Emacs
- GNU Emacs22.3
- GNU Emacs23.1
- OS
- Windows XP SP3
- Mac OS X 10.6.2 以上
- Mac OS X 10.5.8(Intel,PPC)
- Shell
- Bash 3.2.48
- Zsh 4.3.10
- Package Manager
- Cygwin 1.7.1
- Fink 0.29.10
- MacPorts 1.8.2
Warning
未検証の環境によっては問題が発生する可能性があります。どんなことでも良いので問題点に気づいたらコメントいただけるとありがたいです。よろしくお願いします。
Emacs での Shell Mode に関する基礎知識
Emacs から Shell を利用する Mode は大きく分類すると 3種類あります。
- shell
- term (ansi-term)
- eshell
それぞれに特徴があります。
shell
term (ansi-term)
eshell
どのモードを利用するか
Bash や Zsh を利用したいので、この記事では term を利用してカスタマイズしていきます。
利用する Shell について
Windows での Shell の準備
Windows の場合は Bash 、Zsh を利用するなら Cygwin 等でインストールする必要があります。
また fakecygpty をコンパイルしてパスの通った場所に置いておくと良いでしょう。
http://www.meadowy.org/meadow/browser/trunk/nt/fakecygpty.c
gcc -o fakecygpty.exe fakecygpty.c
cp fakecygpty.exe f_zsh.exe
cp fakecygpty.exe f_bash.exe
cp fakecygpty.exe f_ssh.exe
Mac OS X での Shell の準備
Mac OS X にデフォルトでインストールされている Zsh はマルチバイト文字が正常に扱えませんのでマルチバイト文字を利用する場合は fink もしくは MacPorts を利用してマルチバイト対応でコンパイルした Zsh を導入する必要があります。
この手順は必須ではありませんが日本語ファイル等を扱う方はインストールしておいた方が無難かと思います。
fink の場合は以下のようにします。Trees で unstable/main を有効にする必要があります。また最新情報に更新してからインストールした方が良いでしょう。
# 最新情報に更新します
sudo fink selfupdate
# zsh-multibyte をインストールします
sudo fink install zsh-multibyte
MacPorts の場合は以下のようにします。最新情報に更新してからインストールした方が良いでしょう。
# 最新情報に更新します
sudo port -v selfupdate
sudo port -v sync
# zsh-devel をインストールします
sudo port install zsh-devel +mp_completion +pcre
Bash に関しては特に問題はないはずです。
Emacs 側の設定
Emacs で Shell を正常に利用するためには Emacs と Shell の双方に設定が必要です。
Emacs の設定は $HOME/.emacs.d/init.el (旧 .emacs.el) で設定します。
PATH の設定
Mac OS X では Emacs をダブルクリックにて GUI として起動すると PATH を正常に引き継げないようですし、また環境依存性を減らすためにも init.el の中で PATH の設定をした方が無難です。
PATH と exec-path を同時に設定した方が普通の場合は使いやすいと思われますので、以下のようにして PATH を通します。
;; より下に記述した物が PATH の先頭に追加されます
(dolist (dir (list
"/sbin"
"/usr/sbin"
"/bin"
"/usr/bin"
"/opt/local/bin"
"/sw/bin"
"/usr/local/bin"
(expand-file-name "~/bin")
(expand-file-name "~/.emacs.d/bin")
))
;; PATH と exec-path に同じ物を追加します
(when (and (file-exists-p dir) (not (member dir exec-path)))
(setenv "PATH" (concat dir ":" (getenv "PATH")))
(setq exec-path (append (list dir) exec-path))))
MANPATH も設定しておくと良いでしょう。
(setenv "MANPATH" (concat "/usr/local/man:/usr/share/man:/Developer/usr/share/man:/sw/share/man" (getenv "MANPATH")))
利用する Shell の設定
;; shell の存在を確認
(defun skt:shell ()
(or (executable-find "zsh")
(executable-find "bash")
;; (executable-find "f_zsh") ;; Emacs + Cygwin を利用する人は Zsh の代りにこれにしてください
;; (executable-find "f_bash") ;; Emacs + Cygwin を利用する人は Bash の代りにこれにしてください
(executable-find "cmdproxy")
(error "can't find 'shell' command in PATH!!")))
;; Shell 名の設定
(setq shell-file-name (skt:shell))
(setenv "SHELL" shell-file-name)
(setq explicit-shell-file-name shell-file-name)
文字コードの設定
筆者は文字コードを utf-8 に統一しています。 set-language-environment と prefer-coding-system を設定することでほぼ utf-8 になります。
(set-language-environment 'utf-8)
(prefer-coding-system 'utf-8)
(cond
((or (eq window-system 'mac) (eq window-system 'ns))
;; Mac OS X の HFS+ ファイルフォーマットではファイル名は NFD (の様な物)で扱うため以下の設定をする必要がある
(require 'ucs-normalize)
(setq file-name-coding-system 'utf-8-hfs)
(setq locale-coding-system 'utf-8-hfs))
(or (eq system-type 'cygwin) (eq system-type 'windows-nt)
(setq file-name-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)
;; もしコマンドプロンプトを利用するなら sjis にする
;; (setq file-name-coding-system 'sjis)
;; (setq locale-coding-system 'sjis)
;; 古い Cygwin だと EUC-JP にする
;; (setq file-name-coding-system 'euc-jp)
;; (setq locale-coding-system 'euc-jp)
)
(t
(setq file-name-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)))
locale-coding-system は echo $LC_ALL 等で文字コードを確認して Terminal の locale に合せる必要がありますので環境に合せてください。
システムの terminfo を利用しない設定
;; Emacs が保持する terminfo を利用する
(setq system-uses-terminfo nil)
もしこの設定をしても 4m のような文字が消えない場合は 環境変数 TERM の設定 を実施してください。
エスケープを綺麗に表示する
ls などで色が出るようにしていると Shell のエスケープ文字が表示されてしまう場合があります。これを避けるには以下の設定を init.el に記述します。
(autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
term 呼び出しキーの割り当て
(global-set-key (kbd "C-c t") '(lambda ()
(interactive)
(term shell-file-name)))
Shell 側の設定
どうしても Emacs の Shell の中では動作しない設定も存在します。また Terminal では必要ですが Emacs の Shell の中では不要な設定も存在しています。
処理の分岐
echo $EMACS
とりあえずは以下のように分岐可能です。
if [ "$EMACS" ];then
# Emacs 内で起動した時の処理
else
# Terminal から起動した時の処理
fi
Zsh では右プロンプト等が Emacs 内だと邪魔になりやすいようです。Bash や Zsh の設定は人により非常に複雑化しているので Emacs なのかを判定する以下のような関数を作成しておきます。
isemacs(){
[[ "$EMACS" != "" ]] && return 0
return 1
}
環境変数 TERM の設定
# eterm-color.ti から生成した terminfo を利用する。tiファイルのパスは自分で判断して変更してください
tic -o ~/.terminfo /usr/local/share/emacs/23.1/etc/e/eterm-color.ti
# Mac OS X で app 形式の場合は以下のような場所にあります
tic -o ~/.terminfo /Applications/Emacs.app/Contents/Resources/etc/e/eterm-color.ti
terminfo を生成しても動作しない場合は以下のような設定を Shell の設定ファイルに記述すると良いでしょう。
if [ "$EMACS" ];then
export TERM=Eterm-color
fi
eterm-color を利用すると多少普段の Terminal とは挙動が異なります。もし普段の Terminal と表示の挙動を同じにしたい場合は、 以下のような設定にすると良いでしょう。
export TERM=xterm-color
TERM の値は利用している Terminal によって異なりますので、 echo $TERM して自分の環境を確認してください。
Emacs からの Shell 利用を標準以外の機能で拡張する
ここまでの設定は Emacs の標準機能ですが、標準の機能だけで快適さを追求しても個人的には満足な状態にはなりませんでした。
標準以外の機能を追加してより便利にしてみます。
multi-term.el
cd ~/.emacs.d
curl -O http://www.emacswiki.org/emacs/download/multi-term.el
init.el には以下の設定をします。
(require 'multi-term)
(setq multi-term-program shell-file-name)
(add-to-list 'term-unbind-key-list '"M-x")
term は char mode と line mode があり デフォルトは char mode です。
multi-term の char mode では C-n で次の行に移動、 C-p で前の行に移動といった Emacs 的な動作ができ、 M-n や M-p でコマンドの履歴をたどることができます。
さらに Emacs的な操作にしたければ以下のように hook に設定を追加します。
(add-hook 'term-mode-hook
'(lambda ()
;; C-h を term 内文字削除にする
(define-key term-raw-map (kbd "C-h") 'term-send-backspace)
;; C-y を term 内ペーストにする
(define-key term-raw-map (kbd "C-y") 'term-paste)
))
また multi-term 呼びだし用にキーも割り当てておくと良いでしょう。
(global-set-key (kbd "C-c t") '(lambda ()
(interactive)
(multi-term)))
キーで起動した時に複数起動でなく既存のバッファを選択したい場合は以下のように設定します。
(global-set-key (kbd "C-c t") '(lambda ()
(interactive)
(if (get-buffer "*terminal<1>*")
(switch-to-buffer "*terminal<1>*")
(multi-term))))
(global-set-key (kbd "C-c n") 'multi-term-next)
(global-set-key (kbd "C-c p") 'multi-term-prev)
shell-pop.el
shell-pop は shell のウィンドウを簡単に呼び出すための拡張です。
cd ~/.emacs.d
curl -O http://www.emacswiki.org/emacs/download/shell-pop.el
デフォルトでは multi-term には対応していませんが以下のように設定すると対応できます。以下の設定では F8 を押すと、 multi-term で起動した shell がフレームを分割して起動します。
(require 'shell-pop)
;; multi-term に対応
(add-to-list 'shell-pop-internal-mode-list '("multi-term" "*terminal<1>*" '(lambda () (multi-term))))
(shell-pop-set-internal-mode "multi-term")
;; 25% の高さに分割する
(shell-pop-set-window-height 25)
(shell-pop-set-internal-mode-shell shell-file-name)
;; ショートカットも好みで変更してください
(global-set-key [f8] 'shell-pop)
全部設定しても満足できない場合
term だけで全てを簡潔させることを考えず Emacs の機能を利用してみると良いかもしれません。
Emacs には以下のような機能がありますのでその利用を検討してみてください。
- FTP や SSH 等の操作は tramp を利用する
- grep は M-x grep を利用する
- M-! で shell コマンドの実行ができる
- Emacs Lisp からは (shell-command-to-string "pwd") のようにすると Shell コマンドの実行結果を文字として取得できる
以下はゲストコメント可能です。名前とメールアドレスは任意の物を入力していただいてかまいません。 blog comments powered by Disqus