#+TITLE: Auto-completion layer

* Table of Contents                                         :TOC_4_gh:noexport:
 - [[#description][Description]]
 - [[#install][Install]]
 - [[#configuration][Configuration]]
   - [[#key-bindings][Key bindings]]
   - [[#snippets-directories][Snippets directories]]
   - [[#show-snippets-in-auto-completion-popup][Show snippets in auto-completion popup]]
   - [[#tooltips][Tooltips]]
   - [[#sort-results-by-usage][Sort results by usage]]
   - [[#enable-company-or-auto-complete-globally][Enable company or auto-complete globally]]
   - [[#replacing-company-by-auto-complete][Replacing company by auto-complete]]
   - [[#add-auto-completion-in-a-layer][Add auto-completion in a layer]]
     - [[#in-configel][In =config.el=]]
     - [[#in-packagesel][In =packages.el=]]
   - [[#completion-back-ends][Completion back ends]]
   - [[#improved-faces][Improved faces]]
 - [[#key-bindings-1][Key Bindings]]
   - [[#company][Company]]
   - [[#auto-complete][Auto-complete]]
   - [[#yasnippet][Yasnippet]]
   - [[#auto-yasnippet][Auto-yasnippet]]

* Description
This layer provides auto-completion to Spacemacs.

The following completion engines are supported:
- [[http://company-mode.github.io/][company]]
- [[http://auto-complete.org/][auto-complete]]

Snippets are supported via [[https://github.com/capitaomorte/yasnippet][yasnippet]] and [[https://github.com/abo-abo/auto-yasnippet][auto-yasnippet]].

This layer also configures =hippie-expand=.

* Install
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
add =auto-completion= to the existing =dotspacemacs-configuration-layers= list in this
file.

* Configuration
** Key bindings
You can customize the user experience of auto-completion with the following
layer variables:

1. =auto-completion-return-key-behavior= set the action to perform when the
   ~RET~ key is pressed, the possible values are:
   - =complete= completes with the current selection
   - =nil= does nothing

2. =auto-completion-tab-key-behavior= set the action to perform when the ~TAB~
   key is pressed, the possible values are:
   - =complete= completes with the current selection
   - =cycle= completes the common prefix and cycle between candidates
   - =nil= does nothing

3. =auto-completion-complete-with-key-sequence= is a string of two characters
   denoting a key sequence that will perform a =complete= action if the sequence
   as been entered quickly enough. If its value is =nil= then the feature is
   disabled.

4. =auto-completion-complete-with-key-sequence-delay= is the number of seconds
   to wait for the auto-completion key sequence to be entered. The default value
   is 0.1 seconds.

The default configuration of the layer is:

#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-configuration-layers '(
  (auto-completion :variables
                   auto-completion-return-key-behavior 'complete
                   auto-completion-tab-key-behavior 'cycle
                   auto-completion-complete-with-key-sequence nil
                   auto-completion-complete-with-key-sequence-delay 0.1
                   auto-completion-private-snippets-directory nil)
                   ))
#+END_SRC

~jk~ is a good candidate for =auto-completion-complete-with-key-sequence= if
you don't use it already.

** Snippets directories
The following directories are added by default:
- ~/.emacs.d/elpa/yasnippet-xxxxx/snippets
- ~/.emacs.d/layers/auto-completion/snippets
- ~/.emacs.d/private/snippets (conditional to the value of =auto-completion-private-snippets-directory=)
- ~/.spacemacs.d/snippets (conditional to the existence of =~/.spacemacs.d= directory)

You can provide additional directories by setting the variable
=auto-completion-private-snippets-directory= which can take a string in case of
a single path or a list of paths.
If its value is =nil= then the path =~/.emacs.d/private/snippets= is used.

** Show snippets in auto-completion popup
By default, snippets are not shown in the auto-completion popup. To show them in
the popup, set the variable =auto-completion-enable-snippets-in-popup= to =t=.

#+BEGIN_SRC emacs-lisp
  (setq-default dotspacemacs-configuration-layers
                '((auto-completion :variables
                                   auto-completion-enable-snippets-in-popup t)))
#+END_SRC

** Tooltips
To enable automatic docstring tooltips set =auto-completion-enable-help-tooltip=
to =t=.

#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-configuration-layers
  '((auto-completion :variables
                    auto-completion-enable-help-tooltip t)))
#+END_SRC

To enable manual non-automatic invocation of docstring tooltips, set it to
=manual=. The tooltip can be invoked manually by pressing ~M-h~.

#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-configuration-layers
  '((auto-completion :variables
                    auto-completion-enable-help-tooltip 'manual)))
#+END_SRC

** Sort results by usage
To enable sorting auto-completion results by their usage frequency set
=auto-completion-enable-sort-by-usage= to =t=.
This feature is provided by the [[https://github.com/company-mode/company-statistics][company-statistics]] package when =company=
is used.
The variable has no effect when =auto-complete= is used.

#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-configuration-layers
  '((auto-completion :variables
                    auto-completion-enable-sort-by-usage t)))
#+END_SRC

** Enable company or auto-complete globally
By default Spacemacs enables auto-completion explicitly for each supported
major-mode, it means that =company= and =auto-complete= are not enabled
globally, it allows more flexibility to choose an auto-completion engine
for a given mode.

You may want to enable company globally to get auto-completion
everywhere even in the modes which are not configured by Spacemacs. To do
so, you just have to add =(global-company-mode)= in the
=dotspacemacs/user -config= function of your dotfile.

Note that if you want to enable =auto-complete= globally you will have to
disable =company= first, see the next section to do so.

** Replacing company by auto-complete
You can disable =company= by adding it to the =dotspacemacs-excluded-packages=
variable, then you are free to enable =auto-complete= globally.

** Add auto-completion in a layer
Here is an example to add =company= auto-completion to python buffer:

*** In =config.el=
#+BEGIN_SRC emacs-lisp
  ;; Define the buffer local company backend variable
  (spacemacs|defvar-company-backends python-mode)
#+END_SRC

*** In =packages.el=
#+BEGIN_SRC emacs-lisp
  ;; Add the relevant packages to the layer
  (setq python-packages
    '(...
      company
      (company-anaconda :toggle (configuration-layer/package-usedp 'company))
      ...))

  ;; Hook company to python-mode
  (defun python/post-init-company ()
    (spacemacs|add-company-hook python-mode))

  ;; Add the backend to the major-mode specific backend list
  (defun python/init-company-anaconda ()
    (use-package company-anaconda
      :defer t
      :init (push 'company-anaconda company-backends-python-mode)))
#+END_SRC

** Completion back ends
Many spacemacs layers (e.g., python, html, haskell) configure company mode
backends to provide mode-specific completion. These modes will include
completion backends specified in the `spacemacs-default-company-backends`
variable. The defaults should work well, but you can configure this variable in
your ~.spacemacs~ file with (e.g.)
#+BEGIN_SRC emacs-lisp
  (setq-default
   dotspacemacs-configuration-layers
   '((auto-completion :variables
                      spacemacs-default-company-backends '(company-files company-capf))))
#+END_SRC
 
** Improved faces
For nicer-looking faces, try adding the following to `custom-set-faces` in your dotspacemacs file.

#+BEGIN_SRC emacs-lisp
(custom-set-faces
 '(company-tooltip-common
   ((t (:inherit company-tooltip :weight bold :underline nil))))
 '(company-tooltip-common-selection
   ((t (:inherit company-tooltip-selection :weight bold :underline nil)))))
#+END_SRC

* Key Bindings
** Company

| Key Binding | Description                                                                                          |
|-------------+------------------------------------------------------------------------------------------------------|
| ~C-d~       | open minibuffer with documentation of thing at point in company dropdown                             |
| ~C-/~       | show candidates in Helm (for fuzzy searching)                                                        |
| ~C-M-/~     | filter the company dropdown menu                                                                     |
| ~M-h~       | show current candidate's documentation in a tooltip (requires =auto-completion-enable-help-tooltip=) |

Vim Style:

| Key Binding | Description                                  |
|-------------+----------------------------------------------|
| ~C-j~       | (vim style) go down in company dropdown menu |
| ~C-k~       | (vim style) go up in company dropdown menu   |
| ~C-l~       | (vim style) complete selection               |

Emacs style:

| Key Binding | Description                                    |
|-------------+------------------------------------------------|
| ~C-f~       | (emacs style) complete selection               |
| ~C-n~       | (emacs style) go down in company dropdown menu |
| ~C-p~       | (emacs style) go up in company dropdown menu   |

** Auto-complete

| Key Binding | Description                                                          |
|-------------+----------------------------------------------------------------------|
| ~C-j~       | select next candidate                                                |
| ~C-k~       | select previous candidate                                            |
| ~TAB~       | expand selection or select next candidate                            |
| ~S-TAB~     | select previous candidate                                            |
| ~return~    | complete word, if word is already completed insert a carriage return |

** Yasnippet

| Key Binding | Description                                                    |
|-------------+----------------------------------------------------------------|
| ~M-/~       | Expand a snippet if text before point is a prefix of a snippet |
| ~SPC i s~   | List all current yasnippets for inserting                      |

** Auto-yasnippet

| Key Binding | Description                                                               |
|-------------+---------------------------------------------------------------------------|
| ~SPC i S c~ | create a snippet from an active region                                    |
| ~SPC i S e~ | Expand the snippet just created with ~SPC i y~                            |
| ~SPC i S w~ | Write the snippet inside =private/snippets= directory for future sessions |
