I decided it would be fun to use Liquid with REBL (since I use REBL all the time with Atom/Chlorine) so I ended up with this in my ~/.liq
file as a quick hack:
(ns sean.liquid.rebl
(:require [dk.salza.liq.editor :as editor]))
(defn rebl-sexp [sexp]
(editor/eval-sexp (str "
(let [v " sexp "]
((requiring-resolve 'cognitect.rebl/submit) '" sexp " v)
v)
")))
(defn rebl-last-sexp []
(rebl-sexp (or (editor/get-selection) (editor/sexp-at-point))))
;; start REBL in background
(future ((requiring-resolve 'cognitect.rebl/ui)))
;; overwrite c p p to inspect in the REBL
(swap! editor/editor assoc-in [::editor/keymaps "dk.salza.liq.keymappings.normal" "c" "p" "p"] rebl-last-sexp)
;; activate it
(editor/set-keymap "dk.salza.liq.keymappings.normal")
(in-ns 'user)
It works pretty well 🙂
Great 🙂 That is really cool. I just tried it out. Thank you for sharing! I also see that I need to create a function for modifying multi-key keybindings, so you do not have to access the editor map directly 😉
@mogenslund Haha... glad you tried it out. Yeah, I saw a two key add binding I think, but that wasn't quite enough here.
Also, do you have commands/hotkeys for running tests in Liquid?
(I could look in the source but figured it's probably easier just to ask 🙂 )
Hi @seancorfield No, I have not created any commands for running tests yet. I will consider adding that, and need to think about how it should work, since my own flow is probably not very scaleable or systematic. (I usually create test bodies and functions in a scratch area and then move them in place, when I am done. After that I execute the suite through the command line.) One thing to consider is whether the tests should run in the current instance of liquid+project or in a seperate jvm.
The functionality I would want -- to mirror what I currently use in Atom/Chlorine -- is just two commands: run all tests in the current namespace and run the test at the cursor (with the cursor on the name of the test). I'll experiment with adding those in my ~/.liq
file for now and share what I end up with.
Thats great. Please share if you come up with something that does the job 🙂
@mogenslund I see that you bind println
when eval'ing code. clojure.test
writes to stuff at a lower level than that, and would need to bind *out*
to avoid output messing up the editor layout. Any suggestions for an easy way to deal with that?
Figured it out. Kind of ugly code but it works.
(defn run-tests []
(editor/eval-sexp "
(let [s (java.io.StringWriter.)
w (java.io.PrintWriter. s)]
(-> (binding [clojure.test/*test-out* w]
(clojure.test/run-tests))
(assoc :output (.toString s))))
"))
(defn run-test-at-point []
(let [test-name (:value (editor/get-context))]
(editor/eval-sexp (str "
(let [s (java.io.StringWriter.)
w (java.io.PrintWriter. s)]
(do (binding [clojure.test/*test-out* w]
(clojure.test/test-vars [#'" test-name "]))
(str \"Tested \" '" test-name "\" : \" (or (not-empty (.toString s)) \"OK\"))))
"))))
(swap! editor/editor assoc-in [::editor/keymaps "dk.salza.liq.keymappings.normal" "c" "t" "x"] run-tests)
(swap! editor/editor assoc-in [::editor/keymaps "dk.salza.liq.keymappings.normal" "c" "t" "t"] run-test-at-point)
c t x
runs all tests in the current namespace (assuming it's been loaded/eval'd)
c t t
runs the test whose name is at the cursor.
Great. I had just begun looking into it. Just some tips then. If the layout is messed up, typing C-g will redraw the screen. When working with code that writes a lot to stdout using the jFrame implementation (--jframe) is sometimes convenient, since the drawing is separated from stdout. And now I will take a look at your code 🙂
I like that I can easily extend the behaviors locally. I'll probably add a few more REBL-related things. Stuff I've added in Atom in my init.coffee
file.
Inspect namespace and inspect Var are two more useful things I'll probably add. The latter is essentially "eval #'<context>" so if your cursor is on a symbol, you can see its definition, source, and uses in REBL easily.
(defn rebl-namespace []
(rebl-sexp "*ns*"))
(defn rebl-var []
(rebl-sexp (str "#'" (:value (editor/get-context)))))
(swap! editor/editor assoc-in [::editor/keymaps "dk.salza.liq.keymappings.normal" "c" "r" "n"] rebl-namespace)
(swap! editor/editor assoc-in [::editor/keymaps "dk.salza.liq.keymappings.normal" "c" "r" "v"] rebl-var)
Those were easy 🙂@mogenslund What do you do/use to display a symbol's docstring when you're working in Liquid?
It is not so sophisticated, but C-h a will prompt for input to apropos functionality. The function at point will be displayed in parenthesis and chosen if no other input is provided.
Just realized that get-context
is not quite what I thought. Is there a function that returns the symbol name at point?
I was on this code
(is (= 1 (count |rs)))
where |
is the cursor and expected context to be rs
but it's rs)))
-- I wanted just rs
Actually that was the intend with get-context. It will try to guess what type is under the curser: url, filename, function, etc and provide a value. If you type C-t I have created a "test function" that shows get-context result. Your case with the | symbol is probably me, who needs to work a bit more on the regular expressions.
OK, I can probably workaround that for now. It mostly seems to get it right. Just sometimes adds some closing parens/brackets.
Yes. I should write some more test cases on that one to get the edges right 😉
Another glitch in get-context
:
(is (= 1 (:FR|UIT/ID (first rs)))))
context is :FRUIT/ID
(correct) but {:builde|r-fn rs/as-maps})]
context is builder-fn
(incorrect: no leading :
(I'm working on next.jdbc
right now -- these are lines from jdbc_test.clj
if you're curious for test material)
Thanks. I have mostly used get-context for file navigation, url navigation and goto-definition, so those are the cases that have been refined the most. Actually I use a customized version of get-context because I want to recognize tags very specific to the projects I work on on daily basis. I have copied our conversation. There is a lot of input to process 🙂
I'll see whether I can survive without parinfer and paredit 🙂
🙂
For posterity https://github.com/seancorfield/liquid-setup
(I changed the test runner commands to use rebl-sexp
for my convenience, but they could just as easily use editor/eval-sexp
)
Same with the bare bones docstring command.
@mogenslund Is there a reason that both g f
and , g
are bound to context-action
?
@mogenslund Probably my final question of the day: if you resize the Terminal window that Liquid is running in, is there a way to get it to redraw to the new window size?