Yearly Archives: 2014

2014-03-01

Windowsのel-getで非同期インストールがエラーになる

el-getをインストールしたので、Wanderlustをel-getでインストールしようとしたらエラーになりました。

次のエラーメッセージが出ました。(gnupack emacs-24.3-20130503 / el-get version 5.1.1dce781)

el-get install apel
el-get: Package apel installed.
el-get: git submodule update ok
el-get: el-get-build apel: c:/app/emacs-24.3-20130503/bin/emacs -batch -q -no-site-file -l APEL-MK -f compile-apel prefix site-lisp site-lisp ok.
el-get: el-get-build apel: c:/app/emacs-24.3-20130503/bin/emacs -batch -q -no-site-file -l APEL-MK -f install-apel prefix site-lisp site-lisp ok.
apel failed to install: (error process byte-compile no longer connected to pipe; closed it) [2 times]
el-get-installation-failed: process byte-compile no longer connected to pipe; closed it

(el-get 'sync 'wanderlust)を評価して同期でインストールしようとするとこのエラーは出ないようなので(別のエラーは出るw)、非同期の時だけの問題のようです。

原因

結論から言うと shell-file-name が "cmdproxy.exe" になっていないことが原因です。
el-getはwindows-ntで実行しているとき、shell-file-nameを強制的に "cmdproxy.exe" に変更してからプロセス呼び出しを行うようになっています。
ただ、この処理がel-get-build関数内にしかないのが問題です。

el-get-build関数は非同期の時、ビルドの完了を待たずに終了します。el-get-build関数内ででいくら

(let* (...略...
       (shell-file-name (or (and (eq system-type 'windows-nt)
                                 (executable-find "cmdproxy.exe"))
                            shell-file-name))
       ...略...)
  ...処理の本体...

のようなコードを書いても、非同期で実行される後続のプロセス呼び出しには適用されません。

shell-file-name が"cmdproxy.exe"でないと、 shell-quote-argument がWindowsのドライブレターを含むパスを正しくクォートできません。
"C:/home/hoge.el"みたいなパスを"C\:/home/hoge.el"のようにしてしまいます。
結果、サブプロセスで呼ばれるemacsは引数で渡されたファイル名を開けずに異常終了します。
そうすると、上のエラーのように、プロセスとパイプがつながらないよ!ということになります。

対策

el-getがサブプロセスを起動するときは必ず shell-file-name が"cmdproxy.exe"になるようにします。

まず、 el-get で使用する shell-file-name を次のようにして決めます。

;;; el-getが使用するshell-file-nameを決める。
;;; el-get-build内(el-get version 5.1.1dce781)で似たような判定をしているが、
;;; その関数内だけでは不十分。
(setq my-el-get-shell-file-name
   (or (and (eq system-type 'windows-nt)
            (executable-find "cmdproxy.exe"))
       shell-file-name))

そして、 el-get-start-process-list 関数を実行するときは、必ずその決めた shell-file-name を使うようにします。

;;; プロセスを呼び出す前に my-el-get-shell-file-name を適用する。
;;;
;;; el-get-build内(el-get version 5.1.1dce781)で同じような処理をしているが、
;;; それでは不十分。非同期インストールの時はel-get-build関数は処理の完了を
;;; 待たずに終わってしまうので。
(defadvice el-get-start-process-list (around my-el-get-start-process-list--modify-shell-file-name activate)
  (let ((shell-file-name my-el-get-shell-file-name))
    ad-do-it))

el-get-start-process-list 関数内でコマンドライン引数に shell-quote-argument が適用されています。
shell-quote-argument は shell-file-name の値によって動作が変わるので、
この関数の中を実行しているときだけ shell-file-name が"cmdproxy.exe"になっていればOKです。

(setq el-get-verbose t) で詳細を表示するようにして、 :args 部分のパスに問題が無ければOKです。

2014-02-28

今更ながらel-getを使い始めてみた

org-modeやらmagitやらWanderlustやら、Emacs Lispを最新版へ更新するのが億劫になってきたのでEmacsのパッケージ管理システムを検討してみました。

Emacs24からはpackage.elというのが標準で使えるようになったそうで、package-list-packagesでいきなりパッケージのリストが表示されるというお手軽さなのです。
でも、このシステムはパッケージのリポジトリへの登録にハードルがあるらしく、扱えるパッケージに限りがあるようなのです(参考:elispをpackageとel-get両方で管理する - $shibayu36->blog;)。

なので、el-getを試してみることにしました。公式サイトは dimitri/el-get です。

インストールは簡単で、scratchバッファなどから次のelispを実行するだけ。

;; So the idea is that you copy/paste this code into your *scratch* buffer,
;; hit C-j, and you have a working el-get.
(url-retrieve
 "https://raw.github.com/dimitri/el-get/master/el-get-install.el"
 (lambda (s)
   (goto-char (point-max))
   (eval-print-last-sexp)))

のはずだったのですが、Windows上でgnupackのemacs-24.3-20130503を使っていると落ちます。強制終了です。
どうも、httpsから任意のページをurl-retrieveしようとしただけで落ちるみたいです。
Emacs内部に組み込まれたgnutls、実際にはlibgnutls-28.dll内で問題が起きるようです。
解決方法は elpa形式じゃない野良elispをpackage-installする #Emacs @robario cookieswap補助、gist.el、ちょっとtombloo - うぇぶとらばぁす にありました。

(eval-after-load
  "gnutls"
  '(setq gnutls-trustfiles (mapcar 'expand-file-name gnutls-trustfiles)))

gnutlsが読み込まれる前に上を実行しておけば(.emacsのel-getの設定等より先に書いておけば)落ちなくなりました。
どうもlibgnutls-28.dllがcygwin的なパスを認識できないことが原因のようです。expand-file-nameを通すことでWindows形式の絶対パスに展開され、落ちなくなるようです。

というわけで、無事にインストールできました。el-get-list-packageでパッケージの一覧を見ることが出来ます。iでマークしてxでインストールできます。

公式の Basic Setup のところに書いていますが、.emacsは次のようにすると良いみたいですね。

(add-to-list 'load-path "~/.emacs.d/el-get/el-get")

(unless (require 'el-get nil 'noerror)
  (with-current-buffer
      (url-retrieve-synchronously
       "https://raw.github.com/dimitri/el-get/master/el-get-install.el")
    (goto-char (point-max))
    (eval-print-last-sexp)))

(add-to-list 'el-get-recipe-path "~/.emacs.d/el-get-user/recipes")
(el-get 'sync)

こうすると、el-getがインストールされていなければ自動的にインストールされます。
.emacsをバージョン管理して他のマシンと共有している場合は便利ですね。

.emacsを共有している他のマシンにも同じパッケージを自動的にインストールしたいことがあると思います。
そういう場合は、

(el-get 'sync
  'color-moccur
  'magit
)

のように'syncの後にパッケージ名を書いておくと良いみたいです。(参考: 自分の el-get のワークフローについて整理する - そんなこと覚えてない)

2014-02-28

URLとタイトルのコピー

皆さんは開いているWebページのURLやタイトルをコピーする時ってどうしてます?

URLはロケーションバーからコピーすれば良いとして、問題はタイトルです。

私は普段Firefoxを使っているので、ページの上で右クリック→「ページの情報を表示」を選んで、タイトルを範囲選択してコピーしていました。
そしてテキストエディタにペーストしてから書式を整える。

面倒くさい。

今日もその作業をしていたときに、ふとブックマークレットにすれば良いんじゃね? と思いついてやってみました。

javascript:alert("%20%20[["+document.URL+"]["+document.title+"]]");

「ブックマークの追加」を選んで、名前を「URLをorg形式で表示」とし、URLのところに上を打ち込みます。
このブックマークを開こうとすると、現在開いているページのURLとタイトルをEmacs org-modeのリンク書式で表示してくれるというわけです。
ちなみに、先頭の%20%20はalertダイアログで範囲選択しやすくするために追加した空白です。

これだと範囲選択してコピー操作する面倒は残ります。
Firefoxのaddonならクリップボードへのコピーまで出来るのだろうなー、と思ったところで、
ひょっとしたらFirefox用のAddonがあるんじゃないかと思い至りました。

「copy url firefox」で検索してみると、次のものが。

Copy Urls Expert :: Add-ons for Firefox

書式設定まで出来る! 完璧です。

2014-01-29

git-encwrapper再び

git-encwrapper のバグを修正しました。

git-encwrapper は、gitのencoding属性(.gitattributesで指定)を活用してgit diffの出力の文字コードを統一したり、git applyの入力の文字コードを統一されたものから元に戻したりするgitラッパーです。

ところがCygwinを64bit版にしたときになぜかgit-encwrapperが動かなくなってしまいました。
原因を突き止めるのが面倒だったので、elisp側でなんとかするコードを書きました。

今日 magit.el を開発最新版へ更新したら、案の定上のelispは使えなくなってしまいました。
magit.elの中をざっと見てみたのですが、プロセスを呼び出すところ(つまり、フックすべきところ)が沢山あり、
修正は大変そうでした。

なので、再びgit-encwrapperを復活させることにしました。

調査した結果、次の二つの問題が見つかりました。

  • -cオプションを使っているとgitコマンド名を誤認識する不具合
  • NULLポインタの判定ミス

前者は「git -c diff.submodule=short diff」のようなコマンドラインへの対応です。
ハイフンで始まらない一番最初のコマンドライン引数をコマンド名として扱っていたので、
「diff」ではなく「diff.submodule=short」がコマンド名だと認識されていました。

後者は単純なミスで、if(p)と書くべきところをif(*p)と書いていたというものです。
おそらくこれによって動いたり動かなかったりしていた模様です。

これらを修正したところ、おおむね正常に動いているようです。

2014-01-27

2014-01冬の新番組

ようやく新番組一通り見終わりました。

今のところ一押しは「世界征服~謀略のズヴィズダー~」でしょうか。

2014-01-16

ノートPC吟味

今新しいノートPCを買うとしたら何が良いかなぁと最近考えてます。

十分な性能を持ち、出来るだけ軽量、画面は小さすぎず、キーボードがまとも、出来ればタッチパネルは欲しいなと。

製品名 価格 画面サイズ CPU 外部記憶 重量 備考
Surface Pro 2 99800+12100円 10.6" Core i5 4200U/1.6GHz 128GB 907g+216g タイプカバー2込み
Lavie Z(LZ650/NS) 122267円 13.3" Core i5 4200U/1.6GHz 128GB 945g  
Let's note AX3(CF-AX3SEGJR) 21万円程度? 11.6" Core i5 4200U/1.6GHz 128GB 1140g  
Let's note MX3(CF-MX3SEBJR) 20万円前後 12.5" Core i5 4200U/1.6GHz 128GB 1198g  
Let's note MX3(CF-MX3TEABR) 27万円前後 12.5" Core i7 4500U/1.8GHz 256GB 1198g  

条件に合うのはこの辺りでしょうか。もう数百グラム重量を増やして良いなら選択肢はグッと広がりそうですが。

値段と財布と使用頻度と今持っているノートPCとを考慮すると、もう少し先でも良いかなぁと思います。

2014-01-03

書籍の取り込みと整理

年末年始の休みを利用して書籍の電子化、いわゆる自炊を少しずつ進めています。
まとまった時間が無いとなかなか手をつける気にならなかったのです。
それでも一日に10~16冊程度、2~3時間でできる程度にしています。
一気に取り込もうとすると疲れるので。

本を取り込むには、次のステップが必要です。

  1. 本の選定。
  2. 裁断(裁断機による本体の裁断、カッターによるカバーの裁断はスキャン直前に行うことが多い)。
  3. スキャン(ScanSnapによるスキャン設定の調整と取り込み)。
  4. PDFファイルの加工(ページの結合や回転、ファイル名の設定、閉じ方向の設定)。
  5. 文字認識。
  6. 分類。
  7. バックアップPCへの転送。

これらを一冊ずつやるのではなく、ある程度まとまった冊数ごとにやることにしています。
つまり、次のような流れになります。

  1. 取り込む本を30冊くらい床に積む。
  2. 選んだ本を裁断機で裁断する。裁断機は重くて取扱が面倒なので、スキャンと平行して行わず、まとめて行うようにした。
  3. 適当な冊数(15冊くらい)まとめてスキャンする。カッターでカバーを切り、スキャンし、PDFを加工する。
  4. スキャンした本を文字認識(検索可能なPDFに)する。一冊スキャンする毎に文字認識すると、微妙な予測できない待ち時間が発生するので、後で一括で行うようにした。
  5. スキャンした本を分類する。フォルダ分けする。分類が直感的に分かるものはそうする。分からないものは日本十進分類法(NDC)で分ける。
  6. スキャンした本をバックアップPCへ転送する。
  7. 裁断した本が残っているなら3へ。
  8. 裁断した本が無くなったら1へ。

疲れたらどの段階で中断してもOKです。

最近ようやくライブラリが充実してきて、電子化の意味が出てきつつあります。
これまで、どうでも良い本から取り込んでいく方針で進めてきました。
そうするとせっかく苦労して取り込んでも、そのデータにアクセスすることはほとんど無いわけです。
何のためにスキャンしているんだろうと疑問に思うこともしばしばありました(部屋が片付くくらいの意味はあるのですが)。
最近は読まずに放置されている本(いわゆる積ん読)も少しずつ取り込んでいます。
電子化することで読むきっかけになればという期待を込めつつ、読まれなくても損は無いとの考えです。