簡易 eshell-pop, cde, cdp

個人的に Emacsから shellを使うことは苦手で基本使わないんですが、
それでもわざわざ Emacsから shellに Alt-Tab等で切り替える必要も
ないかってこともあるので、eshellをちょろっと使うようの関数を
書いてみました。


cdeは eshell-popを実行したバッファのディレクトリに移動するための
コマンド、cdpはプロジェクトトップ(.gitがあるディレクトリ)に
移動するコマンドです。shell用バッファを簡単に閉じるために、
popwinを使って popupしています。

(require 'eshell)
(require 'popwin)

(defvar eshell-pop-buffer "*eshell-pop*")
(defvar eshell-prev-buffer nil)

(defun eshell-pop ()
  (interactive)
  (setq eshell-prev-buffer (current-buffer))
  (unless (get-buffer eshell-pop-buffer)
    (save-window-excursion
      (pop-to-buffer (get-buffer-create eshell-pop-buffer))
      (eshell-mode)))
  (popwin:popup-buffer (get-buffer eshell-pop-buffer) :height 20))

(defun eshell/cde ()
  (let* ((file-name (buffer-file-name eshell-prev-buffer))
         (dir (or (and file-name (file-name-directory file-name))
                  (and (eq major-mode 'dired-mode) dired-directory)
                  (with-current-buffer eshell-prev-buffer
                    default-directory))))
    (eshell/cd dir)))

(defun eshell/cdp ()
  (let* ((cmd "git rev-parse --show-toplevel")
         (dir (with-temp-buffer
                (unless (call-process-shell-command cmd nil t)
                  (error "Here is not Git Repository"))
                (goto-char (point-min))
                (buffer-substring-no-properties
                 (point) (line-end-position)))))
    (eshell/cd dir)))

イメージ

おわりに

やっぱり Emacsから手軽に shellが操作できると便利ですね。


このへんはいろいろチャレンジしたんですが、結局どれも
しっくりこなかったので、使うのを諦めていましたが、
すべてを Emacsからでなくて、ちょこっと利用するときに
限定すればなんとかなりそうに思えました。その辺はバランスを
みつつ検討していければよりよい環境が作れるのではない
かと思います。

追記

ついでに emacsclientっぽいコマンドも作りました.
find-fileして shellの windowを消すだけのものです。

(defun eshell/e (file)
  (let ((curwin (get-buffer-window))
        (filepath (concat default-directory file)))
    (other-window 1)
    (find-file filepath)
    (delete-window curwin)))

Emacs Lispで例外処理

direx.elでgitプロジェクトのディレクトリツリーを表示する、またはdirex-project.elの紹介 - $shibayu36->blog;


Emacs Lispというか Lisp系の言語はエラー処理が豊富です。
私もよくわかっていない部分もあるので問題があればお知らせください。

ignore-errors

エラーが発生したことだけ検知したいのであれば ignore-errorsで
事足りるのではないでしょうか。ingore-errorsはエラーが返ると
そのブロックからは nilが返るというものです。

(let ((result (ignore-errors
                (do-something)
                t)))
  (unless result
    (do-failed-case)))

do-somethingerrorが発生すると、エラーの発生を抑制し、 resultが nil
なります。成功するとそのままブロックの処理を続け tとなります。あとは
その結果に応じて失敗時の処理を行えば良いわけです。

condition-case

ignore-errorsは単にエラーを無視する側面もありますが、condition-caseは
エラー処理専用の構文です。

(condition-case err-var
    (progn
      (error "Failed"))
  (error "Error: %s" err-var))

第一引数がエラーが格納される変数名、第二引数が body、第三引数以降が
エラーハンドラです。第三引数の errorっていうのは error関数ではなく、
エラーの種類です。他に arith-error等あります。詳しくはドキュメントを
参照してください。errorというのはすべて補足するものです。


try-catch的なものを利用したい場合は、構文的にもこちらの方が
いいかもしれません。

unwind-protect

try-catch-finallyの finallyを扱いときに使うものです。成功しても
失敗しても実行したい処理がある場合に利用できます。上記の示した
フォームと組み合わせて try-catch-finallyを実現できます。

(ignore-errors
  (unwind-protect
      (progn
        (error "hoge"))
    (message "This code is must executed!!")))

unwind-protectの第一引数の bodyが失敗しても成功しても、
messageの部分が利用されます。ファイルを deleteするとか
終了処理を入れることが多いでしょうか。


他にもあると思いますが、このへんを知っておけばだいたい
なんとかなります。


Enjoy hacking Emacs Lisp!!

import-popwin 各種言語の import文付近を popupする

emacsでperlのuse文挿入を簡単に - $shibayu36->blog;


を種々の言語で使えるようにして、自分で hook関数を設定できるように
したものです。

必要要件

  • popwin 0.6以降

イメージ

C言語だと include文あたりを popupし、Rubyだと import文、Perlだと
use, require文あたりを popupします。


以下は Pythonの例ですが、import-popwinを実行することで、最寄りの
import, from文近辺を popupしています。

対応言語

設定

(require 'import-popwin)
(global-set-key (kbd "M-g M-i") 'import-popwin)

設定を追加する

以下のように import-popwin:add関数を呼ぶことで設定を追加できます。
登録済みのやつは上書きされます。

(import-popwin:add :mode 'java-mode
                   :regexp "^import\\s-"
                   :before (lambda () (do-something))
                   :fallback (lambda () (do-something))
                   :after (lambda () (do-something)))

import-popwin:addの引数の概要を以下に示します。

キー 概要
:mode メジャーモード(リストでも可)
:regexp import文の正規表現。マッチした次の行へ移動する
:before import文へ移動する前に実行する関数
:fallback :regexpにマッチするものがなかった場合実行する関数
:after import文へ移動後実行する関数

おわりに

画面分割して、その部分に移動することを特に何も考えず行なっていましたが、
こういう作業こそ効率化を考えなくてはいけないと考えさせられました。
わりとよく行う行為でもありますしね。