1. use temporary buffer if current buffer does not have enough space
for it.
2. a few shortcuts like C-n/C-p and simple number to make it more or
less look like textmate UI.
> Oh! Awesome! I misunderstood dropdown-list.el. It is really cool!
> Cooler than popup another buffer window! :D
> 2008/3/16, Chiyuan Zhang <plus...@gmail.com>:
> > Hi! Nice job! I'm going to add support for this in yasnippet.
> > I noticed the author of dropdown-list.el is also Jay.
> > Maybe it's your work! So I would let user use this if
> > they downloaded the dropdown-list.el. I'm not goint to
> > included the source of dropdown-list.el as a part of
> > yasnippet because I think you will maintain and update
> > it constantly. :)
> > I searched through Google but seems no official address
> > to download this .el. And the code you paste here has
> > some problems (due to line-break of the email, maybe
> > paste as attachment will be better. :) ). However, you
> > might upload it to emacswiki (www.emacswiki.org). So
> > that I can give a link on the Tips page of yasnippet to
> > let users download this file.
> > BTW: maybe my personal taste: would it better to popup
> > another window below (like C-x 2) than to replace the
> > current window entirely?
> > 2008/3/14, jay <jay.ch...@gmail.com>:
> > > Hi folks,
> > > I really enjoy yasnippet mode. Since I usually use emacs in terminal
> > > mode, I cannot choose from a few candidates where there are multiple
> > > expansions for a single name.
> > > Here's my solution for it:
> > > (defun yas/popup-for-template (templates)
> > > (yas/template-content
> > > (cdr (nth (dropdown-list (mapcar (lambda (i) (yas/template-name
> > > (cdr i))) templates)) templates))))
> > > and the dropdown-list goes like this:
> > > ;;; dropdown-list.el --- dropdown menu interface
> > > ;; Copyright (C) 2008 Jaeyoun Chung
> > > ;; Author: jay at kldp DOT org
> > > ;; Keywords: convenience
> > > ;;
> > > ;; overlay code stolen from company-mode.el
> > > ;;
> > > ;;; Code:
> > > (defface dropdown-list-face
> > > '((t :inherit default
> > > :background "lightyellow"
> > > :foreground "black"))
> > > "*Bla."
> > > :group 'dropdown-list)
> > > (defface dropdown-list-selection-face
> > > '((t :inherit dropdown-list
> > > :background "purple"))
> > > "*Bla."
> > > :group 'dropdown-list)
> > > (defvar dropdown-list-overlays nil)
> > > (defun dropdown-list-hide ()
> > > (while dropdown-list-overlays
> > > (delete-overlay (pop dropdown-list-overlays))))
> > > (defun dropdown-list-put-overlay (beg end &optional prop value prop2
> > > value2)
> > > (let ((ov (make-overlay beg end)))
> > > (overlay-put ov 'window t)
> > > (when prop
> > > (overlay-put ov prop value)
> > > (when prop2
> > > (overlay-put ov prop2 value2)))
> > > ov))
> > > (defun dropdown-list-line (start replacement &optional no-insert)
> > > ;; start might be in the middle of a tab, which means we need to
> > > hide the
> > > ;; tab and add spaces
> > > (let ((end (+ start (length replacement)))
> > > beg-point end-point
> > > before-string after-string)
> > > (goto-char (point-at-eol))
> > > (if (< (current-column) start)
> > > (progn (setq before-string
> > > (make-string (- start (current-column)) ? ))
> > > (setq beg-point (point)))
> > > (goto-char (point-at-bol)) ;; Emacs bug, move-to-column is wrong
> > > otherwise
> > > (move-to-column start)
> > > (setq beg-point (point))
> > > (when (> (current-column) start)
> > > (goto-char (1- (point)))
> > > (setq beg-point (point))
> > > (setq before-string (make-string (- start (current-
> > > column)) ? ))))
> > > (move-to-column end)
> > > (setq end-point (point))
> > > (let ((end-offset (- (current-column) end)))
> > > (when (> end-offset 0)
> > > (setq after-string (make-string end-offset ?b))))
> > > (when no-insert
> > > ;; prevent inheriting of faces
> > > (setq before-string (when before-string
> > > (propertize before-string 'face
> > > 'default)))
> > > (setq after-string (when after-string
> > > (propertize after-string 'face 'default))))
> > > (let ((string (concat before-string
> > > replacement
> > > after-string)))
> > > (if no-insert
> > > string
> > > (push (dropdown-list-put-overlay beg-point end-point
> > > 'invisible t
> > > 'after-string string)
> > > dropdown-list-overlays)))))
> > > (defun dropdown-list-start-column (display-width)
> > > (let ((column (mod (current-column) (window-width)))
> > > (width (window-width)))
> > > (cond ((<= (+ column display-width) width)
> > > column)
> > > ((> column display-width)
> > > (- column display-width))
> > > ((>= width display-width)
> > > (- width display-width))
> > > (t
> > > nil))))
> > > (defun dropdown-list-move-to-start-line (candidate-count)
> > > (decf candidate-count)
> > > (let ((above-line-count (save-excursion (- (vertical-motion (-
> > > candidate-count)))))
> > > (below-line-count (save-excursion (vertical-motion candidate-
> > > count))))
> > > (cond ((= below-line-count candidate-count)
> > > t)
> > > ((= above-line-count candidate-count)
> > > (vertical-motion (- candidate-count))
> > > t)
> > > ((>= (+ below-line-count above-line-count) candidate-count)
> > > (vertical-motion (- (- candidate-count below-line-count)))
> > > t)
> > > (t
> > > nil))))
> > > (defun dropdown-list-at-point (candidates &optional selidx)
> > > (dropdown-list-hide)
> > > (let* ((lengths (mapcar #'length candidates))
> > > (max-length (apply #'max lengths))
> > > (start (dropdown-list-start-column (+ max-length 3)))
> > > (i -1)
> > > (candidates (mapcar* (lambda (candidate length)
> > > (let ((diff (- max-length length)))
> > > (propertize
> > > (concat (if (> diff 0)
> > > (concat candidate (make-string diff ? ))
> > > (substring candidate 0 max-length))
> > > (format "%3d" (+ 2 i)))
> > > 'face (if (eql (incf i) selidx)
> > > 'dropdown-list-selection-face
> > > 'dropdown-list-face))))
> > > candidates lengths)))
> > > (save-excursion
> > > (and start
> > > (dropdown-list-move-to-start-line (length candidates))
> > > (loop initially (vertical-motion 0)
> > > for candidate in candidates
> > > do (dropdown-list-line (+ (current-column) start) candidate)
> > > while (/= (vertical-motion 1) 0)
> > > finally return t)))))
> > > (defun dropdown-list (candidates)
> > > (let ((selection) (temp-buffer))
> > > (save-window-excursion
> > > (unwind-protect
> > > (let ((candidate-count (length candidates))
> > > done key selidx)
> > > (while (not done)
> > > (unless (dropdown-list-at-point candidates selidx)
> > > (switch-to-buffer (setq temp-buffer (get-buffer-create "
> > > *selection*")) 'norecord)
> > > (delete-other-windows)
> > > (delete-region (point-min) (point-max))
> > > (insert (make-string (length candidates) ?\n))
> > > (goto-char (point-min))
> > > (dropdown-list-at-point candidates selidx))
> > > (setq key (read-key-sequence ""))
> > > (cond ((and (stringp key) (>= (aref key 0) ?1) (<= (aref key 0)
> > > (+ ?0 (min 9 candidate-count))))
> > > (setq selection (- (aref key 0) ?1)
> > > done t))
> > > ((member key '(" " [up]))
> > > (setq selidx (mod (+ candidate-count (1- (or selidx 0)))
> > > candidate-count)))
> > > ((member key '(" " [down]))
> > > (setq selidx (mod (1+ (or selidx -1)) candidate-count)))
> > > ((member key '(" ")))
> > > ((member key '("
> > > " [return]))
> > > (setq selection selidx
> > > done t))
> > > (t
> > > (setq done t)))))
> > > (dropdown-list-hide)
> > > (and temp-buffer (kill-buffer temp-buffer)))
> > > ;; (when selection
> > > ;; (message "your selection => %d: %s" selection (nth
> > > selection candidates))
> > > ;; (sit-for 1))
> > > selection)))
> > > (provide