Adding Ruby LSP Backend and DAP support

This commit is contained in:
Billy Kaplan 2019-04-18 14:16:01 -04:00 committed by smile13241324
parent 348e996f7d
commit 5a0ab04653
7 changed files with 175 additions and 26 deletions

1
.gitignore vendored
View File

@ -54,6 +54,7 @@ eclipse.jdt.ls
.dap-breakpoints
.lsp-session-*
.trello
.extension
# Private directory
private/

View File

@ -2134,6 +2134,7 @@ Other:
- Added ~SPC m s l~ to send line to REPL (thanks to Paweł Siudak)
- Added the =seeing-is-believing= package (thanks to Brandon Conway)
- Added prefixes for ruby major mode keybindings (thanks to Seong Yong-ju)
- Added =lsp= and =dap= support (thanks to Billy Kaplan)
**** Ruby on Rails
- Changed leader keys to be configured for the =projectile-rails-mode= minor
mode instead of =ruby-mode= and =enh-ruby-mode= so that the key bindings will

View File

@ -8,11 +8,15 @@
- [[#description][Description]]
- [[#features][Features:]]
- [[#install][Install]]
- [[#backends][Backends]]
- [[#robe][Robe]]
- [[#language-server-protocol][Language Server Protocol]]
- [[#prerequisites][Prerequisites]]
- [[#ruby-version-management][Ruby version management]]
- [[#test-runner][Test runner]]
- [[#key-bindings][Key bindings]]
- [[#ruby-enh-ruby-mode-robe-inf-ruby-ruby-tools][Ruby (enh-ruby-mode, robe, inf-ruby, ruby-tools)]]
- [[#debugger][Debugger]]
- [[#bundler][Bundler]]
- [[#rubocop][RuboCop]]
- [[#tests][Tests]]
@ -50,6 +54,22 @@ This layer supports two different Ruby modes: Emacs's built-in Ruby Mode and
'((ruby :variables ruby-enable-enh-ruby-mode t)))
#+END_SRC
** Backends
*** Robe
The default Ruby-mode backend. See Prerequisites for the necessary Gems to support Robe.
*** Language Server Protocol
IDE-like backend for Ruby. The only prerequisite gem is =solargraph= which can be
installed globally with:
#+BEGIN_SRC sh
gem install solargraph
#+END_SRC
LSP also supports the DAP debugger which will be automatically configured upon
using the LSP backend. Dap-mode can be setup here:
https://github.com/emacs-lsp/dap-mode#ruby
** Prerequisites
Some of the advanced features supported by this layer depend on external gems
that need to be installed in the context of your project (see below for guidance
@ -58,6 +78,7 @@ based on your version manager):
- =ruby_parser= is required for *goto-step_definition* in =feature-mode=
- =rubocop= is required for rubocop integration
- =seeing_is_believing= helps you evaluate code inline
- =solargraph= is required for using the language server protocol in =ruby-mode=
You can install the gems in the context of your current project by
adding them to the =Gemfile=, e.g.:
@ -129,6 +150,53 @@ directory local variables.
| ~SPC m x h~ | toggle hash syntax in active region |
| ~%~ | [[https://github.com/redguardtoo/evil-matchit][evil-matchit]] jumps between blocks |
** Debugger
| Key binding | Description |
|---------------+---------------------------------|
| ~SPC m d d d~ | start debugging |
| ~SPC m d d l~ | debug last configuration |
| ~SPC m d d r~ | debug recent configuration |
|---------------+---------------------------------|
| ~SPC m d c~ | continue |
| ~SPC m d i~ | step in |
| ~SPC m d o~ | step out |
| ~SPC m d s~ | next step |
| ~SPC m d v~ | inspect value at point |
| ~SPC m d r~ | restart frame |
|---------------+---------------------------------|
| ~SPC m d .~ | debug transient state |
|---------------+---------------------------------|
| ~SPC m d a~ | abandon current session |
| ~SPC m d A~ | abandon all process |
|---------------+---------------------------------|
| ~SPC m d e e~ | eval |
| ~SPC m d e r~ | eval region |
| ~SPC m d e t~ | eval value at point |
|---------------+---------------------------------|
| ~SPC m d S s~ | switch session |
| ~SPC m d S t~ | switch thread |
| ~SPC m d S f~ | switch frame |
|---------------+---------------------------------|
| ~SPC m d I i~ | inspect |
| ~SPC m d I r~ | inspect region |
| ~SPC m d I t~ | inspect value at point |
|---------------+---------------------------------|
| ~SPC m d b b~ | toggle a breakpoint |
| ~SPC m d b c~ | change breakpoint condition |
| ~SPC m d b l~ | change breakpoint log condition |
| ~SPC m d b h~ | change breakpoint hit count |
| ~SPC m d b a~ | add a breakpoint |
| ~SPC m d b d~ | delete a breakpoint |
| ~SPC m d b D~ | clear all breakpoints |
|---------------+---------------------------------|
| ~SPC m d '_~ | Run debug REPL |
|---------------+---------------------------------|
| ~SPC m d w l~ | list local variables |
| ~SPC m d w o~ | goto output buffer if present |
| ~SPC m d w s~ | list sessions |
| ~SPC m d w b~ | list breakpoints |
** Bundler
| Key binding | Description |
@ -144,12 +212,12 @@ directory local variables.
| Key binding | Description |
|---------------+------------------------------------------------------|
| ~SPC m r r f~ | Runs RuboCop on the currently visited file |
| ~SPC m r r F~ | Runs auto-correct on the currently visited file |
| ~SPC m r r d~ | Prompts from a directory on which to run RuboCop |
| ~SPC m r r D~ | Prompts for a directory on which to run auto-correct |
| ~SPC m r r p~ | Runs RuboCop on the entire project |
| ~SPC m r r P~ | Runs auto-correct on the project |
| ~SPC m R r f~ | Runs RuboCop on the currently visited file |
| ~SPC m R r F~ | Runs auto-correct on the currently visited file |
| ~SPC m R r d~ | Prompts from a directory on which to run RuboCop |
| ~SPC m R r D~ | Prompts for a directory on which to run auto-correct |
| ~SPC m R r p~ | Runs RuboCop on the entire project |
| ~SPC m R r P~ | Runs auto-correct on the project |
** Tests
*** RSpec-mode
@ -228,3 +296,4 @@ When =ruby-test-runner= equals =minitest=.
| =ruby-version-manager= | =nil= | If non nil, defines the Ruby version manager.Possible values are =rbenv=, =rvm= or =chruby=. |
| =ruby-test-runner= | =ruby-test= | Test runner to use. Possible values are =ruby-test=, =minitest= or =rspec=. |
| =ruby-highlight-debugger-keywords= | =t= | If non-nil, enable highlight for debugger keywords. |
| =ruby-backend= | =robe= | Defines the backend for IDE feature. Possible values are =robe= or =lsp=. |

View File

@ -14,6 +14,10 @@
(spacemacs|define-jump-handlers enh-ruby-mode)
(spacemacs|define-jump-handlers ruby-mode)
(defvar ruby-backend 'robe
"Defines the backend for IDE features, defaulting to robe.
Possible values are `robe', and `lsp'.")
(defvar ruby-enable-enh-ruby-mode nil
"If non-nil, use `enh-ruby-mode' package instead of the built-in Ruby Mode.")

View File

@ -9,6 +9,60 @@
;;
;;; License: GPLv3
;; backend
(defun spacemacs//ruby-setup-backend ()
"Conditionally configure Ruby backend"
(spacemacs//ruby-setup-version-manager)
(pcase ruby-backend
(`lsp (spacemacs//ruby-setup-lsp))
(`robe (spacemacs//ruby-setup-robe))))
(defun spacemacs//ruby-setup-company ()
"Configure backend company"
(pcase ruby-backend
(`robe (spacemacs//ruby-setup-robe-company))
(`lsp nil))) ;; Company is automatically set up by lsp
;; lsp
(defun spacemacs//ruby-setup-lsp ()
"Setup Ruby lsp."
(if (configuration-layer/layer-used-p 'lsp)
(lsp)
(message "`lsp' layer is not installed, please add `lsp' layer to your dotfile."))
(if (configuration-layer/layer-used-p 'dap)
(progn
(require 'dap-ruby)
(spacemacs/dap-bind-keys-for-mode 'ruby-mode))
(message "`dap' layer is not installed, please add `dap' layer to your dotfile.")))
;; robe
(defun spacemacs//ruby-setup-robe ()
(robe-mode))
(defun spacemacs//ruby-setup-robe-company ()
"Setup robe auto-completion."
(when (configuration-layer/package-used-p 'robe)
(spacemacs|add-company-backends
:backends company-robe
:modes ruby-mode enh-ruby-mode))
(with-eval-after-load 'company-dabbrev-code
(dolist (mode '(ruby-mode enh-ruby-mode))
(add-to-list 'company-dabbrev-code-modes mode))))
;; version manager
(defun spacemacs//ruby-setup-version-manager ()
"Setup ruby version manager."
(pcase ruby-version-manager
(`rbenv (spacemacs//enable-rbenv))))
;; rbenv

View File

@ -52,13 +52,7 @@
"bo" 'bundle-open))))
(defun ruby/post-init-company ()
(when (configuration-layer/package-used-p 'robe)
(spacemacs|add-company-backends
:backends company-robe
:modes ruby-mode enh-ruby-mode))
(with-eval-after-load 'company-dabbrev-code
(dolist (mode '(ruby-mode enh-ruby-mode))
(add-to-list 'company-dabbrev-code-modes mode))))
(add-hook 'ruby-mode-local-vars-hook #'spacemacs//ruby-setup-company))
(defun ruby/init-chruby ()
(use-package chruby
@ -78,9 +72,12 @@
(progn
(setq enh-ruby-deep-indent-paren nil
enh-ruby-hanging-paren-deep-indent-level 2)
(spacemacs/declare-prefix-for-mode 'enh-ruby-mode "mr" "refactor/RuboCop/robe")
(spacemacs/declare-prefix-for-mode 'enh-ruby-mode "mr" "refactor/robe")
(spacemacs/declare-prefix-for-mode 'enh-ruby-mode "mt" "test")
(spacemacs/declare-prefix-for-mode 'enh-ruby-mode "mT" "toggle"))
(spacemacs/declare-prefix-for-mode 'enh-ruby-mode "mT" "toggle")
(spacemacs/add-to-hooks #'spacemacs//ruby-setup-backend
'(ruby-mode-hook enh-ruby-mode-hook)))
:config
(spacemacs/set-leader-keys-for-major-mode 'enh-ruby-mode
"T{" 'enh-ruby-toggle-block)))
@ -147,12 +144,11 @@
(defun ruby/init-rbenv ()
(use-package rbenv
:if (equal ruby-version-manager 'rbenv)
:defer t
:init (spacemacs/add-to-hooks 'spacemacs//enable-rbenv
'(ruby-mode-hook enh-ruby-mode-hook))))
:defer t))
(defun ruby/init-robe ()
(use-package robe
:if (eq ruby-backend 'robe)
:defer t
:init
(progn
@ -225,14 +221,14 @@
:init (spacemacs/add-to-hooks 'rubocop-mode '(ruby-mode-hook
enh-ruby-mode-hook))
:config (dolist (mode '(ruby-mode enh-ruby-mode))
(spacemacs/declare-prefix-for-mode mode "mrr" "RuboCop")
(spacemacs/declare-prefix-for-mode mode "mR" "RuboCop")
(spacemacs/set-leader-keys-for-major-mode mode
"rrd" 'rubocop-check-directory
"rrD" 'rubocop-autocorrect-directory
"rrf" 'rubocop-check-current-file
"rrF" 'rubocop-autocorrect-current-file
"rrp" 'rubocop-check-project
"rrP" 'rubocop-autocorrect-project))))
"Rd" 'rubocop-check-directory
"RD" 'rubocop-autocorrect-directory
"Rf" 'rubocop-check-current-file
"RF" 'rubocop-autocorrect-current-file
"Rp" 'rubocop-check-project
"RP" 'rubocop-autocorrect-project))))
(defun ruby/init-ruby-mode ()
(use-package ruby-mode
@ -241,9 +237,14 @@
("Puppetfile" . ruby-mode))
:init
(progn
(spacemacs/declare-prefix-for-mode 'ruby-mode "mr" "refactor/RuboCop/robe")
(spacemacs/declare-prefix-for-mode 'ruby-mode "mr" "refactor/robe")
(spacemacs/declare-prefix-for-mode 'ruby-mode "mt" "test")
(spacemacs/declare-prefix-for-mode 'ruby-mode "mT" "toggle")
;; setup version manager which is necessary to find gems in path for backend
(spacemacs//ruby-setup-version-manager)
(spacemacs/add-to-hooks #'spacemacs//ruby-setup-backend
'(ruby-mode-hook enh-ruby-mode-hook))
(spacemacs/add-to-hooks
'spacemacs/ruby-maybe-highlight-debugger-keywords
'(ruby-mode-local-vars-hook enh-ruby-mode-local-vars-hook)))

19
layers/+lang/ruby/test.rb Normal file
View File

@ -0,0 +1,19 @@
class HelloWorld
# Top level class
attr_reader :hello_s
def initialize(hello_s:)
@hello_s = hello_s
end
def say_hello
puts hello_s
end
def run
say_hello
end
end
hello_world = HelloWorld.new(hello_s: 'Hello')
hello_world.say_hello