mirror of
https://github.com/doomemacs/doomemacs
synced 2025-08-05 12:37:33 -05:00
In the interest of slimming down Doom's core (as we near v3), I've deprecated these macros. They doesn't really need to exist. Sure, the alternatives aren't as ergonomic or elegant, but they're good enough that we don't need these trivial wrappers. Their local uses have been refactored out as well.
186 lines
9.6 KiB
EmacsLisp
186 lines
9.6 KiB
EmacsLisp
;;; completion/company/config.el -*- lexical-binding: t; -*-
|
|
|
|
(use-package! company
|
|
:commands (company-complete-common
|
|
company-complete-common-or-cycle
|
|
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-idle-delay 0.26
|
|
company-global-modes
|
|
'(not erc-mode
|
|
circe-mode
|
|
message-mode
|
|
help-mode
|
|
gud-mode
|
|
vterm-mode)
|
|
company-frontends
|
|
'(company-pseudo-tooltip-frontend ; always show candidates in overlay tooltip
|
|
company-echo-metadata-frontend) ; show selected candidate docs in echo area
|
|
|
|
;; 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-commit-chars' is typed. This is too magical. We
|
|
;; already have the much more explicit RET and TAB.
|
|
company-auto-commit 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)
|
|
|
|
(when (modulep! +tng)
|
|
(add-hook 'global-company-mode-hook #'company-tng-mode))
|
|
|
|
:config
|
|
(when (modulep! :editor evil)
|
|
(add-hook 'company-mode-hook #'evil-normalize-keymaps)
|
|
(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 'company-mode-hook #'+company-init-backends-h 'append)
|
|
|
|
;; 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)))
|
|
|
|
;; Fix #4355: allow eldoc to trigger after completions.
|
|
(after! eldoc
|
|
(eldoc-add-command 'company-complete-selection
|
|
'company-complete-common
|
|
'company-capf
|
|
'company-abort)))
|
|
|
|
|
|
;;
|
|
;;; Packages
|
|
|
|
(after! company-files
|
|
;; Fix `company-files' completion for org file:* links
|
|
(add-to-list 'company-files--regexps "file:\\(\\(?:\\.\\{1,2\\}/\\|~/\\|/\\)[^\]\n]*\\)"))
|
|
|
|
|
|
(use-package! company-box
|
|
:when (modulep! +childframe)
|
|
:hook (company-mode . company-box-mode)
|
|
:config
|
|
(setq company-box-show-single-candidate t
|
|
company-box-backends-colors nil
|
|
company-box-tooltip-limit 50
|
|
company-box-icons-alist 'company-box-icons-nerd-icons
|
|
;; Move company-box-icons--elisp to the end, because it has a catch-all
|
|
;; clause that ruins icons from other backends in elisp buffers.
|
|
company-box-icons-functions
|
|
(cons #'+company-box-icons--elisp-fn
|
|
(delq 'company-box-icons--elisp
|
|
company-box-icons-functions))
|
|
company-box-icons-nerd-icons
|
|
`((Unknown . ,(nerd-icons-codicon "nf-cod-code" :face 'font-lock-warning-face))
|
|
(Text . ,(nerd-icons-codicon "nf-cod-text_size" :face 'font-lock-doc-face))
|
|
(Method . ,(nerd-icons-codicon "nf-cod-symbol_method" :face 'font-lock-function-name-face))
|
|
(Function . ,(nerd-icons-codicon "nf-cod-symbol_method" :face 'font-lock-function-name-face))
|
|
(Constructor . ,(nerd-icons-codicon "nf-cod-triangle_right" :face 'font-lock-function-name-face))
|
|
(Field . ,(nerd-icons-codicon "nf-cod-symbol_field" :face 'font-lock-variable-name-face))
|
|
(Variable . ,(nerd-icons-codicon "nf-cod-symbol_variable" :face 'font-lock-variable-name-face))
|
|
(Class . ,(nerd-icons-codicon "nf-cod-symbol_class" :face 'font-lock-type-face))
|
|
(Interface . ,(nerd-icons-codicon "nf-cod-symbol_interface" :face 'font-lock-type-face))
|
|
(Module . ,(nerd-icons-codicon "nf-cod-file_submodule" :face 'font-lock-preprocessor-face))
|
|
(Property . ,(nerd-icons-codicon "nf-cod-symbol_property" :face 'font-lock-variable-name-face))
|
|
(Unit . ,(nerd-icons-codicon "nf-cod-symbol_ruler" :face 'font-lock-constant-face))
|
|
(Value . ,(nerd-icons-codicon "nf-cod-symbol_field" :face 'font-lock-builtin-face))
|
|
(Enum . ,(nerd-icons-codicon "nf-cod-symbol_enum" :face 'font-lock-builtin-face))
|
|
(Keyword . ,(nerd-icons-codicon "nf-cod-symbol_keyword" :face 'font-lock-keyword-face))
|
|
(Snippet . ,(nerd-icons-codicon "nf-cod-symbol_snippet" :face 'font-lock-string-face))
|
|
(Color . ,(nerd-icons-codicon "nf-cod-symbol_color" :face 'success))
|
|
(File . ,(nerd-icons-codicon "nf-cod-symbol_file" :face 'font-lock-string-face))
|
|
(Reference . ,(nerd-icons-codicon "nf-cod-references" :face 'font-lock-variable-name-face))
|
|
(Folder . ,(nerd-icons-codicon "nf-cod-folder" :face 'font-lock-variable-name-face))
|
|
(EnumMember . ,(nerd-icons-codicon "nf-cod-symbol_enum_member" :face 'font-lock-builtin-face))
|
|
(Constant . ,(nerd-icons-codicon "nf-cod-symbol_constant" :face 'font-lock-constant-face))
|
|
(Struct . ,(nerd-icons-codicon "nf-cod-symbol_structure" :face 'font-lock-variable-name-face))
|
|
(Event . ,(nerd-icons-codicon "nf-cod-symbol_event" :face 'font-lock-warning-face))
|
|
(Operator . ,(nerd-icons-codicon "nf-cod-symbol_operator" :face 'font-lock-comment-delimiter-face))
|
|
(TypeParameter . ,(nerd-icons-codicon "nf-cod-list_unordered" :face 'font-lock-type-face))
|
|
(Template . ,(nerd-icons-codicon "nf-cod-symbol_snippet" :face 'font-lock-string-face))
|
|
(ElispFunction . ,(nerd-icons-codicon "nf-cod-symbol_method" :face 'font-lock-function-name-face))
|
|
(ElispVariable . ,(nerd-icons-codicon "nf-cod-symbol_variable" :face 'font-lock-variable-name-face))
|
|
(ElispFeature . ,(nerd-icons-codicon "nf-cod-globe" :face 'font-lock-builtin-face))
|
|
(ElispFace . ,(nerd-icons-codicon "nf-cod-symbol_color" :face 'success))))
|
|
|
|
;; HACK Fix oversized scrollbar in some odd cases
|
|
;; REVIEW `resize-mode' is deprecated and may stop working in the future.
|
|
;; TODO PR me upstream?
|
|
(setq x-gtk-resize-child-frames 'resize-mode)
|
|
|
|
;; Disable tab-bar in company-box child frames
|
|
;; TODO PR me upstream!
|
|
(add-to-list 'company-box-frame-parameters '(tab-bar-lines . 0))
|
|
|
|
;; Don't show documentation in echo area, because company-box displays its own
|
|
;; in a child frame.
|
|
(cl-callf2 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)))))
|
|
|
|
;; `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-user-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))))))
|