unrepl

discussing specification of an edn-based repl and its implementations.
bozhidar 2018-01-03T07:40:40.000137Z

> so if we want to side load also AOT-id/Java, probably the best option would be to refactor mranderson and package it as boot library

bozhidar 2018-01-03T07:41:08.000112Z

Why so? Because unrepl is using boot?

bozhidar 2018-01-03T07:41:42.000158Z

I’m assuming it won’t be hard to make mranderson play well with boot.

cgrand 2018-01-03T07:42:48.000103Z

No, unrepl uses Leiningen

pesterhazy 2018-01-03T09:35:02.000203Z

Personally I don't think there's anything wrong with lein, especially if it's used for a specific task like shading a library

volrath 2018-01-03T11:54:52.000200Z

@cgrand last night I started thinking/coding a way to interactively switch the REPL namespace to the one my current working buffer holds, i.e. my user conn REPL is in the user ns, and I'm looking at a file/buffer that's represented by foo.bar ns, I want to have an editor command to switch the user conn's ns to foo.bar, so this would have to go through the aux conn... I couldn't find an easy way to do that, any thoughts?

cgrand 2018-01-03T11:57:04.000169Z

You don’t want to send (ns foo) over the userconn?

cgrand 2018-01-03T11:58:02.000082Z

(where (ns foo) is the full ns form)

volrath 2018-01-03T11:58:03.000113Z

I could, but I'm avoiding it since I think this is more of a tooling thing.. it'd be an interactive editor command, don't know if I want that in the user repl history

cgrand 2018-01-03T11:58:47.000128Z

If you want to read the repl log, knowing when you switch ns may be useful.

cgrand 2018-01-03T12:00:16.000018Z

An aux command would also have to force reprompt on user otherwise there would be no feedback in the repl buffer

pesterhazy 2018-01-03T12:00:19.000010Z

(ns foo) seems the natural thing to me as well

pesterhazy 2018-01-03T12:01:09.000228Z

good point about the repl transcript too

volrath 2018-01-03T12:01:45.000236Z

I agree with that on premise, and I also had implemented a notification system so that the user sees when this happens... what I don't like as much is cluttering *1 *2 *3 with things that the user may not have wanted to evaluate

volrath 2018-01-03T12:03:09.000184Z

and what I mean by that, is that some times the editor may want to automatically switch to a namespace, without the user explicitly telling so

pesterhazy 2018-01-03T12:03:09.000224Z

you mean this?

clojure.set=> (in-ns 'user)
#unrepl/ns user
user=> *1
#unrepl/ns user

volrath 2018-01-03T12:03:22.000087Z

yes

volrath 2018-01-03T12:03:32.000061Z

here's the use case I have in mind

pesterhazy 2018-01-03T12:03:49.000313Z

are you talking about spiral-eval-buffer?

pesterhazy 2018-01-03T12:05:09.000001Z

I'm wondering now if spiral-eval-last-sexp will affect *1

volrath 2018-01-03T12:05:39.000072Z

the user repl is in user, and the user is looking at a foo.bar file. When the user tries to evaluate a form in foo.bar I want the REPL to automatically switch to foo.bar (this would be customizable of course), a notification will be seen so that the user know it happened and the form will be evaluated after the ns was switched

volrath 2018-01-03T12:06:22.000038Z

at this point, *1 would hold the evaluated form, but if I sent the (ns foo.bar) through the user conn, *2 will hold that as well

cgrand 2018-01-03T12:06:24.000199Z

and do you revert to user after?

volrath 2018-01-03T12:06:58.000190Z

I'm meaning to make it customizable.. I might not

volrath 2018-01-03T12:07:10.000118Z

I might stay in foo.bar

pesterhazy 2018-01-03T12:07:52.000238Z

do people actually use *2 ...? I mostly care about *1

pesterhazy 2018-01-03T12:08:49.000083Z

it's kind of a tradeoff between truth and convenience

pesterhazy 2018-01-03T12:09:16.000325Z

truth: we don't want to hide unnecessarily what gets sent to the repl

pesterhazy 2018-01-03T12:09:44.000233Z

convenience: access to previous evaluations you actually care about

cgrand 2018-01-03T12:09:44.000346Z

`(do (ns foo) (my expr))` ?

cgrand 2018-01-03T12:10:01.000205Z

splicing do

cgrand 2018-01-03T12:11:07.000017Z

nah won’t work is there are syntax quotes, aliases etc.

pesterhazy 2018-01-03T12:11:28.000020Z

also you can't switch back like that

volrath 2018-01-03T12:11:44.000359Z

tbh, switching back is not something that I love

volrath 2018-01-03T12:12:21.000050Z

in nrepl what they do is pass a :ns key to their input messages

pesterhazy 2018-01-03T12:12:38.000030Z

suppose I'm working in the repl buffer visiting 'user and running a test command repeatedly (foo.bar/quux)

volrath 2018-01-03T12:12:52.000208Z

so the REPL buffer can be in user, but the interactive buffer evaluations happen in the buffers ns (cider)

pesterhazy 2018-01-03T12:12:55.000118Z

now I change quux - but that switches my ns in the repl buffer

cgrand 2018-01-03T12:12:55.000220Z

(unrepl/do (ns foo))

volrath 2018-01-03T12:13:02.000163Z

I think this is a source of confusion

pesterhazy 2018-01-03T12:13:37.000019Z

(unrepl/incognito (ns foo))

😄 1
pesterhazy 2018-01-03T12:13:38.000298Z

🙂

volrath 2018-01-03T12:13:46.000021Z

@cgrand that over the aux conn? I'm not entirely sure what unrepl/do does

cgrand 2018-01-03T12:14:52.000133Z

unrepl/do only works at top level and works like top-level do except the return value is never printed and it doesn’t affect *1

cgrand 2018-01-03T12:15:05.000096Z

it’s already in unrepl

pesterhazy 2018-01-03T12:15:15.000127Z

oh! TIL!

cgrand 2018-01-03T12:15:43.000298Z

and I was on the verge of removing it 😉

volrath 2018-01-03T12:16:38.000024Z

ok, let me try that then 🙂

cgrand 2018-01-03T12:17:10.000016Z

unrepl/do saved by the bell?

volrath 2018-01-03T12:18:22.000029Z

(if (and (seq?  r) (= (first r) 'unrepl/do))
                                       (do
                                         (flushing [*err* (tagging-writer :err id write)
                                                    *out* (scheduled-writer :out id write)]
                                                   (eval (cons 'do (next r))))
                                         request-prompt)
                                       r)
haha it took me a while to find that definition

volrath 2018-01-03T12:18:37.000013Z

cool, I'll try it out, I think it will work

cgrand 2018-01-03T12:18:39.000113Z

^:unrepl/shhhh could be a better syntax

volrath 2018-01-03T12:18:46.000089Z

hahaha

pesterhazy 2018-01-03T12:18:53.000028Z

unrepl/undo 🙂

volrath 2018-01-03T12:19:11.000004Z

gonna go grab something to eat first, then I'll try it

cgrand 2018-01-03T12:19:17.000048Z

I like the metadata because it wouldn’t introduce a special

volrath 2018-01-03T12:19:51.000014Z

what would be the problem with a special form? just curious

cgrand 2018-01-03T12:21:26.000168Z

(use of *1 notwithstanding) a transcript could be replayable in any repl (metadata would be ignored); unrepl/do would break

pesterhazy 2018-01-03T12:24:55.000123Z

you mean ^:silently (in-ns 'foo.bar) ?

cgrand 2018-01-03T12:25:02.000254Z

yeah

pesterhazy 2018-01-03T12:25:22.000018Z

I'm not so sure — metadata usually doesn't apply to fn calls, right?

pesterhazy 2018-01-03T12:25:56.000036Z

only to literals

cgrand 2018-01-03T12:26:06.000314Z

no

pesterhazy 2018-01-03T12:26:10.000345Z

hmmmm that's not true actually

cgrand 2018-01-03T12:26:24.000264Z

you can type hint an expression

cgrand 2018-01-03T12:26:36.000259Z

there’s the ^:once metadata on fn*

pesterhazy 2018-01-03T12:27:01.000068Z

it's still a bit of an obscure feature

cgrand 2018-01-03T12:27:22.000329Z

and it doesn’t apply to a fn call: it’s an annotation on an expression 😉

pesterhazy 2018-01-03T12:27:26.000213Z

a "repl-special form" is easier to grok

cgrand 2018-01-03T12:28:40.000301Z

dunno

pesterhazy 2018-01-03T12:28:47.000048Z

yeah not sure either

volrath 2018-01-03T14:02:54.000044Z

@cgrand @pesterhazy alright I tried unrepl/do and it works but there are a couple of things that seem fishy somehow: 1. unrepl/do makes unrepl return a :read message with updated line-col positions, which is not a big deal to spiral, but to clients that use those values to keep sync with the input sent, it's problematic. 2. unrepl doesn't return an :eval message, which in this case is not a big deal cause I'm not interested in the result, but that may not always be the case

volrath 2018-01-03T14:04:23.000103Z

I'm not entirely sure about #2 though, it might be a problem on my side, I'll confirm in a few minutes

cgrand 2018-01-03T14:06:16.000242Z

I don’t see what’s wrong with #1

volrath 2018-01-03T14:06:55.000135Z

no, you are right, that's not problematic...

volrath 2018-01-03T14:07:17.000506Z

#2 is happening though

volrath 2018-01-03T14:07:34.000330Z

I mean, there's no :eval back from unrepl/do

cgrand 2018-01-03T14:08:05.000188Z

@otfrom welcome Bruce!

cgrand 2018-01-03T14:08:39.000498Z

#2 is somehow by design

2018-01-03T14:08:41.000526Z

👋

2018-01-03T14:09:04.000083Z

was intrigued after seeing spiral https://melpa.org/?utm_source=dlvr.it&utm_medium=twitter#/spiral

volrath 2018-01-03T14:11:52.000386Z

great! it's a work in progress, let me know if you try it out 🙂

cgrand 2018-01-03T14:15:32.000365Z

I have the feeling we are over thinking here

cgrand 2018-01-03T14:16:49.000111Z

A couple of observations: 1/ (ns foo.bar) in lumo doesn’t affect *1 and friends

volrath 2018-01-03T14:18:41.000413Z

it does in clj, but I wouldn't mind if unrepl would take the lumo approach

volrath 2018-01-03T14:19:43.000272Z

nope

volrath 2018-01-03T14:19:53.000646Z

in clj it basically deletes *1 *2 *3

volrath 2018-01-03T14:20:00.000247Z

when you do (ns some.ns)

cgrand 2018-01-03T14:20:03.000070Z

2/ what you really want atm is (ns buffer.ns) (expr-from-buffer) and we are complaining that *1 is messed up with while there’s little chance that expr-from-buffer would ref it, so (ns buffer.ns) (set! *1 *2) (set! *2 *3) (expr-from-buffer) would be safe

cgrand 2018-01-03T14:21:06.000262Z

user=> 1
1
user=> 2
2
user=> 3
3
user=> (ns foo.bar)
nil
foo.bar=> [*1 *2 *3]
[nil 3 2]

cgrand 2018-01-03T14:22:38.000328Z

The fact that lumo doesn not behave like clj tells that it may be wise to consider a command since behaviour is going to vary amongst targets

cgrand 2018-01-03T14:23:25.000250Z

so is doesn’t delete, it just shifts as usual

volrath 2018-01-03T14:24:21.000170Z

other.test=> 1
1
other.test=> 2
2
other.test=> 3
3
other.test=> (ns new.ns)
nil
new.ns=> *1 *2 *3
nil
nil
nil
new.ns=> 

volrath 2018-01-03T14:24:27.000250Z

bah, nevermind

volrath 2018-01-03T14:24:29.000591Z

I see now

dominicm 2018-01-03T14:24:44.000416Z

I think ns is quite weird in cljs, so I'm not particularly surprised the behaviour is different.

cgrand 2018-01-03T14:25:00.000168Z

*3 *3 *3 would be better 🙂

cgrand 2018-01-03T14:25:24.000391Z

side effects, we ❤️ you

volrath 2018-01-03T14:25:27.000307Z

lumo does its own handling of *1 *2 *3, from what I remember

volrath 2018-01-03T14:25:37.000450Z

haha yes ❤️

volrath 2018-01-03T14:26:42.000041Z

yep, there's no such thing as clojure.main/repl in cljs

volrath 2018-01-03T14:26:51.000322Z

afaik

cgrand 2018-01-03T14:27:08.000229Z

@volrath @pesterhazy how your clients handle a :prompt out of the blue?

volrath 2018-01-03T14:27:50.000016Z

mine just prints it, I'm not taking special precaution

cgrand 2018-01-03T14:28:14.000107Z

so it could print a new prompt mid editing of the user?

volrath 2018-01-03T14:28:59.000042Z

it could

volrath 2018-01-03T14:29:10.000139Z

the user can only type when there's a prompt

volrath 2018-01-03T14:29:48.000522Z

so if for any reason a new prompt would appear without the user hitting enter, it would print the new prompt and copy/paste the user's input into the new one

cgrand 2018-01-03T14:29:58.000498Z

cool

volrath 2018-01-03T14:30:08.000666Z

that's what's coded, but I haven't tested it cause I don't know how to reproduce that

volrath 2018-01-03T14:31:31.000225Z

you know what, I lied, I do take one precaution

cgrand 2018-01-03T14:31:40.000471Z

so the scenario would be 1/ send command to aux 2/ wait for matching prompt on user 3/ send expr to user

volrath 2018-01-03T14:33:05.000152Z

I distinguish between interactive evals and repl evals.. if the new prompt is associated with a repl eval, I print it, if not, I ignore it

volrath 2018-01-03T14:34:15.000100Z

I don't understand that scenario 😕 when I send forms through aux I don't care about the prompts, I only care about user prompts

cgrand 2018-01-03T14:50:27.000325Z

the :prompt appearing on user is the conformation that the ns had effectively been changed

cgrand 2018-01-03T14:51:20.000623Z

it’s too complex

cgrand 2018-01-03T14:51:55.000403Z

back to unrepl/do

cgrand 2018-01-03T14:52:45.000399Z

I’m ok with it emitting an :eval

cgrand 2018-01-03T14:59:47.000348Z

and renaming it

volrath 2018-01-03T15:00:53.000068Z

ah, I see what you mean... I mean, tbh, I wouldn't mind just adding an extra check: if the user :prompt comes out of nowhere and its namespace is different from the one before (I always keep reference of the current namespace in the client) -> print it out

volrath 2018-01-03T15:01:12.000468Z

but emitting :eval also works, an maybe it's better imo

volrath 2018-01-03T15:01:23.000568Z

I'm not sure

volrath 2018-01-03T15:03:51.000719Z

when you say "rename it" you mean emit another type of message different from :eval?

cgrand 2018-01-03T15:09:32.000186Z

the whole scenario exposed above is brittle as you have to use two conns and wait etc.

cgrand 2018-01-03T15:10:04.000152Z

re: “rename it”, no rename unrepl/do

volrath 2018-01-03T15:10:29.000538Z

got it

cgrand 2018-01-03T15:12:03.000241Z

I’m event thinking about a :sneaky command (that would just be (unrepl/do #unrepl/param :expr))

pesterhazy 2018-01-03T17:26:51.000495Z

I think an unexpected :prompt should cause the prompt to be reprinted in unravel (and the ns portion to be changed)