emacs: implement completion-at-point

Fixes #261
This commit is contained in:
Jake Shilling 2022-12-01 14:28:41 -05:00 committed by Etienne Millon
parent c50173caf9
commit 0e9f0c6893
2 changed files with 50 additions and 15 deletions

View File

@ -1,3 +1,8 @@
unreleased
----------
* emacs: add completion-at-point implementation (#406, fixes #261, @j-shilling)
2.12.0 (2023-04-17) 2.12.0 (2023-04-17)
------------------- -------------------

View File

@ -101,6 +101,16 @@ This hook is only run if exiting actually kills the buffer."
:type 'boolean :type 'boolean
:safe 'booleanp) :safe 'booleanp)
(defcustom utop-capf-wait-interval 0.01
"Length of time to wait when polling for completion candidates."
:type 'float
:safe 'floatp)
(defcustom utop-capf-max-wait-time 0.1
"Maximum time to wait before giving up on completion."
:type 'float
:safe 'floatp)
(defface utop-prompt (defface utop-prompt
'((((background dark)) (:foreground "Cyan1")) '((((background dark)) (:foreground "Cyan1"))
(((background light)) (:foreground "blue"))) (((background light)) (:foreground "blue")))
@ -157,6 +167,9 @@ This hook is only run if exiting actually kills the buffer."
(defvar-local utop-completion nil (defvar-local utop-completion nil
"Current completion.") "Current completion.")
(defvar-local utop-capf-completion-candidates nil
"Current completion when using capf.")
(defvar-local utop-completion-prefixes nil (defvar-local utop-completion-prefixes nil
"Prefixes for current completion.") "Prefixes for current completion.")
@ -595,19 +608,14 @@ it is started."
(cadr (split-string prefix "\\.")) (cadr (split-string prefix "\\."))
prefix))) prefix)))
(when (string-prefix-p prefix argument) (when (string-prefix-p prefix argument)
(push argument utop-completion) (push argument utop-completion)
(throw 'done t)))))) (throw 'done t))))))
;; End of completion ;; End of completion
("completion-stop" ("completion-stop"
(utop-set-state 'edit) (utop-set-state 'edit)
(if (utop--supports-company) (if (utop--supports-company)
(funcall utop--complete-k (nreverse utop-completion)) (funcall utop--complete-k (nreverse utop-completion))
(progn (setq utop-capf-completion-candidates (nreverse utop-completion)))
(if (> (length utop-completion) 1)
(with-current-buffer utop-complete-buffer
(with-output-to-temp-buffer "*Completions*"
(display-completion-list (nreverse utop-completion))))
(minibuffer-hide-completions))))
(setq utop-completion nil))))) (setq utop-completion nil)))))
(defun utop-process-output (_process output) (defun utop-process-output (_process output)
@ -704,10 +712,7 @@ If ADD-TO-HISTORY is t then the input will be added to history."
;; We are now waiting for completion ;; We are now waiting for completion
(utop-set-state 'comp) (utop-set-state 'comp)
;; Send all lines to utop ;; Send all lines to utop
(utop-send-string (utop-send-string "complete-company:\n")
(if (utop--supports-company)
"complete-company:\n"
"complete:\n"))
;; Keep track of the prefixes, so we can avoid returning ;; Keep track of the prefixes, so we can avoid returning
;; completion which don't have a match. ;; completion which don't have a match.
(setq utop-completion-prefixes lines) (setq utop-completion-prefixes lines)
@ -716,9 +721,8 @@ If ADD-TO-HISTORY is t then the input will be added to history."
(utop-send-string (concat "data:" line "\n"))) (utop-send-string (concat "data:" line "\n")))
(utop-send-string "end:\n"))) (utop-send-string "end:\n")))
(defun utop-complete () (defun utop-complete-start ()
"Complete current input." "Conditionally begins to request completion candidates from utop."
(interactive)
;; Complete only if the cursor is after the prompt ;; Complete only if the cursor is after the prompt
(when (and (eq utop-state 'edit) (>= (point) utop-prompt-max)) (when (and (eq utop-state 'edit) (>= (point) utop-prompt-max))
;; Use this buffer ;; Use this buffer
@ -727,6 +731,30 @@ If ADD-TO-HISTORY is t then the input will be added to history."
(utop-complete-input (utop-complete-input
(buffer-substring-no-properties utop-prompt-max (point))))) (buffer-substring-no-properties utop-prompt-max (point)))))
(defun utop-completion-at-point ()
"Complete thing at point."
(setq utop-capf-completion-candidates nil)
(utop-complete-start)
(let ((elapsed-time 0))
(while (and (eq utop-state 'comp)
(> utop-capf-max-wait-time elapsed-time))
(sleep-for utop-capf-wait-interval)
(setq elapsed-time (+ elapsed-time utop-capf-wait-interval))))
(when (>= (length utop-capf-completion-candidates) 1)
(list
utop-prompt-max
(point)
utop-capf-completion-candidates)))
(defun utop-complete ()
"Complete current input."
(interactive)
(if (utop--supports-company)
(utop-complete-start)
(completion-at-point)))
;; +-----------------------------------------------------------------+ ;; +-----------------------------------------------------------------+
;; | Eval | ;; | Eval |
;; +-----------------------------------------------------------------+ ;; +-----------------------------------------------------------------+
@ -1186,6 +1214,8 @@ defaults to 0."
(with-eval-after-load 'company (with-eval-after-load 'company
(add-to-list 'company-backends #'utop-company-backend)) (add-to-list 'company-backends #'utop-company-backend))
(add-hook 'completion-at-point-functions #'utop-completion-at-point nil 'local)
;; Start utop ;; Start utop
(utop-start (utop-arguments))) (utop-start (utop-arguments)))