Category Archives: 未分類

2016-04-23

Emacs25(MinGW64)+cygwin-mount.elでtramp経由でリモートファイルを開けない

diredでリモートのディレクトリリストは表示されてもファイルを開こうとすると次のようなエラーが。

Tramp: Encoding remote file ‘/scpx:user@example.jp:/home/user/tmp/test1.txt’ with ‘openssl enc -base64 <%s’...done
Tramp: Decoding local file ‘c:/app/cygwin/tmp/tramp.6920y_V.txt’ with ‘base64-decode-region’...done
Tramp: Inserting ‘/scpx:user@example.jp:/home/user/tmp/test1.txt’...failed
Removing old name: No such file or directory, /app/cygwin/app/cygwin/tmp/tramp.6920y_V.txt

調べていくとカレントディレクトリ(default-directory)によって結果が変わった。 scratchバッファからリモートファイルをfind-fileすると問題なく開いた。 tramp上のパスをdiredで開いて、そこから開こうとするとエラーになった。

  1. find-file
  2. insert-file-contents
  3. tramp-handle-insert-file-contents
  4. tramp-sh-handle-file-local-copy
  5. with-temp-file
  6. write-region

と追っていくと、次のようなコードでエラーが再現。

(let ((default-directory "/scpx:user@example.jp:/home/user/tmp"))
  (write-region nil nil "c:/app/cygwin/tmp/a.txt"))

default-directoryがローカルなら何事もなく成功する。

write-regionはCで書かれているので見てみると、中でexpand-file-nameを使ってファイル名を展開し、そのファイルに対して出力している。

絶対パスにしているならカレントディレクトリによって動作が変わるはずはない。

エラーメッセージとして/app/cygwin/app/cygwin/tmp/tramp.6920y_V.txtのような全くおかしなパスが表示されているので、念のためexpand-file-nameを調べたところ、おかしな挙動に気がついた。

  • (expand-file-name "c:/a.txt" "c:/")c:/a.txt
  • (expand-file-name "c:/a.txt" "/ssh:/")/a.txt

あれれ?

expand-file-nameもCで書かれていたので中身を見てみると、default-directoryを元にfind-file-name-handlerして実際にexpand-file-nameを処理する関数を求めていた。

あー、ローカルとリモートでファイルシステムが違うんだ。default-directoryがtrampパスの時tramp-sh-handle-expand-file-nameが使われるんだ。 で、tramp-sh-handle-expand-file-nameはWindowsのことをこれっぽっちも考慮していないからc:/aが/aになってしまうのね。

C:/app/cygwin/tmp/a.txt が tramp-sh-handle-expand-file-name によって /app/cygwin/tmp/a.txt になり、これがcygwin-mount.elによってcygwinルートディレクトリを基準にしたパスとして展開され、/app/cygwin/app/cygwin/tmp/a.txtになるわけだ。ヤレヤレ。

というか、そもそもexpand-file-nameにローカルの絶対パスを渡したときにtrampのexpand-file-nameが使われるってどうなのよ。 ここは展開対象パスがローカルの絶対パスなのだから、default-directoryに関わらずローカルのハンドラによってexpandするべきなんじゃないのか? というわけで、expand-file-nameにadvice-addしたのだけど、何故かうまく行かなかった。Cから呼んでいるからだろうか。

仕方ないのでtramp-sh-handle-expand-file-name側にadvice-addしてc:/がc:/のまま/にならないようにしたところ、リモートのファイルがtramp経由で開けるようになった。

(advice-add
 'tramp-sh-handle-expand-file-name :around
 (lambda (orig-func name &optional dir)
   (if (save-match-data (string-match "^[a-z]+:[/\\]" name))
       (expand-file-name name (file-name-directory name))
     (apply orig-func (list name dir)))))

ちなみに、リモート・ローカル間でコピーできない現象は次のページの tramp-do-copy-or-rename-file-out-of-band へのadviceで治った。

NTEmacs @ ウィキ - tramp を tramp-method “scp” で使うための設定 - @ウィキモバイル

最後に、trampのコードを追うためにはファイル名ハンドラのことを知っていないといけないのでしっかり押さえておくこと。

2016-04-22 ,

Windows10でウィンドウのアクティブタイトルバーに色をつける

Vistaからだったろうか、Win7からだったろうか。アクティブタイトルバーに色が付かなくなったのは。主にキーボードで操作している人間にとって、今どこにキーフォーカスが当たっているのかは非常に重要な情報だ。特に最近のディスプレイは大きい。23インチ、マルチディスプレイ環境で沢山のウィンドウがあると、一目で全てのウィンドウに目を通すのは難しい。ましてやわずかな明暗の差しか無いアクティブウィンドウを識別するのは容易ではない。

そんな状況が続きつつも最近は諦めていたのだが、ひょんな事から何か状況が変わっていないかと「windows10 active titlebar」で検索したら「タイトルバーに色づけ」なんて記事が大量に出てくるではないか!

どうもWindows10のThreshold2から(Insider Previewではその前から)出来るようになっていたらしい。

最近の私の情報感度の低さというか、情弱っぷりには我ながらびっくりするくらいだ。

などと記事を辿っていくと、Aero Liteなるテーマがあったようだ。

何はともあれ、あるべき設定があるべき場所にあるのは良いことだ。

2016-04-21

Windows(MSYS2 MinGW64)でEmacs25+IMEパッチをビルド

(2019-12-08追記: 新しいものを書きました Windows用のEmacs26.3をMSYS2でビルドする方法(IMEパッチ、ImageMagick-6))

新しいPCにしてからEmacsの適当なWindows用バイナリを試してみたのですが、gnutlsが使えなかったりIMEまわりが不安定だったりどれが最新だか分からなかったり色々したので諦めて自分でビルドすることにしました。SSDになったことですし!

ビルドの方法については nt/INSTALLnt/INSTALL.W64 が一次情報となり、詳しいと思います。私はW64の方を参考にしました。

日本語では次のページが参考になりました。

特にIMEパッチを提供されている rzl24ozi’s gists のREADME.txtが最も参考になりました。

以下、私がビルドした時の手順です。

ソースコードは emacs.git - Emacs source repository (GitHubならemacs/nt at master - emacs-mirror/emacs)、リリース版なら http://ftp.gnu.org/gnu/emacs/ からダウンロード可能です。 (Gitで落とすときは改行コードを変換しないように注意(autocrlf=false))

Gitでは全て落とすとリポジトリがかなりの容量になるそうなので、 --depth 1 を指定してみました。それでも時間はちょっとかかりますね。

git clone --depth 1 git://git.savannah.gnu.org/emacs.git --config core.autocrlf=false

emacs-25ブランチなら次のようにします(masterは少し不具合があるのでこちらの方が良いかも)。

git clone --depth=1 -b emacs-25 git://git.savannah.gnu.org/emacs.git --config core.autocrlf=false

ビルドの前にMSYS2のインストールとパッケージの設定が必要です。 MSYS2 に書かれていることに加えて nt/INSTALL.W64 に書かれているパッケージをインストールしました。

  1. MSYS2ダウンロード: http://sourceforge.net/projects/msys2/files/latest/download?source=files
  2. MSYS2インストール: msys2-x86_64-20160205.exeを実行
  3. MSYS2のbashから pacman -Sy
  4. パッケージのインストール

       pacman -S base-devel \
       mingw-w64-x86_64-toolchain \
       mingw-w64-x86_64-xpm-nox \
       mingw-w64-x86_64-libtiff \
       mingw-w64-x86_64-giflib \
       mingw-w64-x86_64-libpng \
       mingw-w64-x86_64-libjpeg-turbo \
       mingw-w64-x86_64-librsvg \
       mingw-w64-x86_64-libxml2 \
       mingw-w64-x86_64-gnutls   
    

    (1回でうまく入らないことあり)

私の場合、ここでautocrlf=trueにしていたことに気がついたので、その解消をしました。 cloneしたディレクトリで git config core.autocrlf false して、.git以外全て消して、 git reset --hard しました。

そしてビルド。

  1. (重要) mingw64_shell.bat (スタートメニューからMinGW-w64 Win64 Shell)を実行してMinGW64環境へ切り替える(これをしないとmake段階でエラーになります)
  2. 後はだいたい以下のような感じ

    ./autogen.sh
    ./autogen.sh git #こうしろと言われたので
    ./autogen.sh  #こうしろと言われたので
    
    PKG_CONFIG_PATH=/mingw64/lib/pkgconfig ./configure --prefix=/c/<checkout-dir> --without-imagemagick
    
    make -j4 #4コアで
    
    make install prefix=/c/<install-dir>
    
    <install-dir>/bin/runemacs #起動
    

    最適化するなら chuntaro/NTEmacs64: Windows 版 Emacs (通称 NTEmacs) の 64bit 版 にあるようにCFLAGSを指定して以下のようにすれば良い。

       PKG_CONFIG_PATH=/mingw64/lib/pkgconfig CFLAGS='-Ofast -march=x86-64 -mtune=corei7' ./configure --prefix=/c/<checkout-dir>/ --without-imagemagick
    
  3. (おっと、パッチを当ててなかった)rzl24ozi’s gists から emacs-25.0.92-x64.diff をダウンロード
  4. ソースコードのあるディレクトリトップで patch -b -p0 < emacs-25.0.92-x64.diff (patchはCygwinでテキストマウントを使っていると色々ハマるので注意)
  5. いくつかのHunkが失敗したり曖昧だったりするので一つ一つ確認して修正

    現時点でリジェクトされたのは次の2箇所のみでした。前後の内容が変わってしまって失敗しただけなので、手作業で修正すれば難しくありません。 (ちなみにemacs-25ブランチなら特にリジェクト無くパッチが当たる模様。masterは不具合もあるのでそっちの方が良いかも)

    --- ./src/Makefile.in.orig      2016-03-02 19:21:43.000000000 +0900
    +++ ./src/Makefile.in   2016-03-26 11:17:17.908757300 +0900
    @@ -396,7 +396,7 @@
            region-cache.o sound.o atimer.o \
            doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
            $(XWIDGETS_OBJ) \
    -       profiler.o decompress.o \
    +       profiler.o decompress.o cmigemo.o \
            $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
            $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
     obj = $(base_obj) $(NS_OBJC_OBJ)
    
    --- ./src/w32fns.c.orig 2016-03-02 19:21:43.000000000 +0900
    +++ ./src/w32fns.c      2016-03-26 11:17:17.988761000 +0900
    @@ -52,6 +52,11 @@
     #include "w32.h"
     #endif
     
    +#ifdef USE_W32_IME
    +#include "fontset.h"
    +#include "w32font.h"
    +#endif
    +
     #include <commctrl.h>
     #include <commdlg.h>
     #include <shellapi.h>
    
  6. 再度makeしてmake installでok

    作成するexeのサイズを小さくするなら make install-strip とする。

       make install-strip prefix=/c/<install-dir>/
    

うん、ちゃんとIME使える!