Emacs上からのコマンド実行方法は多くありますが、Emacs Lispの関数から使うことに焦点をあてます。
基本パターン
一番単純な使い方
pwd
を実行して結果を文字列で得ます。
(defun my-pwd ()
(interactive)
(shell-command-to-string "pwd"))
;; (my-pwd) ; => "/Users/username\n"
M-x my-pwd
もしくはM-: (my-pwd)
で実行できます。
(pwd
: カレントディレクトリを返すコマンド)
非同期でコマンドを実行
Mac OSXのsayコマンドでAlexに喋ってもらいます。shell-command-to-string
で同期実行した場合はAlexが喋っている間にEmacsを動かすことができません。そこで非同期実行のasync-shell-command
を使って実行中もEmacsを動かせるようにしています。
(defun my-say-hello ()
(interactive)
(async-shell-command "say -v Alex Hello! I am Emacs, at your service."))
選択範囲に対してコマンドを実行
選択範囲のaをbに置き換えます。perlコマンドの正規表現で置換
(defun my-replace-a-b ()
(interactive)
(when (region-active-p) ;; 選択範囲があるとき
(shell-command-on-region (region-beginning) (region-end) "perl -0 -p -w -e \'s/a/b/g\'" nil t)))
Dired上のファイル/フォルダに対してコマンドを実行
カーソル位置の画像ファイルの情報を表示します。マークしたファイルも対象になります。
(defun my-dired-display-file-info ()
(interactive)
(let ((files (dired-get-marked-files t current-prefix-arg)))
(dired-do-shell-command "file *" nil files)))
その他
コマンドのチェック
パスが通っていて使用可能ならコマンドのパスが返ります。
(executable-find "cmigemo") ; => "/usr/local/bin/cmigemo"
Emacs用にコマンドへのパスを通す
こちらを参考に
PATH の設定
実践サンプル
Mac OS X向けのコマンドが多めです。
選択範囲を指定したタグで囲む
選択範囲をミニバッファに入力したタグ名で囲みます。
(defun my-wrap-lines-with-html-tag (tag)
(interactive "sTag: ")
(if (region-active-p)
(shell-command-on-region
(region-beginning) (region-end)
(concat "perl -0 -p -w -e \'"
"s/^([^\\S\\r\\n]*)(\\S.*?)[^\\S\\r\\n]*$/$1<"
tag ">$2<\\/" tag ">/gm\'")
nil t)))
カレントディレクトリ以下の特定ファイルを削除
カレントディレクトリ以下の.DS_Storeファイルを削除します。
(defun my-delete-DS_Store-under-current-directory-recursively ()
(interactive)
(shell-command "find . -name '*.DS_Store' -type f -delete")
;; Diredを開いていたらバッファを更新
(if (eq major-mode 'dired-mode)
(revert-buffer)))
Diredからsqliteファイルの内容を閲覧
(defun my-dired-sqlite ()
(interactive)
(let ((file (dired-get-filename))
(buffer (format "SQLite-%s" (random 100000))))
(async-shell-command (format "sqlite3 '%s'" file) buffer)
(switch-to-buffer buffer)
(insert ".header on")
(execute-kbd-macro (kbd "RET")) ;; returnキー実行
(insert ".mode column")
(execute-kbd-macro (kbd "RET"))
(insert ".tables")
(execute-kbd-macro (kbd "RET"))))
Diredでマークしたファイルの特殊属性を除去
(defun my-dired-delete-mac-atmark-permission ()
(interactive)
(let ((files (dired-get-marked-files t current-prefix-arg)))
(mapc (lambda (file)
;; マークしたファイルそれぞれに対して実行
(dired-do-shell-command "xattr -c *" nil (list file)))
files)
(dired-unmark-all-marks) ;; マーク解除
(revert-buffer) ;; バッファ更新
))
Diredでマークしたファイルを別アプリに送る
Image Optimアプリへ送り、画像の容量を落とします。
(defun my-dired-image-optim ()
(interactive)
(let ((files (dired-get-marked-files t current-prefix-arg)))
(mapc (lambda (file)
(cond ((string-match ".*\\.\\(png\\|jpe?g\\|gif\\)$" file)
;; 指定した種類の画像ファイルの場合
(dired-do-shell-command "open -a ImageOptim.app *" nil (list file)))))
files)
(dired-unmark-all-marks)
(revert-buffer)))
Diredでマークしたファイルを入力値を使って処理
実行後にミニバッファに値を入力します。その値で画像のリサイズを行います。
(sips: 画像をリサイズする Mac OS X 標準コマンド)
(defun my-dired-image-width-resize-with-sips (width)
(interactive "sWidth: ")
(let ((files (dired-get-marked-files t current-prefix-arg)))
(mapc (lambda (file)
(cond ((string-match ".*\\.\\(png\\|jpe?g\\|gif\\)$" file)
(dired-do-shell-command
(concat "sips --resampleWidth " width " *")
nil (list file)))))
files)
(dired-unmark-all-marks)
(revert-buffer)))
選択範囲を任意の正規表現で置換
私のお気に入りのコードです。
M-x my-perl-replace-command
のあとに例えばs/[\n\r]//g
とすると、選択範囲の改行を削除します。
他によく使うのが、s/\t/ /g
でタブ文字を空白文字2つに置換しています。標準の変換関数より高速です。
;; 履歴用
(defvar my-perl-replace-history nil
"History for the `my-perl-replace-command'.")
(defun my-perl-replace-command (command)
"Utilize Perl regular expression to replace string in the current buffer."
(interactive (list (read-shell-command "s[perl regexp] : "
""
'my-perl-replace-history)))
(when (string-match "'" command)
(setq command (replace-regexp-in-string "'" "\\\\x27" command)))
(if (region-active-p)
(shell-command-on-region
(region-beginning) (region-end) (concat "perl -0 -p -w -e \'" command "\'") nil t)
(let ((po (point))
(win (window-start)))
(mark-whole-buffer)
(shell-command-on-region
(region-beginning) (region-end)
(concat "perl -0 -p -w -e \'" command "\'") nil t)
(goto-char po)
(set-window-start (selected-window) win))))