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
;;ein ; tame Jupyter notebooks with emacs
;;gist ; interacting with github gists
;;lsp
;;macos ; MacOS-specific commands
;;magit ; a git porcelain for Emacs
;;make ; run make tasks from Emacs

View file

@ -125,7 +125,7 @@ compilation database is present in the project.")
(def-package! irony
:when (featurep! +irony)
:unless (featurep! +lsp)
:commands (irony-install-server irony-mode)
:preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
@ -181,7 +181,7 @@ compilation database is present in the project.")
;; Rtags Support
(def-package! rtags
:when (featurep! +rtags)
:unless (featurep! +lsp)
:commands rtags-executable-find
:preface
(setq rtags-install-path (concat doom-etc-dir "rtags/"))
@ -219,3 +219,22 @@ compilation database is present in the project.")
(when (featurep 'evil)
(add-hook 'rtags-jump-hook #'evil-set-jump))
(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)
(package! company-glsl :recipe (:fetcher github :repo "Kaali/company-glsl"))))
(when (featurep! +irony)
(package! irony)
(if (featurep! +lsp)
(package! cquery)
(when (package! irony)
(package! irony-eldoc)
(when (featurep! :feature syntax-checker)
(package! flycheck-irony))
(when (featurep! :completion company)
(package! company-irony)
(package! company-irony-c-headers)))
(when (featurep! +rtags)
(package! rtags)
(when (package! rtags)
(when (featurep! :completion ivy)
(package! ivy-rtags))
(when (featurep! :completion helm)
(package! helm-rtags)))
(package! helm-rtags))))

View file

@ -20,7 +20,9 @@
"gofmt"
"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
:localleader
@ -57,7 +59,8 @@
(def-package! company-go
:when (featurep! :completion company)
:when (and (featurep! :completion company)
(not (featurep! +lsp)))
:after go-mode
:config
(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)
(cond ((featurep! +meghanada) (load! "+meghanada"))
(cond ((featurep! +lsp) (load! "+lsp"))
((featurep! +meghanada) (load! "+meghanada"))
;; TODO lang/java +lsp (lsp-java?)
;; ((featurep! +lsp) (load! "+lsp"))
)

View file

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

View file

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

View file

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

View file

@ -1,5 +1,9 @@
;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
(when (featurep! +lsp)
(add-hook! (tuareg-mode reason-mode) #'+lsp|init))
(after! tuareg
;; tuareg-mode has the prettify symbols itself
(set-pretty-symbols! 'tuareg-mode :alist
@ -18,6 +22,7 @@
(def-package! merlin
:unless (featurep! +lsp)
:defer t
:init
(defun +ocaml|init-merlin ()
@ -37,7 +42,20 @@
(map! :localleader
:map tuareg-mode-map
"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
@ -53,22 +71,6 @@
(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
:when (featurep! :feature eval)
:defer t ; loaded by hook below

View file

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

View file

@ -5,9 +5,10 @@
(package! php-extras :recipe (:fetcher github :repo "arnested/php-extras"))
(package! php-mode)
(package! php-refactor-mode)
(package! phpactor :recipe (:fetcher github :repo "emacs-php/phpactor.el" :files ("*")))
(package! phpunit)
(when (featurep! +hack)
(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"
: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
(sp-local-pair 'python-mode "'" nil
:unless '(sp-point-before-word-p
@ -63,6 +66,7 @@ called.")
(def-package! anaconda-mode
:unless (featurep! +lsp)
:hook python-mode
:init
(setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/")

View file

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

View file

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

View file

@ -5,6 +5,9 @@
(set-docsets! 'rust-mode "Rust")
(setq rust-indent-method-chain t)
(when (featurep! +lsp)
(add-hook 'rust-mode-hook #'+lsp|init))
(map! :map rust-mode-map
:localleader
:prefix "b"
@ -15,6 +18,7 @@
(def-package! racer
:unless (featurep! +lsp)
:after rust-mode
:config
(add-hook 'rust-mode-hook #'racer-mode)
@ -27,4 +31,3 @@
:when (featurep! :feature syntax-checker)
:after rust-mode
: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))))
(after! ensime
(def-package! ensime
:unless (featurep! +lsp)
:defer t
:config
(setq ensime-startup-snapshot-notification nil
ensime-startup-notification nil
ensime-eldoc-hints 'all
@ -23,3 +26,9 @@
(def-package! sbt-mode
:after scala-mode
: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; -*-
;;; lang/scala/packages.el
(package! ensime)
(package! sbt-mode)
(package! scala-mode)
(if (featurep! +lsp)
(package! lsp-scala)
(package! ensime))

View file

@ -5,14 +5,21 @@
(def-package! flycheck-swift
:when (featurep! :feature syntax-checker)
:when (and (featurep! :feature syntax-checker)
(not (featurep! +lsp)))
:after swift-mode
:config (flycheck-swift-setup))
(def-package! company-sourcekit
:when (featurep! :completion company)
:when (and (featurep! :completion company)
(not (featurep! +lsp)))
:after swift-mode
:config
(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)
(if (featurep! +lsp)
(package! lsp-sourcekit)
(when (featurep! :completion company)
(package! company-sourcekit))
(when (featurep! :feature syntax-checker)
(package! flycheck-swift))
(package! flycheck-swift)))

View file

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

View file

@ -139,3 +139,7 @@
(set-company-backend! 'web-mode 'company-web-html))
(after! slim-mode
(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))