複数候補を選択して補完できる動的略語展開 dabbrev-expand-multiple (未完成)
まとまったエントリを作るべきか迷い中.
まあ, ある程度の状態になるまでは, 毎回エントリ作る形式で行こうと思う.
まだまだ問題点は山積みなわけやし.
plus さんが, メールで前回のものの更新版を送ってくれました.
変数にすべき部分や, 似たような処理を繰り返して部分が綺麗にまとめられていました.
ありがとうございます.
今回は, その plus さんが改良してくれたものに, tooltip を使えるようにしました.
けっこう良い感じです.
まだまだ完成にはほど遠いですが.
とりあえず, ソースをば.
;; -*- Coding: iso-2022-7bit -*- (autoload 'dabbrev--reset-global-variables "dabbrev" nil t) ;; (require 'dabbrev nil t) (defvar dabbrev-expand-multiple-select-key ;; '("^A" "^S" "^D" "^F" "^G") ;; キーを増やしていくと C-g に当たったためコントロール文字は避ける '("a" "s" "d")) (defvar dabbrev-expand-multiple-timeout 5) (defvar dabbrev-expand-multiple-tooltip-params nil) ;; ------------------------------------------------------------ ;; 設定例 ;; ------------------------------------------------------------ ;; ;; (setq dabbrev-expand-multiple-tooltip-params ;; '((foreground-color . "white") ;; (background-color . "navy blue") ;; (border-color . "royal blue"))) ;; (setq dabbrev-expand-multiple-select-key ;; '("a" "s" "d" "f" "g")) ;; ;; ------------------------------------------------------------ (defvar dabbrev-expand-multiple-use-tooltip t "ツールチップを使って表示するかどうか.") (defun dabbrev-expand-multiple () "動的略語展開において, 補完候補を複数掲示する関数. ミニバッファに候補を表示したまま, dabbrev-expand-multiple-timeout 秒間何もしないと, タイムアウトとなり, 関数の実行が終了する." (interactive) (when dabbrev-expand-multiple-use-tooltip (require 'tooltip)) (dabbrev--reset-global-variables) (let* ((target (dabbrev--abbrev-at-point)) (key (reverse dabbrev-expand-multiple-select-key)) (i (length key)) (prompt "") abbrev-list abbrev action sel) (while (and (> i 0) (setq abbrev (dabbrev--find-expansion target 0 dabbrev-case-fold-search))) (add-to-list 'abbrev-list abbrev t) (if dabbrev-expand-multiple-use-tooltip (setq prompt (format "%s(%s): %s\n" prompt (nth (1- i) key) abbrev)) (setq prompt (format "%s(%s): %s " prompt (nth (1- i) key) abbrev))) (setq i (1- i))) (cond (abbrev-list (if dabbrev-expand-multiple-use-tooltip (let* ((P (dabbrev-expand-multiple-mouse-position)) (frame (car P)) (x (cadr P)) (y (cddr P)) (oP (mouse-position)) (oframe (car oP)) (ox (cadr oP)) (oy (cddr oP))) (set-mouse-position frame x y) (dabbrev-expand-multiple-show-tooltip prompt) (setq action (read-char "" nil dabbrev-expand-multiple-timeout)) ;; 外部プログラムである unclutter を使ってマウスカーソルを隠していると, ;; 元のマウス位置が取得できず, エラーが出るので, その対策. (when (eq ox nil) (setq ox 0)) (when (eq oy nil) (setq oy 0)) (tooltip-hide) (set-mouse-position oframe ox oy)) (setq action (read-char prompt nil dabbrev-expand-multiple-timeout))) (setq sel (length (member (string (or action 0)) key))) (cond ;; 時間切れ ((not action) (message "Timeout")) ;; 独自拡張 ;; スペースで挿入 ;; ((eq action ? ) ;; (insert ;; (substring (nth 1 abbrev-list) (string-width target)))) ;; 独自拡張されたキー, dabbrev-expand-multiple-select-key 以外のキーが押された ((or (= sel 0) (> sel (length abbrev-list))) (message "Quit")) ;; 選択された文字を挿入 (t (insert (substring (nth (1- sel) abbrev-list) (string-width target)))))) (t (error "No dynamic expansion for `%s' found" target))))) (defun dabbrev-expand-multiple-show-tooltip (text) "ほぼ SKK の skk-tooltip-show-1 のコピー. 変数設定を dabbrev-expand-multiple-tooltip-params にしたのみ." (condition-case error (let ((params (copy-sequence tooltip-frame-parameters)) fg bg) (if dabbrev-expand-multiple-tooltip-params ;; ユーザが独自に tooltip 表示設定する (dolist (cell dabbrev-expand-multiple-tooltip-params) (setq params (tooltip-set-param params (car cell) (cdr cell)))) ;; tooltip のデフォルトの設定をする (setq fg (face-attribute 'tooltip :foreground)) (setq bg (face-attribute 'tooltip :background)) (when (stringp fg) (setq params (tooltip-set-param params 'foreground-color fg)) (setq params (tooltip-set-param params 'border-color fg))) (when (stringp bg) (setq params (tooltip-set-param params 'background-color bg)))) (unless (ignore-errors (or (get-text-property 0 'face text) (get-text-property 2 'face text))) (setq text (propertize text 'face 'tooltip))) (x-show-tip text (selected-frame) params dabbrev-expand-multiple-timeout tooltip-x-offset tooltip-y-offset)) (error (message "Error while displaying tooltip: %s" error) (sit-for 1) (message "%s" text)))) (defun dabbrev-expand-multiple-mouse-position () "Return the position of point as (FRAME X . Y). Analogous to mouse-position. SKK の skk-e21-mouse-position をほぼ流用. ミニバッファを振り分けていたのを消し, コメントを削除してしまったぐらい." (let* ((w (selected-window)) (edges (window-edges w)) (list (compute-motion (max (window-start w) (point-min)) '(0 . 0) (point) (cons (window-width w) (window-height w)) (1- (window-width w)) (cons (window-hscroll w) 0) w))) (cons (selected-frame) (cons (+ (car edges) (car (cdr list))) (+ (car (cdr edges)) (car (cdr (cdr list)))))))) ;; dabbrev.el ends here
候補選択に使うキーが, C-a, C-s, C-d ... から, a, s, d, f になっています.
これは, C-a, C-s ... と増やしていくと, いずれ, C-g にぶちあたるためです.
この件は, plus さんにより御指摘頂きました. ありがとうございます.
また, いくつか変数が追加されています.
代表的なものは, dabbrev-expand-multiple-use-tooltip で,
これが t だと tooltip を使用します.
他の変数については, 上記に設定例があります.
timeout は, 秒数です. デフォルトでは, 5秒でタイムアウトとなります.
使用例のスクリーンショットは, このようになります.
これは, 設定例の設定を適用している場合です.
このように表示されます.
tooltip は, マウスカーソルがある部分に表示されるので,
元のカーソル位置を記憶し, ポイント付近に移動, そして, 記憶しておいた元の場所に戻すという処理をしています.
これは, SKK が行っているもので, その処理をほぼそのまま持ってきました.
今後の予定は, 以下のようなものです.
- defvar を defcustom にする
- インライン表示を実装する
- 漢字変換のような補完候補のサイクルを実現する
- 補完元のハイライトをする.
インライン表示を優先的に実装したいと考えています.
これは, SKK によるものと同じです.
サンプルとして, SKKによる例を下にスクリーンショットで上げておきます.
これは, tooltip も同時に表示させています.
これが実装できれば,
tooltip が使えない環境でも使えるようになりので, より便利になりと思います.
それにしても, SKK ってやっぱりものすごくよく出来てるなあと思った. ほんと.
更新時刻
2007年, 7月29日, 2:53