Vue layer
Thanks to sei40kr, duianto and others involved in https://github.com/thanhvg/vue/issues for contribution
This commit is contained in:
parent
4e76cdefdf
commit
088a036979
|
@ -305,6 +305,8 @@ sane way, here is the complete list of changed key bindings
|
|||
Kalle Lindqvist)
|
||||
**** Fonts
|
||||
- unicode-fonts (thanks to Aaron Jensen)
|
||||
**** Frameworks
|
||||
- vue (thanks to Thanh Vuong)
|
||||
**** Languages
|
||||
- alda (thanks to Andrew Hill (AstroEngiSci))
|
||||
- coffeescript (thanks to Sylvain Benner)
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
#+TITLE: Vue layer
|
||||
|
||||
[[file:img/vue.png]]
|
||||
|
||||
* Table of Contents :TOC_4_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-keybindings][Lsp keybindings]]
|
||||
|
||||
* 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 keybinding). 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 needed to be installed
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
$ npm install -g vue-language-server
|
||||
#+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 keybindings
|
||||
See the [=lsp= layer](https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Btools/lsp).
|
|
@ -0,0 +1,16 @@
|
|||
;;; config.el --- vue layer config file for Spacemacs. -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; Copyright (c) 2012-2019 Sylvain Benner & Contributors
|
||||
;;
|
||||
;; Author: Thanh Vuong <thanhvg@gmail.com>
|
||||
;; URL: https://github.com/thanhvg
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
|
||||
(defvar vue-backend 'dumb
|
||||
"The backend to use for IDE features. Possible values are `dumb' and `lsp'.")
|
||||
|
||||
(spacemacs|define-jump-handlers vue-mode)
|
|
@ -0,0 +1,136 @@
|
|||
;;; funcs.el --- vue layer funcs file for Spacemacs. -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; Copyright (c) 2012-2019 Sylvain Benner & Contributors
|
||||
;;
|
||||
;; Author: Thanh Vuong <thanhvg@gmail.com>
|
||||
;; URL: https://github.com/thanhvg
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
|
||||
;; backend
|
||||
(defun spacemacs//vue-setup-backend ()
|
||||
"Conditionally setup vue backend."
|
||||
(pcase vue-backend
|
||||
('dumb (spacemacs//vue-setup-dumb))
|
||||
('lsp (spacemacs//vue-setup-lsp))))
|
||||
|
||||
(defun spacemacs//vue-setup-company ()
|
||||
"Conditionally setup company based on backend."
|
||||
(pcase vue-backend
|
||||
('dumb (spacemacs//vue-setup-dumb-company))
|
||||
('lsp (spacemacs//vue-setup-lsp-company))))
|
||||
|
||||
|
||||
;; lsp
|
||||
(defun spacemacs//vue-setup-lsp ()
|
||||
"Setup lsp backend."
|
||||
(if (configuration-layer/layer-used-p 'lsp)
|
||||
(progn
|
||||
;; error checking from lsp langserver sucks, turn it off
|
||||
;; so eslint won't be overriden
|
||||
(setq-local lsp-prefer-flymake :none)
|
||||
(lsp))
|
||||
(message (concat "`lsp' layer is not installed, "
|
||||
"please add `lsp' layer to your dotfile."))))
|
||||
|
||||
(defun spacemacs//vue-setup-lsp-company ()
|
||||
"Setup lsp auto-completion."
|
||||
(if (configuration-layer/layer-used-p 'lsp)
|
||||
(progn
|
||||
(spacemacs|add-company-backends
|
||||
:backends company-lsp
|
||||
:modes vue-mode
|
||||
:variables company-minimum-prefix-length 2
|
||||
:append-hooks nil
|
||||
:call-hooks t)
|
||||
(company-mode))
|
||||
(message "`lsp' layer is not installed, please add `lsp' layer to your dotfile.")))
|
||||
|
||||
|
||||
;; dumb
|
||||
|
||||
(defun spacemacs//vue-setup-dumb-imenu ()
|
||||
(setq imenu-generic-expression '(("html" "^<template>$" 0)
|
||||
("js" "^<script>$" 0)
|
||||
("js" "^\\s-*\\(data\\).*()\\s-?{" 1)
|
||||
("js" "^\\s-*\\(mounted\\).*()\\s-?{" 1)
|
||||
("js" "^\\s-*\\(beforeMount\\).*()\\s-?{" 1)
|
||||
("js" "^\\s-*\\(beforeDestroy\\).*()\\s-?{" 1)
|
||||
("js" "^\\s-*\\(created\\).*()\\s-?{" 1)
|
||||
("js" "^\\s-*\\(computed\\):\\s-?{" 1)
|
||||
("js" "^\\s-*\\(watch\\):\\s-?{" 1)
|
||||
("js" "^\\s-*\\(methods\\):\\s-?{" 1)
|
||||
("js" "^\\s-*\\(props\\):\\s-?{" 1)
|
||||
("css" "^<css>$" 0))
|
||||
imenu-create-index-function #'imenu-default-create-index-function))
|
||||
|
||||
(defun spacemacs//vue-setup-dumb ()
|
||||
(add-to-list 'spacemacs-jump-handlers-vue-mode 'dumb-jump-go)
|
||||
(spacemacs//vue-setup-dumb-imenu))
|
||||
|
||||
(defun spacemacs//vue-setup-dumb-company ()
|
||||
(spacemacs|add-company-backends :backends (company-web-html company-css company-files company-dabbrev)
|
||||
:modes vue-mode
|
||||
:variables company-minimum-prefix-length 2)
|
||||
(company-mode))
|
||||
|
||||
|
||||
;; Others
|
||||
(defun spacemacs//vue-setup-yasnippet ()
|
||||
(spacemacs/load-yasnippet)
|
||||
(yas-activate-extra-mode 'js-mode))
|
||||
|
||||
(defun spacemacs//vue-setup-editor-style ()
|
||||
"such as indent rules comment style etc"
|
||||
;; https://stackoverflow.com/questions/36701024/how-can-i-indent-inline-javascript-in-web-mode
|
||||
(setq web-mode-script-padding 0)
|
||||
;; https://emacs.stackexchange.com/questions/27683/change-comment-style-in-web-mode
|
||||
(add-to-list 'web-mode-comment-formats '("javascript" . "//")))
|
||||
|
||||
(defun spacemacs//vue-setup-keybindings ()
|
||||
"free stuff from `html' layer"
|
||||
(spacemacs/declare-prefix-for-mode 'vue-mode "m=" "format")
|
||||
(spacemacs/declare-prefix-for-mode 'vue-mode "mE" "errors")
|
||||
(spacemacs/declare-prefix-for-mode 'vue-mode "me" "element")
|
||||
(spacemacs/declare-prefix-for-mode 'vue-mode "mg" "goto")
|
||||
(unless (equal vue-backend 'lsp)
|
||||
(spacemacs/declare-prefix-for-mode 'vue-mode "mh" "help")
|
||||
(spacemacs/declare-prefix-for-mode 'vue-mode "mr" "refactor"))
|
||||
(spacemacs/set-leader-keys-for-major-mode 'vue-mode
|
||||
"El" 'web-mode-dom-errors-show
|
||||
"eb" 'web-mode-element-beginning
|
||||
"ec" 'web-mode-element-child
|
||||
"ep" 'web-mode-element-parent
|
||||
"es" 'web-mode-element-sibling-next
|
||||
"hp" 'web-mode-dom-xpath
|
||||
"rc" 'web-mode-element-clone
|
||||
"rd" 'web-mode-element-vanish
|
||||
"rk" 'web-mode-element-kill
|
||||
"rn" 'web-mode-element-rename
|
||||
"rw" 'web-mode-element-wrap
|
||||
"z" 'web-mode-fold-or-unfold)
|
||||
(spacemacs|define-transient-state vue-mode
|
||||
:title "Web-mode Transient State"
|
||||
:columns 4
|
||||
:foreign-keys run
|
||||
:evil-leader-for-mode (vue-mode . ".")
|
||||
:bindings
|
||||
("D" web-mode-element-kill "kill")
|
||||
("J" web-mode-element-sibling-next "next sibling")
|
||||
("K" web-mode-element-sibling-previous "previous sibling")
|
||||
("c" web-mode-element-clone "clone")
|
||||
("d" web-mode-element-vanish "delete")
|
||||
("gj" web-mode-element-sibling-next)
|
||||
("gk" web-mode-element-sibling-previous)
|
||||
("h" web-mode-element-parent "parent")
|
||||
("j" web-mode-element-next "next")
|
||||
("k" web-mode-element-previous "previous")
|
||||
("l" web-mode-element-child "child")
|
||||
("p" web-mode-dom-xpath "xpath")
|
||||
("q" nil "quit" :exit t)
|
||||
("r" web-mode-element-rename "rename" :exit t)
|
||||
("w" web-mode-element-wrap "wrap")
|
||||
("<escape>" nil nil :exit t)))
|
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,12 @@
|
|||
;;; layers.el --- react Layer layers File for Spacemacs
|
||||
;;
|
||||
;; Copyright (c) 2012-2019 Sylvain Benner & Contributors
|
||||
;;
|
||||
;; Author: Thanh Vuong <thanhvg@gmail.com>
|
||||
;; URL: https://github.com/thanhvg
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
(configuration-layer/declare-layers '(node html prettier))
|
|
@ -0,0 +1,55 @@
|
|||
;;; packages.el --- vue layer packages file for Spacemacs. -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; Copyright (c) 2012-2019 Sylvain Benner & Contributors
|
||||
;;
|
||||
;; Author: Thanh Vuong <thanhvg@gmail.com>
|
||||
;; URL: https://github.com/thanhvg
|
||||
;;
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;;; License: GPLv3
|
||||
|
||||
|
||||
(defconst vue-packages
|
||||
'(web-mode
|
||||
add-node-modules-path
|
||||
company
|
||||
evil-matchit
|
||||
flycheck
|
||||
prettier-js
|
||||
smartparens
|
||||
yasnippet))
|
||||
|
||||
(defun vue/post-init-web-mode ()
|
||||
(define-derived-mode vue-mode web-mode "Vue")
|
||||
(add-to-list 'auto-mode-alist '("\\.vue\\'" . vue-mode))
|
||||
(spacemacs/add-to-hook 'vue-mode-hook '(spacemacs//vue-setup-editor-style
|
||||
spacemacs//vue-setup-keybindings))
|
||||
(add-hook 'vue-mode-local-vars-hook #'spacemacs//vue-setup-backend))
|
||||
|
||||
(defun vue/post-init-add-node-modules-path ()
|
||||
(add-hook 'vue-mode-hook #'add-node-modules-path))
|
||||
|
||||
(defun vue/post-init-company ()
|
||||
(add-hook 'vue-mode-local-vars-hook #'spacemacs//vue-setup-company))
|
||||
|
||||
(defun vue/post-init-evil-matchit ()
|
||||
(evilmi-load-plugin-rules '(vue-mode) '(template simple html))
|
||||
(add-hook 'vue-mode-hook 'turn-on-evil-matchit-mode))
|
||||
|
||||
(defun vue/post-init-flycheck ()
|
||||
(with-eval-after-load 'flycheck
|
||||
(flycheck-add-mode 'javascript-eslint 'vue-mode))
|
||||
(spacemacs/enable-flycheck 'vue-mode)
|
||||
(add-hook 'vue-mode-hook #'spacemacs//javascript-setup-checkers 'append))
|
||||
|
||||
(defun vue/pre-init-prettier-js ()
|
||||
(add-to-list 'spacemacs--prettier-modes 'vue-mode))
|
||||
|
||||
(defun vue/post-init-smartparens ()
|
||||
(if dotspacemacs-smartparens-strict-mode
|
||||
(add-hook 'vue-mode-hook #'smartparens-strict-mode)
|
||||
(add-hook 'vue-mode-hook #'smartparens-mode)))
|
||||
|
||||
(defun vue/post-init-yasnippet ()
|
||||
(add-hook 'vue-mode-hook #'spacemacs//vue-setup-yasnippet))
|
Loading…
Reference in New Issue