unrepl lives now in vimpire's shading scheme. Nice. š
heh?
However we went from
=> (let [a] 2)
IllegalArgumentException let requires an even number of forms in binding vector in hwlc5.core:1 clojure.core/let (core.clj:4333)
to
=> (let [a] 2)
CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
In: [0] val: () fails spec: :clojure.core.specs.alpha/bindings at: [:args :bindings :init-expr] predicate: any?, Insufficient input
#:clojure.spec.alpha{:problems [{:path [:args :bindings :init-expr], :reason āInsufficient inputā, :pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x64ba3208 āclojure.spec.alpha$regex_spec_impl$reify__2436@64ba3208"], :value ([a] 2), :args ([a] 2)}, compiling:(NO_SOURCE_PATH:1:1)
Heh
With expound:
=> (let [a] 2)
CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
-- Syntax error -------------------
([a] ...)
^^^
should have additional elements. The next element ā:argsā should satisfy
any?
-- Relevant specs -------
:clojure.core.specs.alpha/bindings:
(clojure.spec.alpha/and
clojure.core/vector?
(clojure.spec.alpha/* :clojure.core.specs.alpha/binding))
-------------------------
Detected 1 error
#:clojure.spec.alpha{:problems [{:path [:args :bindings :init-expr], :reason āInsufficient inputā, :pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x5aa360ea āclojure.spec.alpha$regex_spec_impl$reify__2436@5aa360eaā], :value ([a] 2), :args ([a] 2)}, compiling:(NO_SOURCE_PATH:3:1)
Much better for sure
I wonder if it should say "The vector should have additional elements." ā That's what I would say in conversation
And the formatting around
The next element ":args" should satisfy
any?
is weirdI'll bring this up to Ben, he's my coworker
Iām not even sure to what it refers
really? thatās awesome!
Yup š Happy coincidence
So given the state of 1.9 exceptions, I believe shipping expound with unrepl is a necessity
@bbrinck good job
I wouldn't say it's necessary but it would be awesome
s/necessity/would be a strong differentiator/
Hello š !
Feedback on expound messages is always welcome. I may also be able to provide a little context on why things are the way they are š
the "next element" in (let [a 1])
would be the 1
right?
thatās correct, but I agree thatās not easy to see
Generally speaking, the errors around arg lists are the worst part of expound, but something Iām very interested in improving
(well, around any regex spec, but the most common case is around arglists)
:args
is the name of the spec?
Yes, thatās correct ā¦ when you call fdef
for a function or macro, you can provide 3 parts: :args
, :ret
and :fn
. Later, you do something like (:args (s/get-spec
`let))`
hm, my backtick escaping is failing in slack
trying this: ā(s/form (:args (s/get-spec `let)))ā
eh, you get the idea
the whole spec for :args
is (clojure.spec.alpha/cat :bindings :clojure.core.specs.alpha/bindings :body (clojure.spec.alpha/* clojure.core/any?))
user=> (s/get-spec 'clojure.core/let)
#object[clojure.spec.alpha$fspec_impl$reify__2451 0x732f29af "clojure.spec.alpha$fspec_impl$reify__2451@732f29af"]
I'm a spec-newb š
so I was tempted to interpret
The next element ":args" should satisfy
any?
as āthe next element of :args
out of :bindings
@pesterhazy call s/form
on it
Using the -m friendly
option from the expound README. Fun!
@cgrand Agreed, this looks like a bug in expound.
And yeah s/form
shows the right spec
I suspect I failed to account for some extra data spec puts in the explain-data in this case
Iāve created an issue, thanks for pointing this out!
In general, the problem with the core macros is that there is a lot of branching
but itās something Iām working on
thanks to you! Iām looking at the code, problems
is the ns where most magic happens?
if by āmagicā, you mean āchaosā, then yes š
generally speaking the complexity of expound comes from a design constraint
the message after the announcement of spec was that anyone could print the explain-data
however they wanted, so I really wanted to follow that to the logical conclusion
(as opposed to say, pinpointer, which analyzes the actual spec forms itself. really cool idea! but I wanted to flush out bugs w/ spec that would prevent others from building things like expound)
however, the trick with using explain-data
is that the :in
path is often ambiguous and, in any case, you canāt use the path to trivially find the bad value
i.e. you canāt just use the path in get-in
or update-in
. As a result, thereās a ton of code to a) disambiguate paths and b) highlight bad values.
this code is kind of a mess but I havenāt yet had time to rework it š
anyway, a few things to point out:
1. If you donāt like the fact that expound adds ...
for irrelevant values, that can be controlled
2. you can also omit the ārelevant specsā section
3. Iāve got a branch right now that includes colorization
for the record, here is with pinpoint
=> (let [a] 2)
CompilerException clojure.lang.ExceptionInfo: Call to clojure.core/let did not conform to spec:
Detected 1 spec error:
----------------------------------------------------------------------
(1/1)
Cause: ([a ...] 2)
^^^
Expected: any?
Failure
Reason: Insufficient input
----------------------------------------------------------------------
#:clojure.spec.alpha{:problems [{:path [:args :bindings :init-expr], :reason āInsufficient inputā, :pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings :clojure.core.specs.alpha/bindings], :in [0]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x1d6d1d42 āclojure.spec.alpha$regex_spec_impl$reify__2436@1d6d1d42"], :value ([a] 2), :args ([a] 2)}, compiling:(NO_SOURCE_PATH:3:1)
Much nicer!
@bbrink well I would be interested in a more data-ish/less formated output
like the colors
the ...
is a nice touch
@cgrand Do you mean youād like to get something like explain-data
so that unrepl can format it accordingly?
yeah somewhere between you annotated explain-data and your printer
[warning: thinking out loud]
the idea for unrepl integration would be to not bing *explain-out*
but in the exception handler of the repl to sniff spec exceptions and pimp them
Also thinking out loud here ā¦
itās possible that expound could provide an option to just print a more parseable thing with the data, although IIRC, the result of the normal explain-data
is not readable in some cases due to the actual specs included
(this may change with new version of spec that is supposed more data focused, but i donāt know what that will look like)
you could potentially bind *explain-out*
and just capture the explain-data
that is passed in, then pass it to expound to annotate it with more data
(that inner API is not stable right now, but eventually it could be)
also, in general, iāll be curious to see how unrepl catches exceptions and improves them. thereās quite a lot of interest in trying to do that generally for any project, so I
Iām keeping my eye on efforts on this front - related to stuff in maria.cloud, pyro, a discussion in #clojure yesterday about heuristics for better errors, https://github.com/always-be-clojuring/issues/issues/7 ā¦ lots of interesting discussions around this
but AFAICT, spec doesnāt let a printer like expound really control the actual exception data, so I canāt attach more data to the exception.
(at least, thatās my memory of the situation, I havenāt actually tried it)
so unrepl installs its own read eval print loop and there are two places where exceptions can be intercepted
* when the exception is caught by the loop * when any exception is printed (including as part of a result value)
so it would be quite possible to detect when ex-data contains ::s/problems
and enrich the map before printing
I see, thatās cool
Iām biased of course, but Iād be happy to see expound used in some way within unrepl. Bug reports are always welcome and Iām open to expanding the API to make unrepl integration easier. Let me know how I can help!
what I like about expound is that it has no deps (unlike pinpointer)
Why is that a preference?
I know sideloader, shading etc.
@volrath @pesterhazy @kotarak you all use your own actions (or even no actions at all) for completion, right?
yeah unravel doesn't use an action currently
Are you implying they don't work transitively? I don't understand sorry.
I use my own
IIRC the proposed general contract for a standardize completion actions was: ā¢ in: code (string) ā¢ in: offset (int) ā¢ in: ns-name (sym) ā¢ out: coll of candidates (strings)
do you use any extra information (in or out)?
I may imagine more output: ā¢ candidate (string) ā¢ relative offset (relative to the input offset) and length to specify what to replace by the candidate
For example:
=> (complete "(let [x (mapc" 13 'user) ; 13 is the end of the string
({:candidate "mapcat", :roffset -4, :len 4})
No I just imply that itās a matter of taste and that I tend to consider any dep as a liability
Now for something a bit more controversial:
=> (complete "(let [x (mapc" 12 'user)
({:candidate "map", :roffset -3, :len 3}
{:candidate "map?", :roffset -3, :len 3}
{:candidate "mapv", :roffset -3, :len 3}
{:candidate "mapcat", :roffset -3, :len 3}
{:candidate "map-entry?", :roffset -3, :len 3}
{:candidate "map-indexed", :roffset -3, :len 3})
so here the completion is asked as if the caret ws between p
and c
with compliment I'm getting the type and ns of each candidate
type as in: function, keyword, namespace, blah blah
do you use this info?
yes
how?
sec..
map|c
so how would you substitue the candidate map?
? and mapcat
?
<f>
as in function...
oh
I can't upload files to the channel
haha
I see your screenshot just fine
oh ok... I got a message saying that the workspace doesn't have any storage space left
the screenshot comes from cider (I'm doing cljs right now), but I'm using the same underlying lib to display the candidates in spiral
and do you pass the context or only the prefix to compliment?
Vim has an option to show doc string while completing options. It would be good to support that.
@dominicm canāt it be done in two steps? or does vim show all docstrings at once?
@cgrand it can't, but not for that reason. It's not possible to show it in response to a callback.
I also pass the context
also = in addition to the prefix?
if I remember correctly, I pass the context as a string with a __prefix__
ok
yes I double checked, I pass context with a __prefix__
substring
@cgrand I use my own action which uses compliment under the hood and then transforms/enriches things for vim to digest.
Trying to make screenshot.
From compliment I get the candidate and it's type. I look up the various information based on the type. Compliment accepts the prefix and the namespace. The action looks like this:
`#:vimpire {:complete (vimpire.complete/completions #unrepl/param :prefix #unrepl/param :nspace)}`
Unrepl is now shaded as: vv-8zmXciM-6qVYjA3apmzDNEzIgiRFW7EXcizIgAqgAAU.un repl.repl.
This also gets rid of the unshaded unrepl.core
since I can make it available to the other shading units in its unshaded form.