1

I would like to have natural language completion (company-ispell for e.g.) but only when editing comments.

How should the company back-end be swapped out when editing commensts?

2 Answers 2

1

Insert below code into ~/.emacs to enable company-ispell in comment,

(defun my-in-comment-p (pos)
  "Check whether the code at POS is comment by comparing font face."
  (let* ((fontfaces (get-text-property pos 'face)))
    (if (not (listp fontfaces))
        (setq fontfaces (list fontfaces)))
    (delq nil
          (mapcar #'(lambda (f)
                      ;; learn this trick from flyspell
                      (or (eq f 'font-lock-comment-face)
                          (eq f 'font-lock-comment-delimiter-face)))
                  fontfaces))))

(eval-after-load 'company-ispell
  '(progn
     ;; use company-ispell in comment when coding
     (defadvice company-ispell-available (around company-ispell-available-hack activate)
       (cond
        ((and (derived-mode-p 'prog-mode)
              (or (not (company-in-string-or-comment)) ; respect advice in `company-in-string-or-comment'
                  (not (my-in-comment-p (point))))) ; auto-complete in comment only
         (setq ad-return-value nil))
        (t
         ad-do-it)))))
3
  • Notes: seems setf could be setq? Also let* can be let. Added alternate answer.
    – ideasman42
    Jan 9, 2020 at 1:02
  • setf is still syntax correct though I admit it's kind of over-engineering in this case. let* is more powerful then let when multiple variable are initialized and there is dependency of initialization among the variables.
    – chen bin
    Jan 9, 2020 at 2:22
  • The function (face-at-point nil t) looks like it can replace the font accessing logic here.
    – ideasman42
    Jan 9, 2020 at 8:48
1

This is a modified version of @chen-bin's answer which uses a wrapper function instead of using advice (avoids interfering with other uses). It also generalizes the syntax checking to allow checking for other kinds of syntax.

(defun company-complete-common-use-context ()
  (interactive)
  (let ((faces-found (face-at-point nil t))
        (faces-comment-list
         '(font-lock-comment-face
           font-lock-comment-delimiter-face
           font-lock-doc-face)))
    (cond
     ((seq-intersection faces-found faces-comment-list)
      (let ((company-backends (list 'company-ispell)))
        (company-complete-common)))
     (t
      (company-complete-common)))))

Then bind the key to company-complete-common-use-context.

2
  • This solution works for me if I am using something like <M-tab>, but is there any way of making it also work for completion on any key stroke? Sep 20, 2020 at 11:47
  • The other answer here (chen bin's) uses advice which should work automatically without having to bind a key to a spesific function.
    – ideasman42
    Sep 21, 2020 at 2:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.