2016年8月9日火曜日

poor-grep-dired

で、つくってみた。

(require 'em-unix)

(defun poor-grep-dired (string)
  "貧乏人のgrep"
  (interactive "s検索文字列: ")
  (let ((file-list
  (dired-get-marked-files nil nil 'dired-nondirectory-p))
 (display-buffer-function nil))    ; popwinを無効化
    (eshell-poor-mans-grep (cons string file-list))))

 dired-modeでmarkしたファイルにたいしてpoor-grepをかける。

2016年8月8日月曜日

dired-modeは奥が深い

 ここのサイトを見てはじめて知った。
 dired-modeでmarkしたファイルにたいして置換することができるそうだ。キーアサインは「Q」——「dired-do-query-replace-regexp」——あ、これは使える! これはmarkしたファイルに検索をかけることができる、ということじゃないか。
 しかもdired-modeはfind-fileでディレクトリを選んだときだけつくられる一覧というわけでもない。「find-lisp-find-dired」でも「mdfind-dired」でも生成される。「locate」でも。ごっそりファイルをひっぱりだしてきてそれにたいして操作ができる。
 「dired-do-query-replace-regexp」をもとにmarkしたファイルにたいして「eshell-poor-mans-grep」をかける関数なんて簡単にでっち上げられそうだし。

2016年8月7日日曜日

poor-grepを拡張してみた

(require 'em-unix)
(require 'cl)

(defun poor-grep (string regexp)
  "貧乏人のgrep"
  (interactive "s検索文字列: \nsファイルregexp: ")
  (let ((file-list (loop for x in (split-string regexp)
   append
   (file-expand-wildcards x)))
 (display-buffer-function nil))    ; popwinを無効化
    (eshell-poor-mans-grep (cons string file-list))))

 ファイルregexpを「* / */*/*」という感じで指定して複数のディレクトリを対象にできるようにした。

2016年8月6日土曜日

Spotlite

 MacOSのSpotliteをコマンド(mdfind)からEmacsで使えることは知っていたのだけど、ほとんど使ってなかった。下記のようにしてlocateのかわりにしていたのだけど。

(setq locate-command "mdfind")

 検索がファイル名のリストで、しかもファイルの中身や、タグもひっかかってしまうので、わけがわからなかったからだ。Spotliteだと、プレビューがあるからいいのだけど。でもファイル検索はやはりfindを使うより圧倒的に早い。
 el-getでmdfind-dired.elを落としてきたりした。mdfind-dired-nameでファイル名検索もできる。でもやっぱりhelmから使いたいよね。
 というわけでググってみた。
 helm-locateから使うには

(setq helm-locate-command
      (case system-type
 ('gnu/linux "locate -i -r %s")
 ('berkeley-unix "locate -i %s")
 ('windows-nt "es %s")
 ('darwin "mdfind -name %s %s")
 (t "locate %s")))

 で、helm-spotliteをつくる方法も同じとことにあった。

(defun helm-spotlight ()
  (interactive)
  (helm :buffer "*helm: spotlight*"
 :sources '(helm-source-mac-spotlight)))

Use mdfind instead of locate in helm-locate in OS X layer

;; locateのコマンドで引数を使う方法(こんな感じ?)
(setq locate-make-command-line (lambda(x) (list locate-command "-name"
search-string)))

2016年8月5日金曜日

Xcodeを削除

 MacBook Airの容量不足が深刻である。
 このところ、99%をこえ、残り容量が1Gになることもしばしばだ(今は2.2G)。
 EL Capitanの次のOSでは使ってないファイルをクラウドへ自動的に掃き出して容量を確保してくれるPlan9のような機能が追加されるそうだけど——その前にこちらはまだ、Yosemiteだ。残り容量1GではEL Capitanにすることすらできないだろう(試していない)。
 SSD換装をしようか、と思って検索してみたところ、結構な値段がする。それなら新しいMacBookを買った方がよくないか? そんな値段。
 どうしよう。
 しかたないので空きをつくため、Xcodeを削除した。「svn」などのコマンドは「Command Line Developer Tools」をもってくれば、使えるそうだし。
 削除したら残り容量7.4Gになった。
 94%である。
 うーん、90%を切りたいところなのだが。ついこのあいだまで10Gはあったんだがなぁ。どうしてこんなに減っちゃったんだろ。

2016年8月4日木曜日

Emacsからゴミ箱へ

 Emacsからファイルを削除してゴミ箱にはいるなんて必要ないや、と思っていたらそのような案件が発生した。Emacsでdeleteして復活させたくなったのだ。
 これはいかん。
 というわけで下記のように設定した。

(setq delete-by-moving-to-trash t)

 ところがMacでは次のメッセージをだしてうまくいかなかった。
 あれ?

ls does not support --dired; see `dired-use-ls-dired' for more details.

 どうやらCocoaEmacsではネイティブにはサポートされてないらしい。
 emacswikiでやり方を見つけた。

(setq delete-by-moving-to-trash t)

(defun system-move-file-to-trash (file)
  "Use \"trash\" to move FILE to the system trash.
When using Homebrew, install it using \"brew install trash\"."
  (call-process (executable-find "trash")
  nil 0 nil
  file))

 このやり方だとHomeBrewからtrashというコマンドをインストール必要がある。——「brew install trash」。
 それにしても「system-move-file-to-trash」を定義するだけで行くのはどうしてだろう、と思ってelispをあさってみたら

6 matches for "system-move-file-to-trash" in buffer: files.el.gz
   6796:This directory is only used when the function `system-move-file-to-trash'
   6806:(declare-function system-move-file-to-trash "w32fns.c" (filename))
   6814:If the function `system-move-file-to-trash' is defined, call it
   6841: ;; If `system-move-file-to-trash' is defined, use it.
   6842: ((fboundp 'system-move-file-to-trash)
   6843:  (system-move-file-to-trash filename))

 ということで、Windowsの場合はCで書かれた「system-move-file-to-trash」がバンドルされるらしい。

2016年8月3日水曜日

w32-shell-execute

 先日、Org-ModeのHyperLinkのことを調べていて「org-file-apps-defaults-windowsnt」という変数を見つけた。見るからにWindowsで何かアプリケーションを動かしてくれそうだ。
 その中に次のように定義されているところがあった。

(system w32-shell-execute "open" file)

 ——へっ?
 てなもんだ。先日、my-x-openをつくった(ググって見つけたものをパクったものだけれど)ばかりだというのに。あれ、Windowsにも「open」コマンドがあったっけ?
 だいたい「w32-shell-execute」って何よ。MacのEmacsには見当たらないんだけど。それでもしつこくelispをあさってみたら。

2 matches for "w32-shell-execute" in buffer: org.el.gz
   1951:                 'w32-shell-execute)
   1956:                 'w32-shell-execute)
2 matches for "w32-shell-execute" in buffer: browse-url.el.gz
    875:(declare-function w32-shell-execute "w32fns.c")    ;; Defined in C.
    885:        (t (w32-shell-execute "open" url))))

 というのがひっかかってきた。
 ——w32fns.c!
 Cか。
 するとこれはWindowsのときだけリンケージされるようなものなのかもしれない。ああ、もしかしたらcmdを呼ばなくてもすでにEmacsの中からWindowsでもファイル指定でエクセルを立ち上げるなんてことができるようになっていたってことではないだろうか……。

 Emacs for Windows1をあらためて調べてみたら「w32-shell-execute」という関数がやはり存在していてしかもこれなら——当たり前だが——わざわざ、file-pathをWindows用に変換しなくても動くのだった。
 というわけで

(defun my-x-open (file)
  "open file."
  (interactive "FOpen File: ")
  (message "Opening %s..." file)
  (w32-shell-execute "open" file)
  (message "Opening %s...done" file))

 これでいいのだった。しかもなんか、色々できそうな感じ……。
 というか、my-x-openなんで定義せずにw32-shell-executeを直接、呼び出せば、いいじゃん……orz

w32-shell-execute is a built-in function in `C source code'.

(w32-shell-execute OPERATION DOCUMENT &optional PARAMETERS SHOW-FLAG)

Get Windows to perform OPERATION on DOCUMENT.
This is a wrapper around the ShellExecute system function, which
invokes the application registered to handle OPERATION for DOCUMENT.

OPERATION is either nil or a string that names a supported operation.
What operations can be used depends on the particular DOCUMENT and its
handler application, but typically it is one of the following common
operations:

 "open"    - open DOCUMENT, which could be a file, a directory, or an
               executable program (application).  If it is an application,
               that application is launched in the current buffer's default
               directory.  Otherwise, the application associated with
               DOCUMENT is launched in the buffer's default directory.
 "opennew" - like "open", but instruct the application to open
               DOCUMENT in a new window.
 "openas"  - open the "Open With" dialog for DOCUMENT.
 "print"   - print DOCUMENT, which must be a file.
 "printto" - print DOCUMENT, which must be a file, to a specified printer.
               The printer should be provided in PARAMETERS, see below.
 "explore" - start the Windows Explorer on DOCUMENT.
 "edit"    - launch an editor and open DOCUMENT for editing; which
               editor is launched depends on the association for the
               specified DOCUMENT.
 "find"    - initiate search starting from DOCUMENT, which must specify
               a directory.
 "runas"   - run DOCUMENT, which must be an excutable file, with
               elevated privileges (a.k.a. "as Administrator").
 "properties"
           - open the the property sheet dialog for DOCUMENT; works
               for *.lnk desktop shortcuts, and little or nothing else.
 nil       - invoke the default OPERATION, or "open" if default is
               not defined or unavailable.

DOCUMENT is typically the name of a document file or a URL, but can
also be an executable program to run, or a directory to open in the
Windows Explorer.  If it is a file, it must be a local one; this
function does not support remote file names.

If DOCUMENT is an executable program, the optional third arg PARAMETERS
can be a string containing command line parameters that will be passed
to the program.  Some values of OPERATION also require parameters (e.g.,
"printto" requires the printer address).  Otherwise, PARAMETERS should
be nil or unspecified.

Optional fourth argument SHOW-FLAG can be used to control how the
application will be displayed when it is invoked.  If SHOW-FLAG is nil
or unspecified, the application is displayed as if SHOW-FLAG of 10 was
specified, otherwise it is an integer between 0 and 11 representing
a ShowWindow flag:

  0 - start hidden
  1 - start as normal-size window
  3 - start in a maximized window
  6 - start in a minimized window
 10 - start as the application itself specifies; this is the default.

Footnotes:

1

「GNU Emacs 24.5.1 (x8664-pc-mingw32) of 2015-04-14 on NTEMACS64」と「GNU Emacs 25.0.95.1 (i686-pc-cygwin) of 2016-07-09」

2016年8月2日火曜日

fullscreen

 使っているのは「GNU Emacs 24.5.1 (x86_64-apple-darwin14.3.0, NS apple-appkit-1347.57)」である。どうせMacBookAir上ではつねにフルスクリーン表示だ。それならelispからフルスクリーンにする方法はないか?

(toggle-frame-fullscreen)

 というのがあった。ところがinit.elの中で呼び出すようにしてみても——たしかにフルスクリーンになるのだが、frameだけだ。Emacsでいうところのウィンドウはフルスクリーンにならない。バグかな、これは、という動きだった。
 ——だめかぁ。

 と思ってすっかりあきらめていたらinit.elを整理したらうまく行くようになっていた。どうしてかは不明。もしかしたらMacOSのUPDATEがだめだったときからずいぶんあたっているからそのせいかもしれない。よくわからん。

 ちなみに

(toggle-frame-maximized)

 というのもある。

2016年8月1日月曜日

Org-ModeのHyperLink

 使っているのは「GNU Emacs 24.5.1 (x86_64-apple-darwin14.3.0, NS apple-appkit-1347.57)」である。Org-Modeのバージョンは「8.2.10」——そのorgでHyperLinkでリンクを張ったところ、いきなりVLCが立ち上がった。C-cC-oでHyperLinkからjumpしたところで、である。
 ——えっ。
 Linkのタイプは「file:」でEmacsでそのファイルを開いてくれるものだとばかり思っていた。これが「elisp:」のようにそれなりの処理を想定していたのならまだ、わかる。
 理解不能だった。
 あきらかにMacの「open」コマンドを呼び出したような動き。
 そこで該当の関数、「org-open-at-point」のソースを追っかけてみたところ、意外なことに「auto-mode-alist」を参照していた。Emacsのファイルとメジャーモードを関連づけている変数である。半分以上、カンだが、そこに定義されていないと、外部コマンドを呼び出すようになっているような。
 それで「.dat」ファイルを次のように定義した。

(add-to-list 'auto-mode-alist '("\\.dat$" . fundamental-mode))

 HayperLinkから無事、Emacsのfind-fileで開くようになった。

2016年7月29日金曜日

Tips

 時々、Emacsを検索語にくわえて適当にググってあちらこちらのサイトを見ていると、目からウロコが落ちる。もうちょっと使い易くならないかな、と薄々思っているようなことのTipsにあったりして。
 最近だとediffがそうだし、古くはtruncate-linesとか。
 今回はこれ。dired

;; diredを2つのウィンドウで開いている時に、デフォルトの移動orコピー先をもう一方のdiredで開いているディレクトリにする
(setq dired-dwim-target t)
;; ディレクトリを再帰的にコピーする
(setq dired-recursive-copies 'always)
;; diredバッファでC-sした時にファイル名だけにマッチするように
(setq dired-isearch-filenames t)

 早速、init.elにコピーだ。再帰コピーの指定はコメントアウトしたけれど。

2016年7月28日木曜日

winner-mode

 左にhowmの一覧を表示して、右側でその中身をいじっていて——ふとほかのものを見ると、右側のバッファが切り替わってしまう。まぁ、通常の動作なのだが、元のバッファを表示しなおすのにいつもこまってしまう。
 ファイル名が年月日+時刻だからどれもそっくりなのだ。helmのswitch bufferも形無しだ。どうしたらいいんだろう、といつも思っていたら解決する手段がすでにあることを知った。
 winner-modeである。
 しかも標準だ。
 Windowの構成をundoしてくれる。「global minor mode」なんて存在、はじめて知った。デフォルトのキーバインドはC-c <left>とC-c <right>。
 Emacsに矢印キーは不要だぜ、と思っていたのだけど、最近はOrg-modeでも使用することもあってすっかりお世話になっている。

2016年7月27日水曜日

scroll-all-mode

 できるということは知っていたのだけれど、どうすれば、いいか、わからなかった。昔、Infoでちらりと見ただけなのだ——夢だったのかもしれない。どういうわけか、最新のInfoにその記述をで見つけ切れないのだ。
 左右に二分割したバッファを同期してスクロールする方法があったはずなんだがなぁ。どうやるんだっけなぁ。helmでscrollで検索したらあっさりそれらしいものを見つけた。これか?

scroll-lock-mode

 外れだった。正解は「scroll-all-mode」。

2016年7月26日火曜日

poor-grep

 Emacs for Windowsではgrepが使えないので、とりあえずpoor-grepをでっち上げた。

(defun poor-grep (string regexp)
  "貧乏人のgrep"
  (interactive "s検索文字列: \nsファイルregexp: ")
  (let ((file-list (file-expand-wildcards regexp))
 (display-buffer-function nil)) ; popwinを無効化
    (eshell-poor-mans-grep (cons string file-list))))

2016年7月25日月曜日

同一フレーム内にediffのコントロールバッファを表示

 たぶんあるんじゃね、と思って探していたのだけど、見つけられなかった。何度もググってもだめで、speedbarのようにできないのかな、とあきらめていたところ——偶然、判明した。->「来年も使いたいelispランキング2013
 同一フレーム内にediffのコントロールバッファをだす方法である。
 ediffは超絶便利なのだけれど、コントロールバッファが別フレームにでるのがデフォルトなのだ。フルスクリーンで使っているとこまってしかたがなかった。しかもdiff対象のバッファが上下二分割されてしまうし。これは左右分割にしたい。howmのときのように
 とういうわけで上記、サイトより設定をinitにコピー。

;; コントロール用のバッファを同一フレーム内に表示
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; diffのバッファを上下ではなく左右に並べる
(setq ediff-split-window-function 'split-window-horizontally)

2016年7月24日日曜日

WindowsのEmacsからエクセルのファイルはエクセルで開くようにしたいんだよ

 たとえば、Macだと下記のようなコードをinit.elに放りこんでおくと、dired-modeでWで、指定したファイルをopenコマンドで呼び出してくれる。これはファインダーでダブルクリックしたときと同じ動きをしてくれるもので——pdfファイルだったらpdfビュアーで開いてくれる。これでエクセルのようなEmacsで開いてもしかたがないようなファイルを対応したアプリケーションで開くことができるようになる。

(require 'deferred)

;; diredで外部プロセス起動
(add-hook 'dired-mode-hook
   (lambda ()
     (define-key dired-mode-map
       "W" 'dired-open)))

(defun dired-open ()
  (interactive)
    (deferred:process "open" (dired-get-filename)))

 元々、このコードはMeadowがらみで知った1。Meadowにはfiberという、Macのopenコマンドに相当するものが同梱されていたのだ。そのMeadowも今はメンテされていない。
 Windowsで動くEmacsはいくつか、あるのだけれど、さすがにfiberはなくてかわりにstartコマンドがある。でもこいつを呼び出すにはどうしたらいいのかなぁ、なんかstartコマンドが見つからないんですけど、と思っていたら内部コマンドだということを知った。そうか。2
 ところがEmacsのパス構文がちがうため、フルパスでstartコマンドを渡すとうまく動作しない。前記のサイト2でもディレクトリの部分をのぞいたファイル名だけにしていた。MeadowはWindowsのパス構文の変換ができた。もしかしたらEmacsに取り込まれているんじゃないか、とelispを漁って、見つけた。

 w32-convert-standard-filename

 で、前記サイトのコードを元にこうした。

(defun my-x-open (file)
  "open file."
  (interactive "FOpen File: ")
  (message "Opening %s..." file)
  (call-process "cmd.exe" nil 0 nil "/c" "start" "" (w32-convert-standard-filename file))
  (message "Opening %s...done" file))

 これを使ってbookmarkの一覧バッファや、orgのハイパーリンクから外部コマンドで立ち上げることができるようになる。良きことかな。

追記:2016年7月31日(日)
cmd.exeをcall-processなどしなくてw32-shell-executeで呼び出せることが判明……。

Footnotes:

1

もちろんもうすこしちがうコードだった。当時はdeferredとか、なかったし。

2

サイトはググっても見つからなくなってしまった……。

2016年7月23日土曜日

Emacs for Windows

 事情があってWindows上でEmacsを使うことになった。
 かつてはMeadowというすぐれものがあったのだけれど、Emacs本体に取り込まれてしまったのか、現在はメンテされていない。四月ぐらいにはWindows上でgnupackのEmacsを使っていてまぁ、それでいいか、と思ってさっそくインストールした。これだと、CygnusというWindows上で動くUnix環境もついてくる。なのでいろんなコマンドが使えて便利だ——grepとか、findとか。
 ところがCygnus上で動作しているためか、動きはもっさりしているし、やたらとvforkエラーがでる1。四月のころはそんなにエラーにならなかったような記憶があるのだけれど(それでもエラーはでた)。32bit環境で動作しているせいかもしれない。なんとなく、Windows3.0のころのMS-DOSを思い出した。
 それくらいエラーが頻発する。

 こりゃ、たまらんというわけでNTEmacs64を入れることにした。
 IMEパッチはいらないので(どうせSKKを使う)、emacs-24.5.zipだ。
 動作はgnupackより機敏。vforkエラーもいまのところでていない。ただ問題はUnixコマンドが全然、使えないことで、たとえば、圧縮されたファイルを開けない。おかげで同梱されているelispが圧縮されていて往生した。外部コマンドに依存している機能は基本的にはだめだろうが、まぁ、vforkエラーの不快さよりはましだ。
 一番、使いそうなgrepはeshellのpoor grep2, 3で代用できるだろうし。

Footnotes:

1

diredだけでvforkエラーになる。くり返せば、いずれいくのだが、はっきりいってうざい。

2

ただし、popwinを使っていると画面がむちゃくちゃになるのでオフにしていた方がいいかも。

3

実はpoor grepだと文字コードが混在してもgrepが効くので(たぶん)逆にCygnusのgrepよりもよかったりする。遅いけどね。

2016年7月20日水曜日

バッチ処理

 たとえば、Emacsだと、batchモードというものがあって画面を表示できないような状況でも処理を実行できる。つまりログインしてなくてもcronの時間起動で動かすことができるというわけ。ところがほかの画面を持つアプリケーションだとそうはいかない。
 画面表示でエラーになってしまう。
 これがちょいとばかり問題で、というのも時間起動で勝手に動かしておきたいのに、わざわざログインして手作業で動かさなくていけない——そのまま、放ったらかしにしておけば、いいのだが、不用心だし、猫がキーボードの上にのったりしたらおかしくなってしまう。でも画面を表示しなければ、だめなわけだからどうしようもないよなぁ、と思っていたら——。
 Xvfbというものの存在を知った。
 仮想的にXサーバを立ち上げてくれるソフトで極端な話、ノンディスプレイのハード構成でも画面を表示するアプリケーションを動かすことができる。つまりアプリの画面が仮想的なXサーバに表示されるわけだ。見えないけど。でもアプリは動く。もし表示されている内容を確認したいのなら画面ダンプをとれば、いい。

import  -display :1 -window root test.jpg

 あとは時間がきたらCtrl+qのキーボードイベントをその画面にたいして発行して終了させれば、いい——それにはxautomationが使える。1

xte -x :1 "keydown Control_L"
xte -x :1 "key q"

 これでもしかしたらFireFox2を動かして特定のhtmlをPDF出力なんてできるんじゃないか、自動で。

Footnotes:

1

:1はXvfbで立ち上げたディスプレイID

2

FreeBSDのFireFoxではPDF出力ができる

2016年7月16日土曜日

remount

 また、やってしまった。
 ひさしぶりにThinkPadのFreeBSDの/etc/fstabをいじって——bootできなくしてしまった。shellに落ちる。ところが、/etc/fstabを元にもどそうと思ってもディスクがread-onlyでmountされているので、/etc/fstabを修正することができない。
 頭を抱えこむ。
 今までにも何度も似たようなことをやっていて、そのたびに、ディスクを筐体の中から取り出してほかのマシンにつないで事なきを得ていたのだが——。また、同じことをやらなければ、ならないのか、とちょっと自分に嫌になってしまった。しかもすぐにUFSでマウントできるようなマシンがない……。
 まいったな。
 ふと気づく。もしかしたら何か手があるんじゃないか。
 グーグル先生におうかがいをたててread-onlyのディスクをremountして書きこみ可能にできるらしいことを知る。

mount -o remount ,rw /

 ところがこれでうまくいかなかった。optionにremountなんてない、といわれる。たしかにグーグル先生が教えてくれたのはLinux環境のものだった。同じだろうと思ったのだが、たしかに「man mount」で調べてみても「remount」なんてoptionはない。
 ——FreeBSDではできないのか……。
 半分、絶望して検索ワードにFreeBSDを追加してようやく正解が判明。

mount -o rw /

 だった。

2016年7月1日金曜日

地下沢中也「預言者ピッピ」

 地下沢中也「預言者ピッピ」(1)
 地下沢中也「預言者ピッピ」(2)

 購入しようと思ってAmazonへ行ってみると、Kindle版しかなかった。1
 しかたなく、Kindle版を買ったのだけれど、あまりにもおもしろくて夜中にあわてて2巻も買ってしまった。そうでなかったら何日間か、やきもきしていただろう。ところが——。
 ところがである。
 3巻はまだ、でてない。
 なのでさらにやきもきしている。ああ、どうなるんだろう、この話……。

Footnotes:

1

今は紙の本も入荷しているようだ。