Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/volrath/spiral

Emacs Clojure IDE based on UNREPL
https://github.com/volrath/spiral

clojure clojure-development emacs emacs-lisp ide repl unrepl

Last synced: 3 months ago
JSON representation

Emacs Clojure IDE based on UNREPL

Awesome Lists containing this project

README

        

#+TITLE: SPIRAL (beta)
#+AUTHOR: Daniel Barreto
#+EMAIL: [email protected]
#+DESCRIPTION: SPIRAL project README
#+LANGUAGE: en
#+OPTIONS: H:4 num:nil toc:2 p:t
#+STARTUP: showall

[[https://www.gnu.org/software/emacs/][file:https://img.shields.io/badge/Emacs-25-8e44bd.svg]] [[https://travis-ci.org/Unrepl/spiral][file:https://travis-ci.org/Unrepl/spiral.svg?branch=master]] [[https://melpa.org/#/spiral][file:https://melpa.org/packages/spiral-badge.svg]]

Emacs >= 25.1, Clojure >= 1.8.0

Pick your definition:
- SPIRAL is a Clojure IDE for Emacs.
- SPIRAL is a client interface to a Clojure's Socket REPL through the [[https://github.com/unrepl/unrepl][UNREPL]]
protocol.

* Introduction
Both definitions above are correct and complement each other.

SPIRAL started as a simple experiment for using the [[https://github.com/unrepl/unrepl][UNREPL]] protocol as the
communication method between an Emacs buffer and a Clojure Socket REPL. With
the pass of time, it has been evolving into a baby Clojure IDE. Currently it
has a fair amount of [[#features][Features]].

SPIRAL's UI is meant to rely heavily on the REPL buffer for displaying any
kind of data that may be too big or complex to display in the Echo Area or as
an overlay. The main idea is to allow you maintain focus on only two things
during your development workflow: Your Clojure code (in =clojure-mode=
buffers) and the REPL buffer. SPIRAL will try, whenever possible and
reasonable, to favor displaying data in the REPL buffer over using external
temporary buffers.

SPIRAL is of the same nature as [[https://cider.readthedocs.io/en/latest/][CIDER]]. In fact, SPIRAL takes a lot of
inspiration from CIDER's features, but both differ in certain UI decisions
(included the aforementioned.)

Another important difference is that SPIRAL is meant to be used to connect to
Socket REPLs, where CIDER is built to connect to [[https://github.com/clojure/tools.nrepl][nREPL]]. Both Socket REPLs and
nREPL serve the purpose of allowing you to connect to a running Clojure
process, send it stuff to be evaluated and get data back. If you want to get
deeper into these concepts, I encourage you to go read Arne Brasseur's
[[https://lambdaisland.com/guides/clojure-repls][The Ultimate Guide To Clojure REPLs]].

Lastly, SPIRAL is a young project, so if you are new to Clojure development in
Emacs, for now I would recommend to start with [[https://cider.readthedocs.io/en/latest/][CIDER]], since it's more stable,
more & better documented, and has a bigger community behind it.

* Quick Start

** Installing

*** Package.el

SPIRAL is available in [[http://melpa.milkbox.net/#/][MELPA]], and it's the recommended way to install it.
Simply run:

#+BEGIN_SRC
M-x package-install [RET] spiral [RET]
#+END_SRC

*** Manual installation

1. Install [[https://github.com/plexus/a.el][a.el]], [[https://github.com/clojure-emacs/clojure-mode][clojure-mode]], and [[https://github.com/volrath/treepy.el][treepy]]. All available in [[http://melpa.milkbox.net/#/][MELPA]].

2. Download this repository, or clone it with its submodules:

#+BEGIN_SRC shell-script
$ git clone --recursive https://github.com/unrepl/spiral
#+END_SRC

3. Then place this repository, and its *parseclj* submodule copy, somewhere
in your load-path. Or just paste this in your emacs configuration and
evaluate it:

#+BEGIN_SRC emacs-lisp
(let ((spiral-dir "/path/to/your/copy/of/spiral/"))
(add-to-list 'load-path spiral-dir)
(add-to-list 'load-path (expand-file-name "parseclj" spiral-dir))
(require 'spiral))
#+END_SRC

** Connecting to a Socket REPL
The main way to connect to a Socket REPL in SPIRAL is by issuing:
=M-x spiral-connect=.

When this command is executed in a buffer that belongs to a Clojure project,
it will automagically create a Socket REPL for it and connect. Right now,
SPIRAL supports only automatic connection in projects using [[https://leiningen.org/][Leiningen]] or [[http://boot-clj.com/][Boot]]
>= 2.7.2.

If you already have a Socket REPL running, you can prefix the connect command
(=C-u M-x spiral-connect=) or issue =M-x spiral-connect-to= to get a prompt
for inserting your Socket's host and port.

There are several ways to create your own Socket REPL, here are some examples:

#+BEGIN_SRC shell-script
# clojure 1.9.0
$ clj -J-Dclojure.server.myrepl="{:port 5555,:accept,clojure.core.server/repl}"
# lein:
$ JVM_OPTS='-Dclojure.server.myrepl={:port,5555,:accept,clojure.core.server/repl}' lein repl
# or boot < 2.7.2:
$ boot -i "(do (require 'clojure.core.server) (clojure.core.server/start-server {:port 5555 :name :repl :accept 'clojure.core.server/repl}))" wait
# or boot >= 2.7.2:
$ boot socket-server --port 5555 wait
# or plain Clojure jar:
$ java -Dclojure.server.myrepl="{:port 5555,:accept,clojure.core.server/repl}" -jar ~/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar
#+END_SRC

After SPIRAL successfully connects to a Socket REPL you will be greeted with
a REPL Buffer, and all your Clojure buffers related to the project you just
connected will have the =spiral-mode= activated automatically.

** Usage
Besides the REPL Buffer, SPIRAL enables a few commands in each Clojure Buffer
running =spiral-mode=:

- Autocompletion with [[http://company-mode.github.io/][company-mode]].
- =C-c C-z=: Switch to REPL buffer
- =C-x C-e=: Evaluate expression before point.
- =C-c C-c=: Evaluate top level expression.
- =C-c C-r=: Send last evaluation to the REPL buffer.
- =C-c C-b=: Evaluate buffer.
- =C-c C-g=: Interrupt current evaluation.
- =M-s-.=: Easy jumping through buttons with [[https://github.com/abo-abo/avy/][avy]].
- =C-c q=: Quit SPIRAL.

* Features
:PROPERTIES:
:CUSTOM_ID: Features
:END:

*** Automatically create a Socket REPL using your project's build tool
SPIRAL currently supports [[https://leiningen.org/][Leiningen]], [[http://boot-clj.com/][Boot]] >= 2.7.2, or Clojure's [[https://clojure.org/guides/deps_and_cli][clj CLI]].
In this example, the project has both a `build.boot` file and a `deps.edn`
file, so `spiral-connect` prompts for a way to run the project.

#+caption: M-x spiral-connect
[[file:gifs/connect.gif]]

*** Connect to an existing Socket REPL

#+caption: M-x spiral-connect-to
[[file:gifs/connect-to.gif]]

*** Elided data structures
Taking advantage of one of UNREPL's nice features, the REPL buffer will
elide big or complex data structures with clickable buttons.

#+caption: Elided data structures
[[file:gifs/elision.gif]]

*** Easy shortcut to navigate buttons
Making use of the awesome [[https://github.com/abo-abo/avy/][avy]] library, SPIRAL provides a REPL shortcut to
jump to any button in the screen. Bound to =M-s-.=. Watch how easy is to
jump to the 1st, 3rd, and 5th button on the screen.

#+caption: Navigate REPL buttons
[[file:gifs/avy.gif]]

*** Playing with Images? why not opening them in the REPL?
SPIRAL supports displaying buffered images directly in the REPL.

#+caption: Image support
[[file:gifs/hendrix.gif]]

*** Standard output strings can be grouped into their respective REPL entries
This is a customizable feature, you can turn it off by setting
=spiral-repl-group-stdout= to =nil=.

#+caption: Grouped stdout strings
[[file:gifs/grouped-outs.gif]]

*** In place documentation
A la [[https://github.com/unrepl/unravel][Unravel]]. Hit =C-c C-d= to get in-place documentation of the symbol at
point.

#+caption: In place documentation
[[file:gifs/in-place-doc.gif]]

*** Pretty (and elided) stacktraces
For now, stacktraces show differently between Clojure 1.8.0 and 1.9.0, due
to a [[https://github.com/clojure/clojure/blob/master/changes.md#33-other-fixes][breaking change in Clojure]]. See also [[https://github.com/Unrepl/unrepl/issues/27][unrepl#27]].

#+caption: Elided stacktraces
[[file:gifs/exceptions.gif]]

*** Even for lazy errors
Lazy errors are reduced to a minimum expression, with a button to inspect
further.

#+caption: Lazy errors
[[file:gifs/lazy-errors.gif]]

*** Interactive evaluation results overlays
Same as [[https://github.com/clojure-emacs/cider/][CIDER]] and [[http://lighttable.com/][LightTable]].

#+caption: Interactive evaluation overlays
[[file:gifs/overlays.gif]]

*** Is the result too big? Inspect it in the REPL
When interactive results are too big for in-buffer overlays, you can just
move them to the REPL buffer and inspect them there.

SPIRAL will also copy/paste the evaluated expression and add it to the
REPL history.

#+caption: Interactive inspection
[[file:gifs/interactive-inspection.gif]]

*** Interactive Exception happened? Inspect it in the REPL
Exceptions are shown in the REPL buffer, no matter where they come from.
SPIRAL will try to figure out which expression caused the exception and
will copy it to the REPL buffer as well.

#+caption: Interactive exception
[[file:gifs/interactive-exception.gif]]

* Contributing

Please refer to [[file:CONTRIBUTING.org][CONTRIBUTING.org]].

* Resources
- [[https://github.com/unrepl/unrepl][UNREPL]]: the protocol.
- [[https://github.com/unrepl/unravel][Unravel]]: an UNREPL terminal-based client.
- The Ultimate Guide To Clojure REPLs on the [[https://lambdaisland.com/guides/clojure-repls/clojure-repls#orgheadline20][Socket REPL]].
- [[https://github.com/puredanger/replicant][replicant]]: proof of concept of using Socket REPL for tooling

Join the =#unrepl= channel in the [[http://clojurians.net/][Clojurians slack]]!

* License

© 2017 Daniel Barreto

Distributed under the terms of the GNU GENERAL PUBLIC LICENSE, version 3.