java: multiple backends support

Define multiple dispatch functions for each service:
- spacemacs//java-setup-backend
- spacemacs//java-setup-auto-completion
- spacemacs//java-setup-syntax-checking
- spacemacs//java-setup-spell-checking
- spacemacs//java-setup-eldoc

java: replace ensime-configure-keybindings function by a variable

It's not convenient to have key bindings in funcs.el file, instead of relying
on a function we define a private layer variable java--ensime-modes which
can be updated by other layers using a :pre-config use-package hook.

java: refactor key bindings

- define key bindings for meghanada back-end
- move ensime key bindings documentation from scala layer to java layer
- change SPC m d for daemon to SPC m D (since SPC m d is reserved for debugging)
This commit is contained in:
syl20bnr 2017-02-09 17:22:38 -05:00
parent 12827c03d8
commit dd85084826
8 changed files with 985 additions and 546 deletions

View File

@ -6,73 +6,152 @@
- [[#description][Description]]
- [[#layer-installation][Layer Installation]]
- [[#layer][Layer]]
- [[#backends][Backends]]
- [[#eclim][Eclim]]
- [[#installation][Installation]]
- [[#eclipse][Eclipse]]
- [[#eclim-1][Eclim]]
- [[#configuration][Configuration]]
- [[#usage][Usage]]
- [[#ensime][Ensime]]
- [[#ensime][ENSIME]]
- [[#installation-1][Installation]]
- [[#usage-1][Usage]]
- [[#issues][Issues]]
- [[#meghanada][Meghanada]]
- [[#installation-2][Installation]]
- [[#about-maven][About Maven]]
- [[#key-bindings][Key bindings]]
- [[#java-mode][Java-mode]]
- [[#project-management][Project management]]
- [[#eclimd][Eclimd]]
- [[#maven][Maven]]
- [[#goto][Goto]]
- [[#refactoring][Refactoring]]
- [[#documentation-find][Documentation, Find]]
- [[#problems][Problems]]
- [[#tests][Tests]]
- [[#problems-buffer][Problems buffer]]
- [[#projects-buffer][Projects buffer]]
- [[#eclim-2][Eclim]]
- [[#java-mode][Java-mode]]
- [[#project-management][Project management]]
- [[#eclim-daemon][Eclim daemon]]
- [[#maven][Maven]]
- [[#goto][Goto]]
- [[#refactoring][Refactoring]]
- [[#documentation-find][Documentation, Find]]
- [[#errors-problems][Errors (problems)]]
- [[#tests][Tests]]
- [[#errors-problems-buffer][Errors (problems) buffer]]
- [[#projects-buffer][Projects buffer]]
- [[#ensime-1][Ensime]]
- [[#search][Search]]
- [[#sbt][sbt]]
- [[#typecheck][Typecheck]]
- [[#debug][Debug]]
- [[#errors][Errors]]
- [[#goto-1][Goto]]
- [[#print-and-yank-types][Print and yank types]]
- [[#documentation-inspect][Documentation, Inspect]]
- [[#server][Server]]
- [[#refactoring-1][Refactoring]]
- [[#tests-1][Tests]]
- [[#repl][REPL]]
- [[#meghanada-1][Meghanada]]
- [[#server-1][Server]]
- [[#navigation][Navigation]]
- [[#compilation][Compilation]]
- [[#tests-junit][Tests (junit)]]
- [[#refactoring-2][Refactoring]]
- [[#tasks][Tasks]]
* Description
This layer adds support for the Java language using the [[http://eclim.org][Eclim]] client/server by
default, or alternatively the [[https://ensime.github.io/][Ensime]] client/server.
This layer adds support for the Java language, it supports multiple backends:
- the [[http://eclim.org][Eclim]] client/server (default),
- the [[https://github.com/mopemope/meghanada-emacs][Meghanada]] client/server,
- the [[https://ensime.github.io/][ENSIME]] client/server.
* Layer Installation
** Layer
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
add =java= to the existing =dotspacemacs-configuration-layers= list in this
file. To choose a backend explicitly,
#+BEGIN_SRC elips
java :variables java-backend 'eclim
file.
* Backends
To choose a default backend set the layer variable =java-backend=:
#+BEGIN_SRC elisp
(java :variables java-backend 'eclim)
#+END_SRC
Backend can be chosen on a per project basis using directory local variables
(files named =.dir-locals.el= at the root of a project), an example to use the
=meghanada= backend:
#+BEGIN_SRC elisp
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((java-mode (java-backend . meghanada)))
#+END_SRC
*Note:* you can easily add a directory local variable with ~SPC f v d~.
** Eclim
Eclim provides the ability to access Eclipse features such as code completion,
searching, code validation, and many more.
searching, code validation, and many more. This is the default value for the
layer variable =java-backend=.
This layers integrates =flycheck= with Eclim and try to be a good compromise
between reactivity and performance.
*** Installation
For installation check the [[http://eclim.org/install.html#download][official page]].
**** Eclipse
First you need the last version of Eclispe from the [[https://www.eclipse.org/downloads/eclipse-packages/][official Eclipse site]].
Then set the =Eclipse= and =Eclim= paths in =dotspacemacs/user-config=,
for instance:
*Note:* if you are on MacOS there some issues between the new native Eclipse
application installed by the =Eclispe-install.app= wizard and the Eclim
installer wizard. The recommended way to install Eclipse on MacOS is by using
=homebrew= or by get the =tar.gz= compressed file instead. With homebrew
the command line to install Eclipse is =brew cask install eclipse-jee=.
#+BEGIN_SRC elisp
(setq eclim-eclipse-dirs '("~/opt/eclipse")
eclim-executable "~/opt/eclipse/eclim")
**** Eclim
For installation of Eclim check the [[http://eclim.org/install.html#download][official page]] to download the installer
then double click on it or launch it in the command line with the following
command (the example is for MacOS, replace the eclispe.home definition by
your correct location as well as the current version of eclim):
#+BEGIN_SRC shell
$ java -Dvim.skip=true -Declipse.home=/Applications/Eclipse.app/Contents/Eclipse -jar eclim_2.6.0.jar install
#+END_SRC
You can also configure other options, as shown below:
*** Configuration
You may need to set the Eclipse and Eclim paths in your dotfile as layer
variables or in the =dotspacemacs/user-config=, for instance on MacOS as layer
variables:
#+BEGIN_SRC elisp
(setq
;; Use another eclimd executable
eclimd-executable "/path/to/another/executable"
;; Specify the workspace to use by default
eclimd-default-workspace "/path/to/default/eclipse/workspace"
;; Whether or not to block emacs until eclimd is ready
eclimd-wait-for-process t)
#+END_SRC
#+BEGIN_SRC elisp
(java :variables java-backend 'eclim
eclim-eclipse-dirs '("/Applications/Eclipse.app/Contents/Eclipse/")
eclim-executable "/Applications/Eclipse.app/Contents/Eclipse/eclim")
#+END_SRC
You can also configure useful other options like the default location for the
Eclim workspace (default value is =~/workspace=), as shown below:
#+BEGIN_SRC elisp
(setq
;; Specify the workspace to use by default
eclimd-default-workspace "/path/to/default/eclipse/workspace"
;; wether autostarting eclimd or not (default nil)
eclimd-autostart t
;; Whether or not to block emacs until eclimd is ready (default nil)
eclimd-wait-for-process t)
#+END_SRC
*** Usage
Start the eclim daemon with ~SPC m d s~ and stop it with ~SPC m d k~. (See
Start the eclim daemon with ~SPC m D s~ and stop it with ~SPC m D k~. (See
below.)
** Ensime
Another backend option is the Ensime server, which is a lot more responsive than
Eclim. It uses the same keybinding setup as the scala layer.
Syntax checking is performed only on save or on demande with ~SPC e e~ to
preserve perfomance.
** ENSIME
:PROPERTIES:
:CUSTOM_ID: ensime
:END:
Another backend option is the ENSIME server, which is a lot more responsive than
Eclim. ENSIME is originally made to work with Scala but it now works with plain
Java projects as well, some calls it ENJIME.
*** Installation
Find it with your favourite package manager, eg:
@ -81,8 +160,7 @@ Find it with your favourite package manager, eg:
#+END_SRC
or refer to [[http://www.scala-sbt.org/download.html][the sbt installation instructions]].
You also need to follow [[https://ensime.github.io/build_tools/sbt/][the Ensime configuration
instructions]] to run Ensime.
You also need to follow [[https://ensime.github.io/build_tools/sbt/][the ENSIME configuration instructions]] to run ENSIME.
To use the build functions under ~SPC m b~ you need to use version =0.13.5= or
newer of =sbt=, and specify that in your project's =project/build.properties=.
@ -93,117 +171,317 @@ For example,
*** Usage
Start the ensime server by running ~SPC SPC ensime~ or ~M-x ensime~.
*** Issues
Ensime is originally built for Scala, so support for java is not complete, in
ENSIME is originally built for Scala, so support for java is not complete, in
particular refactoring doesn't work.
** Meghanada
Meghanada is composed of a lightweight server and an Emacs minor mode. It
is unintrusive and integrates with =company= and =flycheck=.
Both =Gradle= and =Maven= projects are compatible with Meghanada.
*** Installation
The Meghanada server will be installed automatically whenever a Java file
is opened.
If you get issues with the auto-installation you can either download the
server manually [[https://dl.bintray.com/mopemope/meghanada/][there]] or build from source hosted on [[https://github.com/mopemope/meghanada-server][the GitHub repository]]
and copie the =jar= file to =.emacs.d/.cache/meghanada= folder.
No additional configuration is necessary!
*** About Maven
Maven is not fully supported by Meghanada, if you encounter disconnection
from the server then run =mvn install= at the root of your project first.
* Key bindings
** Java-mode
*** Project management
** Eclim
*** Java-mode
**** Project management
| Key Binding | Description |
|-------------+--------------------------------|
| ~SPC m p b~ | Build project |
| ~SPC m p c~ | Create project |
| ~SPC m p d~ | Delete project |
| ~SPC m p g~ | Open file in current project |
| ~SPC m p i~ | Import project |
| ~SPC m p j~ | Information about project |
| ~SPC m p k~ | Close project |
| ~SPC m p o~ | Open project |
| ~SPC m p p~ | Open project management buffer |
| ~SPC m p u~ | Update project |
| Key Binding | Description |
|-------------+--------------------------------|
| ~SPC m p b~ | Build project |
| ~SPC m p c~ | Create project |
| ~SPC m p d~ | Delete project |
| ~SPC m p g~ | Open file in current project |
| ~SPC m p i~ | Import project |
| ~SPC m p j~ | Information about project |
| ~SPC m p k~ | Close project |
| ~SPC m p o~ | Open project |
| ~SPC m p p~ | Open project management buffer |
| ~SPC m p u~ | Update project |
*** Eclimd
**** Eclim daemon
| Key Binding | Description |
|-------------+--------------|
| ~SPC m d s~ | Start daemon |
| ~SPC m d k~ | Stop daemon |
| Key Binding | Description |
|-------------+--------------|
| ~SPC m D k~ | Kill daemon |
| ~SPC m D s~ | Start daemon |
*** Maven
**** Maven
| Key Binding | Description |
|-------------+--------------------------------|
| ~SPC m m i~ | Run maven clean install |
| ~SPC m m I~ | Run maven install |
| ~SPC m m p~ | Run one already goal from list |
| ~SPC m m r~ | Run maven goals |
| ~SPC m m R~ | Run one maven goal |
| ~SPC m m t~ | Run maven test |
| Key Binding | Description |
|-------------+--------------------------------|
| ~SPC m m i~ | Run maven clean install |
| ~SPC m m I~ | Run maven install |
| ~SPC m m p~ | Run one already goal from list |
| ~SPC m m r~ | Run maven goals |
| ~SPC m m R~ | Run one maven goal |
| ~SPC m m t~ | Run maven test |
**** Goto
| Key Binding | Description |
|-------------+---------------------------------------------|
| ~M-,~ | jump back from go to declaration/definition |
| ~SPC m g g~ | go to declaration |
| ~SPC m g t~ | go to type definition |
**** Refactoring
| Key Binding | Description |
|-------------+------------------|
| ~SPC m r i~ | optimize imports |
| ~SPC m r f~ | Format file |
| ~SPC m r r~ | Rename symbol |
**** Documentation, Find
| Key Binding | Description |
|-------------+----------------------------------------|
| ~SPC m f f~ | general find in project |
| ~SPC m h h~ | show documentation for symbol at point |
| ~SPC m h u~ | show usages for symbol at point |
**** Errors (problems)
| Key Binding | Description |
|-------------+--------------------------------------------|
| ~SPC e e~ | Force an error check |
| ~SPC m e a~ | set all problems for next/prev action |
| ~SPC m e b~ | open buffer with problems |
| ~SPC m e c~ | show options with problem corrections |
| ~SPC m e e~ | set only errors for next/prev action |
| ~SPC m e f~ | set only current file for next/prev action |
| ~SPC m e n~ | go to next problem |
| ~SPC m e o~ | open buffer with problems |
| ~SPC m e p~ | go to previous problem |
| ~SPC m e w~ | set warnings for next/prev action |
**** Tests
| Key Binding | Description |
|-------------+---------------------------------------------------------------|
| ~SPC m t t~ | run JUnit tests for current method or current file or project |
*** Errors (problems) buffer
| Key Binding | Description |
|-------------+-------------------------------------|
| ~RET~ | go to problem place |
| ~a~ | show all problems |
| ~e~ | show only errors |
| ~f~ | show problems only for current file |
| ~g~ | refresh problems |
| ~q~ | quit |
| ~w~ | show only warnings |
*** Projects buffer
| Key Binding | Description |
|-------------+--------------------------------------------|
| ~RET~ | go to current project |
| ~c~ | go to problem place |
| ~D~ | delete project |
| ~g~ | refresh buffer |
| ~i~ | info about current project |
| ~I~ | import existing project into the workspace |
| ~m~ | mark current project |
| ~M~ | mark all projects |
| ~N~ | create new project |
| ~o~ | open project |
| ~p~ | update project |
| ~q~ | quit |
| ~R~ | rename current project |
| ~u~ | unmark current project |
| ~U~ | unmark all projects |
** Ensime
:PROPERTIES:
:CUSTOM_ID: ensime-key-bindings
:END:
*** Search
| Key Binding | Description |
|-------------+-----------------------------------------------------|
| ~SPC m /~ | incremental search using =ensime-scalex= major mode |
| ~SPC m ?~ | incremental search in all live buffers |
*** sbt
| Key Binding | Description |
|-------------+---------------------|
| ~SPC m b .~ | sbt transient state |
| ~SPC m b b~ | sbt command |
| ~SPC m b c~ | compile |
| ~SPC m b C~ | clean command |
| ~SPC m b i~ | switch to sbt shell |
| ~SPC m b p~ | package command |
| ~SPC m b r~ | run command |
*** Typecheck
| Key Binding | Description |
|-------------+---------------------------------|
| ~SPC m c t~ | type check the current file |
| ~SPC m c T~ | type check all the open buffers |
*** Debug
| Key Binding | Description |
|-------------+-----------------------------|
| ~SPC m d A~ | Attach to a remote debugger |
| ~SPC m d b~ | set breakpoint |
| ~SPC m d B~ | clear breakpoint |
| ~SPC m d C~ | clear all breakpoints |
| ~SPC m d c~ | continue |
| ~SPC m d i~ | inspect value at point |
| ~SPC m d n~ | next |
| ~SPC m d o~ | step out |
| ~SPC m d q~ | quit |
| ~SPC m d r~ | run |
| ~SPC m d s~ | step |
| ~SPC m d t~ | backtrace |
*Note:* These key bindings need a transient-state, PR welcome :-)
*** Errors
| Key Binding | Description |
|-------------+----------------------------------------------------|
| ~SPC m e e~ | print error at point |
| ~SPC m e l~ | show all errors and warnings |
| ~SPC m e s~ | switch to buffer containing the stack trace parser |
*** Goto
| Key Binding | Description |
|-------------+---------------------------------------------|
| ~M-,~ | jump back from go to declaration/definition |
| ~SPC m g g~ | go to declaration |
| ~SPC m g t~ | go to type definition |
| Key Binding | Description |
|-------------+----------------------|
| ~SPC m g g~ | go to definition |
| ~SPC m g i~ | go to implementation |
| ~SPC m g t~ | go to test |
*** Refactoring
*** Print and yank types
|-------------+--------------------------------|
| ~SPC m h T~ | print full type name at point |
| ~SPC m h t~ | print short type name at point |
| ~SPC m y T~ | yank full type name at point |
| ~SPC m y t~ | yank short type name at point |
| Key Binding | Description |
|-------------+------------------|
| ~SPC m r i~ | optimize imports |
| ~SPC m r f~ | Format file |
| ~SPC m r r~ | Rename symbol |
*** Documentation, Find
*** Documentation, Inspect
| Key Binding | Description |
|-------------+----------------------------------------|
| ~SPC m f f~ | general find in project |
| ~SPC m h h~ | show documentation for symbol at point |
| ~SPC m h u~ | show usages for symbol at point |
| ~SPC m h u~ | show uses for symbol at point |
| ~SPC m i i~ | inspect type at point |
| ~SPC m i I~ | inspect type in other frame |
| ~SPC m i p~ | inspect project package |
*** Problems
*** Server
| Key Binding | Description |
|-------------+--------------------------------------------|
| ~SPC m e a~ | set all problems for next/prev action |
| ~SPC m e b~ | open buffer with problems |
| ~SPC m e c~ | show options with problem corrections |
| ~SPC m e e~ | set only errors for next/prev action |
| ~SPC m e f~ | set only current file for next/prev action |
| ~SPC m e n~ | go to next problem |
| ~SPC m e o~ | open buffer with problems |
| ~SPC m e p~ | go to previous problem |
| ~SPC m e w~ | set warnings for next/prev action |
| Key Binding | Description |
|-------------+--------------------------------------------------------|
| ~SPC m D f~ | reload open files |
| ~SPC m D r~ | regenerate the =.ensime= and restart the ensime server |
| ~SPC m D s~ | start ensime server |
*** Refactoring
| Key Binding | Description |
|-------------+----------------------------------------------------------------------|
| ~SPC m r a~ | add type annotation |
| ~SPC m r f~ | format source |
| ~SPC m r d~ | get rid of an intermediate variable (=ensime-refactor-inline-local=) |
| ~SPC m r D~ | get rid of an intermediate variable (=ensime-undo-peek=) |
| ~SPC m r i~ | organize imports |
| ~SPC m r m~ | extract a range of code into a method |
| ~SPC m r r~ | rename a symbol project wide |
| ~SPC m r t~ | import type at point |
| ~SPC m r v~ | extract a range of code into a variable |
| ~SPC m z~ | expand/contract region |
*** Tests
| Key Binding | Description |
|-------------+---------------------------------------------------------------|
| ~SPC m t t~ | run JUnit tests for current method or current file or project |
| Key Binding | Description |
|-------------+--------------------------|
| ~SPC m t a~ | test command (sbt) |
| ~SPC m t r~ | test quick command (sbt) |
| ~SPC m t t~ | test only (sbt) |
** Problems buffer
*** REPL
| Key Binding | Description |
|-------------+-------------------------------------|
| ~RET~ | go to problem place |
| ~a~ | show all problems |
| ~e~ | show only errors |
| ~f~ | show problems only for current file |
| ~g~ | refresh problems |
| ~q~ | quit |
| ~w~ | show only warnings |
| Key Binding | Description |
|-------------+---------------------------------------------------------------------|
| ~SPC m s a~ | ask for a file to be loaded in the REPL |
| ~SPC m s b~ | send buffer to the REPL |
| ~SPC m s B~ | send buffer to the REPL and focus the REPL buffer in =insert state= |
| ~SPC m s i~ | start or switch to the REPL inferior process |
| ~SPC m s r~ | send region to the REPL |
| ~SPC m s R~ | send region to the REPL and focus the REPL buffer in =insert state= |
** Projects buffer
** Meghanada
*** Server
| Key Binding | Description |
|-------------+--------------------------------------------|
| ~RET~ | go to current project |
| ~c~ | go to problem place |
| ~D~ | delete project |
| ~g~ | refresh buffer |
| ~i~ | info about current project |
| ~I~ | import existing project into the workspace |
| ~m~ | mark current project |
| ~M~ | mark all projects |
| ~N~ | create new project |
| ~o~ | open project |
| ~p~ | update project |
| ~q~ | quit |
| ~R~ | rename current project |
| ~u~ | unmark current project |
| ~U~ | unmark all projects |
| Key Binding | Description |
|-------------+----------------------------------------------|
| ~SPC m D c~ | Connect to server |
| ~SPC m D d~ | Disconnect from server |
| ~SPC m D i~ | Install server (should be done automatically |
| ~SPC m D k~ | Kill server |
| ~SPC m D l~ | Clear server cache |
| ~SPC m D p~ | Ping server |
| ~SPC m D r~ | Restarrt server |
| ~SPC m D s~ | Start server |
| ~SPC m D u~ | Update server |
| ~SPC m D v~ | Print version of the server |
*** Navigation
| Key Binding | Description |
|-------------+--------------------------------|
| ~SPC m g b~ | Jump back to previous location |
| ~SPC m g g~ | Jump to declaration |
*** Compilation
| Key Binding | Description |
|-------------+-----------------------|
| ~SPC m c b~ | Compile file (buffer) |
| ~SPC m c c~ | Compile project |
*** Tests (junit)
| Key Binding | Description |
|-------------+-----------------------------|
| ~SPC m t a~ | Run all tests |
| ~SPC m t c~ | Run test class around point |
| ~SPC m t l~ | Run last tests |
| ~SPC m t t~ | Run test cause around point |
*** Refactoring
| Key Binding | Description |
|-------------+----------------------------------------------|
| ~SPC m =~ | Beautify code |
| ~SPC m r i~ | Optimize imports |
| ~SPC m r I~ | Import all |
*** Tasks
| Key Binding | Description |
|-------------+-------------|
| ~SPC m x :~ | Run task |

View File

@ -3,6 +3,7 @@
;; Copyright (c) 2012-2017 Sylvain Benner & Contributors
;;
;; Author: Lukasz Klich <klich.lukasz@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
@ -12,6 +13,9 @@
(spacemacs|define-jump-handlers java-mode)
(defvar java-backend 'eclim
"The backend to use for IDE features. Possible values are `eclim' and
`ensime'.")
(defvar java-backend 'meghanada
"The backend to use for IDE features. Possible values are `eclim', `ensime'
and `meghanada'.")
(defvar java--ensime-modes '(java-mode)
"Modes using ensime. Mainly used to define ENSIME key bindings.")

View File

@ -24,6 +24,41 @@
(mapc (lambda(x) (spacemacs/declare-prefix-for-mode
'java-mode (car x) (cdr x)))
java/key-binding-prefixes))
(defun spacemacs//java-setup-backend ()
"Conditionally setup java backend."
(pcase java-backend
(`eclim (spacemacs//java-setup-eclim))
(`ensime (spacemacs//java-setup-ensime))
(`meghanada (spacemacs//java-setup-meghanada))))
(defun spacemacs//java-setup-company ()
"Conditionally setup company based on backend."
(pcase java-backend
(`eclim (spacemacs//java-setup-eclim-company))
(`ensime (spacemacs//java-setup-ensime-company))
(`meghanada (spacemacs//java-setup-meghanada-company))))
(defun spacemacs//java-setup-flycheck ()
"Conditionally setup flycheck based on backend."
(pcase java-backend
(`eclim (spacemacs//java-setup-eclim-flycheck))
(`ensime (spacemacs//java-setup-ensime-flycheck))
(`meghanada (spacemacs//java-setup-meghanada-flycheck))))
(defun spacemacs//java-setup-flyspell ()
"Conditionally setup flyspell based on backend."
(pcase java-backend
(`ensime (spacemacs//java-setup-ensime-flyspell))
(`meghanada (spacemacs//java-setup-meghanada-flyspell))))
(defun spacemacs//java-setup-eldoc ()
"Conditionally setup eldoc based on backend."
(pcase java-backend
(`ensime (spacemacs//java-setup-ensime-eldoc))
(`meghanada (spacemacs//java-setup-meghanada-eldoc))))
;; ensime
@ -31,31 +66,43 @@
(autoload 'ensime-config-find "ensime-config")
(autoload 'projectile-project-p "projectile")
(defun spacemacs//ensime-init (mode &optional enable-eldoc auto-start)
(let ((hook (intern (format "%S-hook" mode)))
(jump-handlers (intern (format "spacemacs-jump-handlers-%S" mode))))
(spacemacs/register-repl 'ensime 'ensime-inf-switch "ensime")
(when enable-eldoc
(add-hook 'ensime-mode-hook 'spacemacs//ensime-enable-eldoc))
(add-hook hook 'spacemacs//ensime-configure-flyspell)
(add-hook hook 'spacemacs//ensime-configure)
(when auto-start
(add-hook mode 'spacemacs//ensime-maybe-start))
(add-to-list jump-handlers 'ensime-edit-definition)))
(defun spacemacs//ensime-configure ()
"Ensure the file exists before starting `ensime-mode'."
(defun spacemacs//java-setup-ensime ()
"Setup ENSIME."
;; jump handler
(add-to-list 'spacemacs-jump-handlers 'ensime-edit-definition)
;; ensure the file exists before starting `ensime-mode'
(cond
((and (buffer-file-name) (file-exists-p (buffer-file-name)))
(ensime-mode +1))
(ensime-mode))
((buffer-file-name)
(add-hook 'after-save-hook (lambda () (ensime-mode +1)) nil t))))
(add-hook 'after-save-hook 'ensime-mode nil t))))
(defun spacemacs//java-setup-ensime-company ()
"Setup ENSIME auto-completion.")
(defun spacemacs//java-setup-ensime-flycheck ()
"Setup ENSIME syntax checking.")
(defun spacemacs//java-setup-ensime-flyspell ()
"Setup ENSIME spell checking."
(flyspell-mode)
(setq-local flyspell-generic-check-word-predicate
'spacemacs//ensime-flyspell-verify))
(defun spacemacs//java-setup-ensime-eldoc ()
"Setup ENSIME eldoc."
(setq-local eldoc-documentation-function
(lambda ()
(when (ensime-connected-p)
(ensime-print-type-at-point))))
(eldoc-mode))
(defun spacemacs//ensime-maybe-start ()
(when (buffer-file-name)
(let ((ensime-buffer (spacemacs//ensime-buffer-for-file (buffer-file-name)))
(file (ensime-config-find-file (buffer-file-name)))
(is-source-file (s-matches? (rx (or "/src/" "/test/")) (buffer-file-name))))
(is-source-file (s-matches? (rx (or "/src/" "/test/"))
(buffer-file-name))))
(when (and is-source-file (null ensime-buffer))
(noflet ((ensime-config-find (&rest _) file))
@ -68,115 +115,15 @@
(-when-let (project-name (projectile-project-p))
(--first (-when-let (bufname (buffer-name it))
(and (s-contains? "inferior-ensime-server" bufname)
(s-contains? (file-name-nondirectory project-name) bufname)))
(s-contains? (file-name-nondirectory project-name)
bufname)))
(buffer-list)))))
(defun spacemacs//ensime-enable-eldoc ()
(setq-local eldoc-documentation-function
(lambda ()
(when (ensime-connected-p)
(ensime-print-type-at-point))))
(eldoc-mode +1))
(defun spacemacs//ensime-flyspell-verify ()
"Prevent common flyspell false positives in scala-mode."
(and (flyspell-generic-progmode-verify)
(not (s-matches? (rx bol (* space) "package") (current-line)))))
(defun spacemacs//ensime-configure-flyspell ()
(setq-local flyspell-generic-check-word-predicate 'spacemacs//ensime-flyspell-verify))
;; key bindings
(defun spacemacs/ensime-configure-keybindings (mode)
"Define Ensime key bindings for MODE."
(dolist (prefix '(("mb" . "build")
("mc" . "check")
("md" . "debug")
("me" . "errors")
("mg" . "goto")
("mh" . "docs")
("mi" . "inspect")
("mn" . "ensime")
("mr" . "refactor")
("mt" . "test")
("ms" . "repl")
("my" . "yank")))
(spacemacs/declare-prefix-for-mode mode (car prefix) (cdr prefix)))
(spacemacs/set-leader-keys-for-major-mode mode
"/" 'ensime-search
"'" 'ensime-inf-switch
"bc" 'ensime-sbt-do-compile
"bC" 'ensime-sbt-do-clean
"bi" 'ensime-sbt-switch
"bp" 'ensime-sbt-do-package
"br" 'ensime-sbt-do-run
"ct" 'ensime-typecheck-current-buffer
"cT" 'ensime-typecheck-all
"dA" 'ensime-db-attach
"db" 'ensime-db-set-break
"dB" 'ensime-db-clear-break
"dC" 'ensime-db-clear-all-breaks
"dc" 'ensime-db-continue
"di" 'ensime-db-inspect-value-at-point
"dn" 'ensime-db-next
"do" 'ensime-db-step-out
"dq" 'ensime-db-quit
"dr" 'ensime-db-run
"ds" 'ensime-db-step
"dt" 'ensime-db-backtrace
"ee" 'ensime-print-errors-at-point
"el" 'ensime-show-all-errors-and-warnings
"es" 'ensime-stacktrace-switch
"gp" 'ensime-pop-find-definition-stack
"gi" 'ensime-goto-impl
"gt" 'ensime-goto-test
"hh" 'ensime-show-doc-for-symbol-at-point
"hT" 'ensime-type-at-point-full-name
"ht" 'ensime-type-at-point
"hu" 'ensime-show-uses-of-symbol-at-point
"ii" 'ensime-inspect-type-at-point
"iI" 'ensime-inspect-type-at-point-other-frame
"ip" 'ensime-inspect-project-package
"nF" 'ensime-reload-open-files
"ns" 'ensime
"nS" 'spacemacs/ensime-gen-and-restart
"ra" 'ensime-refactor-add-type-annotation
"rd" 'ensime-refactor-diff-inline-local
"rD" 'ensime-undo-peek
"rf" 'ensime-format-source
"ri" 'ensime-refactor-diff-organize-imports
"rm" 'ensime-refactor-diff-extract-method
"rr" 'ensime-refactor-diff-rename
"rt" 'ensime-import-type-at-point
"rv" 'ensime-refactor-diff-extract-local
"ta" 'ensime-sbt-do-test-dwim
"tr" 'ensime-sbt-do-test-quick-dwim
"tt" 'ensime-sbt-do-test-only-dwim
"sa" 'ensime-inf-load-file
"sb" 'ensime-inf-eval-buffer
"sB" 'spacemacs/ensime-inf-eval-buffer-switch
"si" 'ensime-inf-switch
"sr" 'ensime-inf-eval-region
"sR" 'spacemacs/ensime-inf-eval-region-switch
"yT" 'spacemacs/ensime-yank-type-at-point-full-name
"yt" 'spacemacs/ensime-yank-type-at-point
"z" 'ensime-expand-selection-command))
;; interactive functions
(defun spacemacs/ensime-gen-and-restart()
@ -231,18 +178,53 @@
(interactive)
(ensime-type-at-point t t))
;; Completion
;; eclim
(defun spacemacs/java-completing-dot ()
(defun spacemacs//java-setup-eclim ()
"Setup Eclim."
;; jump handler
(add-to-list 'spacemacs-jump-handlers '(eclim-java-find-declaration :async t))
;; enable eclim
(eclim-mode))
(defun spacemacs//java-setup-eclim-company ()
"Setup Eclim auto-completion."
(spacemacs|add-company-backends
:backends company-emacs-eclim
:modes eclim-mode
:hooks nil)
;; call manualy generated functions by the macro
(spacemacs//init-company-eclim-mode)
(set (make-variable-buffer-local 'company-idle-delay) 0.5)
(set (make-variable-buffer-local 'company-minimum-prefix-length) 1)
(company-mode))
(defun spacemacs//java-setup-eclim-flycheck ()
"Setup Eclim syntax checking."
(flycheck-eclim-setup)
(setq eclim-autoupdate-problems nil)
;; check syntax only when save
(set (make-local-variable 'flycheck-check-syntax-automatically)
'(save))
(flycheck-mode))
(defun spacemacs//java-eclim-save-buffer-no-flycheck (&rest args)
"Save buffer without triggering flycheck."
(when (buffer-modified-p)
(let ((backup-inhibited t)
flycheck-check-syntax-automatically
auto-save-default)
(save-buffer 0))))
(defun spacemacs/java-eclim-completing-dot ()
"Insert a period and show company completions."
(interactive "*")
(spacemacs//java-delete-horizontal-space)
(insert ".")
(company-emacs-eclim 'interactive))
(defun spacemacs/java-completing-double-colon ()
(defun spacemacs/java-eclim-completing-double-colon ()
"Insert double colon and show company completions."
(interactive "*")
(spacemacs//java-delete-horizontal-space)
@ -251,6 +233,44 @@
(when (s-matches? (buffer-substring (- curr 2) (- curr 1)) ":")
(company-emacs-eclim 'interactive))))
;; meghanada
(defun spacemacs//java-setup-meghanada ()
"Setup Meghanada."
(require 'meghanada)
;; jump handler
(add-to-list 'spacemacs-jump-handlers
'(meghanada-jump-declaration
:async spacemacs//java-meghanada-server-livep))
;; auto-install meghanada server
(let ((dest-jar (meghanada--locate-server-jar)))
(unless dest-jar
(meghanada-install-server)))
;; enable meghanada
(meghanada-mode))
(defun spacemacs//java-setup-meghanada-company ()
"Setup Meghanada auto-completion."
(meghanada-company-enable))
(defun spacemacs//java-setup-meghanada-flycheck ()
"Setup Meghanada syntax checking."
(spacemacs/add-flycheck-hook 'java-mode)
(require 'flycheck-meghanada)
(add-to-list 'flycheck-checkers 'meghanada)
(flycheck-mode))
(defun spacemacs//java-setup-meghanada-flyspell ()
"Setup Meghanada spell checking.")
(defun spacemacs//java-setup-meghanada-eldoc ()
"Setup Meghanada eldoc.")
(defun spacemacs//java-meghanada-server-livep ()
"Return non-nil if the Meghanada server is up."
(and meghanada--client-process (process-live-p meghanada--client-process)))
;; Maven

View File

@ -0,0 +1,93 @@
;; flycheck-eclim.el --- an interface to the Eclipse IDE. -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2015 Łukasz Klich
;;
;; Author: Lukasz Klich <klich.lukasz@gmail.com>
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Contributors
;;
;;; Conventions
;;
;; Conventions used in this file: Name internal variables and functions
;; "eclim--<descriptive-name>", and name external program invocations
;; "eclim/command-name", like eclim/project-list.
;;; Description
;;
;; flycheck-eclim.el -- flycheck extension to use error/warning information
;; provided by eclim
;;
(require 'flycheck)
(require 'eclim)
(require 'json)
(defun eclim--problems-for-file ()
(when (buffer-modified-p)
(let ((backup-inhibited t)
auto-save-default)
(save-buffer 0)))
(eclim/execute-command "project_build" "-p")
(setq eclim--problems-filter nil)
(eclim--problems-mode-init t)
(eclim-problems-buffer-refresh)
eclim--problems-list)
(defun flycheck-verify-eclim ()
"Verify the Eclim syntax checker"
(list
(flycheck-verification-result-new
:label "Eclim Mode"
:message (if eclim-mode "Enabled" "Disabled")
:face (if eclim-mode 'success '(bold warning)))))
(defun flycheck-eclim-parse-problems (problems checker)
"Parse Eclim PROBLEMS for CHECKER into Flycheck errors."
(mapcar (lambda (p) (eclim-problem-->-flycheck-error p checker)) problems))
(defun flycheck-eclim-start (checker callback)
"Start a syntax CHECKER with Eclim."
(condition-case err
(let* ((problems (eclim--problems-for-file))
(errors (flycheck-eclim-parse-problems problems checker)))
(funcall callback 'finished errors))
(error (funcall callback 'errored (error-message-string err)))))
(defun eclim-problem-->-flycheck-error (problem checker)
(let* ((warning? (cdr (assoc 'warning problem)))
(severity (if (equal warning? :json-false) 'error 'warning)))
(flycheck-error-new-at
(cdr (assoc 'line problem))
(cdr (assoc 'column problem))
severity
(cdr (assoc 'message problem))
:checker checker
:filename (cdr (assoc 'filename problem))
:buffer (current-buffer))))
(flycheck-define-generic-checker 'java-eclim
"A Java syntax checker using Eclim.
See URL `https://github.com/senny/emacs-eclim'."
:start #'flycheck-eclim-start
:verify #'flycheck-verify-eclim
:modes '(java-mode)
:predicate (lambda () (and eclim-mode)))
(defun flycheck-eclim-setup ()
"Setup Flycheck for Eclim."
(interactive)
(add-to-list 'flycheck-checkers 'java-eclim))
(provide 'flycheck-eclim)

View File

@ -11,35 +11,264 @@
(setq java-packages
'(
company
(company-emacs-eclim :toggle
(configuration-layer/package-usedp 'company))
eclim
eldoc
ensime
flycheck
(flycheck-eclim :location local
:toggle (configuration-layer/package-usedp 'flycheck))
flyspell
ggtags
gradle-mode
groovy-imports
groovy-mode
helm-gtags
(java-mode :location built-in)
(meghanada :toggle (not (version< emacs-version "25.1")))
))
(defun java/post-init-company ()
(add-hook 'java-mode-local-vars-hook #'spacemacs//java-setup-company))
(defun java/init-company-emacs-eclim ()
(use-package company-emacs-eclim
:defer t
:init
(spacemacs|add-company-backends
:backends company-emacs-eclim
:modes java-mode)))
(setq company-emacs-eclim-ignore-case nil)
;; see `spacemacs//java-setup-eclim-company'
:config
(advice-add
'company-emacs-eclim
:before 'spacemacs//java-eclim-save-buffer-no-flycheck)))
(defun java/init-eclim ()
(use-package eclim
:defer t
:init (setq eclim-auto-save nil)
:config
(progn
(spacemacs|hide-lighter eclim-mode)
(require 'eclimd)
;; enable help at point
(setq help-at-pt-display-when-idle t
help-at-pt-timer-delay 0.1)
(help-at-pt-set-timer)
(add-to-list 'minor-mode-alist
'(eclim-mode (:eval (eclim-modeline-string))))
;; hack to support Maven multi-modules
(defun my-eclim-fix-relative-path (path)
(replace-regexp-in-string "^.*src/" "src/" path))
(advice-add 'eclim--project-current-file :filter-return
#'my-eclim-fix-relative-path)
;; key bindings
(dolist (prefix '(("ma" . "ant")
("mD" . "daemon")
("mg" . "goto")
("mh" . "help/doc")
("mi" . "issues")
("mm" . "maven")
("mp" . "project")
("mr" . "refactor")
("mt" . "test")))
(spacemacs/declare-prefix-for-mode
'java-mode (car prefix) (cdr prefix)))
(spacemacs/set-leader-keys-for-major-mode 'java-mode
;; ant
"aa" 'eclim-ant-run
"ac" 'eclim-ant-clear-cache
"ar" 'eclim-ant-run
"av" 'eclim-ant-validate
;; daemon
"Dk" 'stop-eclimd
"Ds" 'start-eclimd
;; errors (problems)
"ea" 'eclim-problems-show-all
"eb" 'eclim-problems
"ec" 'eclim-problems-correct
"ee" 'eclim-problems-show-errors
"ef" 'eclim-problems-toggle-filefilter
"en" 'eclim-problems-next-same-window
"eo" 'eclim-problems-open
"ep" 'eclim-problems-previous-same-window
"ew" 'eclim-problems-show-warnings
;; find
"ff" 'eclim-java-find-generic
;; goto
"gt" 'eclim-java-find-type
;; help/doc
"hc" 'eclim-java-call-hierarchy
"hh" 'eclim-java-show-documentation-for-current-element
"hi" 'eclim-java-hierarchy
"hu" 'eclim-java-find-references
;; maven
"mi" 'spacemacs/java-maven-clean-install
"mI" 'spacemacs/java-maven-install
"mp" 'eclim-maven-lifecycle-phases
"mr" 'eclim-maven-run
"mR" 'eclim-maven-lifecycle-phase-run
"mt" 'spacemacs/java-maven-test
;; project
"pb" 'eclim-project-build
"pc" 'eclim-project-create
"pd" 'eclim-project-delete
"pg" 'eclim-project-goto
"pi" 'eclim-project-import
"pj" 'eclim-project-info-mode
"pk" 'eclim-project-close
"po" 'eclim-project-open
"pp" 'eclim-project-mode
"pu" 'eclim-project-update
;; refactor
"rc" 'eclim-java-constructor
"rg" 'eclim-java-generate-getter-and-setter
"rf" 'eclim-java-format
"ri" 'eclim-java-import-organize
"rj" 'eclim-java-implement
"rr" 'eclim-java-refactor-rename-symbol-at-point
;; test
"tt" 'eclim-run-junit)
(evil-define-key 'insert java-mode-map
(kbd ".") 'spacemacs/java-eclim-completing-dot
(kbd ":") 'spacemacs/java-eclim-completing-double-colon
(kbd "M-.") 'eclim-java-find-declaration
(kbd "M-,") 'pop-tag-mark
(kbd "M-<mouse-3>") 'eclim-java-find-declaration
(kbd "<mouse-8>") 'pop-tag-mark)
(evil-define-key 'normal java-mode-map
(kbd "M-.") 'eclim-java-find-declaration
(kbd "M-,") 'pop-tag-mark
(kbd "M-<mouse-3>") 'eclim-java-find-declaration
(kbd "<mouse-8>") 'pop-tag-mark)
(evil-define-key 'normal eclim-problems-mode-map
(kbd "a") 'eclim-problems-show-all
(kbd "e") 'eclim-problems-show-errors
(kbd "g") 'eclim-problems-buffer-refresh
(kbd "q") 'eclim-quit-window
(kbd "w") 'eclim-problems-show-warnings
(kbd "f") 'eclim-problems-toggle-filefilter
(kbd "c") 'eclim-problems-correct
(kbd "RET") 'eclim-problems-open-current)
(evil-define-key 'normal eclim-project-mode-map
(kbd "N") 'eclim-project-create
(kbd "m") 'eclim-project-mark-current
(kbd "M") 'eclim-project-mark-all
(kbd "u") 'eclim-project-unmark-current
(kbd "U") 'eclim-project-unmark-all
(kbd "o") 'eclim-project-open
(kbd "c") 'eclim-project-close
(kbd "i") 'eclim-project-info-mode
(kbd "I") 'eclim-project-import
(kbd "RET") 'eclim-project-goto
(kbd "D") 'eclim-project-delete
(kbd "p") 'eclim-project-update
(kbd "g") 'eclim-project-mode-refresh
(kbd "R") 'eclim-project-rename
(kbd "q") 'eclim-quit-window)
)))
(defun java/post-init-eldoc ()
(add-hook 'java-mode-local-vars-hook #'spacemacs//java-setup-eldoc))
(defun java/init-ensime ()
(use-package ensime
:defer t
:commands ensime-mode
:init
(progn
(setq ensime-startup-dirname (concat spacemacs-cache-directory "ensime/"))
(spacemacs/register-repl 'ensime 'ensime-inf-switch "ensime"))
:config
(progn
(setq ensime-startup-dirname (expand-file-name "ensime" spacemacs-cache-directory))
;; key bindings
(spacemacs/ensime-configure-keybindings 'java-mode)
(dolist (mode java--ensime-modes)
(dolist (prefix '(("mb" . "build")
("mc" . "check")
("md" . "debug")
("mD" . "daemon")
("me" . "errors")
("mg" . "goto")
("mh" . "docs")
("mi" . "inspect")
("mr" . "refactor")
("mt" . "test")
("ms" . "repl")
("my" . "yank")))
(spacemacs/declare-prefix-for-mode mode (car prefix) (cdr prefix)))
(spacemacs/set-leader-keys-for-major-mode mode
"/" 'ensime-search
"'" 'ensime-inf-switch
"bc" 'ensime-sbt-do-compile
"bC" 'ensime-sbt-do-clean
"bi" 'ensime-sbt-switch
"bp" 'ensime-sbt-do-package
"br" 'ensime-sbt-do-run
"ct" 'ensime-typecheck-current-buffer
"cT" 'ensime-typecheck-all
"dA" 'ensime-db-attach
"db" 'ensime-db-set-break
"dB" 'ensime-db-clear-break
"dC" 'ensime-db-clear-all-breaks
"dc" 'ensime-db-continue
"di" 'ensime-db-inspect-value-at-point
"dn" 'ensime-db-next
"do" 'ensime-db-step-out
"dq" 'ensime-db-quit
"dr" 'ensime-db-run
"ds" 'ensime-db-step
"dt" 'ensime-db-backtrace
"Df" 'ensime-reload-open-files
"Dr" 'spacemacs/ensime-gen-and-restart
"Ds" 'ensime
"ee" 'ensime-print-errors-at-point
"el" 'ensime-show-all-errors-and-warnings
"es" 'ensime-stacktrace-switch
"gp" 'ensime-pop-find-definition-stack
"gi" 'ensime-goto-impl
"gt" 'ensime-goto-test
"hh" 'ensime-show-doc-for-symbol-at-point
"hT" 'ensime-type-at-point-full-name
"ht" 'ensime-type-at-point
"hu" 'ensime-show-uses-of-symbol-at-point
"ii" 'ensime-inspect-type-at-point
"iI" 'ensime-inspect-type-at-point-other-frame
"ip" 'ensime-inspect-project-package
"ra" 'ensime-refactor-add-type-annotation
"rd" 'ensime-refactor-diff-inline-local
"rD" 'ensime-undo-peek
"rf" 'ensime-format-source
"ri" 'ensime-refactor-diff-organize-imports
"rm" 'ensime-refactor-diff-extract-method
"rr" 'ensime-refactor-diff-rename
"rt" 'ensime-import-type-at-point
"rv" 'ensime-refactor-diff-extract-local
"ta" 'ensime-sbt-do-test-dwim
"tr" 'ensime-sbt-do-test-quick-dwim
"tt" 'ensime-sbt-do-test-only-dwim
"sa" 'ensime-inf-load-file
"sb" 'ensime-inf-eval-buffer
"sB" 'spacemacs/ensime-inf-eval-buffer-switch
"si" 'ensime-inf-switch
"sr" 'ensime-inf-eval-region
"sR" 'spacemacs/ensime-inf-eval-region-switch
"yT" 'spacemacs/ensime-yank-type-at-point-full-name
"yt" 'spacemacs/ensime-yank-type-at-point
"z" 'ensime-expand-selection-command))
(evil-define-key 'insert ensime-mode-map
(kbd ".") 'spacemacs/ensime-completing-dot
(kbd "M-.") 'ensime-edit-definition
@ -77,133 +306,28 @@
;; (progn
;; (spacemacs/ensime-configure-keybindings 'java-mode)))))
(defun java/init-eclim ()
(use-package eclim
:defer t
:init
(progn
(add-hook 'java-mode-hook 'eclim-mode)
(add-to-list 'spacemacs-jump-handlers-java-mode
'eclim-java-find-declaration))
:config
(progn
(spacemacs|hide-lighter eclim-mode)
(require 'eclimd)
(setq help-at-pt-display-when-idle t
help-at-pt-timer-delay 0.1)
(help-at-pt-set-timer)
(defun java/post-init-flycheck ()
(add-hook 'java-mode-local-vars-hook #'spacemacs//java-setup-flycheck))
(add-to-list 'minor-mode-alist
'(eclim-mode (:eval (eclim-modeline-string))))
(defun java/init-flycheck-eclim ()
(use-package flycheck-eclim
:commands flycheck-eclim-setup
;; see `spacemacs//java-setup-eclim-flycheck'
))
(evil-define-key 'insert java-mode-map
(kbd ".") 'spacemacs/java-completing-dot
(kbd ":") 'spacemacs/java-completing-double-colon
(kbd "M-.") 'eclim-java-find-declaration
(kbd "M-,") 'pop-tag-mark
(kbd "M-<mouse-3>") 'eclim-java-find-declaration
(kbd "<mouse-8>") 'pop-tag-mark)
(evil-define-key 'normal java-mode-map
(kbd "M-.") 'eclim-java-find-declaration
(kbd "M-,") 'pop-tag-mark
(kbd "M-<mouse-3>") 'eclim-java-find-declaration
(kbd "<mouse-8>") 'pop-tag-mark)
(evil-define-key 'normal eclim-problems-mode-map
(kbd "a") 'eclim-problems-show-all
(kbd "e") 'eclim-problems-show-errors
(kbd "g") 'eclim-problems-buffer-refresh
(kbd "q") 'eclim-quit-window
(kbd "w") 'eclim-problems-show-warnings
(kbd "f") 'eclim-problems-toggle-filefilter
(kbd "c") 'eclim-problems-correct
(kbd "RET") 'eclim-problems-open-current)
(evil-define-key 'normal eclim-project-mode-map
(kbd "N") 'eclim-project-create
(kbd "m") 'eclim-project-mark-current
(kbd "M") 'eclim-project-mark-all
(kbd "u") 'eclim-project-unmark-current
(kbd "U") 'eclim-project-unmark-all
(kbd "o") 'eclim-project-open
(kbd "c") 'eclim-project-close
(kbd "i") 'eclim-project-info-mode
(kbd "I") 'eclim-project-import
(kbd "RET") 'eclim-project-goto
(kbd "D") 'eclim-project-delete
(kbd "p") 'eclim-project-update
(kbd "g") 'eclim-project-mode-refresh
(kbd "R") 'eclim-project-rename
(kbd "q") 'eclim-quit-window)
(spacemacs/set-leader-keys-for-major-mode 'java-mode
"ea" 'eclim-problems-show-all
"eb" 'eclim-problems
"ec" 'eclim-problems-correct
"ee" 'eclim-problems-show-errors
"ef" 'eclim-problems-toggle-filefilter
"en" 'eclim-problems-next-same-window
"eo" 'eclim-problems-open
"ep" 'eclim-problems-previous-same-window
"ew" 'eclim-problems-show-warnings
"ds" 'start-eclimd
"dk" 'stop-eclimd
"ff" 'eclim-java-find-generic
"gt" 'eclim-java-find-type
"rc" 'eclim-java-constructor
"rg" 'eclim-java-generate-getter-and-setter
"rf" 'eclim-java-format
"ri" 'eclim-java-import-organize
"rj" 'eclim-java-implement
"rr" 'eclim-java-refactor-rename-symbol-at-point
"hc" 'eclim-java-call-hierarchy
"hh" 'eclim-java-show-documentation-for-current-element
"hi" 'eclim-java-hierarchy
"hu" 'eclim-java-find-references
"mi" 'spacemacs/java-maven-clean-install
"mI" 'spacemacs/java-maven-install
"mp" 'eclim-maven-lifecycle-phases
"mr" 'eclim-maven-run
"mR" 'eclim-maven-lifecycle-phase-run
"mt" 'spacemacs/java-maven-test
"aa" 'eclim-ant-run
"ac" 'eclim-ant-clear-cache
"ar" 'eclim-ant-run
"av" 'eclim-ant-validate
"pb" 'eclim-project-build
"pc" 'eclim-project-create
"pd" 'eclim-project-delete
"pg" 'eclim-project-goto
"pi" 'eclim-project-import
"pj" 'eclim-project-info-mode
"pk" 'eclim-project-close
"po" 'eclim-project-open
"pp" 'eclim-project-mode
"pu" 'eclim-project-update
"tt" 'eclim-run-junit))))
(defun java/post-init-flyspell ()
(add-hook 'java-mode-local-vars-hook #'spacemacs//java-setup-flyspell))
(defun java/post-init-ggtags ()
(add-hook 'java-mode-local-vars-hook #'spacemacs/ggtags-mode-enable))
(defun java/init-gradle-mode ()
(use-package gradle-mode
:defer t
))
:defer t))
(defun java/init-groovy-imports ()
(use-package groovy-imports
:defer t
))
:defer t))
(defun java/init-groovy-mode ()
(use-package groovy-mode
@ -219,5 +343,58 @@
:init
(progn
(add-hook 'java-mode-local-vars-hook #'spacemacs//java-setup-backend)
(put 'java-backend 'safe-local-variable 'symbolp)
(spacemacs//java-define-command-prefixes))))
(defun java/init-meghanada ()
(use-package meghanada
:defer t
:init
(progn
(setq meghanada-server-install-dir (concat spacemacs-cache-directory
"meghanada/")
company-meghanada-prefix-length 1
;; let spacemacs handle company and flycheck itself
meghanada-use-company nil
meghanada-use-flycheck nil))
:config
(progn
;; key bindings
(dolist (prefix '(("mc" . "comppile")
("mD" . "daemon")
("mg" . "goto")
("mr" . "refactor")
("mt" . "test")
("mx" . "execute")))
(spacemacs/declare-prefix-for-mode
'java-mode (car prefix) (cdr prefix)))
(spacemacs/set-leader-keys-for-major-mode 'java-mode
"cb" 'meghanada-compile-file
"cc" 'meghanada-compile-project
"Dc" 'meghanada-client-direct-connect
"Dd" 'meghanada-client-disconnect
"Di" 'meghanada-install-server
"Dk" 'meghanada-server-kill
"Dl" 'meghanada-clear-cache
"Dp" 'meghanada-ping
"Dr" 'meghanada-restart
"Ds" 'meghanada-client-connect
"Du" 'meghanada-update-server
"Dv" 'meghanada-version
"gb" 'meghanada-back-jump
"=" 'meghanada-code-beautify
"ri" 'meghanada-optimize-import
"rI" 'meghanada-import-all
"ta" 'meghanada--run-junit
"tc" 'meghanada-run-junit-class
"tl" 'meghanada-run-junit-recent
"tt" 'meghanada-run-junit-test-case
;; meghanada-switch-testcase
;; meghanada-local-variable
"x:" 'meghanada-run-task))))

View File

@ -6,8 +6,6 @@
- [[#description][Description]]
- [[#layer-installation][Layer Installation]]
- [[#ensime][Ensime]]
- [[#installation][Installation]]
- [[#usage][Usage]]
- [[#scalastyle][Scalastyle]]
- [[#use-java-doc-style][Use Java doc-style]]
- [[#automatically-show-the-type-of-the-symbol-under-the-cursor][Automatically show the type of the symbol under the cursor]]
@ -15,19 +13,6 @@
- [[#automatically-replace-arrows-with-unicode-ones][Automatically replace arrows with unicode ones]]
- [[#auto-start][Auto-start]]
- [[#key-bindings][Key bindings]]
- [[#ensime-key-bindings][Ensime key bindings]]
- [[#search][Search]]
- [[#sbt][sbt]]
- [[#typecheck][Typecheck]]
- [[#debug][Debug]]
- [[#errors][Errors]]
- [[#goto][Goto]]
- [[#print-and-yank-types][Print and yank types]]
- [[#documentation-inspect][Documentation, Inspect]]
- [[#server][Server]]
- [[#refactoring][Refactoring]]
- [[#tests][Tests]]
- [[#repl][REPL]]
* Description
This layer adds support for the Scala language using the excellent [[http://ensime.github.io/][ENSIME]]
@ -45,25 +30,8 @@ and project-wide type-checking.
ENSIME requires a configuration file at the root of each Scala project. It
provides an SBT plugin to generate these files.
** Installation
Refer to the [[https://ensime.github.io/build_tools/sbt/][Ensime installation instructions]] to install the =sbt-ensime=
plugin.
Please note you have to use a version newer than =0.13.5= of =sbt= in your
project's =project/build.properties=. For example,
#+BEGIN_SRC scala
sbt.version=0.13.11
#+END_SRC
** Usage
1. Create a =.ensime= file at the root of your Scala project using =sbt
ensimeConfig= and =sbt ensimeConfigProject= at the shell.
2. Run =M-x ensime= within Emacs to start an ENSIME session.
Each Scala project uses a dedicated ENSIME session, so you only need to run =M-x
ensime= once per project. Any Scala files you create or visit within the project
will automatically use ENSIME for the remainder of your editing session.
Installation instructions and usage can be found in the =Java= layer
[[file:../java/README.org::#ensime][README.org]].
* Scalastyle
[[http://www.scalastyle.org/][Scalastyle]] provides style-checking and linting. The Emacs functionality is
@ -144,123 +112,4 @@ with
#+END_SRC
* Key bindings
** Ensime key bindings
*** Search
| Key Binding | Description |
|-------------+-----------------------------------------------------|
| ~SPC m /~ | incremental search using =ensime-scalex= major mode |
| ~SPC m ?~ | incremental search in all live buffers |
*** sbt
| Key Binding | Description |
|-------------+---------------------|
| ~SPC m b .~ | sbt transient state |
| ~SPC m b b~ | sbt command |
| ~SPC m b c~ | compile |
| ~SPC m b C~ | clean command |
| ~SPC m b i~ | switch to sbt shell |
| ~SPC m b p~ | package command |
| ~SPC m b r~ | run command |
*** Typecheck
| Key Binding | Description |
|-------------+---------------------------------|
| ~SPC m c t~ | type check the current file |
| ~SPC m c T~ | type check all the open buffers |
*** Debug
| Key Binding | Description |
|-------------+-----------------------------|
| ~SPC m d A~ | Attach to a remote debugger |
| ~SPC m d b~ | set breakpoint |
| ~SPC m d B~ | clear breakpoint |
| ~SPC m d C~ | clear all breakpoints |
| ~SPC m d c~ | continue |
| ~SPC m d i~ | step |
| ~SPC m d n~ | next |
| ~SPC m d o~ | step out |
| ~SPC m d q~ | quit |
| ~SPC m d r~ | run |
| ~SPC m d t~ | backtrace |
| ~SPC m d v~ | inspect value at point |
*Note:* These key bindings need a transient-state, PR welcome :-)
*** Errors
| Key Binding | Description |
|-------------+----------------------------------------------------|
| ~SPC m e e~ | print error at point |
| ~SPC m e l~ | show all errors and warnings |
| ~SPC m e s~ | switch to buffer containing the stack trace parser |
*** Goto
| Key Binding | Description |
|-------------+----------------------|
| ~SPC m g g~ | go to definition |
| ~SPC m g i~ | go to implementation |
| ~SPC m g t~ | go to test |
*** Print and yank types
|-------------+--------------------------------|
| ~SPC m h T~ | print full type name at point |
| ~SPC m h t~ | print short type name at point |
| ~SPC m y T~ | yank full type name at point |
| ~SPC m y t~ | yank short type name at point |
*** Documentation, Inspect
| Key Binding | Description |
|-------------+----------------------------------------|
| ~SPC m h h~ | show documentation for symbol at point |
| ~SPC m h u~ | show uses for symbol at point |
| ~SPC m i i~ | inspect type at point |
| ~SPC m i I~ | inspect type in other frame |
| ~SPC m i p~ | inspect project package |
*** Server
| Key Binding | Description |
|-------------+--------------------------------------------------------|
| ~SPC m n F~ | reload open files |
| ~SPC m n s~ | start ensime server |
| ~SPC m n S~ | regenerate the =.ensime= and restart the ensime server |
*** Refactoring
| Key Binding | Description |
|-------------+----------------------------------------------------------------------|
| ~SPC m r a~ | add type annotation |
| ~SPC m r f~ | format source |
| ~SPC m r d~ | get rid of an intermediate variable (=ensime-refactor-inline-local=) |
| ~SPC m r D~ | get rid of an intermediate variable (=ensime-undo-peek=) |
| ~SPC m r i~ | organize imports |
| ~SPC m r m~ | extract a range of code into a method |
| ~SPC m r r~ | rename a symbol project wide |
| ~SPC m r t~ | import type at point |
| ~SPC m r v~ | extract a range of code into a variable |
| ~SPC m z~ | expand/contract region |
*** Tests
| Key Binding | Description |
|-------------+--------------------------|
| ~SPC m t a~ | test command (sbt) |
| ~SPC m t r~ | test quick command (sbt) |
| ~SPC m t t~ | test only (sbt) |
*** REPL
| Key Binding | Description |
|-------------+---------------------------------------------------------------------|
| ~SPC m s a~ | ask for a file to be loaded in the REPL |
| ~SPC m s b~ | send buffer to the REPL |
| ~SPC m s B~ | send buffer to the REPL and focus the REPL buffer in =insert state= |
| ~SPC m s i~ | start or switch to the REPL inferior process |
| ~SPC m s r~ | send region to the REPL |
| ~SPC m s R~ | send region to the REPL and focus the REPL buffer in =insert state= |
All ensime key bindings are listed in the =java= layer [[file:../java/README.org::#ensime-key-bindings][README.org]].

View File

@ -9,6 +9,13 @@
;;
;;; License: GPLv3
(defun spacemacs//scala-setup-ensime ()
"Setup ENSIME for Scala."
(spacemacs//java-setup-ensime))
(defun spacemacs//scala-disable-flycheck-scala ()
(push 'scala flycheck-disabled-checkers))
(defun spacemacs/scala-join-line ()
"Adapt `scala-indent:join-line' to behave more like evil's line join.

View File

@ -11,8 +11,10 @@
(setq scala-packages
'(
eldoc
ensime
flycheck
flyspell
ggtags
helm-gtags
noflet
@ -21,31 +23,38 @@
sbt-mode
))
(defun scala/post-init-eldoc ()
(add-hook 'scala-mode-hook #'spacemacs//java-setup-ensime-eldoc))
(defun scala/pre-init-ensime ()
(spacemacs|use-package-add-hook ensime
:pre-config (add-to-list 'java--ensime-modes 'scala-mode)))
(defun scala/post-init-ensime ()
(use-package ensime
:defer t
:init
;; note ensime-mode is hooked to scala-mode-hook automatically by
;; ensime-mode via an autoload
(spacemacs//ensime-init 'scala-mode scala-enable-eldoc scala-auto-start-ensime)
(progn
(add-hook 'scala-mode-hook #'spacemacs//scala-setup-ensime)
(when scala-auto-start-ensime
(add-hook 'scala-mode-hook 'spacemacs//ensime-maybe-start)))
:config
(progn
(spacemacs/ensime-configure-keybindings 'scala-mode)
;; Don't use scala checker if ensime mode is active, since it provides
;; better error checking.
(with-eval-after-load 'flycheck
(defun scala/disable-flycheck-scala ()
(push 'scala flycheck-disabled-checkers))
(add-hook 'ensime-mode-hook 'scala/disable-flycheck-scala))
;; Enable Expand Region integration from Ensime. Ignore load errors to
;; handle older Ensime versions gracefully.
(when (configuration-layer/package-usedp 'expand-region)
(require 'ensime-expand-region nil 'noerror)))))
(defun scala/post-init-flycheck ()
(spacemacs/add-flycheck-hook 'scala-mode))
(spacemacs/add-flycheck-hook 'scala-mode)
;; Don't use scala checker if ensime mode is active, since it provides
;; better error checking.
(with-eval-after-load 'flycheck
(add-hook 'ensime-mode-hook 'spacemacs//scala-disable-flycheck-scala)))
(defun scala/post-init-flyspell ()
(spell-checking/add-flyspell-hook 'scala-mode)
(add-hook 'scala-mode-hook #'spacemacs//java-setup-ensime-spell-checking))
(defun scala/init-noflet ()
(use-package noflet))
@ -100,15 +109,16 @@ it can be undone."
(insert (cdr arrow)))))
(defun scala/gt ()
"Insert a `>' to the buffer. If it's part of a right arrow (`->' or `=>'),
replace it with the corresponding unicode arrow."
"Insert a `>' to the buffer.
If it's part of a right arrow (`->' or `=>'),replace it with the corresponding
unicode arrow."
(interactive)
(insert ">")
(scala/replace-arrow-at-point))
(defun scala/hyphen ()
"Insert a `-' to the buffer. If it's part of a left arrow (`<-'),
replace it with the unicode arrow."
"Insert a `-' to the buffer.
If it's part of a left arrow (`<-'),replace it with the unicode arrow."
(interactive)
(insert "-")
(scala/replace-arrow-at-point))
@ -124,7 +134,8 @@ replace it with the unicode arrow."
;; Compatibility with `aggressive-indent'
(setq scala-indent:align-forms t
scala-indent:align-parameters t
scala-indent:default-run-on-strategy scala-indent:operator-strategy))))
scala-indent:default-run-on-strategy
scala-indent:operator-strategy))))
(defun scala/post-init-ggtags ()
(add-hook 'scala-mode-local-vars-hook #'spacemacs/ggtags-mode-enable))