Hatena::Groupemacs

はてなグループEmacs@kiwanami

 | 

2011-07-04

Emacs でドロップダウンリスト

19:07

emacs-devel に投稿した内容から。

Emacs上で、ドロップダウンもしくはポップアップして一覧から選択するインタフェースを実現するには、以下のものがある。

  • dropdown-list (dropdown-list.el)
  • popup-menu (mouse.el)
  • popup-menu* (popup.el)

各サンプルコードは後ろの方に掲載。

dropdown-list (dropdown-list.el)

yasnippet に付属。260行程度とコンパクト。APIもシンプル。

実装はオーバーレイテキストを使っているので、ターミナル環境でも使える。マウスでの選択は出来ない。

一方で、シンプルすぎて汎用的な目的には機能が若干足りない。特に、項目数が多いときは画面からはみ出てしまう。(一応専用バッファでのフォールバック機能があるみたい)

popup-menu (mouse.el)

標準でEmacsに付属。GUIポップアップメニューを出す。ターミナル環境では使えないが、マウスで選択が出来る。

通常のメニューと同じような構築をするので、Emacsのメニューをよく知っている人はすぐ使えるけども、知らない人にとってはちょっと複雑かもしれない。

popup-menu* (popup.el)

Auto-Complete で使われているもの。オーバーレイで描画しているため、ターミナル環境でも使える。マウスでの選択は出来ない。

コードは1000行ぐらいなので小さくはないけども、ポップアップメニューだけでなく、リッチな補完メニューとしての使用に耐えられるくらい機能がそろっている。

  • スクロールできるので項目が多くても大丈夫
  • インクリメンタルサーチで絞り込める
  • 入れ子のメニューも作れる
    • popup-menu も作れる
  • サマリー欄やドキュメント表示枠がある(Eclipse や VS で関数のヘルプが出るようなもの)

popup-menu* にマウスでの選択機能とかが標準で付けば一押しではないかと思っている。

;;; Simple popup menu comparing

(require 'dropdown-list)
(require 'popup)

(defvar ddtest-list 
  '("Dictaphone" "Dictaphone's" "dicta" "dicta's" "dictate" 
    "dictated" "dictates" "dictating" "dictation" "dictation's"
    "dictations" "dictator" "dictator's" "dictatorial" "dictators"
    "dictatorship" "dictatorship's" "dictatorships" "diction"
    "diction's" "dictionaries" "dictionary" "dictionary's" "dictum"
    "dictum's" "dictums"))


(defun ddtest-show-dropdown-list ()
  (interactive)
  (let ((num (dropdown-list ddtest-list)))
    (and num (insert (nth num ddtest-list)))))

(defun ddtest-show-x-popup-menu ()
  (interactive)
  (let* ((menu-map (make-sparse-keymap "Popup Test")) val)
    (mapc (lambda (x) 
            (lexical-let ((x x))
              (define-key menu-map 
                (vector (intern x))
                (cons x (lambda () (interactive) (insert x))))))
          ddtest-list)
    (popup-menu menu-map)))

(defun ddtest-show-popup-menu ()
  (interactive)
  (let ((val (popup-menu*
              (mapcar (lambda (x) 
                        (popup-make-item x :value x))
                      ddtest-list)
              :scroll-bar t)))
    (and val (insert val))))

;; Do it.

;; (ddtest-show-dropdown-list)
;; (ddtest-show-x-popup-menu)
;; (ddtest-show-popup-menu)

company-mode でのポップアップメニュー

@khiker さんから company-mode の情報を教えてもらいました。情報ありがとうございます!

company-modeは、 Auto-Complete のような、プラグイン的なシステムによって拡張可能な、高機能補完プログラムです。このプログラムはオーバーレイによる補完メニューを表示します。

元々補完専用なのですが、無理矢理メニューのように使う場合は以下のようになると思います。

(defun company-menu-backend (command &optional arg &rest ignored)
  (case command
    ('prefix "")
    ('candidates ddtest-list)
    ('sorted t)))

(defun company-menu ()
  (interactive)
  (company-begin-backend 'company-menu-backend
                         (lambda (item) (message item))))

;; (company-mode) ; マイナーモードON
;; (company-menu) ; ←メニュー表示

大量データ時のスクロール、絞り込み、ドキュメント表示など、 popup-menu* と同様な機能を持っています。

マウスでクリックできるところなど、機能的にはかなり頑張っています。余談ですがcompany-backendの拡張の仕方はメッセージパッシング的で面白いです。

ちょっと残念なのは、ポップアップメニューとして機能を切り出せないところとか、日本語幅を考慮してないようなので日本語を含むと表示が少し崩れてしまうところでしょうか。

 |