unrepl 2018-01-03

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

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

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

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

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

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

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

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

good point about the repl transcript too

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

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

you mean this?

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

here's the use case I have in mind

are you talking about spiral-eval-buffer?

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

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

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

and do you revert to user after?

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

I might stay in foo.bar

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

it's kind of a tradeoff between truth and convenience

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

convenience: access to previous evaluations you actually care about

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

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

also you can't switch back like that

tbh, switching back is not something that I love

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

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

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

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

(unrepl/do (ns foo))

I think this is a source of confusion

(unrepl/incognito (ns foo))

😄 1

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

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

it’s already in unrepl

and I was on the verge of removing it 😉

ok, let me try that then 🙂

unrepl/do saved by the bell?

(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

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

^:unrepl/shhhh could be a better syntax

unrepl/undo 🙂

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

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

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

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

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

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

only to literals

hmmmm that's not true actually

you can type hint an expression

there’s the ^:once metadata on fn*

it's still a bit of an obscure feature

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

a "repl-special form" is easier to grok

yeah not sure either

@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

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

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

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

#2 is happening though

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

#2 is somehow by design

hmm I do not feel it would be too crazy to think that some client would want to do an unrepl/do expecting some result back. but I can ping back if I'm ever into that situation

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

I have the feeling we are over thinking here

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

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

in clj it basically deletes *1 *2 *3

not the asumption I had, let me check

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

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

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=> 

bah, nevermind

*3 *3 *3 would be better 🙂

side effects, we ❤️ you

haha yes ❤️

when you do (ns some.ns)

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

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

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

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

true because handling of *1 etc is the repl job

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

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

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

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

the user can only type when there's a prompt

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

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

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

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

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

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

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

it’s too complex

back to unrepl/do

I’m ok with it emitting an :eval

and renaming it

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

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

I'm not sure

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

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

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

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

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

> 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

Why so? Because unrepl is using boot?

No, unrepl uses Leiningen

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