diff --git a/modules/completion/company/autoload.el b/modules/completion/company/autoload.el index 7d3177a54..05e606c4b 100644 --- a/modules/completion/company/autoload.el +++ b/modules/completion/company/autoload.el @@ -2,9 +2,9 @@ ;;;###autoload (defvar +company-backend-alist - '((text-mode :derived (company-dabbrev company-yasnippet company-ispell)) - (prog-mode :derived (:separate company-capf company-yasnippet)) - (conf-mode :derived company-capf company-dabbrev-code company-yasnippet)) + '((text-mode company-dabbrev company-yasnippet company-ispell) + (prog-mode company-capf company-yasnippet) + (conf-mode company-capf company-dabbrev-code company-yasnippet)) "An alist matching modes to company backends. The backends for any mode is built from this.") @@ -28,40 +28,37 @@ Examples: (set-company-backend! '(c-mode c++-mode) '(:separate company-irony-c-headers company-irony)) - (set-company-backend! 'sh-mode nil) ; unsets backends for sh-mode - -To have BACKENDS apply to any mode that is a parent of MODES, set MODES to -:derived, e.g. - - (set-company-backend! :derived 'text-mode 'company-dabbrev 'company-yasnippet)" + (set-company-backend! 'sh-mode nil) ; unsets backends for sh-mode" (declare (indent defun)) - (let ((type :exact)) - (when (eq modes :derived) - (setq type :derived - modes (pop backends))) - (dolist (mode (doom-enlist modes)) - (if (null (car backends)) - (setq +company-backend-alist - (delq (assq mode +company-backend-alist) - +company-backend-alist)) - (setf (alist-get mode +company-backend-alist) - (cons type backends)))))) + (dolist (mode (doom-enlist modes)) + (if (null (car backends)) + (setq +company-backend-alist + (delq (assq mode +company-backend-alist) + +company-backend-alist)) + (setf (alist-get mode +company-backend-alist) + backends)))) ;; ;;; Library (defun +company--backends () - (append (cl-loop for (mode . rest) in +company-backend-alist - for type = (car rest) - for backends = (cdr rest) - if (or (and (eq type :derived) (derived-mode-p mode)) ; parent modes - (and (eq type :exact) - (or (eq major-mode mode) ; major modes - (and (boundp mode) - (symbol-value mode))))) ; minor modes - append backends) - (default-value 'company-backends))) + (let (backends) + (let ((mode major-mode) + (modes (list major-mode))) + (while (setq mode (get mode 'derived-mode-parent)) + (push mode modes)) + (dolist (mode modes) + (dolist (backend (append (cdr (assq mode +company-backend-alist)) + (default-value 'company-backends))) + (push backend backends))) + (delete-dups + (append (cl-loop for (mode . backends) in +company-backend-alist + if (or (eq major-mode mode) ; major modes + (and (boundp mode) + (symbol-value mode))) ; minor modes + append backends) + (nreverse backends)))))) ;; @@ -70,9 +67,11 @@ To have BACKENDS apply to any mode that is a parent of MODES, set MODES to ;;;###autoload (defun +company|init-backends () "Set `company-backends' for the current buffer." - (unless (eq major-mode 'fundamental-mode) - (set (make-local-variable 'company-backends) (+company--backends))) - (add-hook 'after-change-major-mode-hook #'+company|init-backends nil 'local)) + (if (not company-mode) + (remove-hook 'change-major-mode-after-body-hook #'+company|init-backends 'local) + (unless (eq major-mode 'fundamental-mode) + (setq-local company-backends (+company--backends))) + (add-hook 'change-major-mode-after-body-hook #'+company|init-backends nil 'local))) (put '+company|init-backends 'permanent-local-hook t) diff --git a/modules/completion/company/test/test-company.el b/modules/completion/company/test/test-company.el index ed69404b0..9c6148db5 100644 --- a/modules/completion/company/test/test-company.el +++ b/modules/completion/company/test/test-company.el @@ -26,7 +26,7 @@ (expect (backends 'text-mode) :to-equal '(a t))) (it "sets backends for a derived-mode" - (set-company-backend! :derived 'prog-mode 'a) + (set-company-backend! 'prog-mode 'a) (expect (backends 'prog-mode) :to-equal '(a t)) (expect (backends 'emacs-lisp-mode) :to-equal '(a t))) @@ -35,12 +35,12 @@ (expect (backends 'text-mode) :to-equal (backends 'emacs-lisp-mode))) (it "sets cumulative backends" - (set-company-backend! :derived 'prog-mode '(a b c)) + (set-company-backend! 'prog-mode '(a b c)) (set-company-backend! 'emacs-lisp-mode 'd 'e) (expect (backends 'emacs-lisp-mode) :to-equal '(d e (a b c) t))) (it "sets cumulative backends with a minor mode" - (set-company-backend! :derived 'prog-mode '(a b c)) + (set-company-backend! 'prog-mode '(a b c)) (set-company-backend! 'emacs-lisp-mode 'd 'e) (set-company-backend! 'some-minor-mode 'x 'y) (setq-local some-minor-mode t) @@ -57,19 +57,19 @@ (expect (backends 'text-mode) :to-equal (default-value 'company-backends))) (it "unsets past parent backends" - (set-company-backend! :derived 'prog-mode 'old) + (set-company-backend! 'prog-mode 'old) (set-company-backend! 'emacs-lisp-mode 'child) - (set-company-backend! :derived 'prog-mode nil) + (set-company-backend! 'prog-mode nil) (expect (backends 'emacs-lisp-mode) :to-equal '(child t))) (it "overwrites past cumulative backends" - (set-company-backend! :derived 'prog-mode 'base) + (set-company-backend! 'prog-mode 'base) (set-company-backend! 'emacs-lisp-mode 'old) (set-company-backend! 'emacs-lisp-mode 'new) (expect (backends 'emacs-lisp-mode) :to-equal '(new base t))) (it "overwrites past parent backends" - (set-company-backend! :derived 'prog-mode 'base) + (set-company-backend! 'prog-mode 'base) (set-company-backend! 'emacs-lisp-mode 'child) - (set-company-backend! :derived 'prog-mode 'new) + (set-company-backend! 'prog-mode 'new) (expect (backends 'emacs-lisp-mode) :to-equal '(child new t)))))