Skip to content

Commit

Permalink
[crystal] Add lsp support and revise key bindings
Browse files Browse the repository at this point in the history
Also fixed not working flycheck integration.
  • Loading branch information
smile13241324 committed Nov 10, 2020
1 parent 48f2591 commit c3872f1
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 48 deletions.
75 changes: 57 additions & 18 deletions layers/+lang/crystal/README.org
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
- [[#description][Description]]
- [[#features][Features:]]
- [[#install][Install]]
- [[#configuration][Configuration]]
- [[#choosing-a-backend][Choosing a backend]]
- [[#company-crystal][company-crystal]]
- [[#lsp][LSP]]
- [[#repl][REPL]]
- [[#ameba][Ameba]]
- [[#layer][Layer]]
- [[#key-bindings][Key bindings]]
- [[#crystal-commands][Crystal commands]]
- [[#repl-1][REPL]]
Expand All @@ -20,19 +23,60 @@
This layer provides support for the Crystal language.

** Features:
- =crystal tool format= on file save
- integration [[https://play.crystal-lang.org][play.crystal-lang.org]] using [[https://github.com/veelenga/play-crystal.el][play-crystal.el]]
- Linting with flycheck
- test runner (=crystal spec=)
- Format on save
- Integration of [[https://play.crystal-lang.org][play.crystal-lang.org]] using [[https://github.com/veelenga/play-crystal.el][play-crystal.el]]
- Syntax checking
- Auto completion
- Test execution (=crystal spec=)
- =crystal tool= integration
- Interactive REPL ([[https://github.com/brantou/inf-crystal.el][inf-crystal.el]] and [[https://github.com/crystal-community/icr][icr]])
- static code analysis using [[https://github.com/veelenga/ameba.el][ameba]]
- Static code analysis using [[https://github.com/veelenga/ameba.el][ameba]]

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

* Configuration
All layer configurations can be done by setting layer variables in your dotfile.
No custom user config lines are necessary

** Choosing a backend
This layer provides two alternative backends to choose from.

*** Company-crystal
This is the default choice if nothing is set and no lsp layer
is loaded in your dotfile. This mode only provides very
limited IDE capabilities. Used best if only small files
are edited. To set explicitly set the following in your
dotfile:

#+BEGIN_SRC emacs-lisp
(crystal :variables crystal-backend 'company-crystal)
#+END_SRC

*** LSP
For proper IDE support this backend should be used. It is
based on an external server which will be started automatically
by emacs, once a crystal file is opened. The key bindings are
the same for all lsp modes so if you are already familiar with
one you should be able to work the same in all modes.

To set explicitly do the following in your dotfile:

#+BEGIN_SRC emacs-lisp
(crystal :variables
crystal-backend 'lsp)
#+END_SRC

For this to work you will also need to obtain
the latest version of the lsp server from [[https://github.com/crystal-lang-tools/scry#installation][here]].

NOTE: Key bindings for LSP are defined in the
LSP layer. Also it is advisable to have a look
at the autocomplete layer for an optimal
intellisense config for LSP.

** REPL
To be able to connect to [[https://github.com/brantou/inf-crystal.el][inf-crystal]], you need to make sure that [[https://github.com/crystal-community/icr][icr]] is
installed.
Expand All @@ -51,11 +95,6 @@ To be able to use [[https://github.com/veelenga/ameba.el][ameba.el]], you need t

Installation instructions can be found on the main page of [[https://github.com/veelenga/ameba][ameba]].

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

* Key bindings
** Crystal commands

Expand All @@ -74,11 +113,11 @@ file.
| ~SPC m u e~ | show macro expansion |
| ~SPC m u f~ | format the current buffer |
| ~SPC m u i~ | show implementations for given call |
| ~SPC m x x~ | run =crystal run= for the current file |
| ~SPC m a x~ | run =crystal run= for the current file |

** REPL
Start a inferior crystal REPL process with ~SPC m '​~ or ~SPC m s i~.
Send code to inferior process commands:
Then you can send code to it with the bindings below:

| Key binding | Description |
|-------------+---------------------------------------------|
Expand All @@ -94,8 +133,8 @@ Send code to inferior process commands:

** Ameba

| Key binding | Description |
|-------------+------------------------------------------------|
| ~SPC m a d~ | Prompts from a directory on which to run Ameba |
| ~SPC m a f~ | Runs Ameba on the current visited file |
| ~SPC m a p~ | Runs Ameba on the entire project |
| Key binding | Description |
|---------------+------------------------------------------------|
| ~SPC m u a d~ | Prompts from a directory on which to run Ameba |
| ~SPC m u a f~ | Runs Ameba on the current visited file |
| ~SPC m u a p~ | Runs Ameba on the entire project |
5 changes: 5 additions & 0 deletions layers/+lang/crystal/config.el
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@

(defvar crystal-enable-auto-format nil
"If non-nil then auto-format on save.")

(defvar crystal-backend nil
"The backend to use for IDE features.
Possible values are `lsp' and `company-crystal'.
If `nil' then 'company-crystal` is the default backend unless `lsp' layer is used")
26 changes: 26 additions & 0 deletions layers/+lang/crystal/funcs.el
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,29 @@
(shell-command
(format "crystal run %s"
(shell-quote-argument (buffer-file-name))))))

(defun spacemacs//crystal-backend ()
"Return selected backend."
(if crystal-backend
crystal-backend
(cond
((configuration-layer/layer-used-p 'lsp) 'lsp)
(t 'company-crystal))))

(defun spacemacs//crystal-setup-company ()
"Conditionally setup company based on backend."
(pcase (spacemacs//crystal-backend)
;; Activate lsp company explicitly to activate
;; standard backends as well
(`lsp (spacemacs|add-company-backends
:backends company-capf
:modes crystal-mode))
(`company-crystal (spacemacs|add-company-backends
:backends company-capf
:modes crystal-mode
:variables company-tooltip-align-annotations t))))

(defun spacemacs//crystal-setup-backend ()
"Conditionally setup crystal backend."
(pcase (spacemacs//crystal-backend)
(`lsp (lsp))))
14 changes: 14 additions & 0 deletions layers/+lang/crystal/layers.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
;;; layers.el --- Crystal Layer layers File for Spacemacs
;;
;; Copyright (c) 2012-2020 Sylvain Benner & Contributors
;;
;; Author: Maximilian Wolff <smile13241324@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3

(when (and (boundp 'crystal-backend)
(eq crystal-backend 'lsp))
(configuration-layer/declare-layer-dependencies '(lsp)))
49 changes: 20 additions & 29 deletions layers/+lang/crystal/packages.el
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
;;; License: GPLv3

(defconst crystal-packages
'(
(ameba :location (recipe :fetcher github
'((ameba :location (recipe :fetcher github
:repo "veelenga/ameba.el"
:files ("ameba.el")))
company
Expand All @@ -20,38 +19,35 @@
(flycheck-crystal :requires flycheck)
inf-crystal
ob-crystal
play-crystal
))
play-crystal))

(defun crystal/post-init-company ()
(spacemacs//crystal-setup-company))

(defun crystal/init-ameba()
(use-package ameba
:defer t
:init (add-hook 'crystal-mode-hook 'ameba-mode)
:config
:init
(progn
(spacemacs/declare-prefix-for-mode 'crystal-mode "ma" "ameba")
(add-hook 'crystal-mode-hook 'ameba-mode)
(spacemacs/declare-prefix-for-mode 'crystal-mode "mua" "ameba")
(spacemacs/set-leader-keys-for-major-mode 'crystal-mode
"ad" 'ameba-check-directory
"af" 'ameba-check-current-file
"ap" 'ameba-check-project))))

(defun crystal/post-init-company()
(spacemacs|add-company-backends
:backends company-capf
:modes crystal-mode
:variables company-tooltip-align-annotations t))
"uad" 'ameba-check-directory
"uaf" 'ameba-check-current-file
"uap" 'ameba-check-project))))

(defun crystal/init-crystal-mode()
(use-package crystal-mode
:defer t
:config
:init
(progn
(add-hook 'crystal-mode-hook 'spacemacs//crystal-auto-format-setup)

(spacemacs/declare-prefix-for-mode 'crystal-mode "mg" "goto")
(spacemacs/declare-prefix-for-mode 'crystal-mode "mt" "test")
(add-hook 'crystal-mode-hook #'spacemacs//crystal-setup-backend)
(spacemacs/declare-prefix-for-mode 'crystal-mode "mu" "tool")
(spacemacs/declare-prefix-for-mode 'crystal-mode "mx" "execute")
(unless (eq (spacemacs//crystal-backend) 'lsp)
(spacemacs/declare-prefix-for-mode 'crystal-mode "mg" "goto")
(spacemacs/declare-prefix-for-mode 'crystal-mode "mt" "test")
(spacemacs/declare-prefix-for-mode 'crystal-mode "ma" "action"))
(spacemacs/set-leader-keys-for-major-mode 'crystal-mode
"ga" 'crystal-spec-switch
"tb" 'crystal-spec-buffer
Expand All @@ -60,25 +56,21 @@
"ue" 'crystal-tool-expand
"uf" 'crystal-tool-format
"ui" 'crystal-tool-imp
"xx" 'spacemacs/crystal-run-main))))
"ax" 'spacemacs/crystal-run-main))))

(defun crystal/post-init-flycheck()
(spacemacs/enable-flycheck 'crystal-mode))

(defun crystal/init-flycheck-crystal ()
(use-package flycheck-crystal
:defer t
:init (add-hook 'crystal-mode-hook 'flycheck-mode)))
(use-package flycheck-crystal))

(defun crystal/init-inf-crystal()
(use-package inf-crystal
:defer t
:init
(progn
(spacemacs/register-repl 'inf-crystal 'inf-crystal "inf-crystal")
(add-hook 'crystal-mode-hook 'inf-crystal-minor-mode))
:config
(progn
(add-hook 'crystal-mode-hook 'inf-crystal-minor-mode)
(spacemacs/declare-prefix-for-mode 'crystal-mode "ms" "repl")
(spacemacs/set-leader-keys-for-major-mode 'crystal-mode
"'" 'inf-crystal
Expand Down Expand Up @@ -109,4 +101,3 @@
"ee" 'play-crystal-browse
"ei" 'play-crystal-insert
"er" 'play-crystal-submit-region))))

2 changes: 1 addition & 1 deletion layers/+lang/fsharp/README.org
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ intellisense config for LSP.
|--------------------------+------------------------------------------------------------------|
| ~SPC m s b~ | Send buffer to the REPL |
| ~SPC m s B~ | Send buffer to the REPL and switch to the REPL in =insert state= |
| ~SPC m s i~ or ~SPC m '~ | Start a REPL |
| ~SPC m s i~ or ~SPC m '~ | Start a REPL process |
| ~SPC m s p~ | Send phrase to the REPL |
| ~SPC m s P~ | Send phrase to the REPL and switch to the REPL in =insert state= |
| ~SPC m s r~ | Send region to the REPL |
Expand Down

0 comments on commit c3872f1

Please sign in to comment.