Setting a default for this variable is dangerous. Set it to low and modes with slow backends will give users the impression that this is typing latency (they'll suspect something else, likely Doom, before suspecting their lsp servers or company backends). Set it too high and users may misinterpret this as latency. Turn it off (set to nil) and I'll get a dozen "code completion isn't working" bug reports. I've settled on company's own default of 0.5 (which is twice as slow as Doom's original default) because responsiveness while typing is more important (and more frustrating to deal with), but it's still enabled, so users are more likely to notice it than assume code completion isn't working.
165 lines
8.8 KiB
EmacsLisp
165 lines
8.8 KiB
EmacsLisp
;;; completion/company/config.el -*- lexical-binding: t; -*-
|
|
|
|
(use-package! company
|
|
:commands company-complete-common company-manual-begin company-grab-line
|
|
:hook (doom-first-input . global-company-mode)
|
|
:init
|
|
(setq company-minimum-prefix-length 2
|
|
company-tooltip-limit 14
|
|
company-tooltip-align-annotations t
|
|
company-require-match 'never
|
|
company-global-modes '(not erc-mode message-mode help-mode gud-mode)
|
|
company-frontends '(company-pseudo-tooltip-frontend
|
|
company-echo-metadata-frontend)
|
|
|
|
;; Buffer-local backends will be computed when loading a major mode, so
|
|
;; only specify a global default here.
|
|
company-backends '(company-capf)
|
|
|
|
;; These auto-complete the current selection when
|
|
;; `company-auto-complete-chars' is typed. This is too magical. We
|
|
;; already have the much more explicit RET and TAB.
|
|
company-auto-complete nil
|
|
company-auto-complete-chars nil
|
|
|
|
;; Only search the current buffer for `company-dabbrev' (a backend that
|
|
;; suggests text your open buffers). This prevents Company from causing
|
|
;; lag once you have a lot of buffers open.
|
|
company-dabbrev-other-buffers nil
|
|
;; Make `company-dabbrev' fully case-sensitive, to improve UX with
|
|
;; domain-specific words with particular casing.
|
|
company-dabbrev-ignore-case nil
|
|
company-dabbrev-downcase nil)
|
|
|
|
:config
|
|
(when (featurep! :editor evil)
|
|
(add-hook 'company-mode-hook #'evil-normalize-keymaps)
|
|
(unless (featurep! +childframe)
|
|
;; Don't persist company popups when switching back to normal mode.
|
|
;; `company-box' aborts on mode switch so it doesn't need this.
|
|
(add-hook! 'evil-normal-state-entry-hook
|
|
(defun +company-abort-h ()
|
|
;; HACK `company-abort' doesn't no-op if company isn't active; causing
|
|
;; unwanted side-effects, like the suppression of messages in the
|
|
;; echo-area.
|
|
;; REVIEW Revisit this to refactor; shouldn't be necessary!
|
|
(when company-candidates
|
|
(company-abort)))))
|
|
;; Allow users to switch between backends on the fly. E.g. C-x C-s followed
|
|
;; by C-x C-n, will switch from `company-yasnippet' to
|
|
;; `company-dabbrev-code'.
|
|
(defadvice! +company--abort-previous-a (&rest _)
|
|
:before #'company-begin-backend
|
|
(company-abort)))
|
|
|
|
(add-hook 'after-change-major-mode-hook #'+company-init-backends-h 'append)
|
|
|
|
(when (featurep! +tng)
|
|
(company-tng-mode +1))
|
|
|
|
;; NOTE Fix #1335: ensure `company-emulation-alist' is the first item of
|
|
;; `emulation-mode-map-alists', thus higher priority than keymaps of
|
|
;; evil-mode. We raise the priority of company-mode keymaps
|
|
;; unconditionally even when completion is not activated. This should not
|
|
;; cause problems, because when completion is activated, the value of
|
|
;; `company-emulation-alist' is ((t . company-my-keymap)), when
|
|
;; completion is not activated, the value is ((t . nil)).
|
|
(add-hook! 'evil-local-mode-hook
|
|
(when (memq 'company-emulation-alist emulation-mode-map-alists)
|
|
(company-ensure-emulation-alist))))
|
|
|
|
|
|
;;
|
|
;; Packages
|
|
|
|
(after! company-files
|
|
(add-to-list 'company-files--regexps "file:\\(\\(?:\\.\\{1,2\\}/\\|~/\\|/\\)[^\]\n]*\\)"))
|
|
|
|
|
|
(use-package! company-box
|
|
:when (featurep! +childframe)
|
|
:hook (company-mode . company-box-mode)
|
|
:config
|
|
(setq company-box-show-single-candidate t
|
|
company-box-backends-colors nil
|
|
company-box-max-candidates 50
|
|
company-box-icons-alist 'company-box-icons-all-the-icons
|
|
company-box-icons-functions
|
|
(cons #'+company-box-icons--elisp-fn
|
|
(delq 'company-box-icons--elisp
|
|
company-box-icons-functions))
|
|
company-box-icons-all-the-icons
|
|
(let ((all-the-icons-scale-factor 0.8))
|
|
`((Unknown . ,(all-the-icons-material "find_in_page" :face 'all-the-icons-purple))
|
|
(Text . ,(all-the-icons-material "text_fields" :face 'all-the-icons-green))
|
|
(Method . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
|
|
(Function . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
|
|
(Constructor . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
|
|
(Field . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
|
|
(Variable . ,(all-the-icons-material "adjust" :face 'all-the-icons-blue))
|
|
(Class . ,(all-the-icons-material "class" :face 'all-the-icons-red))
|
|
(Interface . ,(all-the-icons-material "settings_input_component" :face 'all-the-icons-red))
|
|
(Module . ,(all-the-icons-material "view_module" :face 'all-the-icons-red))
|
|
(Property . ,(all-the-icons-material "settings" :face 'all-the-icons-red))
|
|
(Unit . ,(all-the-icons-material "straighten" :face 'all-the-icons-red))
|
|
(Value . ,(all-the-icons-material "filter_1" :face 'all-the-icons-red))
|
|
(Enum . ,(all-the-icons-material "plus_one" :face 'all-the-icons-red))
|
|
(Keyword . ,(all-the-icons-material "filter_center_focus" :face 'all-the-icons-red))
|
|
(Snippet . ,(all-the-icons-material "short_text" :face 'all-the-icons-red))
|
|
(Color . ,(all-the-icons-material "color_lens" :face 'all-the-icons-red))
|
|
(File . ,(all-the-icons-material "insert_drive_file" :face 'all-the-icons-red))
|
|
(Reference . ,(all-the-icons-material "collections_bookmark" :face 'all-the-icons-red))
|
|
(Folder . ,(all-the-icons-material "folder" :face 'all-the-icons-red))
|
|
(EnumMember . ,(all-the-icons-material "people" :face 'all-the-icons-red))
|
|
(Constant . ,(all-the-icons-material "pause_circle_filled" :face 'all-the-icons-red))
|
|
(Struct . ,(all-the-icons-material "streetview" :face 'all-the-icons-red))
|
|
(Event . ,(all-the-icons-material "event" :face 'all-the-icons-red))
|
|
(Operator . ,(all-the-icons-material "control_point" :face 'all-the-icons-red))
|
|
(TypeParameter . ,(all-the-icons-material "class" :face 'all-the-icons-red))
|
|
(Template . ,(all-the-icons-material "short_text" :face 'all-the-icons-green))
|
|
(ElispFunction . ,(all-the-icons-material "functions" :face 'all-the-icons-red))
|
|
(ElispVariable . ,(all-the-icons-material "check_circle" :face 'all-the-icons-blue))
|
|
(ElispFeature . ,(all-the-icons-material "stars" :face 'all-the-icons-orange))
|
|
(ElispFace . ,(all-the-icons-material "format_paint" :face 'all-the-icons-pink)))))
|
|
|
|
(delq! 'company-echo-metadata-frontend company-frontends)
|
|
|
|
(defun +company-box-icons--elisp-fn (candidate)
|
|
(when (derived-mode-p 'emacs-lisp-mode)
|
|
(let ((sym (intern candidate)))
|
|
(cond ((fboundp sym) 'ElispFunction)
|
|
((boundp sym) 'ElispVariable)
|
|
((featurep sym) 'ElispFeature)
|
|
((facep sym) 'ElispFace)))))
|
|
|
|
(defadvice! +company-remove-scrollbar-a (orig-fn &rest args)
|
|
"This disables the company-box scrollbar, because:
|
|
https://github.com/sebastiencs/company-box/issues/44"
|
|
:around #'company-box--update-scrollbar
|
|
(letf! ((#'display-buffer-in-side-window #'ignore))
|
|
(apply orig-fn args)))
|
|
|
|
;; `company-box' performs insufficient frame-live-p checks. Any command that
|
|
;; "cleans up the session" will break company-box.
|
|
;; TODO Fix this upstream.
|
|
(defadvice! +company-box-detect-deleted-frame-a (frame)
|
|
:filter-return #'company-box--get-frame
|
|
(if (frame-live-p frame) frame))
|
|
(defadvice! +company-box-detect-deleted-doc-frame-a (_selection frame)
|
|
:before #'company-box-doc
|
|
(and company-box-doc-enable
|
|
(frame-local-getq company-box-doc-frame frame)
|
|
(not (frame-live-p (frame-local-getq company-box-doc-frame frame)))
|
|
(frame-local-setq company-box-doc-frame nil frame))))
|
|
|
|
|
|
(use-package! company-dict
|
|
:defer t
|
|
:config
|
|
(setq company-dict-dir (expand-file-name "dicts" doom-private-dir))
|
|
(add-hook! 'doom-project-hook
|
|
(defun +company-enable-project-dicts-h (mode &rest _)
|
|
"Enable per-project dictionaries."
|
|
(if (symbol-value mode)
|
|
(add-to-list 'company-dict-minor-mode-list mode nil #'eq)
|
|
(setq company-dict-minor-mode-list (delq mode company-dict-minor-mode-list))))))
|