Autocompletion

Code Autocompletion

Company is, in my opinion, the best autocompleting engine for Emacs, and it is one of the most popular if not the most popular.

(use-package company
  :straight (:build t)
  :defer t
  :hook (company-mode . evil-normalize-keymaps)
  :init (global-company-mode)
  :config
  (setq company-minimum-prefix-length     2
        company-toolsip-limit             14
        company-tooltip-align-annotations t
        company-require-match             'never
        company-global-modes              '(not erc-mode message-mode help-mode gud-mode)
        company-frontends
        '(company-pseudo-tooltip-frontend ; always show candidates in overlay tooltip
          company-echo-metadata-frontend) ; show selected candidate docs in echo area
        company-backends '(company-capf)
        company-auto-commit         nil
        company-auto-complete-chars nil
        company-dabbrev-other-buffers nil
        company-dabbrev-ignore-case nil
        company-dabbrev-downcase    nil))

This package is a backend for company. It emulates ac-source-dictionary by proposing text related to the current major-mode.

(use-package company-dict
  :after company
  :straight (:build t)
  :config
  (setq company-dict-dir (expand-file-name "dicts" user-emacs-directory)))

On the other hand, company-box is a Company front-end which offers colours, icons, documentation and so on. Very nice.

Declaring all the icons for the variable company-box-icons-all-the-icons is quite verbose in Elisp, so I do it with an org-table.

TypeIconColor
Unknownfind_in_pagepurple
Texttext_fieldsgreen
Methodfunctionsred
Functionfunctionsred
Constructorfunctionsred
Fieldfunctionsred
Variableadjustblue
Classclassred
Interfacesettings_input_componentred
Moduleview_modulered
Propertysettingsred
Unitstraightenred
Valuefilter_1red
Enumplus_onered
Keywordfilter_center_focusred
Snippetshort_textred
Colorcolor_lensred
Fileinsert_drive_filered
Referencecollections_bookmarkred
Folderfolderred
EnumMemberpeoplered
Constantpause_circle_filledred
Structstreetviewred
Eventeventred
Operatorcontrol_pointred
TypeParameterclassred
Templateshort_textgreen
ElispFunctionfunctionsred
ElispVariablecheck_circleblue
ElispFeaturestarsorange
ElispFaceformat_paintpink
(use-package company-box
  :straight (:build t)
  :after (company all-the-icons)
  :config
  (setq company-box-show-single-candidate t
        company-box-backends-colors       nil
        company-box-max-candidates        50
        company-box-icons-alist           'company-box-icons-all-the-icons
        company-box-icons-all-the-icons
        (let ((all-the-icons-scale-factor 0.8))
          `(
            <<gen-company-box-icons()>>))))

Ivy

My main menu package is ivy which I use as much as possible –I’ve noticed helm can be slow, very slow in comparison to ivy, so I’ll use the latter as much as possible. Actually, only ivy is installed for now. I could have used ido too, but I find it to be a bit too restricted in terms of features compared to ivy.

(use-package ivy
  :straight t
  :defer t
  :diminish
  :bind (("C-s" . swiper)
         :map ivy-minibuffer-map
         ("TAB" . ivy-alt-done)
         ("C-l" . ivy-alt-done)
         ("C-t" . ivy-next-line)
         ("C-s" . ivy-previous-line)
         ("C-u" . ivy-scroll-up-command)
         ("C-d" . ivy-scroll-down-command)
         :map ivy-switch-buffer-map
         ("C-t" . ivy-next-line)
         ("C-s" . ivy-previous-line)
         ("C-l" . ivy-done)
         ("C-d" . ivy-switch-buffer-kill)
         :map ivy-reverse-i-search-map
         ("C-t" . ivy-next-line)
         ("C-s" . ivy-previous-line)
         ("C-d" . ivy-reverse-i-search-kill))
  :config
  (ivy-mode 1)
  (setq ivy-wrap                        t
        ivy-height                      17
        ivy-sort-max-size               50000
        ivy-fixed-height-minibuffer     t
        ivy-read-action-functions       #'ivy-hydra-read-action
        ivy-read-action-format-function #'ivy-read-action-format-columns
        projectile-completion-system    'ivy
        ivy-on-del-error-function       #'ignore
        ivy-use-selectable-prompt       t))

There is also prescient.elopen in new window that offers some nice features when coupled with ivy, guess what was born out of it? ivy-prescient, of course!

(use-package ivy-prescient
  :after ivy
  :straight (:build t))

I warned you I’d use too much all-the-icons, I did!

(use-package all-the-icons-ivy
  :straight (:build t)
  :after (ivy all-the-icons)
  :init (all-the-icons-ivy-setup)
  :hook (after-init . all-the-icons-ivy-setup))
(all-the-icons-ivy-setup)

A buffer popping at the bottom of the screen is nice and all, but have you considered a floating buffer in the centre of your frame?

(use-package ivy-posframe
  :defer t
  :after (:any ivy helpful)
  :hook (ivy-mode . ivy-posframe-mode)
  :straight (:build t)
  :init
  (ivy-posframe-mode 1)
  :config
  (setq ivy-fixed-height-minibuffer nil
        ivy-posframe-border-width   10
        ivy-posframe-parameters
        `((min-width  . 90)
          (min-height . ,ivy-height))))

Something that can be missing sometimes in Ivy is the ability to select multiple entries at once. For instance, when programming in Java, LPS can offer you to automatically generate the methods equals and hashCode based on selected members, but with vanilla Ivy, you can only select one. Not really useful. ivy-hydra is a package that offers a Hydra interface when in Ivy which allows you to select multiple choices among other things.

(use-package ivy-hydra
  :requires (ivy hydra)
  :after ivy
  :straight (:build t))

Finally, let’s make ivy richer:

(use-package ivy-rich
  :straight (:build t)
  :after ivy
  :init
  (ivy-rich-mode 1))

Counsel

I could almost merge this chapter with the previous one since counsel is a package that provides loads of completion functions for ivy. The ones I find most useful are counsel-M-x and counsel-find-file.

(use-package counsel
  :straight t
  :after recentf
  :after ivy
  :bind (("M-x"     . counsel-M-x)
         ("C-x b"   . counsel-ibuffer)
         ("C-x C-f" . counsel-find-file)
         :map minibuffer-local-map
         ("C-r" . 'counsel-minibuffer-history)))

Yasnippet

Yasnippet allows you to insert some pre-made code by just typing a few characters. It can even generate some string with Elisp expressions and ask the user for some input in some precise places.

(use-package yasnippet
  :defer t
  :straight (:build t)
  :init
  (yas-global-mode)
  :hook ((prog-mode . yas-minor-mode)
         (text-mode . yas-minor-mode)))

Of course, yasnippet wouldn’t be as awesome as it is without pre-made snippets.

(use-package yasnippet-snippets
  :defer t
  :after yasnippet
  :straight (:build t))

Similarly, yatemplate offers pre-made files rather than just strings. That’s still yasnippet by the way.

(use-package yatemplate
  :defer t
  :after yasnippet
  :straight (:build t))

And finally, with ivy you can choose your snippets from a menu if you’re not sure or if you don’t remember what your snippet is.

(use-package ivy-yasnippet
  :defer t
  :after (ivy yasnippet)
  :straight (:build t))