liquid

seancorfield 2019-06-19T02:49:35.004500Z

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)

seancorfield 2019-06-19T03:04:47.004800Z

It works pretty well 🙂

👍 2
mogenslund 2019-06-19T12:42:46.006800Z

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 😉

seancorfield 2019-06-19T15:25:45.007800Z

@mogenslund Haha... glad you tried it out. Yeah, I saw a two key add binding I think, but that wasn't quite enough here.

seancorfield 2019-06-19T15:26:04.008200Z

Also, do you have commands/hotkeys for running tests in Liquid?

seancorfield 2019-06-19T15:26:37.008700Z

(I could look in the source but figured it's probably easier just to ask 🙂 )

mogenslund 2019-06-19T15:57:57.009Z

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.

seancorfield 2019-06-19T16:00:03.010600Z

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.

mogenslund 2019-06-19T16:08:41.011700Z

Thats great. Please share if you come up with something that does the job 🙂

seancorfield 2019-06-19T17:59:12.013300Z

@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?

seancorfield 2019-06-19T19:11:03.013700Z

Figured it out. Kind of ugly code but it works.

seancorfield 2019-06-19T19:18:00.014800Z

(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)

seancorfield 2019-06-19T19:18:36.015600Z

c t x runs all tests in the current namespace (assuming it's been loaded/eval'd)

seancorfield 2019-06-19T19:18:52.016100Z

c t t runs the test whose name is at the cursor.

mogenslund 2019-06-19T19:20:52.017500Z

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 🙂

seancorfield 2019-06-19T19:22:41.018300Z

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.

seancorfield 2019-06-19T19:24:45.019900Z

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.

seancorfield 2019-06-19T19:38:07.020300Z

(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 🙂

seancorfield 2019-06-19T19:40:18.020800Z

@mogenslund What do you do/use to display a symbol's docstring when you're working in Liquid?

mogenslund 2019-06-19T19:50:16.023200Z

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.

seancorfield 2019-06-19T19:51:00.023900Z

Just realized that get-context is not quite what I thought. Is there a function that returns the symbol name at point?

seancorfield 2019-06-19T19:54:24.025100Z

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

mogenslund 2019-06-19T19:58:33.027500Z

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.

seancorfield 2019-06-19T20:00:06.028200Z

OK, I can probably workaround that for now. It mostly seems to get it right. Just sometimes adds some closing parens/brackets.

mogenslund 2019-06-19T20:04:08.028800Z

Yes. I should write some more test cases on that one to get the edges right 😉

seancorfield 2019-06-19T20:08:06.030300Z

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 :

seancorfield 2019-06-19T20:08:42.030900Z

(I'm working on next.jdbc right now -- these are lines from jdbc_test.clj if you're curious for test material)

mogenslund 2019-06-19T20:14:39.033500Z

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 🙂

seancorfield 2019-06-19T21:03:48.033900Z

I'll see whether I can survive without parinfer and paredit 🙂

😞 1
mogenslund 2019-06-19T21:15:46.034Z

🙂

seancorfield 2019-06-19T21:52:42.034400Z

For posterity https://github.com/seancorfield/liquid-setup

seancorfield 2019-06-19T21:53:12.035200Z

(I changed the test runner commands to use rebl-sexp for my convenience, but they could just as easily use editor/eval-sexp)

seancorfield 2019-06-19T21:53:26.035500Z

Same with the bare bones docstring command.

seancorfield 2019-06-19T22:25:01.036100Z

@mogenslund Is there a reason that both g f and , g are bound to context-action?

seancorfield 2019-06-19T23:38:18.036900Z

@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?