Files
dotemacs/lisp/ux/completion.el
2022-01-09 21:19:46 +01:00

282 lines
11 KiB
EmacsLisp

;;; completion.el --- Configures automatic code completion -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(eval-when-compile
(require 'cl))
(defun user--company-mode-hook ()
"Company mode hook."
(message "user--company-mode-hook")
(when (derived-mode-p 'prog-mode)
(define-key (current-local-map) (user/get-key :code :complete) 'company-indent-or-complete-common))
;; ;; (user/complete-at-point-install)
;; ;;; (Bindings) ;;;
;; ;; (when (current-local-map)
;; ;; (define-key (current-local-map) (user/get-key :code :auto-complete) 'company-complete))
;; (when (current-local-map)
;; (define-key (current-local-map) (user/get-key :code :complete) 'company-complete))
;; (when (current-local-map)
;; (define-key (current-local-map) (user/get-key :code :complete) 'company-indent-or-complete-common))
)
(defun user/company-mode-p ()
"True if auto-complete should be used."
(and (boundp 'global-company-mode)
global-company-mode))
;; (defun user/complete-at-point-install ()
;; "Install completion backend in complete-at-point."
;; (setq
;; ;; Insert completion backend into `completion-at-point'.
;; completion-at-point-functions
;; (cons 'user/complete-at-point
;; (remove 'user/complete-at-point completion-at-point-functions))))
;; (defun user/company-check-expansion ()
;; "Check if expression can be expanded by company."
;; (save-excursion
;; (if (looking-at "\\_>") t
;; (backward-char 1)
;; (if (looking-at "\\.") t
;; (backward-char 1)
;; (if (looking-at "->") t nil)))))
;; (defun user/complete-at-point ()
;; "Complete thing at point using completion backend."
;; (cond
;; ((minibufferp) (minibuffer-complete))
;; ;; ((and (boundp 'auto-complete-mode) auto-complete-mode) #'auto-complete)
;; ((and (boundp 'company-mode) company-mode (user/company-check-expansion)) #'company-complete-common)
;; (t #'indent-for-tab-command)))
;; (defun ac-pcomplete ()
;; "Auto-complete source for pcomplete."
;; ;; eshell uses `insert-and-inherit' to insert a \t if no completion
;; ;; can be found, but this must not happen as auto-complete source
;; (cl-flet ((insert-and-inherit (&rest args)))
;; ;; this code is stolen from `pcomplete' in pcomplete.el
;; (let* (tramp-mode ;; do not automatically complete remote stuff
;; (pcomplete-stub)
;; (pcomplete-show-list t) ;; inhibit patterns like * being deleted
;; pcomplete-seen pcomplete-norm-func
;; pcomplete-args pcomplete-last pcomplete-index
;; (pcomplete-autolist pcomplete-autolist)
;; (pcomplete-suffix-list pcomplete-suffix-list)
;; (candidates (pcomplete-completions))
;; (beg (pcomplete-begin))
;; ;; note, buffer text and completion argument may be
;; ;; different because the buffer text may bet transformed
;; ;; before being completed (e.g. variables like $HOME may be
;; ;; expanded)
;; (buftext (buffer-substring beg (point)))
;; (arg (nth pcomplete-index pcomplete-args)))
;; ;; we auto-complete only if the stub is non-empty and matches
;; ;; the end of the buffer text
;; (when (and (not (zerop (length pcomplete-stub)))
;; (or (string= pcomplete-stub ; Emacs 23
;; (substring buftext
;; (max 0
;; (- (length buftext)
;; (length pcomplete-stub)))))
;; (string= pcomplete-stub ; Emacs 24
;; (substring arg
;; (max 0
;; (- (length arg)
;; (length pcomplete-stub)))))))
;; ;; Collect all possible completions for the stub. Note that
;; ;; `candidates` may be a function, that's why we use
;; ;; `all-completions`.
;; (let* ((cnds (all-completions pcomplete-stub candidates))
;; (bnds (completion-boundaries pcomplete-stub
;; candidates
;; nil
;; ""))
;; (skip (- (length pcomplete-stub) (car bnds))))
;; ;; We replace the stub at the beginning of each candidate by
;; ;; the real buffer content.
;; (mapcar #'(lambda (cand) (concat buftext (substring cand skip)))
;; cnds))))))
;; (defvar ac-source-pcomplete
;; '((candidates . ac-pcomplete)))
;; (defun add-ac-sources (&rest sources)
;; "Add SOURCES for auto-complete after it has been loaded."
;; (when (user/auto-complete-p)
;; (dolist (source sources)
;; (if (boundp 'ac-sources)
;; (add-to-list 'ac-sources source)
;; (error "Declaration of ac-sources is missing!")))))
;; (defun add-ac-modes (&rest major-modes)
;; "Add MAJOR-MODES for auto-complete after it has been loaded."
;; (when (user/auto-complete-p)
;; (dolist (mode major-modes)
;; (if (boundp 'ac-modes)
;; (add-to-list 'ac-modes mode)
;; (error "Declaration of ac-modes is missing!")))))
;; (defun company-complete-common-or-selection ()
;; "Insert the common part of all candidates, or the selection."
;; (interactive)
;; (when (company-manual-begin)
;; (let ((tick (buffer-chars-modified-tick)))
;; (call-interactively 'company-complete-common)
;; (when (eq tick (buffer-chars-modified-tick))
;; (let ((company-selection-wrap-around t))
;; (call-interactively 'company-complete-selection))))))
;; (defun add-company-sources (&rest sources)
;; "Add SOURCES for company completion in current mode, if it has been loaded."
;; (when (user/company-mode-p)
;; (when (boundp 'company-backends)
;; (setq-local
;; company-backends
;; (append sources company-backends)))))
(defun user--completion-config ()
"Initialize automatic code completion."
(setq
;; Activate completion on tab.
tab-always-indent 'complete
;; Cycle completions in minibuffer below a certain threshold.
completion-cycle-threshold 5)
;; Allow completion of acronyms and initialisms.
(add-to-list 'completion-styles 'initials t)
;;; (Packages) ;;;
;; (use-package auto-complete
;; :disabled
;; :requires popup fuzzy
;; :defer
;; :quelpa (auto-complete
;; :fetcher github
;; :repo "auto-complete/auto-complete")
;; :diminish auto-complete-mode
;; :init
;; (add-hook 'flymake-mode-hook 'ac-flyspell-workaround)
;; (add-hook 'auto-complete-mode-hook 'user--auto-complete-mode-hook)
;; :config
;; (with-feature 'auto-complete-config
;; ;; Load default configuration.
;; (ac-config-default)
;; ;; Don't forcibly enable auto-complete.
;; (global-auto-complete-mode -1))
;; (validate-setq
;; ;; Limit the number of candidates.
;; ac-candidate-limit 40
;; ;; Delay until narrowing completions.
;; ac-delay 0.5
;; ;; Do not trigger completion automatically.
;; ac-auto-start nil
;; ;; Use fuzzy matching.
;; ac-fuzzy-enable t
;; ac-use-fuzzy t
;; ;; Do not pop up menu automatically.
;; ac-auto-show-menu nil
;; ;; Allow normal navigation keys in menu.
;; ac-use-menu-map t
;; ;; Do not auto-expand common candidates.
;; ac-expand-on-auto-complete nil
;; ;; Show quick help popup after half a second.
;; ac-use-quick-help t
;; ac-quick-help-delay 0.5
;; ;; Store the completion history in the cache directory.
;; ac-comphist-file (path-join *user-cache-directory* "ac-comphist.dat"))
;; ;; Set up auto-complete for lisp-interaction- and ielm-mode.
;; (dolist (hook (list 'lisp-interaction-mode-hook
;; 'ielm-mode-hook))
;; (add-hook hook 'ac-emacs-lisp-mode-setup))
;; ;;; (Bindings) ;;;
;; (ac-set-trigger-key (user/get-key :code :try-complete))
;; (validate-setq
;; ac-completing-map
;; (let ((map (make-sparse-keymap)))
;; ;; Expand on tab.
;; (define-key map (user/get-key :code :try-complete) 'ac-expand-common)
;; ;; Complete on enter.
;; (define-key map (user/get-key :code :complete) 'ac-complete)
;; ;; Bind configured auto complete key.
;; (define-key map (user/get-key :code :auto-complete) 'auto-complete)
;; ;; Scroll quick-help using M-n/p.
;; (define-key map (kbd "C-M-n") 'ac-quick-help-scroll-down)
;; (define-key map (kbd "C-M-p") 'ac-quick-help-scroll-up)
;; map)))
(use-package company
:diminish company-mode
:hook (company-mode-hook . user--company-mode-hook)
:config
(validate-setq
;; Do not trigger completion automatically.
;; company-idle-delay nil
;; Complete immediately.
company-minimum-prefix-length 0
;; Show commonly used matches first.
company-transformers '(company-sort-by-occurrence)
;; Align annotations to the right of tooltip.
company-tooltip-align-annotations t
;; Active company frontends.
;; company-frontends
;; '(company-pseudo-tooltip-unless-just-one-frontend
;; company-preview-frontend
;; company-echo-metadata-frontend)
)
;; (define-key company-active-map (user/get-key :code :complete) 'company-complete-selection)
;; (define-key company-active-map
;; (user/get-key :code :try-complete) 'company-complete-common-or-selection)
;; (define-key company-active-map
;; (user/get-key :basic :forward-line) 'company-select-next)
;; (define-key company-active-map
;; (user/get-key :basic :backward-line) 'company-select-previous)
;; (define-key company-active-map (user/get-key :code :complete) 'company-search-candidates)
(use-package company-dabbrev-code
:ensure company
:config
(validate-setq
;; Complete even outside of code.
company-dabbrev-code-everywhere t))
(use-package company-flx
:after (company)
:config
(company-flx-mode t))
(use-package company-quickhelp
:if window-system
:after (company)
:hook (company-mode-hook . company-quickhelp-mode)
:config
(validate-setq
;; Show quick help popup after half a second.
company-quickhelp-delay 0.5))
(use-package company-box
:if (display-graphic-p)
:hook (company-mode . company-box-mode))
(global-company-mode t)))
(user--completion-config)
(provide 'ux/completion)
;;; completion.el ends here