This post covers the following sections from my init.

  • Autocompletion


Preamble

Emacs is old school. You're either new to it - which means you wouldn't be here unless it was your type of thing - or you know what you're looking for. In either case, search 'Emacs' in tags or search on this site. Then read the posts y date from oldest to newest.

In the last emacs post I covered lines 2615 - 2708. This post covers lines 2773 - 2942. I include the lines for anyone that wants to patch together the entire init from start to finish. The lines won't always match up because I take stuff out when I'm in the init.

Autocompletion is a major component of any modern text editor and/or word processing set-up. There are currently two primary autocompletion packages offered by Emacs: 'Autocomplete' and 'Company.' I use Company Mode.

I found with my set-up on windows even with a well-tweaked configuration there is a very slight delay in companies autocompletion. The dropdown is an extension of the text you are writing, rather than a stand alone dropdown box. As a result, when typing fast company suggestions interrupt flow.

I've not been before anyway a big proponent of autocompletion. In Emacs, I have the delay toggled to a high number so it doesn't interrupt my flow while still allowing me to call it on demand. Truly, in my opinion, more modern text editors have Emacs beat on autocompletion.

Anyway, here is the code for my company configuration along with some brief explanations. If autocompletion is something you want to use in Emacs, I suggest you look into company a little further than I did. It's likely you will come up with a configuration that works well for you.

P.S. If you're wondering about the connection between the Shatner feature image and company mode, there's no connection. What's life without a little humour? 😉


(use-package company
:pin melpa-stable
:commands (company-mode company-complete company-complete-common company-complete-selection helm-company)
:init
(setq company-minimum-prefix-length 3
      company-require-match nil
      company-selection-wrap-around t
      company-dabbrev-downcase t
      company-tooltip-limit 20; bigger popup window
	  company-tooltip-minimum-width 15
      company-tooltip-align-annotations t; align annotations to the right tooltip border
      company-eclim-auto-save nil
);end setqs
(eval-after-load 'company
'(add-to-list 'company-backends '(company-ispell  company-yasnippet company-abbrev company-dabbrev company-capf)))
:config
;dropdown by default = 0, no dropdown =1
(setq company-idle-delay 1000)
;(setq company-tooltip-idle-delay 0.1)
(setq company-minimum-prefix-length 3)
;(setq company-auto-complete t)
(setq company-ispell-dictionary  comp-ispell-dic-p )
(defun jcs--company-complete-selection--advice-around (fn)
    "Advice execute around `company-complete-selection' command."
    (let ((company-dabbrev-downcase t))
      (call-interactively fn)))
  (advice-add 'company-complete-selection :around #'jcs--company-complete-selection--advice-around)
(with-eval-after-load 'company
(define-key company-active-map (kbd "C-n") 'company-select-next)
(define-key company-active-map (kbd "C-p") 'company-select-previous)
);end set-keys
;orgmode has completion, enable company completion to work also with org
(defun add-pcomplete-to-capf ()
  (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t))
(add-hook 'org-mode-hook #'add-pcomplete-to-capf)
;some other company edits completions
;(setq-local completion-ignore-case t)
;(company-dabbrev-code-ignore-case t)
(setq company-dabbrev-ignore-case nil)
;(company-etags-ignore-case t)
; no ispell on certain modes
;(setq company-global-modes'(not eshell-mode comint-mode erc-mode  ;minibuffer-inactive-mode))
;bind below to tab, if company on manual begin uses tab, otherwise company
(defun complete-or-indent ()
    (interactive)
    (if (company-manual-begin)
        (company-complete-common)
      (indent-according-to-mode)))
;a piece of code that will allow yasnippet completion expansion if company did not complete
;; With this code, yasnippet will expand the snippet if company didn't complete the word. Another thing to remember is to
;; replace company-complete-common with company-complete if you're using it
(advice-add 'company-complete :before (lambda () (setq my-company-point (point))))
(advice-add 'company-complete :after (lambda ()
(when (equal my-company-point (point))
  			  			  (yas-expand))))
(global-company-mode)
:bind (
("C-t"   . company-complete);
;("C-c f" . company-files)
;("C-c a" . company-dabbrev)
;("C-c d" . company-ispell)
(:map company-active-map
("C-n"    . company-select-next)
("C-p"    . company-select-previous)
([return] . company-complete-selection)
("C-w"    . backward-kill-word)
("C-g"    . company-abort)
("C-c"    . company-search-abort)
("<tab>"  . complete-or-indent)
("C-s"  . company-search-candidates)
("C-o" . company-search-toggle-filtering)
));end bind
);end use-package company

Notes:

Company is an engine that takes a back end and a front-end. It comes with its own front-end you can swap out. In the above, the appearance and behavior of dropdown is configured in the setq statements. The minimum prefix length sets the word length that triggers autocompletion engine. Company-idle-delay delays completion for set time. I set 1000 seconds to avoid using company at all. I've a functions in my init that change the delays. See here:



(defun toggle-company-idle-delay ()
"Stops or starts company auto-popup feature by setting delay to a few hours or zero."
(interactive)
(if (featurep 'company)
(if (= company-idle-delay 0.1)
    (setq company-idle-delay 10000)
    (setq company-idle-delay 0.1))));
;stops or starts company auto-complete-inserts wrong word on space for text-modes, great though for programming modes

(defun toggle-company-auto-complete ()
"Stops or starts company auto-complete."
(interactive)
(if (featurep 'company)
(if ( = company-auto-complete 1)
    (setq company-auto-complete nil)
    (setq company-auto-complete 1))));

Backends are just dictionaries company searches to match best suggestions. The backends make all the difference so you want to swap them based on the mode you are in. This code here sets up the original backend list (order matters) `(eval-after-load 'company '(add-to-list 'company-backends '(company-ispell company-yasnippet company-abbrev company-dabbrev company-capf)))`

There's code to configure completion short-cuts to emacs movement shortcuts so you can cycle the dropdown without changing from movement positions. Also code to resolve conflicts, like org-mode and web-mode, and yasnippet completion conflicts.

The following complement company.



(use-package company-try-hard
:config
(global-set-key (kbd "C-l") 'company-try-hard)
(define-key company-active-map (kbd "C-l") 'company-try-hard)
);company-try-hard
;php-extras from 2014
(use-package php-extras
:commands (php-mode company-php)
);php-extras
;ac-php , as company backend
(use-package ac-php
:after (auto-complete yasnippet company php-mode)
:commands (php-mode company-php)
:config
(ac-php-core-eldoc-setup)
;ac-source-php
;:hook (php-mode . ac-php-mode)
);ac-php
;company-php
(use-package company-php
:after (company php-mode)
:commands (php-mode company-php)
:config
(set (make-local-variable 'company-backends)
'((
company-ac-php-backend
php-extras-company
ac-php
company-dabbrev-code
)));end add to backends
;ac-php-find-symbol-at-point
(local-set-key (kbd "M-.") #'ac-php-find-symbol-at-point)
);end company-php
;company-yasnippet
(use-package company-yasnippet
:load-path company-yasnippet-p
:init
(require 'company-yasnippet)
:commands (company-mode yas-minor-mode )
);company-yasnippet
(defvar company-mode/enable-yas t
  "Enable yasnippet for all backends.")
(defun company-mode/backend-with-yas (backend)
  (if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
      backend
    (append (if (consp backend) backend (list backend))
            '(:with company-yasnippet))))
(setq company-backends (mapcar #'company-mode/backend-with-yas company-backends))
;company fuzzy matching combines all backends for buffer into one selection narrowed as you type prefix
(use-package company-fuzzy
:after company
:commands company-fuzzy-mode
:config
(setq company-fuzzy-sorting-backend 'alphabetic)
(setq company-fuzzy-prefix-ontop t)
(setq company-fuzzy-show-annotation t)
;backends without prefixes for completion need this
(add-to-list 'company-fuzzy--no-prefix-backends 'company-yasnippet)
);;end company-fuzzy
;to enable in any give mode add to that modes company-backend hooks
;(company-fuzzy-mode 1)
;; helm-company choose from company completions with C-:
(use-package helm-company
;load-path "path to helm-company.el"
:commands helm-company
);end helm-company
;define key helm-company
(with-eval-after-load 'company
  (define-key company-mode-map (kbd "C-:") 'helm-company)
  (define-key company-active-map (kbd "C-:") 'helm-company))
;company quick-help
(use-package company-quickhelp
:after (company pos-tip)
:commands (company-quickhelp-mode company-quickhelp-manual-begin)
;:config
;(setq company-quickhelp-delay nil)
;(eval-after-load 'company
;  '(define-key company-active-map (kbd "M-h") ;'company-quickhelp-manual-begin))
);end company-quickhelp

Company Try Hard combines all the backends in the backend list. Php-extras, ac-php, and company-php are php completion backends (I was doing some php coding using company). ac-php-core-eldoc-setup enables php info display in mini-buffer when cursor is over a php function. Company Yasnippet puts mode snippets into the (searchable) dropdown. Company fuzzy adds fuzzy matching to the dropdown search (you search with c-s when in the dropdown). Helm Company swaps company from the dropdown to the helm buffer. Most of these packages are tied to shortcuts. This is useful because I toggle company delay high by default. I can can call company helm or company dropdown with a shortcut, like C-:, then toggle company-try-hard with c-l to cycle the backends (rearranging the order).

Company mode is useful because of backends like company-abbrev and company-dabbrev. Abbrevs are found on a list you specify in emacs using a shortcut (to add the word to abbrevs). Dabbrevs are words used already in the current buffer, then all other buffers. Company-capf bridges completion from any mode that comes with a completion into company. This is useful for programming languages when you want for example to complete a function or reserved word.

In all, Emacs Company can be helpful in improving efficiency in your work flow, though personally I find I don't use it that much.


That’s all for now…

comments powered by Disqus