トップ 最新 追記

活動日誌


2012-01-01

[Emacs]Emacs23 に移行

普段 Windows ではエディタに Emacs を使っていますが、これまで、intlfonts が好みだったため、Emacs22 を使い続けていました。 (Windows の Emacs23 は BDF フォントが使えないようなので)

しかし、さすがに移行するべきかなということで、思い切って Emacs23.3 にアップデートしてみました。

フォントは、MeiryoKe_Gothic と Inconsolata の組み合わせがなかなかいい感じだったので、以下のように設定しました。

 (set-face-attribute 'default nil :family "Inconsolata" :height 150)
 (let ((fn (frame-parameter nil 'font)))
   (dolist (target '(katakana-jisx0201
                     japanese-jisx0208
                     japanese-jisx0212
                     japanese-jisx0213.2004-1
                     ))
     (set-fontset-font fn target '("MeiryoKe_Gothic" . "iso10646-1"))))
 (setq face-font-rescale-alist
       '((".*MeiryoKe_Gothic.*" . 0.89)
         ("-cdac$" . 1.3)))
 (setq-default line-spacing 2)
 (setq scalable-fonts-allowed t)
 (setq w32-enable-synthesized-fonts t)

メイリオの大きさは、英数字の行に日本語が混ざっても高さが変化しないぎりぎりで設定してあります。全角文字と半角文字の幅は2:1にはなっていませんが、高さが変わらないことの方を優先しました。


2012-01-09

[Emacs]find-fileで *Completions* バッファに ../ と ./ を出さない

C-x C-f (find-file) でファイルを開くとき、ディレクトリの先頭で補完を行うと補完対象の最初に ../ と ./ が表示されます。

これは邪魔でしかないので消せないものかと思っていたのですが、以下のように find-file-read-args を再定義することで除外することができました。


2012-01-27

[zsh]zsh の vcs-info を Cygwin で高速化する

zsh には vcs-info というものがあり、これを利用すると Git や Mercurial のブランチ名などをプロンプトに表示することができます。 (例: http://d.hatena.ne.jp/mollifier/20090814/p1

しかし使ってみるとわかるのですが、Cygwin だと結構遅いです。 シェルのプロンプトが表示されるたびにちょくちょく待たされる感じになってしまい、かなりストレスを感じます。

どうにかならないものかと思っていたのですが、ひとまず実用上問題なさそうなところまで高速化できたので共有しておきます。 (私が Mercurial メインで使っているので、Mercurial を使う際の高速化が中心です。Git だとまだ改善の余地が多いかと思います)

第一に:使っていないバージョン管理システムは外す

vcs_info はたくさんのバージョン管理システムに対応していますが、 現在のディレクトリがそれぞれのシステムに対応しているか調べるため、 多くのシステムを有効にしていると重くなってしまいます。

デフォルトでは全部有効になっているので、使うものだけを指定するようにします。

 zstyle ':vcs_info:*' enable hg git

ここでは Mercurial と Git を指定しています。 ここに書かれた順にチェックがされるので、Mercurial の作業コピーで作業することが多い人は、 このように hg を先に書いた方がレスポンスが速くなります。

なぜ遅いか

調べてみたところ、Cygwin だとコマンド置換 $(...) が遅いのが一番のネックになっているようです。 例えば私の環境では

 zsh -fc 'repeat 100 $()'

が、Linux(Debian) では 0.04 秒ほどで終了するのに対し、Cygwin では 4 秒弱かかりました。

そこで、なるべくコマンド置換をしないように修正します。

対処方法

 --- /usr/share/zsh/4.3.12/functions/VCS_INFO_bydir_detect       2011-08-08 04:59:41.001000000 +0900
 +++ ./VCS_INFO_bydir_detect     2012-01-19 21:52:35.293434600 +0900
 @@ -6,7 +6,7 @@
  local dirname=$1
  local basedir="." realbasedir file

 -realbasedir="$(VCS_INFO_realpath ${basedir})"
 +realbasedir="${basedir:A}"
  while [[ ${realbasedir} != '/' ]]; do
      [[ -r ${realbasedir} ]] || return 1
      if [[ -n ${vcs_comm[detect_need_file]} ]] ; then
 @@ -20,7 +20,7 @@
      fi

      basedir=${basedir}/..
 -    realbasedir="$(VCS_INFO_realpath ${basedir})"
 +    realbasedir="${basedir:A}"
  done

  [[ ${realbasedir} == "/" ]] && return 1

現在のディレクトリが Mercurial 管理下にあるかどうかを調べるため、 .hg ディレクトリがあるかどうかを現在のディレクトリからルートディレクトリまで順に探しています。

../ 混じりのパスを実際のパスに直すため VCS_INFO_realpath という関数を使っているのですが、 これは変数展開の A 修飾子でできるのでそちらを使います。

 --- /usr/share/zsh/4.3.12/functions/VCS_INFO_formats    2011-08-08 04:59:41.001000000 +0900
 +++ ./VCS_INFO_formats  2012-01-20 02:42:04.744074700 +0900
 @@ -29,7 +29,16 @@
  )
  hook_com[base-name]="${${hook_com[base]}:t}"
  hook_com[base-name_orig]="${hook_com[base_name]}"
 -hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
 +
 +# コマンド置換が遅い Cygwin で高速化するために VCS_INFO_reposub を展開
 +#hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
 +local base=${hook_com[base]%%/##}
 +if [[ ${PWD} == ${base}/* ]]; then
 +  hook_com[subdir]=${PWD#$base/}
 +else
 +  hook_com[subdir]='.'
 +fi
 +
  hook_com[subdir_orig]="${hook_com[subdir]}"

  VCS_INFO_hook 'post-backend'

VCS_INFO_reposub はここでしか使われていなかったので、中身を展開してしまいました。

Mercurial だけを使うならここまででいいのですが、とりあえず Git に対しても vcs-info を使うようにしていたところ、 特にバージョン管理下にないディレクトリにいるときに重い状態でした。

これは、バージョン管理下にないディレクトリに対しては、Mercurial のワーキングコピーであるかどうかのチェックと Git のワーキングコピーであるかどうかのチェックが両方走っていて、Git のチェックが重かったのが原因でした。

よって次の修正を加えています。

 --- /usr/share/zsh/4.3.12/functions/VCS_INFO_detect_git 2011-08-08 04:59:46.001000000 +0900
 +++ ./VCS_INFO_detect_git       2012-01-23 17:40:41.272189100 +0900
 @@ -6,8 +6,10 @@

  [[ $1 == '--flavours' ]] && { print -l git-p4 git-svn; return 0 }

 -if VCS_INFO_check_com ${vcs_comm[cmd]} && ${vcs_comm[cmd]} rev-parse --is-inside-work-tree &> /dev/null ; then
 -    vcs_comm[gitdir]="$(${vcs_comm[cmd]} rev-parse --git-dir 2> /dev/null)" || return 1
 +if VCS_INFO_check_com ${vcs_comm[cmd]} ; then
 +    local gitdir
 +    ${vcs_comm[cmd]} rev-parse --git-dir 2> /dev/null | read gitdir || return 1
 +    vcs_comm[gitdir]=$gitdir
      if   [[ -d ${vcs_comm[gitdir]}/svn ]]             ; then vcs_comm[overwrite_name]='git-svn'
      elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
      return 0

現在のディレクトリが Git の管理下にあるかどうかを調べているのですが、 git rev-parse --git-dir の戻り値をチェックすれば git rev-parse --is-inside-work-tree は不要だと思うので前者だけにしました。 コマンド置換が read になっているのは、ほぼ気分の問題です。(微妙に速くなってる気もしますが、大して変わりません)

おまけ

use-simple true の設定にするときは hexdump を忘れずに入れるようにしましょう。これがないと速くなりません。util-linux パッケージにあります。 (ただし、check-for-changes を有効にするときは use-simple false でないといけません)

まとめ

Cygwin 上で zsh の vcs_info の高速化を試みました。

  • vcs_info は使うシステムに対してのみ有効化すべきです。
  • Cygwin ではコマンド置換が遅いのでなるべく使わないようにすると速くなります。

この修正を加えたスクリプトは https://github.com/kyanagi/faster-vcs-info にあります。(zsh 4.3.12 のスクリプトを修正したものです)

使う際は適当なディレクトリに置いて、そのディレクトリを$fpath の頭の方(システムの vcs_info より優先されるように)に加えてください。


2005|02|03|04|05|06|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|03|04|05|06|10|
2008|04|10|
2009|10|
2010|05|08|
2012|01|02|03|
2014|01|
2022|05|
トップ 最新