とりあえず暇だったし何となく始めたブログ このページをアンテナに追加 RSSフィード

UNIX 系企業のぺーぺー

2011/12/22

[] EmacsSL

このエントリは、Emacs Advent Calendar jp 2011の22日目です。

前日は、id:dev-null さんの アーティストモードでメリークリスマス でした。

明日は、id:r_takaishi さんです。

概要

sl とは、UNIX の有名なジョークコマンドです。

ディレクトリの内容一覧を表示する ls と間違えて sl と打つと、SL 機関車アスキーアートが端末上をかけぬけます。

これを Emacs Lisp で作成してみました。

使用

EmacsWikiソースを置き、Launchpad の個人領域上に bzr リポジトリも作りました。以下より取得できます。

このファイルを load-path の通ったディレクトリに置き、以下のように読み込むだけ使えます。

(require 'sl)

使用方法は、M-x sl とするだけです。

画像

画像はこんな感じです。

f:id:khiker:20111223001508p:image

動画

動画をとって、ニコニコにアップしてみました。エンコードとか考えてないので、ちょっと見辛いです。

動画は、recordmydesktop の gtk 版でとってみました。

D

まとめ

ちょっと急ごしらえで問題があるかもしれませんが、よかったら遊んでみてくださいー。

リンク

更新時刻

  • 2011/12/23 00:16

2011/11/12

[] タイムアウトつき url-retrieve-synchronously

SKKML に書いた内容をブログにもメモしときます。


url-retrieve-synchronously は同期的に HTTP で指定した URL にアクセスすることができますが、相手サイトが重いと反応が中々返ってこず、Emacs が固まってしまいます。


その問題を解決するために、タイムアウトつきの url-retrieve-synchronously を作ってみました。

単純に run-with-timer で url-retrieve のプロセス監視するタイマを作り、タイマが励起されると url-retrieve のプロセスが殺される仕組みです。

タイマウトは、デフォルトで2秒で発生します。


(require 'url-http)

(defun my-url-retrieve-with-timeout (url coding-system &optional timeout-interval)
  (let ((url-max-redirections 0)	; URL リダイレクトを抑制する
	;; `url-retrieve' のためのコールバック関数
	(url-callback #'(lambda (status coding)
			  (let (p)
			    (setq done t)
			    (when (setq p (url-http-symbol-value-in-buffer
					   'url-http-end-of-headers
					   (current-buffer)))
			      (setq jsonp
				    (decode-coding-string
				     (buffer-substring (1+ p) (point-max))
				     coding))))))
	;; タイムアウト発生時に呼ばれるコールバック関数
	(timeout-callback #'(lambda ()
			      ;; `url-retrieve' のプロセスを止める
			      (when (processp proc)
				(delete-process proc))
			      ;; `url-retrieve' は終わったものと見做す
			      (unless done
				(setq done t))))
	;; タイムアウト時間
	(timeout-interval (if timeout-interval timeout-interval 2))
	(done nil)
	buf proc jsonp timeout)
    (unwind-protect
	;; condition-case を用いて全てのエラーを捕捉する。ここで、捕捉した
	;; エラーは無視する。開発、デバッグ時には condition-case のブロック
	;; を外す。
	(condition-case e
	    (when (setq buf
			(url-retrieve url url-callback (list coding-system)))
	      (setq proc (get-buffer-process buf)
		    ;; タイムアウト監視用の timer を設定する
		    timeout (run-with-timer timeout-interval timeout-interval
					    timeout-callback))
	      ;; `url-retrieve' は非同期なので、同期的に結果を得られるよ
	      ;; うに待ち合わせる。ここでは、
	      ;; `url-retrieve-synchronously' が行っていることとほぼ同等
	      ;; のことをしている。本関数では、URL リダイクレトはしない
	      ;; (はず)なので、URL リダイレクトに対する対策の部分のみ削除
	      ;; してある。
	      (while (null done)
		(when (and proc (memq (process-status proc)
				      '(closed exit signal failed))
			   (eq proc (or (get-buffer-process buf) proc)))
		  (delete-process proc)
		  (setq done t))
		(unless (or (with-local-quit
			      (accept-process-output proc))
			    (null proc))
		  (when quit-flag
		    (delete-process proc))
		  (setq proc (and (not quit-flag)
				  (get-buffer-process buf))))))
	  (error
	   ;; 全てのエラーは無視する
	   nil))
      (when (bufferp buf)
	(kill-buffer buf))
      ;; タイムアウト用の timer を削除する
      (when timeout
	(cancel-timer timeout)
	;; 一応、初期化をしておく
	(setq timeout nil)))
    jsonp))

利用例としては、social ime 相手に使うと以下のような感じです。

もし、2秒以内に social ime から応答が無ければ、my-url-retrieve-with-timeout は nil を返します。


(let ((url (concat "http://www.social-ime.com/api/"
		   "?string=" (url-hexify-string
			       (encode-coding-string "あ" 'utf-8))))
      res)
  (when (setq res (my-url-retrieve-with-timeout url 'euc-jp))
    (split-string (substring res 0 (1- (length res))) "\t" t)))
;; => ("亜" "唖" "娃" "阿" "蛙" "吾" "亞" "呀" "堊" "婀" "椏" "痾" "錏" "鐚" "閼" "鴉" "あ" "ア")

timeout の間隔を短くする場合、my-url-retrieve-with-timeout の第3引数に数値を指定します。

少数でもオッケーです。


(my-url-retrieve-with-timeout url 'euc-jp 0.5)


もっと上手いやり方があるだろうなーとか思いながら、そんなこんなで。

更新時刻

  • 2011/11/12 23:20

2011/09/23

[] 行頭と行の最初のインデント位置に移動を C-a でくりかえす

どこかで見たけれども、探すのが面倒だったので書いてみました。Emacs 24 でのみ動作をかくにん。

(global-set-key "\C-a" '(lambda (arg)
			  (interactive "^p")
			  (cond
			   ((bolp)
			    (call-interactively 'back-to-indentation))
			   (t
			    (move-beginning-of-line arg)))))

これで C-a を連打するだけで、「行頭」→「行の最初のインデント位置」→「行頭」以下繰り返しとなるはずー。

ただそれだけ。

更新時刻

- 2011/9/24/02:40

2011/05/08

[][] Gnus でメールの読み書き

Emacs 内でメールを読み書きしようとメーラの設定をしてみました。

以前一時期 Wanderlust を使っていましたが、今回は Wanderlust を選択せず gnus にしました。

選択理由は、最初から Emacs に入っているからです(また、高機能であるという話も耳にするし)。

f:id:khiker:20110508224106p:image


Gnus とは

ニュースリーダです。ニュースリーダって何といっても自分もよく知らないです。

NNTP というプロトコルを使って配信されるネットニュースを読むためのソフトウェアみたいです。

Gnus には、その機能の1つとして、メールを読む機能があります。


Gnus 自体は、随分前から Emacs に標準で入っています。少くとも 21.4 には既に入っていました。

Emacs 24 では、w3m を使った html レンダラが実装されてたりとかみたいです。

# その機能を使ってるかは知りませんが、実際に Twitter から送られてくる HTML メールも崩れる事なく見れました。


以下、自分が行った設定や普段やるであろう操作について書きます。

何か間違っている部分やもっと良い方法等あるのであれば、教えて頂けると幸いです。

初期設定

はじめての起動時にする初期設定

# 記憶で書いてるので間違ってるかもです…。でもプロセスとしてはこれでやりました。

  1. M-x gnus で gnus を起動
  2. 「^」キーでサーバモードへ以降
  3. 「{nnimap:gmail}」を選択
  4. GMail のラベル(Inbox 等)が全て表示されるので、購読したい項目を選択し、「u」を押し登録する。
  5. 購読したい項目の登録が終わったら、「q」を2度押して、グループモードに戻る。
  6. 購読した項目が追加されているので、「RET」で選択すれば読む事ができる。

これ以降は、M-x gnus した直後から購読した項目が読めるようになっている。

# M-x gnus をすると imap ユーザ名やパスワードを聞かれる。

# 現状における24の場合、ユーザ名も聞かれる。23.3 の場合は聞かれない。たぶん一時的なもの?

主なキー操作

詳しくは、info を参照。

# でかすぎて探しづらいけれども…。

  • M-x gnus … グループモードへ
  • グループモードから特定のラベル(メールボックス)を選択 … サマリモードへ
  • サマリモードから特定のメールを選択 … アーティクルモードへ
  • メールの作成 … メッセージモード
グループモード

ラベル(メールボックス?)の一覧を表示

  • g … 全ラベルの更新取得
  • M-g … ポイント上にあるラベル(特定のラベル)のみの更新を取得
  • RET … ポイント上のラベルにあるメール一覧を表示(サマリモードへ)
  • m … メールを作成
  • G G … ポイント上のラベル内にあるメールを検索
  • q … gnus の終了
サマリモード

選択したラベル(メールボックス)内にあるメールの一覧を表示

  • RET … 選択したメールを読む
  • n … 次のメールへ
  • m … メールを作成
  • r … 送信者へ返信
  • S W … メールを引用つきで全員へ返信
  • t … 詳細にヘッダの内容を表示するかどうかを切り替え
  • A T … スレッド全てのメールが表示されていないメールもそのスレッドのメールを取得・表示
  • B DEL … メールの削除(GMail ではアーカイブ)
  • O m (o 等)… メールの保存
  • q … グループモードへ戻る
メッセージモード

メールの作成

  • C-c C-k … 作成途中のメールを破棄
  • C-c C-c … メールの送信
  • C-c C-a … 添付ファイルの添付
  • C-c C-m o … PGP を使って、電子暗号化
  • C-c C-m p … PGP/MIME を使って、電子暗号化
  • C-M-i … To 欄で押すと、メールアドレスの補完(bbdb の機能)
  • q … グループモードへ戻る
アーティクルモード

メールの参照

  • o … 添付ファイルの保存
  • RET … 添付ファイルのインライン表示(表示可能であれば)
  • C … 添付ファイルの文字コード選択(添付がテキストファイルだったときのインライン表示時等)
  • i … 添付ファイルを現在のバッファ(アーティクルモード)に挿入(インライン表示)

感想

使えるようになるまではまりました。おおいにはまりました。

だいたい感じた事です。

  • 動作がちょっと重い
  • スレッド表示でメールの読み書きイイ
  • たいていのやりたいと思った事は、その機能自体や、その機能を実現するための枠組みがまずある
  • けど、非常に情報を探しづらくて、はまる。良く言えば機能が膨大すぎる

こんな感じです。使ってるうちにまた不満等出るかもしれませんが、

読むには不自由しなくなったので、これで生活してみようかなと思ってます。

設定

最後に自分の設定のせます。以下のようになりました。GMail + Imap です。

# 正規表現っぽくなってないメールアドレスは、なんとなくスパム対策に隠しました。それ以外はそのまま。


設定自体は、そんなにたいした事はしてはいないです。

良い設定とかあったら教えてください。

(require 'gnus)
(load "gnus-setup")
(require 'gnus-start)
(require 'gnus-art)
(require 'auth-source)
(require 'starttls)
(require 'nnimap)
(require 'nnir)

;; Username and mail address.
(setq user-full-name "HAMANO Kiyoto"
      user-mail-address "ほげほげ@gmail.com")

;; for reading mail by imap.
(setq gnus-select-method
      '(nnimap "gmail"
	       (nnimap-address "imap.gmail.com")
	       (nnimap-server-port 993)
	       (nnimap-authinfo-file "~/.emacs.d/.authinfo")
	       (nnimap-stream ssl)))

;; for sending mail.
(setq message-send-mail-function 'smtpmail-send-it
      send-mail-function 'smtpmail-send-it
      smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil))
      smtpmail-auth-credentials '(("smtp.gmail.com" 587
				   "ほげほげ@gmail.com" nil))
      smtpmail-default-smtp-server "smtp.gmail.com"
      smtpmail-smtp-server "smtp.gmail.com"
      smtpmail-smtp-service 587
      ;; Cc: and Bcc: to header of message-mode.
      message-default-mail-headers "Cc: \nBcc: \n")

;; customize `gnu-summary-line-foramt'.
(defvar my-gnus-mail-addres-regex "khiker\\.mail\\(\\+[^@]+\\)?@gmail\\.com"
  "*Regular expression of mail address that indicates for me.")

;; from http://emacs.wordpress.com/2007/10/07/gmail-envy/
;; and customize it.
(defun gnus-user-format-function-j (headers)
  "Return a \">\" if variable `my-gnus-mail-addres-regex' matches in To,
CC or Bcc. If not matched, return a \" \"."
  (cond
   ((or (string-match my-gnus-mail-addres-regex
		      (gnus-extra-header 'To headers))
	(string-match my-gnus-mail-addres-regex
		      (gnus-extra-header 'Cc headers))
	(string-match my-gnus-mail-addres-regex
		      (gnus-extra-header 'BCc headers)))
    ">")
   (t
    " ")))
(setq gnus-summary-line-format "%uj%U%R%I%(%[%-23,23f%]%) %s\n")

;; gnu-topic-mode by default
(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)

;; MUA is gnus.
(setq read-mail-command 'gnus
      mail-user-agent 'gnus-user-agent)

(setq ;; Do not use mailcrypt.
      gnus-use-mailcrypt nil
      gnus-check-new-newsgroups nil
      gnus-use-cache t
      gnus-cache-directory "~/Mail/cache/"
      gnus-cache-enter-articles '(ticked dormant read unread)
      gnus-cache-remove-articles nil
      gnus-cacheable-groups "^nnimap"
      gnus-posting-styles '((".*" (name "HAMANO Kiyoto")))
      ;; Do not split the mail when mail was large.
      mime-edit-split-message nil
      ;; treates wide character
      gnus-use-correct-string-widths t
      ;; Do not ask online or not.
      gnus-agent-go-online t
      ;; do not goto cursor to unread group.
      gnus-group-goto-unread nil
      ;; show also user-agent.
      gnus-visible-headers (concat gnus-visible-headers "\\|^User-Agent")
      ;; extra headers to parse.
      gnus-extra-headers '(To Newsgroups X-Newsreader
			      Content-Type CC User-Agent Gnus-Warning)
      nnmail-extra-headers gnus-extra-headers
      ;; If member of thread that includes new article has old
      ;; article, grab old articles to display thread.
      gnus-fetch-old-headers t)

;; Display always 500 articles at least in summary buffer.
(defvar my-gnus-summary-maximum-articles 500
  "*The recent X number of articles that displayed in summary-buffer
by use `gnus-topic-select-group' (RET) in gnus-group-buffer. The default
value is 500. The recent 500 articles are always displayed at least.")
(setq gnus-alter-articles-to-read-function
      #'(lambda (group articles)
	  (let ((active (gnus-active group)))
	    (delete-dups
	     (append articles
		     (gnus-uncompress-range
		      (cond
		       (my-gnus-summary-maximum-articles
			;; show `my-gnus-summary-maximum-articles' messages.
			(cons (max (car active)
				   (- (cdr active)
				      my-gnus-summary-maximum-articles
				      -1))
			      (cdr active)))
		       (t
			;; show always all messages.
			active))))))))

;; Gnus + EasyPG
(require 'epg-config)
(require 'gnus-msg)
(require 'mml2015)
(setq gnus-message-replysign t
      gnus-message-replyencrypt t
      gnus-message-replysignencrypted t
      mm-verify-option 'always
      mm-decrypt-option 'always
      mml2015-use 'epg
      mml2015-encrypt-to-self t
      mml2015-always-trust nil
      mml2015-cache-passphrase t
      mml2015-passphrase-cache-expiry '36000
      mml2015-sign-with-sender t
      gnus-buttonized-mime-types '("multipart/alternative"
				   "multipart/encrypted"
				   "multipart/signed"))

;; mail contacts list manager.
(require 'bbdb)
;; take mail address automatically
(setq bbdb/news-auto-create-p t)
;; add address automatically
(setq bbdb-always-add-addresses t)
;; do not use popup
(setq bbdb-use-pop-up nil)
;; my mail address
(setq bbdb-user-mail-names "khiker\\.mail@gmail\\.com")
(bbdb-initialize 'gnus 'message)

更新時刻

2011/05/08/22:45

[] windows.el に移行

GW 中に .emacs から .emacs.d/init.el に移行しました。やっと。

その際、.emacs の中身の精査をして、ちょっと不満があった elscreen から windows.el に乗り換えました。


設定

全然、特別なことはしてないですが、以下のようなにしてます。

(setq win:use-frame nil
      win:quick-selection nil
      ;; use a-z as prefix.
      win:base-key ?`
      win:switch-prefix "\C-z"
      win:max-configs 27)
(require 'windows)
(win:startup-with-window)
(define-key win:switch-map ";" 'win-switch-menu)
(define-key ctl-x-map "C" 'see-you-again)

elscreen では、10個までだったタブが、27個作れて良い感じです。

# C-z a, C-z b .... C-z z まで。

タブの表示が無いのはどうかなーと思ってましたが、意外と気になりませんでした。

むしろ elscreen のタブは、他の elisp でも同様の事をしている事が多く干渉する事がよくあるので、

表示させて無い方が良いのではないかなと思うようになりました。

参考

更新時刻

2011/05/08/22:45

[] emacs -q -l と initial-major-mode

.emacs から init.el に移行するにあたって、端末から以下のように起動してテストしていたのですが、

$ emacs -q -l init.el

どうしても、以下の設定が反映されないという現象に出会しました。

(setq initial-major-mode 'emacs-lisp-mode)

これは、*scratch* バッファの major-mode 設定で、上のようにすると *scratch* バッファが emacs-lisp-mode になるはずなのですが、ならない。lisp-interaction-mode のまま。


なぜだろうと思って調べてみると、以下のような事みたいです。

  • Emacs が起動 (normal-top-level) 関数が呼ばれる
  • .emacs や init.el の読み込み
  • initial-major-mode の値を見て、scratch バッファの major-mode を決める
  • コマンドライン引数の解析、処理をする (-q や -l の処理)

つまり、initial-major-mode の値を見て、*scratch* バッファの major-mode を決める処理は、コマンドライン引数解析より前にあるから、みたいです。


どうでもいいけど、はまりました。ただそれだけです。

更新時刻

  • 2011:05/08:23:30

2011/04/03

[] text-translator 開発版

今更ですが、text-translator 開発版を Launchpad 上で作ってます。

Launchpad なので、bzr で管理されてます。以下のようにしてソースコードを取ってこれます。

 $ bzr branch lp:~khiker/+junk/text-translator

or

 $ bzr clone bzr+ssh://launchpad/~khiker/+junk/text-translator

変更点をば少し。

  • 翻訳に失敗したら、「TRANSLATION: FAILED」と結果に表示するようにした。
  • サイトが重い等の理由で翻訳に時間がかかった場合、タイムアウトするようにした(デフォルト3秒)。
  • 翻訳結果の表示に pos-tip.el、popup.el も両方使えるようにした。
  • text-translator-all でも pos-tip.el、popup.el での表示を使えるようにした。
  • 翻訳結果のヒストリを変数 text-translator-all-history に保持するようにした。
  • テストコードを追加した。
  • 不要そうな機能を削除した(主に major-mode 関連)。
  • google.com で text-translator では未サポートだった言語を全て追加した(多すぎるのでテストはまだできてない…)。
  • exicte.co.jp で text-translator では未サポートだった言語を全て追加した。
  • livedoor.com が動かなくなっていたので、動くように修正し、また、新たに追加された言語を全てサポートした。
  • yahoo.co.jp が動かなくなり、現状の text-translator の枠組みでは再度サポートが難しいので、一旦未サポートとした。
  • 前回と同じエンジン(exite.co.jp で en -> ja 等)で同じ文字列だったならば、ヒストリにある結果をそのまま表示するようにした。

pos-tip や popup での翻訳結果の表示は、変数 text-translator-display-function に以下のように設定すればできるはず、です。

;; popup
(require 'text-translator-popup)
(setq text-translator-display-function 'text-translator-popup-display)
;; pos-tip
(require 'text-translator-pos-tip)
(setq text-translator-display-function 'text-translator-pos-tip-display)

今後のやりたい事です。

  • README.(ja|en) の追従
  • yahoo.co.jp の再度サポートする。
  • freetranslation.com で text-translator では現状未サポートの言語をサポートする。
  • HTTP リクエスト部のコードを分離する。
  • ヒストリ閲覧のためのインタフェースを何か作成する。
  • 何か新たに翻訳サイトを追加する(あれば)。
  • Makefile に deb ファイルを作成する枠組みの追加

他にも機能追加や新規にサポートして欲しいサイト等何か要望があれば、言っていただければ検討します。

# Emacs では実装が難しい等の理由てごめんなさいする場合もあるかもしれませんが…。

更新時刻

  • 2011年4月3日 21:40
  • 2011年4月4日 00:46

2011/03/27

[] Emacs23(以降) と 曖昧幅文字(East asian ambiguous)

Emacs23 以降の Unicode の曖昧幅文字取り扱いについてのメモです。


曖昧幅文字とは

環境によって、幅が1だったり、2だったりする文字のことで、具体的には、「○」とか「×」とか「α」とかそんな文字を指します。

CJK 環境だと、2 と解釈して欲しいけれども、それ以外の環境は、1と解釈して欲しかったりする文字です。


一覧としては、以下の URL のテキストで、A とついているものがそれにあたります。


Emacs23 での扱い

使っている環境に依存します。具体的には、以下の2つに依存します。

# 23 と書いてありますは、主に 24 で確認しています。やっている事は同じはずです。

  • 環境変数 LC_ALL、LC_CTYPE、LANG に何を設定しているか
  • set-language-environment で何を設定しているか

用は、自分の環境が CJK っぽい環境に設定されていると、曖昧幅文字が2となるように Emacs 側がやってくれます。

日本語 (Japanese) に環境を設定すると、以下のような感じです。

(set-language-environment "Japanese")
(char-width ?α)                        ; => 2 (#o2, #x2)
(char-width ?▽)                        ; => 2 (#o2, #x2)
(char-width ?×)                        ; => 2 (#o2, #x2)
(char-width ?○)                        ; => 2 (#o2, #x2)

英語 (English) に設定していると以下のような感じです。

(set-language-environment "English")
(char-width ?α)                         ; => 1 (#o1, #x1)
(char-width ?▽)                         ; => 1 (#o1, #x1)
(char-width ?×)                         ; => 1 (#o1, #x1)
(char-width ?○)                         ; => 1 (#o1, #x1)

上記と違って、もし set-language-environment で言語環境が設定されていなかった場合、Emacs は前述の3つの環境変数から、起動した環境が何なんのかを推定します。

例えば、環境変数 LANG に ja_JP.UTF-8 となっていた場合、以下のような処理で Japanese 環境であり、UTF-8 だと判断されます。

;; 言語環境
(locale-name-match (locale-translate "ja_JP.UTF-8")
                   locale-language-names) ; => ("Japanese" euc-jp)
;; 文字コード
(locale-name-match (locale-translate "ja_JP.UTF-8")
                   locale-charset-language-names) ; => "UTF-8"

これらは Emacs の起動時に呼ばれる関数 command-line 関数内で set-locale-environment という関数が呼ばれ、その中で自動で行われています。

# よって、LC_ALL= LC_CTYPE= LANG= emacs -Q とかやって起動すると、英語環境で Emacs が起動します。


また、set-language-environment が設定された場合、どこでどのように設定しているかについては、

Linux で Emacs 24 ならは,/usr/local/share/emacs/24.0.50/lisp/language/ 以下にある elisp に書かれています。

日本語環境だと、具体的には、以下のようになります。

  1. (get-language-info "Japanese" 'setup-function) で言語毎のセットアップ関数の取得。
  2. 取得したセットアップ関数の funcall (実行)。
  3. セットアップ関数内で文字幅表の更新を行う関数を呼び出す。

elisp 部分を抜粋すると以下のような感じです。

;; 1. セットアップ関数の取得
(get-language-info "Japanese" 'setup-function) ; => setup-japanese-environment-internal

;; 2. setup-japanese-environment-internal の実行
(defun setup-japanese-environment-internal ()
  ;; By default, we use 'japanese-iso-8bit for file names.  But, the
  ;; following prefer-coding-system will override it.
  (if (memq system-type '(windows-nt ms-dos cygwin))
      (prefer-coding-system 'japanese-shift-jis)
    (prefer-coding-system 'japanese-iso-8bit))
  (use-cjk-char-width-table 'ja_JP))

;; 3. use-cjk-char-width-table の実行
(use-cjk-char-width-table 'ja_JP)

上記のように use-cjk-char-width-table の実行に言語環境をつけており、日本語、中国語、韓国語別に文字幅の設定を行っています。

use-cjk-char-width-table 関数内では、以下のリストが参照され、曖昧幅文字に2が設定されます。

(defvar cjk-char-width-table-list
  '((ja_JP nil (japanese-jisx0208 (#x2121 . #x287E))
	       (cp932-2-byte (#x8140 . #x879F)))
    (zh_CN nil (chinese-gb2312 (#x2121 . #x297E)))
    (zh_HK nil (big5-hkscs (#xA140 . #xA3FE) (#xC6A0 . #xC8FE)))
    (zh_TW nil (big5 (#xA140 . #xA3FE))
	       (chinese-cns11643-1 (#x2121 . #x427E)))
    (ko_KR nil (korean-ksc5601 (#x2121 . #x2C7E)))))

全ての曖昧幅の文字を2に設定するのであれば、この方の行っている設定を真似すればよいかもしれません。


見た目上の長さ

上記のように、言語環境さえ設定していれば、曖昧幅の文字は自動で2でしくれますが、見た目上はそうなっていなかったりします。

例えば、VL ゴシックの場合、このように見えます。

f:id:khiker:20110327222002p:image

α が半角っぽく見えます。ただ、文字自体は、Emacs ではちゃんと幅2の文字であると認識されています。

これは、フォントが文字の幅をどうように扱うかであり、Emacs からどのくらい幅で見せるかを設定するという事はおそらくできないと思います。

# Emacs からできるとしたら、文字の大きさを変えるという事だけで、幅だけ変えるはおそらくできないように思います。

# もし、できるならやり方教えて下さいm(_ _)m


フォントの幅については、以下のブログの方が書かれているように、fontforge を使えば、確認や修正ができるようです。

  • ttp://d.hatena.ne.jp/tmtms/20091204/1259930572

なお、現在表示されている文字のフォントが何かを知るためには、その文字の上で、C-u C-x = とすれば分かります。


対処法としては、以下のどれかだと思います。

  • あきらめる
  • 文字毎にフォントを変えて頑張って対処する
  • 曖昧幅の文字が半角の倍の幅で見えるフォントを使う
  • フォント自体を改造してしまう。

どれを採用するかは好みになるんでしょうか…。



というような感じで以前調べた事をまとめてみました。

何か間違いがあったら、教えて頂けると嬉しいです。

更新時刻

  • 2011/3/27/22:20

2011/01/02

[][] skk-tankan.el を改造して遊ぶ - 読みと画数で候補を絞り込む

DDSKK の総画数変換、部首変換ができる skk-tankan.el の内容を読んでいて、ちょっと思い浮かんだので、少し改造して遊んでみましてた。


概要

「読み」+「画数」+「skk-tankan-search-key (デフォルトだと @)」で変換する事で指定した画数と読みを持つ語句のみを変換候補として出せます。

以下のような感じです。

▽りょう2@  ;; => 了
▽あ7@      ;; => 亜 吾

ただ、skk-tankan.el のデフォルトの機能として、「読み」+ 「skk-tankan-search-key (デフォルトだと @)」で画数で変換候補をソートして出せます。

# 画数の少い候補が先に出るようにソートされる。

そのため、この改造の機能を使用する場合は、おそらく、覚えている画数は少いものになると思うので、上記ソート機能で十分の場合がほとんどであまり嬉しくないかもです。

パッチ

小さいのでパッチをそのまま貼り付け。

patch -p0 < skk-tankan.el.patch みたいな感じであたる思います。

diff --git skk-tankan.el skk-tankan.el
index 34822a8..c297d8a 100644
--- skk-tankan.el
+++ skk-tankan.el
@@ -1698,11 +1698,12 @@ C-u 数値 M-x skk-tankan で総画数変換を開始する。"
   "変数 skk-henkan-key で指定された「読み」に基づいて単漢字変換を実行する。
 通常は skk-search-prog-list の1要素として次の形式で指定される。
 '(skk-tankan-search 'skk-search-jisyo-file
-                    skk-large-jisyo 10000))"
+		     skk-large-jisyo 10000))"
   (when (string-match (format "%s$" (regexp-quote
 				     (char-to-string skk-tankan-search-key)))
 		      skk-henkan-key)
-    (let ((skk-henkan-key (substring skk-henkan-key 0 (match-beginning 0))))
+    (let ((skk-henkan-key (substring skk-henkan-key 0 (match-beginning 0)))
+	  kakusu)
       ;; get KOUHO list
       (skk-tankan-select-tankanji-kouho
        (cons nil (cond
@@ -1715,12 +1716,25 @@ C-u 数値 M-x skk-tankan で総画数変換を開始する。"
 			  skk-henkan-key)
 		   (skk-search-by-stroke-or-radical
 		    (skk-tankan-bushu-compread) 0))
+		  ;; ▽あ7@ => 画数7で読みが「あ」の候補
+		  ((string-match "^\\(.*\\)\\([0-9]+\\)$" skk-henkan-key)
+		   (let ((num (match-string 2 skk-henkan-key))
+			 (skk-henkan-key (match-string 1 skk-henkan-key)))
+		     (setq kakusu (string-to-number num))
+		     (apply func args)))
 		  ;; ▽あ <SPC> => "読み"単漢字変換
 		  (t
-		   (apply func args))))))))
+		   (apply func args))))
+       kakusu))))
 
-(defun skk-tankan-select-tankanji-kouho (lis)
+(defun skk-tankan-select-tankanji-kouho (lis &optional kakusu)
   (let ((top lis)
+	(get-anno #'(lambda (cell)
+		      (format "%d画(%s部%d画)%s"
+			      (nth 4 cell)
+			      (aref skk-tankan-radical-vector (nth 2 cell))
+			      (nth 3 cell)
+			      (or (nth 1 cell) ""))))
 	tmp)
     ;; select TANKANJI KOUHO
       (while (cdr lis)
@@ -1747,21 +1761,29 @@ C-u 数値 M-x skk-tankan で総画数変換を開始する。"
 				    (< xb yb))
 				(< xa ya))
 			    (< xc yc))))))
-      ;; return list with annotation
-      (mapcar (lambda (cell)
-		(let ((anno (if (= 0 (nth 2 cell))
-				(nth 1 cell)
-			      (format "%d画(%s部%d画)%s"
-				      (nth 4 cell)
-				      (aref skk-tankan-radical-vector
-					    (nth 2 cell))
-				      (nth 3 cell)
-				      (or (nth 1 cell) "")
-				      ))))
-		  (if (= 0 (length anno))
-		      (char-to-string (car cell))
-		    (concat (char-to-string (car cell)) ";" anno))))
-	      lis)))
+      (cond
+       (kakusu
+	;; return list that extracted by KAKUSU.
+	(let (l)
+	  (dolist (i lis)
+	    (when (and (/= 0 (nth 2 i))
+		       (= kakusu (nth 4 i)))
+	      (let ((anno (funcall get-anno i)))
+		(setq l (cons (if (= 0 (length anno))
+				  (char-to-string (car i))
+				(concat (char-to-string (car i)) ";" anno))
+			      l)))))
+	  (nreverse l)))
+       (t
+	;; return list with annotation
+	(mapcar (lambda (cell)
+		  (let ((anno (if (= 0 (nth 2 cell))
+				  (nth 1 cell)
+				(funcall get-anno cell))))
+		    (if (= 0 (length anno))
+			(char-to-string (car cell))
+		      (concat (char-to-string (car cell)) ";" anno))))
+		lis)))))
 
 ;;;###autoload
 (defun skk-search-tankanji (&optional jisyo)


まあ、よかったらどうぞという感じで…。

更新時刻

  • 更新時刻 2011/01/03/04:55