604 lines
24 KiB
EmacsLisp
604 lines
24 KiB
EmacsLisp
(require 'slime)
|
||
(require 'slime-repl)
|
||
(require 'slime-c-p-c)
|
||
(require 'cl-lib)
|
||
|
||
(define-slime-contrib slime-fuzzy
|
||
"Fuzzy symbol completion."
|
||
(:authors "Brian Downing <bdowning@lavos.net>"
|
||
"Tobias C. Rittweiler <tcr@freebits.de>"
|
||
"Attila Lendvai <attila.lendvai@gmail.com>")
|
||
(:license "GPL")
|
||
(:swank-dependencies swank-fuzzy)
|
||
(:on-load
|
||
(define-key slime-mode-map "\C-c\M-i" 'slime-fuzzy-complete-symbol)
|
||
(when (featurep 'slime-repl)
|
||
(define-key slime-repl-mode-map "\C-c\M-i"
|
||
'slime-fuzzy-complete-symbol))))
|
||
|
||
(defcustom slime-fuzzy-completion-in-place t
|
||
"When non-NIL the fuzzy symbol completion is done in place as
|
||
opposed to moving the point to the completion buffer."
|
||
:group 'slime-mode
|
||
:type 'boolean)
|
||
|
||
(defcustom slime-fuzzy-completion-limit 300
|
||
"Only return and present this many symbols from swank."
|
||
:group 'slime-mode
|
||
:type 'integer)
|
||
|
||
(defcustom slime-fuzzy-completion-time-limit-in-msec 1500
|
||
"Limit the time spent (given in msec) in swank while gathering
|
||
completions."
|
||
:group 'slime-mode
|
||
:type 'integer)
|
||
|
||
(defcustom slime-when-complete-filename-expand nil
|
||
"Use comint-replace-by-expanded-filename instead of
|
||
comint-filename-completion to complete file names"
|
||
:group 'slime-mode
|
||
:type 'boolean)
|
||
|
||
|
||
(defvar slime-fuzzy-target-buffer nil
|
||
"The buffer that is the target of the completion activities.")
|
||
(defvar slime-fuzzy-saved-window-configuration nil
|
||
"The saved window configuration before the fuzzy completion
|
||
buffer popped up.")
|
||
(defvar slime-fuzzy-start nil
|
||
"The beginning of the completion slot in the target buffer.
|
||
This is a non-advancing marker.")
|
||
(defvar slime-fuzzy-end nil
|
||
"The end of the completion slot in the target buffer.
|
||
This is an advancing marker.")
|
||
(defvar slime-fuzzy-original-text nil
|
||
"The original text that was in the completion slot in the
|
||
target buffer. This is what is put back if completion is
|
||
aborted.")
|
||
(defvar slime-fuzzy-text nil
|
||
"The text that is currently in the completion slot in the
|
||
target buffer. If this ever doesn't match, the target buffer has
|
||
been modified and we abort without touching it.")
|
||
(defvar slime-fuzzy-first nil
|
||
"The position of the first completion in the completions buffer.
|
||
The descriptive text and headers are above this.")
|
||
(defvar slime-fuzzy-last nil
|
||
"The position of the last completion in the completions buffer.
|
||
If the time limit has exhausted during generation possible completion
|
||
choices inside SWANK, an indication is printed below this.")
|
||
(defvar slime-fuzzy-current-completion nil
|
||
"The current completion object. If this is the same before and
|
||
after point moves in the completions buffer, the text is not
|
||
replaced in the target for efficiency.")
|
||
(defvar slime-fuzzy-current-completion-overlay nil
|
||
"The overlay representing the current completion in the completion
|
||
buffer. This is used to hightlight the text.")
|
||
|
||
;;;;;;; slime-target-buffer-fuzzy-completions-mode
|
||
;; NOTE: this mode has to be able to override key mappings in slime-mode
|
||
|
||
(defvar slime-target-buffer-fuzzy-completions-map
|
||
(let ((map (make-sparse-keymap)))
|
||
(cl-labels ((def (keys command)
|
||
(unless (listp keys)
|
||
(setq keys (list keys)))
|
||
(dolist (key keys)
|
||
(define-key map key command))))
|
||
(def `([remap keyboard-quit]
|
||
,(kbd "C-g"))
|
||
'slime-fuzzy-abort)
|
||
(def `([remap slime-fuzzy-indent-and-complete-symbol]
|
||
[remap slime-indent-and-complete-symbol]
|
||
,(kbd "<tab>"))
|
||
'slime-fuzzy-select-or-update-completions)
|
||
(def `([remap previous-line]
|
||
,(kbd "<up>"))
|
||
'slime-fuzzy-prev)
|
||
(def `([remap next-line]
|
||
,(kbd "<down>"))
|
||
'slime-fuzzy-next)
|
||
(def `([remap isearch-forward]
|
||
,(kbd "C-s"))
|
||
'slime-fuzzy-continue-isearch-in-fuzzy-buffer)
|
||
;; some unconditional direct bindings
|
||
(def (list (kbd "<return>") (kbd "RET") (kbd "<SPC>") "(" ")" "[" "]")
|
||
'slime-fuzzy-select-and-process-event-in-target-buffer))
|
||
map)
|
||
"Keymap for slime-target-buffer-fuzzy-completions-mode.
|
||
This will override the key bindings in the target buffer
|
||
temporarily during completion.")
|
||
|
||
;; Make sure slime-fuzzy-target-buffer-completions-mode's map is
|
||
;; before everything else.
|
||
(setf minor-mode-map-alist
|
||
(cl-stable-sort minor-mode-map-alist
|
||
(lambda (a b)
|
||
(eq a 'slime-fuzzy-target-buffer-completions-mode))
|
||
:key #'car))
|
||
|
||
(defun slime-fuzzy-continue-isearch-in-fuzzy-buffer ()
|
||
(interactive)
|
||
(select-window (get-buffer-window (slime-get-fuzzy-buffer)))
|
||
(call-interactively 'isearch-forward))
|
||
|
||
(define-minor-mode slime-fuzzy-target-buffer-completions-mode
|
||
"This minor mode is intented to override key bindings during
|
||
fuzzy completions in the target buffer. Most of the bindings will
|
||
do an implicit select in the completion window and let the
|
||
keypress be processed in the target buffer."
|
||
nil
|
||
nil
|
||
slime-target-buffer-fuzzy-completions-map)
|
||
|
||
(add-to-list 'minor-mode-alist
|
||
'(slime-fuzzy-target-buffer-completions-mode
|
||
" Fuzzy Target Buffer Completions"))
|
||
|
||
(defvar slime-fuzzy-completions-map
|
||
(let ((map (make-sparse-keymap)))
|
||
(cl-labels ((def (keys command)
|
||
(unless (listp keys)
|
||
(setq keys (list keys)))
|
||
(dolist (key keys)
|
||
(define-key map key command))))
|
||
(def `([remap keyboard-quit]
|
||
"q"
|
||
,(kbd "C-g"))
|
||
'slime-fuzzy-abort)
|
||
(def `([remap previous-line]
|
||
"p"
|
||
"\M-p"
|
||
,(kbd "<up>"))
|
||
'slime-fuzzy-prev)
|
||
(def `([remap next-line]
|
||
"n"
|
||
"\M-n"
|
||
,(kbd "<down>"))
|
||
'slime-fuzzy-next)
|
||
(def "\d" 'scroll-down)
|
||
(def `([remap slime-fuzzy-indent-and-complete-symbol]
|
||
[remap slime-indent-and-complete-symbol]
|
||
,(kbd "<tab>"))
|
||
'slime-fuzzy-select)
|
||
(def (kbd "<mouse-2>") 'slime-fuzzy-select/mouse)
|
||
(def `(,(kbd "RET")
|
||
,(kbd "<SPC>"))
|
||
'slime-fuzzy-select))
|
||
map)
|
||
"Keymap for slime-fuzzy-completions-mode when in the completion buffer.")
|
||
|
||
(define-derived-mode slime-fuzzy-completions-mode
|
||
fundamental-mode "Fuzzy Completions"
|
||
"Major mode for presenting fuzzy completion results.
|
||
|
||
When you run `slime-fuzzy-complete-symbol', the symbol token at
|
||
point is completed using the Fuzzy Completion algorithm; this
|
||
means that the token is taken as a sequence of characters and all
|
||
the various possibilities that this sequence could meaningfully
|
||
represent are offered as selectable choices, sorted by how well
|
||
they deem to be a match for the token. (For instance, the first
|
||
choice of completing on \"mvb\" would be \"multiple-value-bind\".)
|
||
|
||
Therefore, a new buffer (*Fuzzy Completions*) will pop up that
|
||
contains the different completion choices. Simultaneously, a
|
||
special minor-mode will be temporarily enabled in the original
|
||
buffer where you initiated fuzzy completion (also called the
|
||
``target buffer'') in order to navigate through the *Fuzzy
|
||
Completions* buffer without leaving.
|
||
|
||
With focus in *Fuzzy Completions*:
|
||
Type `n' and `p' (`UP', `DOWN') to navigate between completions.
|
||
Type `RET' or `TAB' to select the completion near point.
|
||
Type `q' to abort.
|
||
|
||
With focus in the target buffer:
|
||
Type `UP' and `DOWN' to navigate between completions.
|
||
Type a character that does not constitute a symbol name
|
||
to insert the current choice and then that character (`(', `)',
|
||
`SPACE', `RET'.) Use `TAB' to simply insert the current choice.
|
||
Use C-g to abort.
|
||
|
||
Alternatively, you can click <mouse-2> on a completion to select it.
|
||
|
||
|
||
Complete listing of keybindings within the target buffer:
|
||
|
||
\\<slime-target-buffer-fuzzy-completions-map>\
|
||
\\{slime-target-buffer-fuzzy-completions-map}
|
||
|
||
Complete listing of keybindings with *Fuzzy Completions*:
|
||
|
||
\\<slime-fuzzy-completions-map>\
|
||
\\{slime-fuzzy-completions-map}"
|
||
(use-local-map slime-fuzzy-completions-map)
|
||
(set (make-local-variable 'slime-fuzzy-current-completion-overlay)
|
||
(make-overlay (point) (point) nil t nil)))
|
||
|
||
(defun slime-fuzzy-completions (prefix &optional default-package)
|
||
"Get the list of sorted completion objects from completing
|
||
`prefix' in `package' from the connected Lisp."
|
||
(let ((prefix (cl-etypecase prefix
|
||
(symbol (symbol-name prefix))
|
||
(string prefix))))
|
||
(slime-eval `(swank:fuzzy-completions ,prefix
|
||
,(or default-package
|
||
(slime-current-package))
|
||
:limit ,slime-fuzzy-completion-limit
|
||
:time-limit-in-msec
|
||
,slime-fuzzy-completion-time-limit-in-msec))))
|
||
|
||
(defun slime-fuzzy-selected (prefix completion)
|
||
"Tell the connected Lisp that the user selected completion
|
||
`completion' as the completion for `prefix'."
|
||
(let ((no-properties (copy-sequence prefix)))
|
||
(set-text-properties 0 (length no-properties) nil no-properties)
|
||
(slime-eval `(swank:fuzzy-completion-selected ,no-properties
|
||
',completion))))
|
||
|
||
(defun slime-fuzzy-indent-and-complete-symbol ()
|
||
"Indent the current line and perform fuzzy symbol completion. First
|
||
indent the line. If indenting doesn't move point, complete the
|
||
symbol. If there's no symbol at the point, show the arglist for the
|
||
most recently enclosed macro or function."
|
||
(interactive)
|
||
(let ((pos (point)))
|
||
(unless (get-text-property (line-beginning-position) 'slime-repl-prompt)
|
||
(lisp-indent-line))
|
||
(when (= pos (point))
|
||
(cond ((save-excursion (re-search-backward "[^() \n\t\r]+\\=" nil t))
|
||
(slime-fuzzy-complete-symbol))
|
||
((memq (char-before) '(?\t ?\ ))
|
||
(slime-echo-arglist))))))
|
||
|
||
(cl-defun slime-fuzzy-complete-symbol ()
|
||
"Fuzzily completes the abbreviation at point into a symbol."
|
||
(interactive)
|
||
(when (save-excursion (re-search-backward "\"[^ \t\n]+\\=" nil t))
|
||
(cl-return-from slime-fuzzy-complete-symbol
|
||
;; don't add space after completion
|
||
(let ((comint-completion-addsuffix '("/" . "")))
|
||
(if slime-when-complete-filename-expand
|
||
(comint-replace-by-expanded-filename)
|
||
;; FIXME: use `comint-filename-completion' when dropping emacs23
|
||
(funcall (if (>= emacs-major-version 24)
|
||
'comint-filename-completion
|
||
'comint-dynamic-complete-as-filename))))))
|
||
(let* ((end (move-marker (make-marker) (slime-symbol-end-pos)))
|
||
(beg (move-marker (make-marker) (slime-symbol-start-pos)))
|
||
(prefix (buffer-substring-no-properties beg end)))
|
||
(cl-destructuring-bind (completion-set interrupted-p)
|
||
(slime-fuzzy-completions prefix)
|
||
(if (null completion-set)
|
||
(progn (slime-minibuffer-respecting-message
|
||
"Can't find completion for \"%s\"" prefix)
|
||
(ding)
|
||
(slime-fuzzy-done))
|
||
(goto-char end)
|
||
(cond ((slime-length= completion-set 1)
|
||
;; insert completed string
|
||
(insert-and-inherit (caar completion-set))
|
||
(delete-region beg end)
|
||
(goto-char (+ beg (length (caar completion-set))))
|
||
(slime-minibuffer-respecting-message "Sole completion")
|
||
(slime-fuzzy-done))
|
||
;; Incomplete
|
||
(t
|
||
(slime-fuzzy-choices-buffer completion-set interrupted-p
|
||
beg end)
|
||
(slime-minibuffer-respecting-message
|
||
"Complete but not unique")))))))
|
||
|
||
|
||
(defun slime-get-fuzzy-buffer ()
|
||
(get-buffer-create "*Fuzzy Completions*"))
|
||
|
||
(defvar slime-fuzzy-explanation
|
||
"For help on how the use this buffer, see `slime-fuzzy-completions-mode'.
|
||
|
||
Flags: boundp fboundp generic-function class macro special-operator package
|
||
\n"
|
||
"The explanation that gets inserted at the beginning of the
|
||
*Fuzzy Completions* buffer.")
|
||
|
||
(defun slime-fuzzy-insert-completion-choice (completion max-length)
|
||
"Inserts the completion object `completion' as a formatted
|
||
completion choice into the current buffer, and mark it with the
|
||
proper text properties."
|
||
(cl-destructuring-bind (symbol-name score chunks classification-string)
|
||
completion
|
||
(let ((start (point))
|
||
(end))
|
||
(insert symbol-name)
|
||
(setq end (point))
|
||
(dolist (chunk chunks)
|
||
(put-text-property (+ start (cl-first chunk))
|
||
(+ start (cl-first chunk)
|
||
(length (cl-second chunk)))
|
||
'face 'bold))
|
||
(put-text-property start (point) 'mouse-face 'highlight)
|
||
(dotimes (i (- max-length (- end start)))
|
||
(insert " "))
|
||
(insert (format " %s %s\n"
|
||
classification-string
|
||
score))
|
||
(put-text-property start (point) 'completion completion))))
|
||
|
||
(defun slime-fuzzy-insert (text)
|
||
"Inserts `text' into the target buffer in the completion slot.
|
||
If the buffer has been modified in the meantime, abort the
|
||
completion process. Otherwise, update all completion variables
|
||
so that the new text is present."
|
||
(with-current-buffer slime-fuzzy-target-buffer
|
||
(cond
|
||
((not (string-equal slime-fuzzy-text
|
||
(buffer-substring slime-fuzzy-start
|
||
slime-fuzzy-end)))
|
||
(slime-fuzzy-done)
|
||
(beep)
|
||
(message "Target buffer has been modified!"))
|
||
(t
|
||
(goto-char slime-fuzzy-start)
|
||
(delete-region slime-fuzzy-start slime-fuzzy-end)
|
||
(insert-and-inherit text)
|
||
(setq slime-fuzzy-text text)
|
||
(goto-char slime-fuzzy-end)))))
|
||
|
||
(defun slime-minibuffer-p (buffer)
|
||
(if (featurep 'xemacs)
|
||
(eq buffer (window-buffer (minibuffer-window)))
|
||
(minibufferp buffer)))
|
||
|
||
(defun slime-fuzzy-choices-buffer (completions interrupted-p start end)
|
||
"Creates (if neccessary), populates, and pops up the *Fuzzy
|
||
Completions* buffer with the completions from `completions' and
|
||
the completion slot in the current buffer bounded by `start' and
|
||
`end'. This saves the window configuration before popping the
|
||
buffer so that it can possibly be restored when the user is
|
||
done."
|
||
(let ((new-completion-buffer (not slime-fuzzy-target-buffer))
|
||
(connection (slime-connection)))
|
||
(when new-completion-buffer
|
||
(setq slime-fuzzy-saved-window-configuration
|
||
(current-window-configuration)))
|
||
(slime-fuzzy-enable-target-buffer-completions-mode)
|
||
(setq slime-fuzzy-target-buffer (current-buffer))
|
||
(setq slime-fuzzy-start (move-marker (make-marker) start))
|
||
(setq slime-fuzzy-end (move-marker (make-marker) end))
|
||
(set-marker-insertion-type slime-fuzzy-end t)
|
||
(setq slime-fuzzy-original-text (buffer-substring start end))
|
||
(setq slime-fuzzy-text slime-fuzzy-original-text)
|
||
(slime-fuzzy-fill-completions-buffer completions interrupted-p)
|
||
(pop-to-buffer (slime-get-fuzzy-buffer))
|
||
(slime-fuzzy-next)
|
||
(setq slime-buffer-connection connection)
|
||
(when new-completion-buffer
|
||
;; Hook to nullify window-config restoration if the user changes
|
||
;; the window configuration himself.
|
||
(when (boundp 'window-configuration-change-hook)
|
||
(add-hook 'window-configuration-change-hook
|
||
'slime-fuzzy-window-configuration-change))
|
||
(add-hook 'kill-buffer-hook 'slime-fuzzy-abort 'append t)
|
||
(set (make-local-variable 'cursor-type) nil)
|
||
(setq buffer-quit-function 'slime-fuzzy-abort)) ; M-Esc Esc
|
||
(when slime-fuzzy-completion-in-place
|
||
;; switch back to the original buffer
|
||
(if (slime-minibuffer-p slime-fuzzy-target-buffer)
|
||
(select-window (minibuffer-window))
|
||
(switch-to-buffer-other-window slime-fuzzy-target-buffer)))))
|
||
|
||
(defun slime-fuzzy-fill-completions-buffer (completions interrupted-p)
|
||
"Erases and fills the completion buffer with the given completions."
|
||
(with-current-buffer (slime-get-fuzzy-buffer)
|
||
(setq buffer-read-only nil)
|
||
(erase-buffer)
|
||
(slime-fuzzy-completions-mode)
|
||
(insert slime-fuzzy-explanation)
|
||
(let ((max-length 12))
|
||
(dolist (completion completions)
|
||
(setf max-length (max max-length (length (cl-first completion)))))
|
||
|
||
(insert "Completion:")
|
||
(dotimes (i (- max-length 10)) (insert " "))
|
||
;; Flags: Score:
|
||
;; ... ------- --------
|
||
;; bfgctmsp
|
||
(let* ((example-classification-string (cl-fourth (cl-first completions)))
|
||
(classification-length (length example-classification-string))
|
||
(spaces (- classification-length (length "Flags:"))))
|
||
(insert "Flags:")
|
||
(dotimes (i spaces) (insert " "))
|
||
(insert " Score:\n")
|
||
(dotimes (i max-length) (insert "-"))
|
||
(insert " ")
|
||
(dotimes (i classification-length) (insert "-"))
|
||
(insert " --------\n")
|
||
(setq slime-fuzzy-first (point)))
|
||
|
||
(dolist (completion completions)
|
||
(setq slime-fuzzy-last (point)) ; will eventually become the last entry
|
||
(slime-fuzzy-insert-completion-choice completion max-length))
|
||
|
||
(when interrupted-p
|
||
(insert "...\n")
|
||
(insert "[Interrupted: time limit exhausted]"))
|
||
|
||
(setq buffer-read-only t))
|
||
(setq slime-fuzzy-current-completion
|
||
(caar completions))
|
||
(goto-char 0)))
|
||
|
||
(defun slime-fuzzy-enable-target-buffer-completions-mode ()
|
||
"Store the target buffer's local map, so that we can restore it."
|
||
(unless slime-fuzzy-target-buffer-completions-mode
|
||
; (slime-log-event "Enabling target buffer completions mode")
|
||
(slime-fuzzy-target-buffer-completions-mode 1)))
|
||
|
||
(defun slime-fuzzy-disable-target-buffer-completions-mode ()
|
||
"Restores the target buffer's local map when completion is finished."
|
||
(when slime-fuzzy-target-buffer-completions-mode
|
||
; (slime-log-event "Disabling target buffer completions mode")
|
||
(slime-fuzzy-target-buffer-completions-mode 0)))
|
||
|
||
(defun slime-fuzzy-insert-from-point ()
|
||
"Inserts the completion that is under point in the completions
|
||
buffer into the target buffer. If the completion in question had
|
||
already been inserted, it does nothing."
|
||
(with-current-buffer (slime-get-fuzzy-buffer)
|
||
(let ((current-completion (get-text-property (point) 'completion)))
|
||
(when (and current-completion
|
||
(not (eq slime-fuzzy-current-completion
|
||
current-completion)))
|
||
(slime-fuzzy-insert
|
||
(cl-first (get-text-property (point) 'completion)))
|
||
(setq slime-fuzzy-current-completion
|
||
current-completion)))))
|
||
|
||
(defun slime-fuzzy-post-command-hook ()
|
||
"The post-command-hook for the *Fuzzy Completions* buffer.
|
||
This makes sure the completion slot in the target buffer matches
|
||
the completion that point is on in the completions buffer."
|
||
(condition-case err
|
||
(when slime-fuzzy-target-buffer
|
||
(slime-fuzzy-insert-from-point))
|
||
(error
|
||
;; Because this is called on the post-command-hook, we mustn't let
|
||
;; errors propagate.
|
||
(message "Error in slime-fuzzy-post-command-hook: %S" err))))
|
||
|
||
(defun slime-fuzzy-next ()
|
||
"Moves point directly to the next completion in the completions
|
||
buffer."
|
||
(interactive)
|
||
(with-current-buffer (slime-get-fuzzy-buffer)
|
||
(let ((point (next-single-char-property-change
|
||
(point) 'completion nil slime-fuzzy-last)))
|
||
(set-window-point (get-buffer-window (current-buffer)) point)
|
||
(goto-char point))
|
||
(slime-fuzzy-highlight-current-completion)))
|
||
|
||
(defun slime-fuzzy-prev ()
|
||
"Moves point directly to the previous completion in the
|
||
completions buffer."
|
||
(interactive)
|
||
(with-current-buffer (slime-get-fuzzy-buffer)
|
||
(let ((point (previous-single-char-property-change
|
||
(point)
|
||
'completion nil slime-fuzzy-first)))
|
||
(set-window-point (get-buffer-window (current-buffer)) point)
|
||
(goto-char point))
|
||
(slime-fuzzy-highlight-current-completion)))
|
||
|
||
(defun slime-fuzzy-highlight-current-completion ()
|
||
"Highlights the current completion,
|
||
so that the user can see it on the screen."
|
||
(let ((pos (point)))
|
||
(when (overlayp slime-fuzzy-current-completion-overlay)
|
||
(move-overlay slime-fuzzy-current-completion-overlay
|
||
(point) (1- (search-forward " ")))
|
||
(overlay-put slime-fuzzy-current-completion-overlay
|
||
'face 'secondary-selection))
|
||
(goto-char pos)))
|
||
|
||
(defun slime-fuzzy-abort ()
|
||
"Aborts the completion process, setting the completions slot in
|
||
the target buffer back to its original contents."
|
||
(interactive)
|
||
(when slime-fuzzy-target-buffer
|
||
(slime-fuzzy-done)))
|
||
|
||
(defun slime-fuzzy-select ()
|
||
"Selects the current completion, making sure that it is inserted
|
||
into the target buffer. This tells the connected Lisp what completion
|
||
was selected."
|
||
(interactive)
|
||
(when slime-fuzzy-target-buffer
|
||
(with-current-buffer (slime-get-fuzzy-buffer)
|
||
(let ((completion (get-text-property (point) 'completion)))
|
||
(when completion
|
||
(slime-fuzzy-insert (cl-first completion))
|
||
(slime-fuzzy-selected slime-fuzzy-original-text
|
||
completion)
|
||
(slime-fuzzy-done))))))
|
||
|
||
(defun slime-fuzzy-select-or-update-completions ()
|
||
"If there were no changes since the last time fuzzy completion was started
|
||
this function will select the current completion.
|
||
Otherwise refreshes the completion list based on the changes made."
|
||
(interactive)
|
||
; (slime-log-event "Selecting or updating completions")
|
||
(if (string-equal slime-fuzzy-original-text
|
||
(buffer-substring slime-fuzzy-start
|
||
slime-fuzzy-end))
|
||
(slime-fuzzy-select)
|
||
(slime-fuzzy-complete-symbol)))
|
||
|
||
(defun slime-fuzzy-process-event-in-completions-buffer ()
|
||
"Simply processes the event in the target buffer"
|
||
(interactive)
|
||
(with-current-buffer (slime-get-fuzzy-buffer)
|
||
(push last-input-event unread-command-events)))
|
||
|
||
(defun slime-fuzzy-select-and-process-event-in-target-buffer ()
|
||
"Selects the current completion, making sure that it is inserted
|
||
into the target buffer and processes the event in the target buffer."
|
||
(interactive)
|
||
; (slime-log-event "Selecting and processing event in target buffer")
|
||
(when slime-fuzzy-target-buffer
|
||
(let ((buff slime-fuzzy-target-buffer))
|
||
(slime-fuzzy-select)
|
||
(with-current-buffer buff
|
||
(slime-fuzzy-disable-target-buffer-completions-mode)
|
||
(push last-input-event unread-command-events)))))
|
||
|
||
(defun slime-fuzzy-select/mouse (event)
|
||
"Handle a mouse-2 click on a completion choice as if point were
|
||
on the completion choice and the slime-fuzzy-select command was
|
||
run."
|
||
(interactive "e")
|
||
(with-current-buffer (window-buffer (posn-window (event-end event)))
|
||
(save-excursion
|
||
(goto-char (posn-point (event-end event)))
|
||
(when (get-text-property (point) 'mouse-face)
|
||
(slime-fuzzy-insert-from-point)
|
||
(slime-fuzzy-select)))))
|
||
|
||
(defun slime-fuzzy-done ()
|
||
"Cleans up after the completion process. This removes all hooks,
|
||
and attempts to restore the window configuration. If this fails,
|
||
it just burys the completions buffer and leaves the window
|
||
configuration alone."
|
||
(when slime-fuzzy-target-buffer
|
||
(set-buffer slime-fuzzy-target-buffer)
|
||
(slime-fuzzy-disable-target-buffer-completions-mode)
|
||
(if (slime-fuzzy-maybe-restore-window-configuration)
|
||
(bury-buffer (slime-get-fuzzy-buffer))
|
||
;; We couldn't restore the windows, so just bury the fuzzy
|
||
;; completions buffer and let something else fill it in.
|
||
(pop-to-buffer (slime-get-fuzzy-buffer))
|
||
(bury-buffer))
|
||
(if (slime-minibuffer-p slime-fuzzy-target-buffer)
|
||
(select-window (minibuffer-window))
|
||
(pop-to-buffer slime-fuzzy-target-buffer))
|
||
(goto-char slime-fuzzy-end)
|
||
(setq slime-fuzzy-target-buffer nil)
|
||
(remove-hook 'window-configuration-change-hook
|
||
'slime-fuzzy-window-configuration-change)))
|
||
|
||
(defun slime-fuzzy-maybe-restore-window-configuration ()
|
||
"Restores the saved window configuration if it has not been
|
||
nullified."
|
||
(when (boundp 'window-configuration-change-hook)
|
||
(remove-hook 'window-configuration-change-hook
|
||
'slime-fuzzy-window-configuration-change))
|
||
(if (not slime-fuzzy-saved-window-configuration)
|
||
nil
|
||
(set-window-configuration slime-fuzzy-saved-window-configuration)
|
||
(setq slime-fuzzy-saved-window-configuration nil)
|
||
t))
|
||
|
||
(defun slime-fuzzy-window-configuration-change ()
|
||
"Called on window-configuration-change-hook. Since the window
|
||
configuration was changed, we nullify our saved configuration."
|
||
(setq slime-fuzzy-saved-window-configuration nil))
|
||
|
||
(provide 'slime-fuzzy)
|