|
(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)
|