Add basic LSP support

Still needs to be documented, but includes support for the following
languages:

+ C/C++/ObjC
+ Go
+ Java
+ Javascript
+ OCaml
+ PHP
+ Python
+ Ruby
+ Scala
+ Swift
+ HTML/CSS

Relevant to #460, #716, #1186
This commit is contained in:
Henrik Lissner 2019-02-21 16:08:27 -05:00
parent d7308799f6
commit cb923eadcc
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
25 changed files with 182 additions and 57 deletions

View file

@ -67,6 +67,7 @@
;;editorconfig ; let someone else argue about tabs vs spaces ;;editorconfig ; let someone else argue about tabs vs spaces
;;ein ; tame Jupyter notebooks with emacs ;;ein ; tame Jupyter notebooks with emacs
;;gist ; interacting with github gists ;;gist ; interacting with github gists
;;lsp
;;macos ; MacOS-specific commands ;;macos ; MacOS-specific commands
;;magit ; a git porcelain for Emacs ;;magit ; a git porcelain for Emacs
;;make ; run make tasks from Emacs ;;make ; run make tasks from Emacs

View file

@ -125,7 +125,7 @@ compilation database is present in the project.")
(def-package! irony (def-package! irony
:when (featurep! +irony) :unless (featurep! +lsp)
:commands (irony-install-server irony-mode) :commands (irony-install-server irony-mode)
:preface :preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/")) (setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
@ -181,7 +181,7 @@ compilation database is present in the project.")
;; Rtags Support ;; Rtags Support
(def-package! rtags (def-package! rtags
:when (featurep! +rtags) :unless (featurep! +lsp)
:commands rtags-executable-find :commands rtags-executable-find
:preface :preface
(setq rtags-install-path (concat doom-etc-dir "rtags/")) (setq rtags-install-path (concat doom-etc-dir "rtags/"))
@ -219,3 +219,22 @@ compilation database is present in the project.")
(when (featurep 'evil) (when (featurep 'evil)
(add-hook 'rtags-jump-hook #'evil-set-jump)) (add-hook 'rtags-jump-hook #'evil-set-jump))
(add-hook 'rtags-after-find-file-hook #'recenter)) (add-hook 'rtags-after-find-file-hook #'recenter))
;;
;; LSP
(def-package! cquery
:when (featurep! +lsp)
:hook ((c-mode c++-mode objc-mode) . +lsp|init-cquery)
:config
(defun +lsp|init-cquery ()
(setq-local company-transformers nil)
(setq-local company-lsp-cache-candidates nil)
(condition-case nil
(lsp)
(user-error nil)))
(setq cquery-extra-init-params
'(:index (:comments 2)
:cacheFormat "msgpack"
:completion (:detailedLabel t))))

View file

@ -12,18 +12,17 @@
(when (featurep! :completion company) (when (featurep! :completion company)
(package! company-glsl :recipe (:fetcher github :repo "Kaali/company-glsl")))) (package! company-glsl :recipe (:fetcher github :repo "Kaali/company-glsl"))))
(when (featurep! +irony) (if (featurep! +lsp)
(package! irony) (package! cquery)
(package! irony-eldoc) (when (package! irony)
(when (featurep! :feature syntax-checker) (package! irony-eldoc)
(package! flycheck-irony)) (when (featurep! :feature syntax-checker)
(when (featurep! :completion company) (package! flycheck-irony))
(package! company-irony) (when (featurep! :completion company)
(package! company-irony-c-headers))) (package! company-irony)
(package! company-irony-c-headers)))
(when (featurep! +rtags) (when (package! rtags)
(package! rtags) (when (featurep! :completion ivy)
(when (featurep! :completion ivy) (package! ivy-rtags))
(package! ivy-rtags)) (when (featurep! :completion helm)
(when (featurep! :completion helm) (package! helm-rtags))))
(package! helm-rtags)))

View file

@ -20,7 +20,9 @@
"gofmt" "gofmt"
"goimports")))) "goimports"))))
(add-hook 'go-mode-hook #'go-eldoc-setup) (if (featurep! +lsp)
(add-hook 'go-mode-hook #'+lsp|init)
(add-hook 'go-mode-hook #'go-eldoc-setup))
(map! :map go-mode-map (map! :map go-mode-map
:localleader :localleader
@ -57,7 +59,8 @@
(def-package! company-go (def-package! company-go
:when (featurep! :completion company) :when (and (featurep! :completion company)
(not (featurep! +lsp)))
:after go-mode :after go-mode
:config :config
(set-company-backend! 'go-mode 'company-go) (set-company-backend! 'go-mode 'company-go)

10
modules/lang/java/+lsp.el Normal file
View file

@ -0,0 +1,10 @@
;;; lang/java/+lsp.el -*- lexical-binding: t; -*-
;;;###if (featurep! +lsp)
(def-package! lsp-java
:after-call java-mode
:init (add-hook 'java-mode-hook #'+lsp|init)
:config
;; TODO keybinds
;; TODO treemacs integration (?)
)

View file

@ -23,7 +23,8 @@ If the depth is 2, the first two directories are removed: net.lissner.game.")
(add-hook 'java-mode-hook #'rainbow-delimiters-mode) (add-hook 'java-mode-hook #'rainbow-delimiters-mode)
(cond ((featurep! +meghanada) (load! "+meghanada")) (cond ((featurep! +lsp) (load! "+lsp"))
((featurep! +meghanada) (load! "+meghanada"))
;; TODO lang/java +lsp (lsp-java?) ;; TODO lang/java +lsp (lsp-java?)
;; ((featurep! +lsp) (load! "+lsp")) ;; ((featurep! +lsp) (load! "+lsp"))
) )

View file

@ -12,3 +12,5 @@
(when (featurep! :completion company) (when (featurep! :completion company)
(package! company-emacs-eclim))) (package! company-emacs-eclim)))
(when (featurep! +lsp)
(package! lsp-java))

View file

@ -122,7 +122,12 @@
;; ;;
;; Tools ;; Tools
(when (featurep! +lsp)
(add-hook! (js2-mode rjsx-mode typescript-mode) #'+lsp|init))
(def-package! tide (def-package! tide
:unless (featurep! +lsp)
:defer t :defer t
:init :init
;; Don't let hard errors stop the user from opening js files. ;; Don't let hard errors stop the user from opening js files.

View file

@ -1,17 +1,21 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; lang/javascript/packages.el ;;; lang/javascript/packages.el
;; major modes
(package! coffee-mode) (package! coffee-mode)
(package! eslintd-fix)
(package! js2-mode) (package! js2-mode)
(package! rjsx-mode)
(package! typescript-mode)
;; tools
(package! eslintd-fix)
(package! js2-refactor) (package! js2-refactor)
(package! nodejs-repl) (package! nodejs-repl)
(package! rjsx-mode)
(package! skewer-mode)
(package! tide)
(package! typescript-mode)
(package! npm-mode) (package! npm-mode)
(package! skewer-mode)
(when (featurep! :feature lookup) (when (featurep! :feature lookup)
(package! xref-js2)) (package! xref-js2))
(unless (featurep! +lsp)
(package! tide))

View file

@ -1,5 +1,9 @@
;;; lang/ocaml/config.el -*- lexical-binding: t; -*- ;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
(when (featurep! +lsp)
(add-hook! (tuareg-mode reason-mode) #'+lsp|init))
(after! tuareg (after! tuareg
;; tuareg-mode has the prettify symbols itself ;; tuareg-mode has the prettify symbols itself
(set-pretty-symbols! 'tuareg-mode :alist (set-pretty-symbols! 'tuareg-mode :alist
@ -18,6 +22,7 @@
(def-package! merlin (def-package! merlin
:unless (featurep! +lsp)
:defer t :defer t
:init :init
(defun +ocaml|init-merlin () (defun +ocaml|init-merlin ()
@ -37,7 +42,20 @@
(map! :localleader (map! :localleader
:map tuareg-mode-map :map tuareg-mode-map
"t" #'merlin-type-enclosing "t" #'merlin-type-enclosing
"a" #'tuareg-find-alternate-file)) "a" #'tuareg-find-alternate-file)
(def-package! merlin-eldoc
:hook (merlin-mode . merlin-eldoc-setup))
(def-package! merlin-iedit
:when (featurep! :editor multiple-cursors)
:config
(map! :map tuareg-mode-map
:v "R" #'merlin-iedit-occurrences))
(def-package! merlin-imenu
:when (featurep! :emacs imenu)
:hook (merlin-mode . merlin-use-merlin-imenu)))
(def-package! flycheck-ocaml (def-package! flycheck-ocaml
@ -53,22 +71,6 @@
(add-hook 'merlin-mode-hook #'+ocaml|init-flycheck)) (add-hook 'merlin-mode-hook #'+ocaml|init-flycheck))
(def-package! merlin-eldoc
:hook (merlin-mode . merlin-eldoc-setup))
(def-package! merlin-iedit
:when (featurep! :editor multiple-cursors)
:config
(map! :map tuareg-mode-map
:v "R" #'merlin-iedit-occurrences))
(def-package! merlin-imenu
:when (featurep! :emacs imenu)
:hook (merlin-mode . merlin-use-merlin-imenu))
(def-package! utop (def-package! utop
:when (featurep! :feature eval) :when (featurep! :feature eval)
:defer t ; loaded by hook below :defer t ; loaded by hook below

View file

@ -12,9 +12,11 @@
(set-lookup-handlers! 'php-mode :documentation #'php-search-documentation) (set-lookup-handlers! 'php-mode :documentation #'php-search-documentation)
(set-formatter! 'php-mode #'php-cs-fixer-fix) (set-formatter! 'php-mode #'php-cs-fixer-fix)
;; `+php-company-backend' uses `company-phpactor', `php-extras-company' or (if (featurep! +lsp)
;; `company-dabbrev-code', in that order. (add-hook 'php-mode-hook #'+lsp|init)
(set-company-backend! 'php-mode '+php-company-backend 'company-dabbrev-code) ;; `+php-company-backend' uses `company-phpactor', `php-extras-company' or
;; `company-dabbrev-code', in that order.
(set-company-backend! 'php-mode '+php-company-backend 'company-dabbrev-code))
;; Use the smallest `sp-max-pair-length' for optimum `smartparens' performance ;; Use the smallest `sp-max-pair-length' for optimum `smartparens' performance
(setq-hook! 'php-mode-hook sp-max-pair-length 5) (setq-hook! 'php-mode-hook sp-max-pair-length 5)
@ -32,6 +34,7 @@
(def-package! phpactor (def-package! phpactor
:unless (featurep! +lsp)
:after php-mode :after php-mode
:config :config
(set-lookup-handlers! 'php-mode (set-lookup-handlers! 'php-mode

View file

@ -5,9 +5,10 @@
(package! php-extras :recipe (:fetcher github :repo "arnested/php-extras")) (package! php-extras :recipe (:fetcher github :repo "arnested/php-extras"))
(package! php-mode) (package! php-mode)
(package! php-refactor-mode) (package! php-refactor-mode)
(package! phpactor :recipe (:fetcher github :repo "emacs-php/phpactor.el" :files ("*")))
(package! phpunit) (package! phpunit)
(when (featurep! +hack) (when (featurep! +hack)
(package! hack-mode :recipe (:fetcher github :repo "hhvm/hack-mode"))) (package! hack-mode :recipe (:fetcher github :repo "hhvm/hack-mode")))
(unless (featurep! +lsp)
(package! phpactor :recipe (:fetcher github :repo "emacs-php/phpactor.el" :files ("*"))))

View file

@ -46,6 +46,9 @@ called.")
:for "for" :for "for"
:return "return" :yield "yield") :return "return" :yield "yield")
(when (featurep! +lsp)
(add-hook 'python-mode-hook #'+lsp|init))
(define-key python-mode-map (kbd "DEL") nil) ; interferes with smartparens (define-key python-mode-map (kbd "DEL") nil) ; interferes with smartparens
(sp-local-pair 'python-mode "'" nil (sp-local-pair 'python-mode "'" nil
:unless '(sp-point-before-word-p :unless '(sp-point-before-word-p
@ -63,6 +66,7 @@ called.")
(def-package! anaconda-mode (def-package! anaconda-mode
:unless (featurep! +lsp)
:hook python-mode :hook python-mode
:init :init
(setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/") (setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/")

View file

@ -17,6 +17,7 @@
(package! conda)) (package! conda))
;; Programming environment ;; Programming environment
(when (package! anaconda-mode) (unless (featurep! +lsp)
(package! anaconda-mode)
(when (featurep! :completion company) (when (featurep! :completion company)
(package! company-anaconda))) (package! company-anaconda)))

View file

@ -26,6 +26,9 @@
(set-electric! '(ruby-mode enh-ruby-mode) :words '("else" "end" "elsif")) (set-electric! '(ruby-mode enh-ruby-mode) :words '("else" "end" "elsif"))
(set-repl-handler! '(ruby-mode enh-ruby-mode) #'inf-ruby) (set-repl-handler! '(ruby-mode enh-ruby-mode) #'inf-ruby)
(when (featurep! +lsp)
(add-hook 'enh-ruby-mode-hook #'+lsp|init))
(after! company-dabbrev-code (after! company-dabbrev-code
(add-to-list 'company-dabbrev-code-modes 'enh-ruby-mode nil #'eq) (add-to-list 'company-dabbrev-code-modes 'enh-ruby-mode nil #'eq)
(add-to-list 'company-dabbrev-code-modes 'ruby-mode nil #'eq)) (add-to-list 'company-dabbrev-code-modes 'ruby-mode nil #'eq))
@ -42,6 +45,7 @@
(def-package! robe (def-package! robe
:unless (featurep! +lsp)
:hook (enh-ruby-mode . robe-mode) :hook (enh-ruby-mode . robe-mode)
:config :config
(set-repl-handler! 'enh-ruby-mode #'robe-start) (set-repl-handler! 'enh-ruby-mode #'robe-start)

View file

@ -5,6 +5,9 @@
(set-docsets! 'rust-mode "Rust") (set-docsets! 'rust-mode "Rust")
(setq rust-indent-method-chain t) (setq rust-indent-method-chain t)
(when (featurep! +lsp)
(add-hook 'rust-mode-hook #'+lsp|init))
(map! :map rust-mode-map (map! :map rust-mode-map
:localleader :localleader
:prefix "b" :prefix "b"
@ -15,6 +18,7 @@
(def-package! racer (def-package! racer
:unless (featurep! +lsp)
:after rust-mode :after rust-mode
:config :config
(add-hook 'rust-mode-hook #'racer-mode) (add-hook 'rust-mode-hook #'racer-mode)
@ -27,4 +31,3 @@
:when (featurep! :feature syntax-checker) :when (featurep! :feature syntax-checker)
:after rust-mode :after rust-mode
:config (add-hook 'rust-mode-hook #'flycheck-rust-setup)) :config (add-hook 'rust-mode-hook #'flycheck-rust-setup))

View file

@ -6,7 +6,10 @@
(add-to-list 'dtrt-indent-hook-mapping-list '(scala-mode c/c++/java scala-indent:step)))) (add-to-list 'dtrt-indent-hook-mapping-list '(scala-mode c/c++/java scala-indent:step))))
(after! ensime (def-package! ensime
:unless (featurep! +lsp)
:defer t
:config
(setq ensime-startup-snapshot-notification nil (setq ensime-startup-snapshot-notification nil
ensime-startup-notification nil ensime-startup-notification nil
ensime-eldoc-hints 'all ensime-eldoc-hints 'all
@ -23,3 +26,9 @@
(def-package! sbt-mode (def-package! sbt-mode
:after scala-mode :after scala-mode
:config (set-repl-handler! 'scala-mode #'run-scala)) :config (set-repl-handler! 'scala-mode #'run-scala))
(def-package! lsp-scala
:when (featurep! +lsp)
:after scala-mode
:init (add-hook 'scala-mode-hook #'+lsp|init))

View file

@ -1,6 +1,9 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; lang/scala/packages.el ;;; lang/scala/packages.el
(package! ensime)
(package! sbt-mode) (package! sbt-mode)
(package! scala-mode) (package! scala-mode)
(if (featurep! +lsp)
(package! lsp-scala)
(package! ensime))

View file

@ -5,14 +5,21 @@
(def-package! flycheck-swift (def-package! flycheck-swift
:when (featurep! :feature syntax-checker) :when (and (featurep! :feature syntax-checker)
(not (featurep! +lsp)))
:after swift-mode :after swift-mode
:config (flycheck-swift-setup)) :config (flycheck-swift-setup))
(def-package! company-sourcekit (def-package! company-sourcekit
:when (featurep! :completion company) :when (and (featurep! :completion company)
(not (featurep! +lsp)))
:after swift-mode :after swift-mode
:config :config
(set-company-backend! 'swift-mode '(company-sourcekit company-yasnippet))) (set-company-backend! 'swift-mode '(company-sourcekit company-yasnippet)))
(def-package! lsp-sourcekit
:when (featurep! +lsp)
:after swift-mode
:init (add-hook 'swift-mode-hook #'+lsp|init))

View file

@ -3,8 +3,9 @@
(package! swift-mode) (package! swift-mode)
(when (featurep! :completion company) (if (featurep! +lsp)
(package! company-sourcekit)) (package! lsp-sourcekit)
(when (featurep! :completion company)
(when (featurep! :feature syntax-checker) (package! company-sourcekit))
(package! flycheck-swift)) (when (featurep! :feature syntax-checker)
(package! flycheck-swift)))

View file

@ -35,6 +35,10 @@
;; ;;
;; Tools ;; Tools
(when (featurep! +lsp)
(add-hook! (css-mode sass-mode less-css-mode) #'+lsp|init))
(def-package! counsel-css (def-package! counsel-css
:when (featurep! :completion ivy) :when (featurep! :completion ivy)
:commands counsel-css :commands counsel-css

View file

@ -139,3 +139,7 @@
(set-company-backend! 'web-mode 'company-web-html)) (set-company-backend! 'web-mode 'company-web-html))
(after! slim-mode (after! slim-mode
(set-company-backend! 'slim-mode 'company-web-slim)) (set-company-backend! 'slim-mode 'company-web-slim))
(when (featurep! +lsp)
(add-hook! (html-mode web-mode) #'+lsp|init))

View file

@ -0,0 +1,7 @@
;;; feature/lsp/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +lsp|init ()
"Enable LSP as late as possible, to allow users to customize it via file or
dir local variables."
(add-hook 'hack-local-variables-hook #'lsp nil t))

View file

@ -0,0 +1,21 @@
;;; tools/lsp/config.el -*- lexical-binding: t; -*-
(def-package! lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:config
(setq lsp-prefer-flymake nil
lsp-ui-doc-max-height 8
lsp-ui-doc-max-width 35
lsp-ui-sideline-ignore-duplicate t)
(define-key! lsp-ui-mode-map
[remap xref-find-definitions] #'lsp-ui-peek-find-definitions
[remap xref-find-references] #'lsp-ui-peek-find-references)
(set-lookup-handlers! 'lsp-ui-mode
:definition #'lsp-ui-peek-find-definitions
:references #'lsp-ui-peek-find-references))
(def-package! company-lsp
:when (featurep! :completion company)
:after lsp-mode
:config
(set-company-backend! 'lsp-mode 'company-lsp))

View file

@ -0,0 +1,7 @@
;; -*- no-byte-compile: t; -*-
;;; tools/lsp/packages.el
(package! lsp-mode)
(package! lsp-ui)
(when (featurep! :completion company)
(package! company-lsp))