Top / Eshellを使いこなす

Meadow

更新履歴 (常連の方用に)

このページが大きくなってきたため、ページを変更した部分が非常に判断しにくくなっ てきています (差分を見ればわかるのですが)。よって今後は、記事やコメント以外でな にか大きな変更部分があった場合ここに載せるようにしてもらえると助かります。

  • 2004-12-14 - Hoshi - このページを半分以上アップデートしました。かなり多くのセク ション全体を通して (Eshell Tips も含めて) 追加、又は修正しています。もうすでに一度読んでしまった人も軽く 読み流すことを勧めます。Eshellパッケージ(2004-12-14日アップロード)
  • 2004-09-23 - Hoshi - 2004-09-12にダウンロードされたCVS最先端のEshell をこのページに附属しました。このEshellは、Eshell 2.4.2と比べて、様々なバグの改 善、最適化が成されています。 特に Eshell 2.4.2 のコマンド `ls' はのろさが少々感 じられましたが、このEshellでは `ls' の速度が格段とアップしました。
    • `eshell-backward-kill-word' を少々修正する。
    • `Argument 補完' に付け加える
    • `ls でファイルを一行ごとに表示する' のtipを加える
    • `ls でディレクトリーのみの表示、レギュラーファイルのみの表示を可能にする' のtipも追加
    • `Eshellコマンドをテキストの現在行から入力' も追加
  • 2004-05-02 - Hoshi - `よく使用するキーバインド' で C-a にバインドすべき関数と 追加。 `Eshell Tips' に `backward-kill-word' の Eshell バージョン と追加。
  • 2004-04-24 - Hoshi - `Argument 補完' のエイリアス fr において全てのファイルを 開く方法を追加する。`自作 Modifiers' サブセクションを `Argument Modifiers' セクション下に追加。
  • 2004-03-05 - Hoshi - `インタラクティブなコマンド Alias を作成する' サブセクショ ンを追加。`Argument 補完' サブセクションを追加。いくつかのタイポを直す。
  • 2004-02-20 - Hoshi - `Argument Modifiers' サブセクションを追加する。`よく使用 するキーバインド' セクションを追加。
  • 2004-01-16 - Hoshi - Eshell Tips に `Eshell と Escreen を連動させる。' を追 加する (ずっと書こうと思っていたんですが、遅くなってしまいました・・・)。Eshell カスタマイズ例その2 を update する。`Tramp を使用してリモートファイル操作' サブセクションを追加。
  • 2003-12-13 - Hoshi - セクション `更新履歴' を作成。`Eshellスクリプト' であるスクリ プトTemplateを追加。

はじめに

私 (Hoshi) はいろんなShellを使ってきましたが、Emacs上ならばEshellが一番お勧めで す。しかしながら、Eshellについてよい文献がないため、あまりその使い安さや拡張のしやす さ、そして高機能aliasなどは知れ渡ってないようです。ということで、少しでも多くの 人がその機能を知ることができ、みんなとEshellのおもしろさを話し合えればなと思い、 このページ(自分のウェブページではないにしろ)を作ってみました。みんなで 情報をたくさん寄せ合ってEshellをもっと便利にしていきましょう。

このドキュメントに書かれているEshellのテスト環境は以下の通りです:

  • GNU Emacs 21.3.50.1 (i386-mingw-nt5.1.2600) of 2004-12-02 on A208752
  • Windows XP Professional SP2

EshellはBorland社のJohn Wiegley さん(emacs-wikiの作者; compilerなどの仕事に携わっ ているようです) によって、まる1年間かけて開発されたEmacs用高機能Shellです。 Eshellはcsh、zsh、sh、bashなどの良い機能が盛りこまれています・・・が作者が言って いるように、実際に使ってみなければ良さはわからないでしょう。Emacs 21以降ならば Eshellは標準に附属しているので、新らしく導入する必要はありません。しかしながら、 自分の使用しているEshellがCVSリポジトリーに置いてあったノンオフィシャルなEshell である為、この記事内の全ての情報がオフィシャルなバージョンのEshellで動くかはわかりません。

一応、現在私が使用しているEshellパッケージ(2004-12-14日現在)を ここ に置いておきます。

オフィシャルのバージョンは http://www.newartisans.com/ (version: 2.4.2)

で手にいれるか、下のところで直接手にいれてしてください。

スクリーンショット

eshell07.png
eshell04.png
eshell03.png

インストール (Installation)

Emacs 付属のEshellを使用する場合は設定が何も必要ありません。オフィシャルのEshell 2.4.2 をインストールする場合は、$HOME/.emacs か $HOME/.emacs.el に

(add-to-list 'load-path "PATH TO ESHELL") 
(require 'eshell-auto)

を追加し、 "PATH TO ESHELL" の部分をEshellのパスに置き換えてください。

CVSのEshellパッケージをインストールする場合は

(require 'eshell)

(require 'eshell-auto)

の代わりに追加するようにしてください。

`M-x eshell' でeshellが起動します。

Eshell を Emacs 起動時に立ちあげる

Eshell を Emacs 起動時に立ちあげたい場合には

(add-hook 'after-init-hook  (lambda() (eshell)))

を .emacs に追加するだけです。

コマンド (Commands)

Eshell は外部コマンドを認識するに加え、使用中のEmacs上で定義されている関数やマク ロもコマンドとして認識してくれます:

$ wget -q http://www.google.com
$ emacs-version
GNU Emacs 21.3.50.1 (i386-mingw-nt5.1.2600)
 of 2004-12-02 on A208752

Lisp関数への引数も外部コマンドへの引数と同じように

$ lisp-function   arg1 arg2 ... arg_n

と渡すことが可能です。

$ substring "Emacs Shell" 6 
Shell

Eshell に直接 Lisp を打ちこむことも可能です (ですから、 Eshell を *scratch* のよう に使用することもできます):

$ (defun foo () "hello" )
$ (let ((inhibit-read-only t))  (erase-buffer))

Eshellは、幾つかの重要なコマンドを独自で実装していますが (ls、mv、rm など)、もし Eshellの実装コマンドではなく、外部コマンドを実行したい場合は、そのコマンドの絶対 パスか相対パスを明示的にEshellに知らせるようにする、もしくは、 `*' をそのコマンド の前に付けるようにしてください。

;; /bin/grep が存在すると仮定する
$ grep        #  Lisp 関数 `eshell/grep' を実行します
$ /bin/grep  # /bin/grep を実行します
$ *grep        # /bin/grep を実行します

逆に、もしあるLisp 関数のシンボル名とある外部コマンド名が衝突する場合、Eshellはデ フォルトでは外部コマンドを実行してしまいます。この時に Lisp 関数を実行するように Eshellの動作を変えたい場合は、`eshell-prefer-lisp-functions' を t にセットしてく ださい。

サブ・コマンド (subcommands)

サブ・コマンドとは `command' [コマンド] + `sub' [中の、下の] 、つまりコマンドの中 に登場するコマンド表現です。これは `{subcommand}' のフォームで表現され、この場合、 subcommand が評価され、Eshell はその返り値を返します。subcommand は `{' `}' に囲 まれているというだけで、シンタックスはコマンドと一緒なので、 subcommand の中に subcommand が登場しても何ら問題はありません。

$ concat "Emacs "     { echo "Shell" }
Emacs Shell
$ concat  { downcase  { substring (emacs-version) 4 9 } } \
" " {echo  "shell"}
emacs shell

Eshell コマンド変数

Eshell上である変数から値を参照する場合には `$' を変数の前に付けます。変数になりえ るシンボル・キャラクターは [A-Za-z0-9_] だけではなく、 "-" も含むことができます。

$ setq SOME-VAR 10
10
$ echo $SOME-VAR
10

OS上にすでに存在している環境変数と現在稼働しているEmacs上で存在する 変数の値も自然と参照することができます。

$ echo $CVS_RSH
ssh
$ echo $major-mode
eshell-mode

Eshellは変数の値の展開をコマンドの評価前に行うので、使用したい外部コマンドや関数 を変数に格納し、その変数をそれらの間接的な参照オブジェクトとして使用することもで きます:

$ setq a "buffer-name"
buffer-name
$ $a
*eshell*
$#VARIABLE

は 変数 `VARIABLE' の文字列の長さを返します。(Elisp関数lengthと同じです。)

$ setq a "foo" 
foo
$ echo $#a
3

特別な変数

  • `$?' 前回のコマンドのステータス (1は失敗; 0は成功)
  • `$$' 前回のコマンドの結果
  • `$0' コマンド
  • `$1-9' argument
  • `$*' すべてのargument

これらはすべて`$HOME/.eshell/alias' でも使用可能です。

例:

$ 222222
222222: command not found 
$ echo $?
1
$ echo $?
0

変数を宣言する時は、

$ setq var-name value 

のようにしてください。

なお、 `eshell-modify-global-environment' と t にセットしてから

export var-name=value [ var-name=value ... ]

のようにすれば、環境変数の宣言、書き換えができます。

例:

$ setq a oldsmobile
$ export b="delta 88"
$ concat $a " " $b
oldsmobile delta 88

$ export a=1 b=2
$ echo $a $b
("1" "2")

ちなみにeshellが実装しているechoはもしargumentが2つ以上ある場合、outputをlistとし て返します。もし普通のechoの動作を望むのであれば、`eshell-plain-echo-behavior' の 値を `t' にセットしてください(もしこれをすると何か不都合があるかもしれません が・・・)。

$(lisp-expr) と ${subcommand}

$(lisp-expr)

は lisp-expr の戻り値を返します; しかし、 $(lisp-expr) はシンボル展開機能を持つ ので、もし $(lisp-expr) が`$(lisp-expr)-symbol-fragment' のようにして使用された場 合、lisp-expr の戻り値と `-symbol-fragment' の結合されたシンボルがEshellで評価さ れるようになります。 このシンボル展開機能が `$(lisp-expr)' と `(lisp-expr)' の 違いです。

$ (defun foo () "hello" )
foo
$ alias hello-world ' echo "Hello World!" '
$ $(foo)-world
Hello World!
$ (foo)-world
(foo)-world: command not found
${subcommand}

も、 subcommand はeshellのコマンド表現で、 lisp-expr は elisp のS式表現であるとい うことを抜かせば、`$(lisp-expr)' と同じような効果が得られます。

$ alias foo ' echo "hello" '
$ ${foo}-world
Hello World!

アウトプット・リダイレクション (output redirection)

Eshellでは `>' 、`2>&1' 、`2>' (アウトプット・リダイレクション・オペレーター) も 使えます。

例:

$ ls -l file1 file_not_yet_made > file2 2>&1
$ cat file2
file_not_yet_made: no such file or directory
-rw-------  1   user    user    0   March   time

以下のようにすれば複数のファイルに書き込みをすることができます:

$ (+ 1 2) > file1 > file2 > file3
;; file1 に3を書き込みしてからwcでfile1内の単語をカウントする
$ (+ 1 2) > file1 | wc -w

ちなみに、Eshellはまだ `input redirection' ( `<' ) を実装していないので、もし同じ 効果を得たいのならば、

$ cat <file> | <command>

のようにしてください。


Eshellの新機能

$ <command>  >>>  #<buffer *some buffer*>

のようにすれば、ある指定されたバッファにコマンド・アウトプットを挿入することもで きます。もし指定されたバッファが存在しない場合、 `>>>' 以下は無視されてしまうので 注意してください。

例:

$ echo "aa bb cc" > test
$ cat test  >>> #<buffer *eshell*>
;; aa bb cc はtestの内容。
$ aa bb cc

;; もし `some_file' というバッファが存在すればtestの中身を挿入。
$ cat test >>> #<buffer some_file>

`/dev/null', `/dev/kill', and`/dev/clip' などのpseudo-devicesもEshellは実装ずみで す。

;; bit bucket: output は無になります。
$ echo "nilをnullどっちがいいですか?" > /dev/null
;; kill ring: output はキルリングの中へ。
$ touch a b c ; ls > /dev/kill

ここで `C-y' を押すと、

$ a b c

の様になります。

;; clipboard: output はクリップボードの中へ。
$ echo some text   >> /dev/clip

特別な Eshell コマンド

For-i-in ループ

Eshellのfor-i-inループは

for var-name in elements { subcommand }

のフォーマットです。 この場合、`var-name' は一時的に値のバインドされた変数となり ます。値の参照は、 `$var-name' で可能です。もし `subcommand' の中に、あるLisp エ クスプレッション `(lisp-expr)' が存在し、その中で `var-name' の値を参照したいので あれば、そのまま `var-name' を表現内に挿入すれば参照可能です (例えば、 `(lisp-func var-name ...)' のように)。この仕様は一見奇妙な気がするかもしれません が、この場合 Eshell は内部で let 関数により `var-name' に現在参照している値 -- つまり、 `elements' 内のいずれかのエレメント -- をバインドしているのです。

例:

$ for i in 1 2 3 { echo $i } 
1
2
3
$ for i in a b c { (eshell/echo i ) }
a
b
c

;; rename all files with `htm' extension to that of `html' 
$ for i in *.htm { mv $i ${concat  $i l } }
$ for i in ${ls -1} { echo $i }

上のコマンドは

$ for i in * { echo $i }

とオーダーを無視すれば同等です。

EshellのForループを使用すれば、

$ alias chext 'for i in $1 { mv $i ${concat $i(:r) .$2 } }'

のように、簡単に自作のコマンド alias が作れたりします。

便利な Eshell コマンド

  • env - すべての環境変数を表示します
  • addpath - パスを $PATH に追加します
  • history - コマンドヒストリーを表示します
  • printnl - 引数を一行ずつ表示します

メタキャラクター

他のshellと大体同様です。

メタキャラクター意味
?任意の1文字にマッチ
*0文字かそれ以上の文字列にマッチ
#その前のcharacterのゼロ回かそれ以上
##その前のcharacterの1回かそれ以上
(x)'x' を正規表現用にグループ化する
ORキャラクター(このテーブル内では表示できない)OR (もしくは)
[a-z]アルファベット a から z 内の一文字にマッチ
[^a]a 以外の一文字にマッチ

(ちなみに、私の環境ではなぜか最後の [^a] がうまく処理されません。他は大丈夫なので すが。)

例:

$ touch file1 file2
$ echo ?ile[12]
("file2" "file1")
$ echo f*
("file2" "file1")

`**/' を使用すれば簡単に再帰が達成されます。

;; list files that end with `.java' under the 
;; current directory (including its sub-directories).
$ ls **/*.java 
;; echo all files recursively under directory `../c_projects'
$ echo ../c_projects/**/*.c
$ alias fs 'ls **/*$1* # search files containing subexpression $1'

もし、全てのelファイルを再帰的にバイトコンパイルしたいならば、

$ alias elcompile-all 'for i in **/*.el { byte-compile-file $i }'

とすれば、以後

$ elcompile-all

のみで済みます。

`***/' は `**/' と基本的に同じですが、シンボリックリンク以下も見てまわります。

`#' はその前のcharacterのゼロ回かそれ以上を表します。

例:

$ ls *.cc#

は `c', `cc', `ccc...' の拡張子を持つファイルを表示します。

`##' はその前のcharacterの1回かそれ以上を表します。

コマンドエイリアス

Eshellのエイリアス機能は強力です。まず、エイリアスを定義するには

alias alias-name 'command'

として下さい。

例:

$ alias la 'ls -a $*'
$ alias display-itself 'echo $0'
$ alias gel 'grep -rsniI --include=*.el $1 * # grep some-text *.el recursively'

もしあるaliasを消したいときは、

alias alias-name

とするだけです。

ちなみに、もしいままでに定義したエイリアスを編集したいのならば、 `$HOME/.eshell/alias' を開いてください。

Eshellには4回以上定義されてないコマンドが打ちこまれた場合そのコマンドのエイリアスをユー ザーに聞くというauto-alias機能があります。

例:

$ foo
foo: command not found
$ foo
foo: command not found
$ foo
foo: command not found
$ foo

;; in the Mini-buffer
Define alias for "foo":

ダイナミックなコマンドエイリアスを作成する

`if condition a b' などの conditional constructs を用いれば、少しは頭のいいコマン ドエイリアスも作成可能です。

例:

Note: このページを見やすくするために、途中で `\n' をいれてあります。実際に以下 のコマンドを使用するときは、1ラインにしてinputして下さい。

;; もしWindows-NT上であれば、~/bin/mv.exe を実行し、他では普通にmvを実行

$ alias mv  'if (string-equal system-type "windows-nt") 
                  { "~/bin/mv.exe" $* } { "mv" $* }'

;; もしarg1がなんらかの文字列であればファイルをひらく

$ alias f 'if ${ stringp $1 }  { open-file-according-to-extension $1 }  
  { echo "Usage: f filename" } # if ${ eq $1 $nil } '

`open-file-according-to-extension' は自分で好きなように定義してください。 Windowsであれば、Shuichi Kitaguchi さんの `fiber.exe' を使用し、

$ alias f 'if ${ stringp $1 }  { fiber $1 }  
  { echo "Usage: f filename" } # if ${ eq $1 $nil } ' 

とすることもできるでしょう。

インタラクティブなコマンドエイリアスを作成する

インタラクティブなコマンドエイリアス は、ミニバッファでユーザーの入力を求める Elisp 関数などを使用して作成することができます。

とても Emacs っぽい コマンド alias の例:

$ alias how-are-you ' echo {concat "... that is strange, because I am NOT " 
 { read-string {concat "Hello, " $user-full-name ". How are you? : "  } } "." } '
  1. /tmp2 $ how-are-you ;; Mini-buffer で good を入力する Hello, TK. How are you? : good ;; RETURN. すると Eshell から ... that is strange, because I am NOT good. ;; といういらただしい答えが返ってきます。

時々圧縮ファイルを解凍すると、ファイルが一つのディレクトリーの中にひとまとめにさ れておらず、カレントディレクトリーのファイルと解凍したファイルがこんがらがってし まう時があります。そんなときは、2分以内にできた、もしくは修正されたファイル、ディ レクトリを削除するエイリアスを作成し、解答されたファイルを全て削除することもでき ます:

alias rmrecent ' echo {setq tmp-files *(cm-2) } ; if {y-or-n-p "Removing those files above. Is that OK? "} { rm -r $tmp-files ; if { eq $? 0 } {echo "The files were removed succesfully." } {echo "File removal failed." } } { echo "Attempt rejected. " }'

ここまでくれば、Eshellがどれだけ柔軟であるか実感していただけたのではないでしょう か?

コマンドヒストリー

前にinputされたコマンドは `M-p' (eshell-previous-matching-input-from-input) で、 そして、その次のコマンドは `M-n' (eshell-next-matching-input-from-input) でアク セスできます。

コマンドラインでの操作は、

  • `!!' - 前のコマンドを参照。
  • `!?foo' - ヒストリーにあるコマンドの中で"foo"を含むコマンドを参照。
  • `echo !!:2' - 前のコマンドの2つめのargumentをechoする。

のようになります。

例:

$ echo 1
;; echo 1を参照。
$ !!
1

$ cd $HOME/tmp 
$ ls
file1 file2
;; cd $HOME/tmp
$ !?c

$ ls file1 file2 
file1 file2
$ echo !!:2
file2

ちなみに、 `M-r' (eshell-previous-matching-input)もかなり使えます。 `M-r' を押すと、Previous input matching (regexp): というプロンプトにインプット されたREGEXPをヒストリーから探して、始めにマッチしたコマンドをカーソルのポイン トに挿入します。

例:

$ ls file1 file2 
file1  file2
$ echo file2 
file2

M-r ls RET

$ ls file1 file2 
file1  file2

`!n' は `$HOME/.eshell/history' に保存されているn番目のコマンドを参照します。

例:

$ echo 1
$ echo 2
$ echo 3
$ !999 # note that my eshell-history-size is set to 1000
echo 2

History のサイズは `eshell-history-size' を変更することによって変えることが可能 です。なお全てのコマンドヒストリーは `history' ( または eshell/history ) という コマンドによって確認することが可能です。

Eshellスクリプト

あまり知れ渡ってはいませんが、Eshell はスクリプトも読み込めます。

Eshell スクリプトはコマンド `.' で読み込むことが可能です。フォーマットは、

. file [args]

になります。

例:

$ cat foo.esh
# inside the file `foo.esh' 
echo $1
echo $2

$ . foo.esh 1 2
1
2


$ cat foo2.esh

setq n $1

(if n
    (progn
      (eshell/echo n)
      (dotimes (var1 n)    
        (insert  (concat (int-to-string var1) " ")))))

$ . foo2.esh 10
10
10
$ 0 1 2 3 4 5 6 7 8 9 

もうちょっと実用的なスクリプトのテンプレートとして、

some-command

while { eq $? 1 } { 
   some-command
}

のようにすれば `some-command' が成功するまでeshell は処理を繰り返し続けます。

Arguments

Argument 補完

Eshell は、メタキャラクターなどを使用して argument を指定した後、[TAB] キーを押 すことによって、カレントディレクトリー下にあるファイルやディレクトリーなどを簡 単に補完することができます。

例:

$ touch TEST3.EXT  foo.ext2  test1.ext  test2.ext
$ find-file f*.ext?       # ここで Tab を押す。
$ find-file foo.ext2          # このように補完されます。
$ find-file *3*          #  ここで Tab を押す。
$ find-file TEST3.EXT           # このように補完されます。

`**/' を利用すれば、カレントディレクトリー内にあるファイルだけではなく、 その下以降にあるディレクトリー内にあるファイルまで補完することができます。

例:

$ mkdir tmp ; touch tmp/test4.ext
$ find-file **/*4*       # ここで Tab を押す。
$ find-file tmp/test4.ext  

$ mkdir tmp/tmp2 ; touch tmp/tmp2/test5.ext
$ find-file **/*5*       # ここで Tab を押す。
$ find-file tmp/tmp2/test5.ext 

$ find-file **/*tmp?/*     # tab → find-file tmp/tmp2/test5.ext 
$ find-file **/*tmp#/*te*    # tab → find-file tmp/test4.ext 

`**/*some-substring*' は Eshell を使用してファイルを開くときにかなり頻繁にでて きますが、時間がたつにつれて `**/*...*' の部分を打ちこむのが面倒になってきます。 そんな時は、以下のような alias を定義すれば良いでしょう。

;; f: Find file 
$ alias f  ' find-file {car *$1* } ' 

使用方は

$ f  filename-substring

です。

例として、

$ f t5             # もしくは、 fr "5" 

は tmp/tmp2/test5.ext を 開きます。

もしあるディレクトリー下でマッチする全てのファイルに対して find-file したいの であれば、まず以下の関数を定義し、

(defun eshell/find-all-files (&rest args)
  "Open all non-directory files matching $1 on Eshell."
  (if (not (null args))
      ;; We have to expand the file names or else naming a directory in an
      ;; argument causes later arguments to be looked for in that directory,
      ;; not the starting directory
      (mapc
       '(lambda (f)  (unless (file-directory-p f) (find-file f)))
       (mapcar #'expand-file-name (eshell-flatten-list args)))))

そして

;; fa: Find All files
$ alias fa ' find-all-files *$1*'

してください。

`**/*' を使用しすれば far (Find All files Recursively) もaliasすることができ ます:

$ alias far ' find-all-files **/*$1* '

ちょっと複雑になりますが、私は以下のエイリアスを頻繁に使用しています:

alias f ' if { listp *$1*(:o:R:x/\.pdf$\|\.ppt$\|\.xls$\|\.jpg$\|\.jpeg$\|\.png$\|\.eps$\|\.gif$\|\.o$\|\.obj$\|\.a$\|\.ln$\|\.elc$\|\.class$\|\.dvi$\|\.lib\|~/) } { find-all-files *$1*(:o:R:x/\.pdf$\|\.ppt$\|\.xls$\|\.jpg$\|\.jpeg$\|\.png$\|\.eps$\|\.gif$\|\.o$\|\.obj$\|\.a$\|\.ln$\|\.elc$\|\.class$\|\.dvi$\|\.lib\|~/) } { find-file $1 } '

これは、arg1 のサブストリングを持つカレントディレクトリ内のファイル全てを降順に開 くエイリアスです。(不必要なファイルは開かないようにフィルタをかけてあります。やり 方は Argument Modifiers セクションを参照してください。)

Argument Predicates

説明は後ほど書きますので、もう少々おまち下さい。もし待ちきれない時は `em-pred.el' を参照してくださいね。

例:

$ javac **/*.java(c-1)

$ alias cpn 'cp -f $1 /some.server.edu:~/public_html/$2'
;; upload all files in this directory that's been modified in a day.
$ cpn **/*(m-1) top
$ tar cvf foo.tar **/*(a-10)
$ ls -1 **/*(m-1)
;; list files larger than 100KB
$ ls -l **/*(Lk+100)
;; larger than 1MB
$ ls -l **/*(Lm+1)
;; list all directories
$  ls -ld *(/)
$ tar -cvf foo.tar ${ ls -1 **/*(c-5) }
;; list all symlinks owned by 'johnw'
$ ls -l *(@u'johnw')
;; compress everything which hasn't been accessed in 30 days
$ bzip2 -9v **/*(a+30)
;; all non-symlinks not owned by 'root', upcased
$ *(^@:U^u0)
;; remove exec bit on all executables owned by user
$ chmod u-x *(U*)

これらは eshell-display-predicate-help ( `\C-c\M-q' ) でクイックレファレンスを見 ることができます。

Argument Modifiers

Eshell の Argument modifier は、zsh と同じように、ある argument を修正 (modify) したい時に使用されます。

Modifier は

$ command arg1(:modifier) 

もしくは

$ command arg1(:modifier1:modifier2:...:modifier_n) 

のようにして使用されます。

基本的に、 argument が メタキャラクターなどで指定され argument が集合を表すのな らば、全ての エレメント (もしくは メンバー) が修正されます。

以下は Eshell で定義されている modifier です。`' で囲まれているキャラクターがそ れになります:

[ これより下は、~/tmp ディレクトリーの中に 4つのレギュラーファイル、TEST3.EXT、foo.ext2、 test1.ext、そして test2.ext が存在すると仮定します。 ]

L (lowercase) - argumentの (もしargumentが集合を表すのならば、すべての集合内 の要素の)英字を小文字にする。

$ echo TEST.TXT(:L)
;; which, if the argument doesn't represent a set, is equivalent to:
$ echo { downcase TEST.TXT  }

U (uppercase) - L の大文字型。

C (capitalize) - 一番目の英文字を大文字にする。argument を `capitalize' という関数を使用して`mapcar' で順に実行しているだけです。

h - arg のディレクトリー部分を返す。(file-name-directory)

t - arg のディレクトリー部分以外を返す。 (file-name-nondirectory)

$ echo ~/tmp/test1.ext(:h)

は $HOME/tmp/ を返します。

$ echo ~/tmp/test1.ext(:t)

は `test1.ext' を返します。

e (file extension) - 拡張子を返す。(注) Eshell 2.4.2 以下のバージョンでは `evaluate again' の e と `file extension' の e が重複してしまっていて file-name-extension の e がしっ かり評価されません(報告済み)。 ですからこの modifier を使用したいならば、 customize-variable で eshell-modifier-alist のはじめの element の eE に 直すか、CVS での最新Eshellを使用するようにしてください。

r - ファイルの拡張子以外の部分を返す。

q - argument に escaped の テキストプロパティーを追加したものを返す。 つまり、

(add-text-properties 0 (length string) '(escaped t) string)

をする。これは、特別なキャラクターなどをエスケープしたい時などに役立ちます。

u (uniqify) - argument の中で文字列が重複している element を消した argumentを 返す。

o - 昇順 にソートする。

R - argument をリバースする。

例:

$ echo *(:o)
("TEST3.EXT" "foo.ext2" "test1.ext" "test2.ext")
$ echo *(:o:R)
("test2.ext" "test1.ext" "foo.ext2" "TEST3.EXT")

O - 降順にソートする。

j - すべての element を一つの文字列として返す。

$ echo *(:j)
foo.ext2TEST3.EXTtest2.exttest1.ext

Modifier j は、`:j' の後に `/pattern/' として指定すれば、一つ一つのメンバーの 間に pattern で指定された文字列を追加することができます。

$ echo *(:j/_/)
foo.ext2_TEST3.EXT_test2.ext_test1.ext
$ echo *(:j/@@/)
foo.ext2@@TEST3.EXT@@test2.ext@@test1.ext

S (split members) - argument内のメンバー一つ一つをリスト化して返す。

例:

$ echo *(:S)
(("foo.ext2")
("TEST3.EXT")
("test2.ext")
("test1.ext"))
$ car {car *(:S)}
foo.ext2

S/pattern/ - pattern で指定された場所で split する。

$ echo *(:S/st[1-3]/)
(("foo.ext2")
("TE" ".EXT")
("te" ".ext")
("te" ".ext"))
$ echo *(:S/s*/)
(("f" "o" "o" "." "e" "x" "t" "2")
("T" "E" "T" "3" "." "E" "X" "T")
("t" "e" "t" "2" "." "e" "x" "t")
("t" "e" "t" "1" "." "e" "x" "t"))

i/pattern/ (include members) - pattern のマッチするメンバーを返す。

$ echo *(:i/test/)
("TEST3.EXT" "test2.ext" "test1.ext")

x/pattern/ (exclude members) - pattern のマッチするメンバー以外を返す。

s/pattern/match/ - pattern に match を代用する。

$ echo *(:s/test/emacs/)
("foo.ext2" "emacs3.EXT" "emacs2.ext" "emacs1.ext")

g - g modifier は s modifier と一緒に使用すると、もしパターンマッチが 2 つ以上あった場合、その全てへの `match' の代用を可能にします。

例:

$ echo eshell1_eshell2_eshell3(:s/eshell/emacs/)
emacs1_eshell2_eshell3
$ echo eshell1_eshell2_eshell3(:gs/eshell/emacs/)
emacs1_emacs2_emacs3

フィルター、代用 Modifiers

set('lisp-function-predicate)

のフォームで modifier を指定すると、t か nil を返す関数 lisp-function-predicate が nil を返すset 内のエレメントはフィルターされ、それ以外のエレメントが返される ようになります。

$ mkdir tmp2
$ cd tmp2/
$ mkdir a b c
$ touch alpha beta gamma
$ echo *('file-directory-p)
("c/" "b/" "a/" "../" "./")
$ echo *('file-regular-p)
("gamma" "beta" "alpha")
set(|lisp-function)

のフォームで modifier を指定すると、set 内にある一つ一つのエレメントに関数 lisp-function がアプライされた結果の返り値を代用された新しい set が返されます。

$ echo *(|upcase)
("GAMMA" "BETA" "ALPHA" "C/" "B/" "A/" "../" "./")
$ echo *(|file-regular-p)
(t t t nil nil nil nil nil)

自作 Modifiers

よく、あるディレクトリーのファイル名を

ch1, ch2, ..., ch9, ch10, ch11, ..., ch50

のようにしている人を見かけます。この場合、このディレクトリーで `ls' コマンドな どを使用すると、個々のファイルが一部不規則に表示されてしまいます。しかし、もし `ch1' から `ch9' のファイルの ch の後に 0 を挿入することができればこの問題は解 決されそうですね。それを簡単に可能にするために私が作ったのが以下の modifier で す。

b/pattern/insert (before) - ある pattern にマッチした部分の に `insert' を挿入する。

これを使用するためには、まず以下の関数を定義し、

(defun eshell-pred-pad-before (&optional repeat)
  "Return a modifier function that will pad a string before the match-string.
E.g. Given an input `echo some-file(:b/some/1./)', Eshell will return
`1.some-file'. It is also compatible with `g' modifier as well."
  (let ((delim (char-after))
    match padding end)
    (forward-char)
    (setq end (eshell-find-delimiter delim delim nil nil t)
      match (buffer-substring-no-properties (point) end))
    (setq match (concat "\\(" match "\\)" ))
    (goto-char (1+ end))
    (setq end (eshell-find-delimiter delim delim nil nil t)
      padding (buffer-substring-no-properties (point) end))
    (goto-char (1+ end))
    (if repeat
    `(lambda (lst)
       (mapcar
        (function
         (lambda (str)
           (let ((i 0))
         (while (string-match ,match str i)
           (setq i (+ (match-end 0) (length ,padding)))
           (setq str (replace-match (concat ,padding "\\1") t nil str))))
            str)) lst))
      `(lambda (lst)
     (mapcar
      (function
       (lambda (str)
         (if (string-match ,match str)
             (setq str (replace-match (concat ,padding  "\\1") t nil str)))
         str)) lst)))))

`customize-variable' で `eshell-modifier-alist' に以下のように Character `b' を、そ してその Lisp expression には `(eshell-pred-pad-before)' を挿入してください。

INS DEL Cons-cell:
            Character: b 
            Lisp expression: (eshell-pred-pad-before)

例:

$ touch emacs1 emacs2 emacs3
$ printnl  *(:b/emacs/x/)
xemacs3
xemacs2
xemacs1

これをしてしまえば、以下のようなことができます。[カレントディレクトリー内に ch1.pdf, ch2.pdf, ..., ch11.pdf, ch12.pdf のファイルがあると仮定してください。]

$ for i in *(:i/[A-Za-z_-][1-9]\./) { echo  $i(:b/[1-9]/0/) }
ch09.pdf
ch08.pdf
ch07.pdf
ch06.pdf
ch05.pdf
ch04.pdf
ch03.pdf
ch02.pdf
ch01.pdf

echo の部分を mv に変更すれば、このセクションの始めに挙げた問題は解決しそうです ね。 それをエイリアスにしてしまいましょう。

$ alias pad0 ' for i in *(:i/[A-Za-z_-][1-9]\./) { mv $i  $i(:b/[1-9]/0/) } '
$ pad0
$ ls
ch01.pdf  ch03.pdf  ch05.pdf  ch07.pdf  ch09.pdf  ch11.pdf
ch02.pdf  ch04.pdf  ch06.pdf  ch08.pdf  ch10.pdf  ch12.pdf

反対に、あるマッチ部分の にある文字列を挿入することを可能にする modifier も作ってみました。

a/pattern/insert (after) - ある pattern にマッチした部分の に `insert' を挿入する。

まず以下の関数を定義し、

(defun eshell-pred-pad-after (&optional repeat)
  "Return a modifier function that will pad a string after the match-string.
E.g. Given an input `echo some-file1(:a/file/0/)', Eshell will return
`some-file01'. It is also compatible with `g' modifier as well."
  (let ((delim (char-after))
    match padding end)
    (forward-char)
    (setq end (eshell-find-delimiter delim delim nil nil t)
      match (buffer-substring-no-properties (point) end))
    (setq match (concat "\\(" match "\\)" ))
    (goto-char (1+ end))
    (setq end (eshell-find-delimiter delim delim nil nil t)
      padding (buffer-substring-no-properties (point) end))
    (goto-char (1+ end))
    (if repeat
    `(lambda (lst)
       (mapcar
        (function
         (lambda (str)
           (let ((i 0))
         (while (string-match ,match str i)
           (setq i (match-end 0))
           (setq str (replace-match (concat "\\1"   ,padding) t nil str))))
            str)) lst))
      `(lambda (lst)
     (mapcar
      (function
       (lambda (str)
         (if (string-match ,match str)
         (setq str (replace-match (concat "\\1"  ,padding) t nil str)))
         str)) lst)))))

`customize-variable' で `eshell-modifier-alist' に以下のように Character `a' を、そ してその Lisp expression には `(eshell-pred-pad-after)' を挿入してください。

INS DEL Cons-cell:
            Character: a 
            Lisp expression: (eshell-pred-pad-after)

例:

$ touch emacs1 emacs2 emacs3
$ printnl  *(:a/emacs/en/)
emacsen3
emacsen2
emacsen1

これら `a' 、`b' modifier を `g' modifier と一緒に使用することを可能にする ためには、`customize-variable' で `eshell-modifier-alist' 内の Character `g' を 以下のように編集する必要があります:

INS DEL Cons-cell:
            Character: g 
            Lisp expression: 
(progn
  (forward-char)
  (cond
   ((eq
     (char-before)
     115)
    (eshell-pred-substitute t))
   ((eq
     (char-before)
     97)
    (eshell-pred-pad-after t))
   ((eq
     (char-before)
     98)
    (eshell-pred-pad-before t))
   (error "`g' modifier cannot be used alone")))

例:

$ echo foo1_foo2_foo3(:ga/foo/emacs/)
fooemacs1_fooemacs2_fooemacs3
$ echo foo1_foo2_foo3(:gb/foo/emacs/)
emacsfoo1_emacsfoo2_emacsfoo3

eshell-display-modifier-help ( `\C-c\M-m' ) で modifier のクイックレファレンス を見ることができます。

Eshellでリモートファイル操作

Ange ftp を使用してリモートファイル操作

Ange ftpを使用すれば、普通にremoteのファイルをlocalファイルのように扱えます。

例:

 ;;; Ange ftp
(setq ange-ftp-ftp-program-name "~/bin/ftp")
(setq ange-ftp-default-user "foo")

のようにすれば、Eshell上で

$ cd /some.host.edu:/some/dir
$ cd /foo.edu:~/public_html
$ cp ~/some_file /foo.edu:~/public_html/tmp

のようにしてremoveファイル操作できます。

Tramp を使用してリモートファイル操作

Windows 2000 上であれば、Puttyパッケージ内の plink を使用して tramp を正常に(?) 動かすことができます。

まず plink をPutty のサイトからダウンロードしてきて、それを PATH の通った場所に 置いてください。 次に以下のような設定をします。

(require 'tramp)

(when (require 'tramp nil t)
 (cond ((eq system-type 'windows-nt)
    (setq tramp-default-method "plink"))
   (t     (setq tramp-default-method "scp"))))

これで、

$ cd /username@some.server.edu:~/

を Eshell 上でタイプし、password を入力すればリモートサーバー上にあるファイルを 操作することができるでしょう。

Note: 上の方法で tramp を起動し、リモートサーバーに接続を試みるとなぜか一つ一つの コマンドにやたら時間がかかってしまいます。この解決法を知っている方は、ぜひ教え てください。

よく使用するキーバインド

デフォルトでは C-a に beginning-of-line がバインドされています。これは確実に eshell-bol という関数に変更した方が良いです。

my-eshell-hook の中あたりに

(local-set-key "\C-a" 'eshell-bol)

と設定してください。

  • tab - pcomplete-expand-and-complete
  • `\C-c\C-c' - eshell-interrupt-process
  • `\C-c\C-k' - eshell-kill-process
  • `\C-c\C-d' - eshell-send-eof-to-process
  • `\C-c\C-s' - list-processes
  • `\C-c\C-b' - eshell-backward-argument
  • `\C-c\C-f' - eshell-forward-argument
  • `\C-c\M-o' - eshell-mark-output
  • `\C-c' + return - eshell-copy-old-input
  • `\C-c\C-r' - eshell-show-output
  • `\C-c\C-u' - eshell-kill-input
  • `\C-c\C-y' - eshell-repeat-argument
  • `\C-c\M-b' - eshell-insert-buffer-name

EshellサポートElisp

Escreen.el

Fetch.el

FFAP:

.emacs に

(ffap-bindings)

を挿入。

(define-key global-map [mouse-1] 'ffap-at-mouse)

は私のかなりのお気にいりキーバインディング。

Eshell カスタマイズ

カスタマイズ例: John Wiegley (作者) の設定

初めてEshellを使う人の為に、以下は私のお勧め設定を載せておきます。( `customize-variable' で設定するのが一番安全で良いのですが、たぶん以下を .emacs か .emacs.el の `custom-set-variables' の中に挿入してすぐにemacs を再起動すれば 問題はないと思われます。) まずはじめに、John Wiegley の設定です。

(custom-set-variablesの中に入れてください。
'(eshell-ask-to-save-history (quote always))
'(eshell-history-size 1000)
'(eshell-ls-dired-initial-args (quote ("-h")))
'(eshell-ls-exclude-regexp "~\\'")
'(eshell-ls-initial-args "-h")
'(eshell-ls-use-in-dired t nil (em-ls))
'(eshell-modules-list (quote (eshell-alias eshell-basic
                                           eshell-cmpl eshell-dirs eshell-glob
                                           eshell-hist eshell-ls eshell-pred
                                           eshell-prompt eshell-rebind
                                           eshell-script eshell-smart
                                           eshell-term eshell-unix eshell-xtra)))
'(eshell-prefer-to-shell t nil (eshell))
'(eshell-stringify-t nil)
'(eshell-term-name "ansi")
'(eshell-visual-commands (quote ("vi" "top" "screen" "less" "lynx" 
                               "ssh" "rlogin" "telnet")))
) 

;; 本当は私自身の設定例も載せたかったのですが、 それをここに挿入するとサーバーがエラーを返すので載せることができませんでした…

Eshell便利なエイリアス

Eshell Tips

カレントバッファのディレクトリに移動しつつeshellを起動する

kentaro? (2005-09-20 (火) 14:43:16)

編集中のファイルがあるディレクトリでシェルコマンドを打ちたくなったときに、eshellを起動するのと同時にそのディレクトリへ移動します。

(defun eshell-cd-default-directory ()
  (interactive)
  (let ((dir default-directory))
    (eshell)
    (cd dir)
    (eshell-interactive-print (concat "cd " dir "\n"))
    (eshell-emit-prompt)))

Eshellコマンドをテキストの現在行から入力

Hoshi? (2004-09-23 (木) 21:58:51)

まず、以下の関数を定義します。

;;; 2004-07-21 Hoshi
(defun eshell-command-from-current-line ()
  (interactive)
  (save-excursion
    ;;; to prevend an error message from `progn' when we are on a
    ;;; line with no graphic characters: Wrong type argument: listp, progn
    (unless (progn (beginning-of-line) (looking-at "^[[:blank:]]*$" ))
      (eshell-command (buffer-substring (point-at-bol) (point-at-eol))))))


使い方:

現在行に例えば、

echo "Hello from Eshell"


とあった場合に M-x eshell-command-from-current-line をすれば、
ミニバッファに "Hello from Eshell" と表示されます。何のコマンドでも結構です。

ls でファイルを一行ごとに表示する

Hoshi? (2004-09-23 (木) 21:11:26)

この機能はフォントが fixed-pitch ではない時に重宝します。

`M-x customize-variable RET eshell-ls-initial-args RET'
して、その値を "-1" とするだけです。ちなみにこのオプションは
Eshell 2.4.2 にはありません。2004-09-12にダウンロードされたCVS最先端のEshellを使用するようにしてください。

`backward-kill-word' の Eshell バージョン

Hoshi? (2004-05-02 (日) 09:57:16)

つい最近書きました。自分の環境では正常に動作しますが、 eshell-prompt-function に バインドされている関数によっては動作しないかもしれません。

(defun eshell-backward-kill-word ()
  (interactive)
  (if (save-excursion
        (and (search-backward (funcall eshell-prompt-function) nil t)
             (looking-at  (concat (funcall eshell-prompt-function)
                                  "[[:blank:]]*\\([[:graph:]\r\n]+[[:blank:][:alnum:]]*\\)"))))
      (if (string-match "^[^[:alnum:]]+[[:blank:]]*$"  (match-string 1 ))
          ;;           (delete-region (eshell-bol) (point-max))
          (eshell-kill-until-prompt)
        (backward-kill-word 1))))

(defun eshell-kill-until-prompt ()
  (interactive)
  (if (save-excursion (search-backward (funcall eshell-prompt-function) nil t))
      (delete-region (match-end 0) (point-max))))

これを自分は [meta backspace] に割り当てています。 かなり自然になった感じ。

 (local-set-key [(meta backspace)] 'eshell-backward-kill-word)

Eshell が正常に起動するかどうか確かめる。

Hoshi? (2004-02-21 (土) 11:59:44)


もし使用している Emacs 環境で Eshell が正常に起動するかどうか確かめたいのならば、
M-x eshell-test を実行してみてください。もし

Eshell test suite completed: No failures


というメッセージがミニバッファーにでれば Eshell は正常に動作するということです
(たぶん)。

Eshell と Escreen を連動させる。

Hoshi? (2004-01-16 (金) 20:50:59)

まずどこかのローカルでロードされる el ファイルで
`eshell-toggle-buffer-goto-eshell' を以下のように定義し、その関数をオーバーライ
ドします。

;;; RELATE ESHELL TO EACH ESCREEN
(require 'escreen)
(eval-after-load "esh-toggle"
  '(progn 
     (defun eshell-toggle-buffer-goto-eshell (make-cd)
       "Switches other window to the *eshell* buffer.
If no *eshell* buffer exists start a new eshell and switch to it in
other window.  If argument MAKE-CD is non-nil, insert a \"cd DIR\"
command into the eshell, where DIR is the directory of the current
buffer.
Stores the window cofiguration before creating and/or switching window."
       (setq eshell-toggle-pre-eshell-win-conf (current-window-configuration))
       (let* (
              (eshell-buffer-name (concat "*eshell*"
                                  (if (string= escreen-current-screen-string "0" )
                                              ""
                                            (concat "<" (int-to-string 
                                            (+ escreen-current-screen-number 1))
                                                    ">" ))))
              ;; (eshell-buffer (get-buffer "*eshell*"))
              (eshell-buffer (get-buffer eshell-buffer-name))
              (cd-command
               ;; Find out which directory we are in (the method differs for
               ;; different buffers)
               (or (and make-cd
                        (buffer-file-name)
                        (file-name-directory (buffer-file-name))
                        (concat "cd " (file-name-directory (buffer-file-name))))
                   (and make-cd
                        list-buffers-directory
                        (concat "cd " list-buffers-directory)))))
         ;; Switch to an existin eshell if one exists, otherwise switch to
         ;; another window and start a new eshell
         (if eshell-buffer
             (switch-to-buffer-other-window eshell-buffer)
           (eshell-toggle-buffer-switch-to-other-window)
           ;; Sometimes an error is generated when I call `eshell' (it has
           ;; to do with my eshell-mode-hook which inserts text into the
           ;; newly created eshell-buffer and thats not allways a good
           ;; idea).
           (condition-case the-error
               (eshell)
             ;;     (error (switch-to-buffer "*eshell*"))))
             (error (switch-to-buffer eshell-buffer-name))))
         (if (or cd-command eshell-toggle-goto-eob)
             (goto-char (point-max)))
         (if cd-command
             (progn
               (insert cd-command)
               (if eshell-toggle-automatic-cd
                   (eshell-send-input))))))
     ))


次に、↓のようにして escreen を新しく作るときと消すときに eshell が連動するよう
にします:

(defadvice escreen-create-screen
 (after eshell-whatever activate)
 ;;; T.H. Create corresponding eshell buffer as well. Comment out
 ;;; `delete-other-windows' if it doesn't suit your need.
 (eshell t)
 (delete-other-windows))


(defadvice escreen-kill-screen
 (before escreen-whatever activate)
 ;;; Say our current escreen string is `Sn' where `n' represents a natural
 ;;; number. If n > 0, the code kills the eshell buffer named `*eshell*<n+1>';
 ;;; it does nothing otherwise.
 (let ((eshell-buffer-name (concat "*eshell*"
   (if (string= escreen-current-screen-string "0" ) ""
   (concat "<" (int-to-string (+ escreen-current-screen-number 1)) ">" )))))
   ;;; unprotect the eshell buffer to delete. 
   (protect-buffer-from-kill-mode -1 eshell-buffer-name)
   (if (not (string= eshell-buffer-name "*eshell*" ))
       (kill-buffer eshell-buffer-name ))))



最後に、上で変えたコードを有効活用するため、よく使用する関数にキーを割りふりま
しょう。以下は一つの例です:

(define-key global-map [(control tab)] 'escreen-goto-next-screen)
(define-key global-map [(f9)] (lambda () (interactive) (eshell-toggle nil)))

jmanを参照する

ななしさん? (2003-12-07 (日) 00:10:15)

eshell上でmanできますけど、英語のmanを表示してしまう。こいつは内部で
M-x manを呼んでるだけのようなので、

(setq manual-program "jman")

を評価しときゃいい。

ファイルを開くのにファイル名をいちいちタイプせずに開きたい。

Hoshi? (2003-11-15 (土) 14:00:15)

例えば、

http://www1.chapman.edu/~hoshi103/image/eshell_ls01.png

としたとき、ファイルを開くのにファイル名をいちいちタイプするのは面倒ですね。
例えば、some-file2 が開きたいとき、

http://www1.chapman.edu/~hoshi103/image/eshell_ls02.png

のようにsome-file2上にポイントを持っていきEnterを押すだけでファイルを開くようにする
設定です。それと、マウスのカーソルを開きたいファイルの上に持っていくと、

http://www1.chapman.edu/~hoshi103/image/eshell_ls03.png

のように色がついて、左クリックでそのファイルが開けるようになります。楽ですね。

;;; From: http://www.emacswiki.org/cgi-bin/wiki.pl/EshellEnhancedLS
(eval-after-load "em-ls"
  '(progn
     ;; (defun ted-eshell-ls-find-file-at-point (point)
     ;;          "RET on Eshell's `ls' output to open files."
     ;;          (interactive "d")
     ;;          (find-file (buffer-substring-no-properties
     ;;                      (previous-single-property-change point 'help-echo)
     ;;                      (next-single-property-change point 'help-echo))))
     (defun pat-eshell-ls-find-file-at-mouse-click (event)
       "Middle click on Eshell's `ls' output to open files.
 From Patrick Anderson via the wiki."
       (interactive "e")
       (ted-eshell-ls-find-file-at-point (posn-point (event-end event))))
     (defun ted-eshell-ls-find-file ()
       (interactive)
       (let ((fname (buffer-substring-no-properties
                     (previous-single-property-change (point) 'help-echo)
                     (next-single-property-change (point) 'help-echo))))
         ;; Remove any leading whitespace, including newline that might
         ;; be fetched by buffer-substring-no-properties
         (setq fname (replace-regexp-in-string "^[ \t\n]*" "" fname))
         ;; Same for trailing whitespace and newline
         (setq fname (replace-regexp-in-string "[ \t\n]*$" "" fname))
         (cond
          ((equal "" fname)
           (message "No file name found at point"))
          (fname
           (find-file fname)))))
     (let ((map (make-sparse-keymap)))
       ;;          (define-key map (kbd "RET")      'ted-eshell-ls-find-file-at-point)
       ;;          (define-key map (kbd "<return>") 'ted-eshell-ls-find-file-at-point)
       (define-key map (kbd "RET")      'ted-eshell-ls-find-file)
       (define-key map (kbd "<return>") 'ted-eshell-ls-find-file)
       (define-key map (kbd "<mouse-2>") 'pat-eshell-ls-find-file-at-mouse-click)
       (defvar ted-eshell-ls-keymap map))
     (defadvice eshell-ls-decorated-name (after ted-electrify-ls activate)
       "Eshell's `ls' now lets you click or RET on file names to open them."
       (add-text-properties 0 (length ad-return-value)
                            (list 'help-echo "RET, mouse-2: visit this file"
                                  'mouse-face 'highlight
                                  'keymap ted-eshell-ls-keymap)
                            ad-return-value)
       ad-return-value)))

コマンドをいつも最終行で入力したい!!

Hoshi? (2003-11-15 (土) 13:31:42)


他の多くのshellは、commandインプットはいつも画面の最終行でしますよね。Eshellは
なぜか`eshell-scroll-show-maximum-output'を t にしてもoutputがある程度大きくな
ると、recenterしてしまい、outputがとぎれてしまう傾向があるので、それを変更し、
Eshellで他のshellのようにcommandインプットをいつも画面の最終行でする動作を達成
する設定です。以下の設定を custom-set-variables の中に挿入する、もしくはマニュアルで 同様に設定してください。

  ;; ZwaX : http://www.emacswiki.org/cgi-bin/wiki/EshellScrolling
   (custom-set-variables
    [...]
    '(eshell-output-filter-functions (quote (eshell-handle-control-codes 
eshell-watch-for-password-prompt eshell-postoutput-scroll-to-bottom)))
    '(eshell-scroll-show-maximum-output t)
    '(eshell-scroll-to-bottom-on-output nil)
    [...]

eshell でバッファを切り替える etc

松下 (2003-11-08 (土) 08:45:59)

http://xsteve.nit.at/prg/emacs/ の .emacs より

(defun eshell/sb (&rest args)
  "Switch to given buffer."
  (funcall 'switch-to-buffer (apply 'eshell-flatten-and-stringify args)))
(defun pcomplete/sb ()
  "Completion for sb (switch-to-buffer)."
  (while (pcomplete-here (mapcar 'buffer-name (buffer-list)))))
(defun eshell/op (file)
"Invoke (w32-shell-execute \"Open\" FILE) and substitute slashes for backslashes"
  (w32-shell-execute "Open" (substitute ?\\ ?/ (expand-file-name file))))

2つ以上のEshellを起動させる方法

Hoshi? (2003-11-01 (土) 15:26:17)


$ eshell t


とすれば、2つ、3つ、...、と別のEshellが立ちあがります。

Eshell拡張コマンド

Bufferをクリアする。

Hoshi? (2003-11-01 (土) 15:50:42)


(defun eshell/clear ()
 "Clear the current buffer, leaving one prompt at the top."
 (interactive)
 (let ((inhibit-read-only t))
   (erase-buffer)))

lessを実装する

Hagi? (2003-11-03 (月) 16:55:30)

less(more) は view-file に alias すればよいわけですね.
alias less 'view-file $1'

  • そうですね。確かStefan Reichoer(VisEmacs?の作者)が同じようなことをしてました。↓を見てください。 -- Hoshi? 2003-11-08 (土) 16:15:44
;; written by Stefan Reichoer <reichoer@web.de>
(defun eshell/less (&rest args)
 "Invoke `view-file' on the file.
\"less +42 foo\" also goes to line 42 in the buffer."
 (while args
   (if (string-match "\\`\\+\\([0-9]+\\)\\'" (car args))
       (let* ((line (string-to-number (match-string 1 (pop args))))
              (file (pop args)))
         (view-file file)
         (goto-line line))
     (view-file (pop args)))))

Eshellバグや問題点

環境の違い(OSやEmacs Variants)におけるEshellの問題点など

(Meadow2) M-x eshell RET でエラー

Hagi? (2003-11-15 (土) 15:08:51)

eshell 入れ替えたら [MD:4671]
の現象がおきたので挙げておきます.
バイトコンパイルしなければいいだけですが.
Meadow の最新 snapshot でどうなるかはチェックしてません.

Eshell Links

EmacsWiki?、カテゴリー Eshell

Eshell Manualです・・・があんまりまとまっていません。

Eshellのカスタマイズ可能な変数

このページへのコメント

最新の10件を表示しています。 コメントページを参照

  • なぜかページの更新ができないな…サーバ、dnsエラーメッセージがでる。差分ありすぎなのか、ページが大きすぎるのか… 一応最新ドキュメントはこれです。 -- Hoshi? 2004-09-23 (木) 08:40:45
  • ページのプレビューは問題なくできるにも関わらず、更新が失敗してしまいます(この前と同じ症状)。 更新ずみのファイルは「ここ 」です。かなりアップデートしたので、(もし)更新できる方はしておいてくれると助かります。 -- Hoshi? 2004-12-14 (火) 22:35:55
  • 一応、部分更新、部分更新でページ全体を更新できました (テクニカルな問題のため、ページの一部を削除しなければいけませんでしたが、あまり重要な箇所ではないので、あまり問題はないと思います)。 -- Hoshi? 2004-12-17 (金) 02:10:42
  • Eshell Tipsに投稿してみました。 -- kentaro? 2005-09-20 (火) 14:49:40
  • test -- test? 2006-08-16 (水) 16:25:10
  • test -- test? 2006-08-16 (水) 16:25:22
  • test -- test? 2006-08-16 (水) 22:01:33
  • test -- test? 2006-08-16 (水) 22:01:46
  • test -- test? 2006-08-17 (木) 00:02:41
  • eshell のオフィシャルページおよび tarball へのリンクが切れていたので修正させていただきました。 -- kaneko? 2008-07-01 (火) 10:19:56
お名前:

添付ファイル: fileeshell07.png 2147件 [詳細]
fileeshell04.png 2019件 [詳細]
fileeshell03.png 2112件 [詳細]
fileeshell.tar.gz 1550件 [詳細]
fileEshell_Updated.txt 1910件 [詳細]

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: Tue, 01 Jul 2008 10:18:58 JST (3309d)