8

Org mode has completion for all keywords via pcomplete, as noted by Andrew Swann.

However, Company does not seem to pick up on these keywords. Calling company-complete on the following, where | represents point, brings up a list of English vocabulary words instead of Org keywords:

#+|

Is it possible for Company to do Org-specific completion in addition to the helpful textual completion that it normally does?

3 Answers 3

10

company-mode has company-capf. So the easiest way is adding pcomplete-completions-at-point to completion-at-point-functions:

(defun my-org-mode-hook ()
  (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t))
(add-hook 'org-mode-hook #'my-org-mode-hook)

Make sure company-capf is in the list of company-backends.

2
  • Thanks, that works, if somewhat imperfectly. The problem is that the #+ is not considered for the completion, so I still have to type at least 3 letters for Company to complete (this is likely customizable, but 3's a good number in most cases for performance). So instead of #+NAMES: I can type #+NAM and save 3 letters. Mar 23, 2016 at 4:27
  • Personally I have a key binding(control+tab) for company-complete. In that case, you can type control+tab after "#+" and company should be able to give all possible completions. You can also write a simple company backend that recognizes the "^#+" as the prefix in order to begin completion.
    – cutejumper
    Mar 23, 2016 at 5:14
3

Inspired by a comment from @cutejumper, I went ahead and wrote a simple company backend that recognizes the ^#+ prefix to start using pcomplete.

(defun org-keyword-backend (command &optional arg &rest ignored)
  (interactive (list 'interactive))
  (cl-case command
    (interactive (company-begin-backend 'org-keyword-backend))
    (prefix (and (eq major-mode 'org-mode)
                 (cons (company-grab-line "^#\\+\\(\\w*\\)" 1)
                       t)))
    (candidates (mapcar #'upcase
                        (cl-remove-if-not
                         (lambda (c) (string-prefix-p arg c))
                         (pcomplete-completions))))
    (ignore-case t)
    (duplicates t)))

Use it with (add-to-list 'company-backends 'org-keyword-backend)

If you want it to wait a certain number of characters into the keyword before offering completion, change line 7 from t to the number you want.

If you want it to wait according to company-minimum-prefix-length, change lines 6 / 7 from (cons (company-grab-line ...) t) to just (company-grab-line ...).

1

After trying the accepted solution a while back (which ended up not working for me) and then giving up after about 6 months, I went back and found a simple solution.

(defun trigger-org-company-complete ()
  "Begins company-complete in org-mode buffer after pressing #+ chars."
  (interactive)
  (if (string-equal "#" (string (preceding-char)))
    (progn
      (insert "+")
      (company-complete))
    (insert "+")))

(eval-after-load 'org '(define-key org-mode-map
               (kbd "+") 'trigger-org-company-complete))

While this is certainly hacky, it's been working well for me, and it didn't require doing any complex parsing.

This works by only calling the function when the + character is entered in an org-mode buffer. Then, trigger-org-company-complete checks the preceding character, and if it's a # character, the + character is inserted and company-complete is called. If the previous character is not #, the + is only inserted, and everything behaves as normal.

You can see the behavior below. When just entering the # character, nothing happens. When # precedes a +, company-complete is triggered, and when just a + character is entered, nothing happens.

(I zoomed in a lot, which is why it's distorted)

enter image description here

enter image description here

enter image description here

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.