building a better clojure repl - cosmin...

57
Building a better Clojure REPL Cosmin Stejerean @offbytwo

Upload: vuphuc

Post on 31-Jul-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Building a better Clojure REPL

Cosmin Stejerean@offbytwo

Page 2: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Problems with the standard REPL

Page 3: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No line editing

Page 4: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No external editor

Page 5: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No tab completion

Page 6: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No Ctrl-C handling

Page 7: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No history

Page 8: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No useful shortcuts

Page 9: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Lack of color

Page 10: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Building a better solution

Page 11: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

What is a REPL?

Page 12: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Read Eval Print Loop

Page 13: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

while (true) { input = read(); if (input == null) { continue; } output = eval(input); print(output);}

Page 14: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Handling input / output

Page 15: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

jline 2github.com/jline/jline2

Page 16: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

jansijansi.fusesource.org

Page 17: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

new ConsoleReader()RT.readString(reader.readLine(“=>”))

Page 18: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Handling history

Page 19: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

String home = getProperty("user.home");histFile = new File(home, ".repl_history");reader.setHistory(new FileHistory(histFile));

Page 20: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Tab completion

Page 21: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

clojure-completegithub.com/ninjudd/clojure-complete

Page 22: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

reader.addCompleter(new ClojureCompleter());

Page 23: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

public class ClojureCompleter {    private Var completions;    private Var eval;

    public ClojureCompletionWrapper() {        RT.load("complete");        this.eval = RT.var("clojure.core", "eval");        this.completions = RT.var("complete", "completions");    }

    public List<String> getCompletionsForString(String toComplete) {        List<String> returnThis = new ArrayList<String>();

        LazySeq results = completions.invoke(toComplete);        for (Object result : asList(results.toArray())) {            returnThis.add((String) result);        }

        return returnThis;    }}

Page 24: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Bells & whistles

Page 25: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Useful shortcuts

Page 26: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

View docs

?function => (doc function)

Page 27: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

View source

??function => (source function)

Page 28: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Input / output caching

Page 29: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

user[11]: (+ 2 2)user[11]= 4

user[12]: (input 11)user[12]= (+ 2 2)

user[13]: (output 11)user[13]= 4

Page 30: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Java interop

Page 31: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Find classes by name

Page 32: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

class-findergithub.com/cosmin/class-finder

Page 33: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Find classes by name

%f Patternjava.util.regex.Pattern

%f *Set java.utiljava.util.HashSet java.util.LinkedHashSet

Page 34: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Inspect Java objects

Page 35: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Inspect Java objects

%d name<init> java.lang.String()...static String valueOf(int)...char charAt(int)...

Page 36: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Nicer stacktraces

Page 37: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

user[16]: (.toLowerCase name)---------------------------------------------------------------------------java.lang.NullPointerException: null Reflector.java:314 clojure.lang.Reflector.invokeNoArgInstanceMember (Unknown Source) user/eval326 Compiler.java:6469 clojure.lang.Compiler.eval Compiler.java:6435 clojure.lang.Compiler.eval IClojureRepl.java:117 com.offbytwo.iclojure.repl.IClojureRepl.eval IClojureRepl.java:152 com.offbytwo.iclojure.repl.IClojureRepl.loop Main.java:63 com.offbytwo.iclojure.Main.main (Unknown Source) sun.reflect.NativeMethodAccessorImpl.invoke0 NativeMethodAccessorImpl.java:39 sun.reflect.NativeMethodAccessorImpl.invokeDelegatingMethodAccessorImpl.java:25 sun.reflect.DelegatingMethodAccessorImpl.invoke Method.java:597 java.lang.reflect.Method.invoke ExecJavaMojo.java:297 org.codehaus.mojo.exec.ExecJavaMojo$1.run Thread.java:680 java.lang.Thread.run

NullPointerException: null

Page 38: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Ctrl-C handling

Page 39: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

public class ControlCSignalHandler implements SignalHandler {

    public void install() {        Signal signal = new Signal("INT");        Signal.handle(signal, this);    }

    public void handle(Signal signal) {        repl.abortCurrentRead();    }}

Page 40: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

The result?

IClojureiclojure.com

Page 41: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Also supports

Page 42: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

clojure-maven-plugin

Page 43: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

leiningen

Page 44: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Next steps

Page 45: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

External editor

Page 46: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Runtime.exec()

Page 47: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

No TTY

Page 48: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Native wrapper?

Page 49: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

jarkicylisper.in/jark/

Page 50: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;
Page 51: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Smarter completions

Page 52: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Read incomplete forms

Page 53: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

(import ‘java.util

Page 54: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

(def name “Cosmin”)

(. name toL

Page 55: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

(let [inc2 #(+ %1 2)] (in

Page 56: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

clojure-reader

github.com/cosmin/clojure-reader

Page 57: Building a better Clojure REPL - Cosmin Stejereanoffbytwo.com/presentations/building-better-repl.pdf · public class ClojureCompleter { private Var completions; private Var eval;

Cosmin Stejerean@offbytwo