#+TITLE: Vue layer

#+TAGS: framework|layer|programming

[[file:img/vue.png]]

* Table of Contents                     :TOC_5_gh:noexport:
- [[#description][Description]]
  - [[#features][Features:]]
- [[#install][Install]]
- [[#backends][Backends]]
  - [[#dumb][dumb]]
  - [[#lsp][lsp]]
- [[#optional-configuration][Optional Configuration]]
- [[#key-bindings][Key bindings]]
  - [[#web-mode][web-mode]]
  - [[#formatting-prettier][Formatting (prettier)]]
  - [[#auto-complete-and-documentation-dumb][Auto-complete and documentation (dumb)]]
  - [[#lsp-key-bindings][Lsp key bindings]]

* Description
Layer for Vue, for working with =.vue= files.

Note: This layer creates a derived mode called =vue-mode= on the fly out of
=web-mode= to handle vue files. It will conflict with the [[https://github.com/AdamNiederer/vue-mode][vue-mode package]], make sure
you don't use that package together with this layer.

** Features:
- Wholesome features from =web-mode=, especially on template part
- Better performance
- On-the-fly syntax checking with =eslint=
- Proper syntax highlight and indentation with =vue-mode=
- Two options for backend support for autocompletion and code analysis: =lsp= and =dumb=
- Code autocompletion with =company-mode=
- Formatting code with =prettier= layer
- =evil-matchit= =%= to jump between open and close tags
- =emmet-mode= and =yasnippet= for code expanding with the =TAB= key

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

The Vue layer uses the backend that's defined by the variable =vue-backend=. The options are =dumb=
and =lsp=. Default is =dumb= backend. To choose a default backend set the layer
variable =vue-backend=:

#+BEGIN_SRC elisp
  (vue :variables vue-backend 'lsp)
#+END_SRC

To use the on-the-fly syntax checking, install =eslint=:

#+BEGIN_SRC sh
  $ npm install -g eslint-cli
#+END_SRC

Check eslint official doc for setting rules

To use automatic code formatting you need to install =prettier= with:

#+BEGIN_SRC sh
  $ npm install -g prettier
#+END_SRC

If you want to use local =eslint= and =prettier= in your project, turn on node
 layer =dotspacemacs-configuration-layers= function:

#+BEGIN_SRC elisp
  (node :variables node-add-modules-path t)
#+END_SRC

* Backends
** dumb
dumb backend is light weight and fast. =dumb-jump= is used to handled go to
definition (=gd= vim key binding). Because of the template nature of Vue, it
works very well. 

Company backend is set to be very eager in suggestions. 

=eslint= is used for linting.

** lsp
Vue language server needs to be installed

#+BEGIN_SRC sh
  $ npm install -g vls
#+END_SRC

This backend provides all the fancy features like: jump to definition,
references, type inference... However, =eslint= is explicitly selected for
linting because it works better than =lsp= linter.

* Optional Configuration
~web-mode-script-padding~ is set to 0, so indent is zero at root level inside
~script~ tag

Same as =react= layer, you may refer to the =web-mode= configuration for fine
tuning the indenting behaviour.

For example, if you wan't two space indentation, put this in your
=dotspacemacs/user-config=

#+BEGIN_SRC emacs-lisp
  (setq-default
   ;; web-mode
   web-mode-markup-indent-offset 2
   web-mode-css-indent-offset 2
   web-mode-code-indent-offset 2
   web-mode-attr-indent-offset 2)
#+END_SRC

* Key bindings
** web-mode
Free stuff from `html' layer, with minor change to avoid conflict with =lsp= layer

| Key binding | Description                                               |
|-------------+-----------------------------------------------------------|
| ~SPC m E h~ | highlight DOM errors                                      |
| ~SPC m e b~ | go to the beginning of current element                    |
| ~SPC m e c~ | go to the first child element                             |
| ~SPC m e p~ | go to the parent element                                  |
| ~SPC m e s~ | go to next sibling                                        |
| ~SPC m h p~ | show xpath of the current element                         |
| ~SPC m r c~ | clone the current element                                 |
| ~SPC m r d~ | delete the current element (does not delete the children) |
| ~SPC m r n~ | rename current element                                    |
| ~SPC m r w~ | wrap current element                                      |
| ~SPC m z~   | fold/unfold current element                               |
| ~%~         | evil-matchit key binding to jump to closing tag           |

A transient-state is also defined, start it with ~SPC m .~ or ~, .~

| Key binding | Description                                                    |
|-------------+----------------------------------------------------------------|
| ~?~         | Toggle full help                                               |
| ~c~         | clone current element                                          |
| ~d~         | delete (vanish) current element (does not delete the children) |
| ~D~         | delete current element and children                            |
| ~j~         | next element                                                   |
| ~J~ / ~gj~  | next sibling element                                           |
| ~h~         | parent element                                                 |
| ~k~         | previous element                                               |
| ~K~ / ~gk~  | previous sibling element                                       |
| ~l~         | first child element                                            |
| ~p~         | show xpath of current element                                  |
| ~q~         | leave the transient-state                                      |
| ~r~         | rename current element                                         |
| ~w~         | wrap current element                                           |

** Formatting (prettier)

| Key binding | Description               |
|-------------+---------------------------|
| ~SPC m = =~ | format code with prettier |

** Auto-complete and documentation (dumb)

| Key binding | Description                                          |
|-------------+------------------------------------------------------|
| ~SPC m g~   | jump to the definition of the thing under the cursor |
| ~SPC m G~   | jump to definition for the given name                |

** Lsp key bindings
See the [[https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Btools/lsp][lsp layer]].
