一時的にvc-svnの機能を回避する

とくにMeadowで起こる問題。
TortoiseSVNCygwinsvnなど、一つのPCに複数のSubversionクライアントを設置している場合、それぞれのsvnのバージョンが異なると、TortoiseSVNでcheckoutしたコードをMeadowで編集して保存しようとしたときに、

svn: This client is too old to work with working copy 'yourfile'. You need
to get a newer Subversion client, or to downgrade this working copy.
See http://subversion.tigris.org/faq.html#working-copy-format-change
for details.

というふうに怒られ、保存すら許してくれない。このエラーメッセージが示すURLの先にworking copyをダウングレードするスクリプトが用意されているが、とりあえず変更を加えたコードを保存したかったので、場当たり的に次のような vc-svn (psvn) を無効化するコマンド を書いて実行した。

(defun toggle-svn-version-control ()
  (interactive)
  (if (featurep 'vc-hooks)
      (progn
	(unload-feature 'vc-hooks)
	(unload-feature 'vc-svn)
	(defun vc-before-save())
	(defun vc-after-save())
	(message "version control disabled.")
	)
    (progn
      (require 'vc-hooks)
      (require 'vc-svn)
      (message "version control enabled."))
  ))

かなり悪手であるのは承知のうえだけど、このtoggle-svn-version-controlを実行すればとりあえず保存はできるようになる。再度の実行で通常どおりのpsvnの機能が戻ってくる。

emacs終了前に確認を求める

小さなカイゼン
emacsを利用中、小指でCTRLキーを押しながら他の指がキーボード左下に触れてしまうことが多くあり、これがたまたまC-x C-cと引っかかってしまって意図せずにemacsを終了させてしまうことが何度かあった。

そこで、kill-emacs (save-buffers-kill-emacs) の実行時に「ホンマに終わってええの?」と確認してくれるように、次のコード片を.emacsに追加した。

(add-hook 'kill-emacs-query-functions
	  (function
	   (lambda ()
	     (y-or-n-p "Really quit emacs? ")
	     )))

正規表現で指定したファイルの文字コードを一括変換

emacsでファイルの文字コードを一括変換する方法は「http://www.bookshelf.jp/soft/meadow_25.html#SEC277」に先例があるが、いちいちdired で操作するのも面倒くさいので、正規表現でファイルを指定するものを用意した。
需要は低いだろな。

利用法

  1. M-x change-regexp-specified-file-coding-system
  2. 次の順番で尋ねてくるので、適宜答える
    1. 対象ディレクトリ名
    2. 対象ファイルの正規表現
      • 例えば".txt"な拡張子のファイルをすべて変換したいのであれば、「\.txt$」と答えればヨロシ。
    3. 変換前ファイルのバックアップを取るかどうか

注意

  • 動作はMeadowでのみ確認
  • 対象ファイルをemacsで開くときに、文字コードを指定しなくても(変換前の)ファイルが正しい文字コードで開ける場合のみを想定しており、例えばemacsで読み込んだ(find-file)あとにrevert-buffer-with-coding-system をやらないと正しく開けないようなファイルの場合は正しく変換されない
    • そんな破壊的な操作を含むので、事前にバックアップをとれるようにしたのであります。
  • バックアップを取るときに、bkupディレクトリ内に同名ファイルがある場合、そのファイルは新しいもので上書きされる。

Emacs Lispコード

.emacs に書く。

;=======================================================================
; 特定のファイルの文字コードを一括して変更する
;
;=======================================================================


(defun my-interactive-directory-query ()
  ;; moccur-grep-find を参考にした
  (let ((dir default-directory))
    (setq dir
          (if (and (boundp 'running-xemacs) running-xemacs)
              (read-directory-name "target directory: " dir)
            (read-file-name "target directory: " nil nil t)))
    (if (and (file-exists-p dir)
             (file-directory-p  dir))
        (setq dir (file-name-as-directory dir))
      (setq dir (file-name-as-directory (file-name-directory dir)))
      (if (and (file-exists-p dir)
               (file-directory-p  dir))
          ()
        (error (format "No such directory %s" dir))
        (sleep-for 1)
        (setq dir nil)))
    dir))

(defun change-regexp-spcified-file-coding-system (dir regexp coding-system do-bkup)
  "指定したディレクトリ内の、正規表現に該当するファイルの文字コードを変換する。
ただし文字コードを指定しなくても変換前のファイルが正しい文字コードで開ける場合のみを想定しており、これ以外の場合の動作は保証しない。"
  (interactive
   (list (my-interactive-directory-query)
	  (read-string "Filename Regexp: ")
	  (read-coding-system "New Coding System: ")
	  (y-or-n-p "Backup original?: ")))
  (let* (target-files (bkup-dir nil))
    (setq target-files
	  (directory-files dir nil regexp nil))
    (if do-bkup
	(progn
	  (setq bkup-dir (concat dir "bkup"))
	  (if (not				; in case the directory doesnt exist.
	       (and (file-exists-p bkup-dir)
		    (file-directory-p bkup-dir)))
	      (make-directory bkup-dir))
	  ))

    (let ((work-list target-files) work-buffer (counter 0) target-file-path)
      (while work-list
	(setq target-file-path (concat (expand-file-name dir) (car work-list)))
	(setq work-buffer
	      (find-file-noselect target-file-path))
	(if do-bkup
	    (copy-file target-file-path
		       (concat bkup-dir "/" (car work-list)) t t))
	(set-buffer work-buffer)
	(set-buffer-file-coding-system coding-system)
	(save-buffer)
	(kill-buffer work-buffer)
	(setq counter (1+ counter))
	(setq file-name-history (cdr file-name-history)) ;; ファイル名履歴をクリーンに保つ
	(setq work-list (cdr work-list))
	)
      (message (concat (int-to-string counter) " files converted."))
      )
    ))

一行あたりの文字数を指定して改行を挿入する

テキストを書いているときに、指定の文字数で改行を挿入する(指定数で折り返す、と言うのかな)、ていうことをコマンド一発でやりたかったので、簡単なものながら用意した。

;;; 一行あたりの文字数を指定してfill-region
(defun fill-region-with-N (num)
  ""
  (interactive "nfill-column value? ")
  (let ((fill-column num))
    (fill-region (region-beginning) (region-end)))
  )

上のコード片を .emacs に登録。

fill-region を利用してますんで、改行を挿入したい範囲(リージョン)を指定してから M-x fill-region-with-N を実行しておくんなまし。

OSX版FreeMindはATOKと相性が悪い → 解決

LeopardFreeMindをインストールしたが*1、日本語を入力することができない。不思議なのはFreeMindはOSを問わず幅広いユーザに利用されているにもかかわらず、同様の問題がほとんど報告されていないことだ。
OKWaveの「FreeMind OSX Tiger での日本語入力ができない MindMap 【OKWAVE】」という質問の回答にもあるとおり、原因はどうやらATOKFreeMindとの相性問題のようだ。ただしこの問題はOSX特有の問題なようで、WindowsXPでうまく動くことは確認済み。
この問題について詳しい情報をお持ちの方はぜひご一報を。

追記

id:Julianus さんのコメントをいただいて調べました。私のインストールしたバージョンは最新版ではなく 0.9.0 Beta18 でした (だってMac Universalなアーキテクチャを掲げているバイナリはこのバージョンが最新なんですもの)。
私の環境はIntelMacのLeopardですけど、PPCバイナリと掲げられている最新版のFreeMind_0.9.0_RC_3.dmg をインストールしてみたところ、私の環境下でも動作し、ATOKでも日本語入力することができましたよ。
id:Julianusさん、助かりました。

*1:実はインストールにも一手間かかった。詳しくは2008-11-02 - Julianus’s Blog

数を指定して各行の頭の空白を挿入/削除

デフォルトのEmacsでは、指定したスペース分だけインデントをする、ということができない。これは意外と不便だ。とくにテキストを書いているとき。
これに困ってこれを解決するElispを書いた人はおそらく世界で5万人ぐらいいるだろうが、検索するのが面倒くさいのでまた再発明をする。

(defun indent-rigidly-by-n (q)
  (interactive "nHow many colmns to indent by?:")
  (if (and transient-mark-mode mark-active)
      (indent-rigidly
       (region-beginning)
       (region-end)
       q)
    (error "No region selected.")
    ))

dot.emacsにでも書いてください。
インデントしたい箇所をリージョンで指定して M-x indent-rigidly-by-n すると「いくつ分インデントしますか」と聞いてきますんで、インデント量を入力ください。負の数を入れると逆インデントとなります。

追記 (2009.6.23)

上の再発明がなくても、Emacsの標準機能だけで実現できるじゃねーか。

C-u 数値 M-x indent-rigidly

C-u を使えばコマンドにパラメータを渡すことができるなんて、知らんかったよ。

beanstalkフリープランのストレージ容量が100MBに

Subversionレポジトリを提供しているbeanstalkの、Freeアカウントの容量が20MBから100MBに拡大されたようです。
1つのレポジトリを3ユーザで共有、という形式はこれまでと同じ。
http://beanstalkapp.com/pricing