parinfer

cfleming 2017-06-15T01:37:18.512519Z

@shaunlebron I used to use it but removed it.

cfleming 2017-06-15T01:37:58.517572Z

It created too many edge conditions in IntelliJ in non-standard editors.

cfleming 2017-06-15T01:38:35.522422Z

Actually yesterday I found an annoying side effect of not having it enabled, though:

cfleming 2017-06-15T01:40:21.535873Z

(my-fn x y|)
I press enter, but I’m planning to continue entering more parameters for my-fn.
(my-fn x y)
       |
I end up with this. But I can’t remember the parameters, so I ask for parameter info. But Cursive doesn’t show it since I’m no longer inside the function invocation.

cfleming 2017-06-15T01:40:56.541039Z

Worse, that call is probably nested inside some other call, so I’ll probably get the param info for the outer call, which is confusing.

cfleming 2017-06-15T01:41:44.547418Z

I assume the same applies to Emacs et al

shaunlebron 2017-06-15T04:16:11.652421Z

@cfleming: thanks for the example

shaunlebron 2017-06-15T04:17:21.660119Z

incidentally, that case is handled by the patch I landed today that replaces previewCursorScope

shaunlebron 2017-06-15T04:17:42.662462Z

paren mode is run whenever a leading close-paren is found

shaunlebron 2017-06-15T04:18:00.664263Z

you can see the new behavior in the demo: http://shaunlebron.github.io/parinfer/demo

shaunlebron 2017-06-15T04:18:21.666560Z

v3 isn’t released yet, but will at end of the week

cfleming 2017-06-15T04:19:08.671552Z

I still haven’t commented on your v1 vs v2 issue, sorry, but in general I agree with Chris - keeping things balanced seems like a fundamental promise parinfer makes.

shaunlebron 2017-06-15T04:19:28.673600Z

that’s the last issue I’m going to address hopefully tomorrow

cfleming 2017-06-15T04:19:28.673621Z

Inserting unbalanced close parens should just not insert anything IMO.

shaunlebron 2017-06-15T04:19:50.676095Z

yeah, that’s currently landed

shaunlebron 2017-06-15T04:21:13.685367Z

i feel good about the new inline inference that’ll fix the rest of it to keep it balanced

shaunlebron 2017-06-15T04:22:50.696010Z

@cfleming: btw I think the new linter will help fix the race condition in intellij that prevented paren mode from preprocessing a file

cfleming 2017-06-15T04:23:19.699145Z

I meant to ask you about that actually - how would that help?

shaunlebron 2017-06-15T04:24:12.704619Z

well, I mean, if a team agrees to run paren mode on all their files before committing, that tool lets them do that

shaunlebron 2017-06-15T04:24:44.708076Z

but more than the tool is the accompanying readme to help clear up the types of changes and to help convince people it’s not a bad idea to use it

shaunlebron 2017-06-15T04:25:47.714487Z

more concretely: cursive won’t have to process files with paren mode if it’s already processed before opening

cfleming 2017-06-15T04:25:57.715492Z

Ah, ok, thanks.

cfleming 2017-06-15T04:26:17.717741Z

I’m still convinced that some kind of local processing will ultimately prove to be more palatable.

cfleming 2017-06-15T04:26:33.719470Z

But I haven’t had time to prototype it yet.

cfleming 2017-06-15T04:27:06.723133Z

i.e. only processing the range of sexps touched by the deltas of a change.

cfleming 2017-06-15T04:27:41.726878Z

Working out that range is actually a pretty hard problem I’m hammocking at the moment

shaunlebron 2017-06-15T04:27:57.728688Z

that would be very valuable

cfleming 2017-06-15T04:30:35.746163Z

If you can do that, then you don’t need to pre-process, and you could just show a warning if the range actually affected isn’t indented correctly.

shaunlebron 2017-06-15T04:32:19.757543Z

so it would be a stateful thing to track which lines are changed? and only process those lines?

cfleming 2017-06-15T04:34:04.768523Z

So this is tied in with how IntelliJ does things, and I’m not sure how generally applicable it will be.

cfleming 2017-06-15T04:34:18.770029Z

But yes, as a tldr

cfleming 2017-06-15T04:35:40.778795Z

In IntelliJ, I’m not reacting to specific actions. I see a fair amount of the parinfer doc/online literature referring to “on keypress” or “on <some specific thing, like paste>“. I can’t really do that, since there are far too many actions for me to be able to reasonably anticipate them.

cfleming 2017-06-15T04:36:31.784059Z

I basically have to react to document changes, so on a doc change I get: change position, old length, new length, old text, new text.

cfleming 2017-06-15T04:37:04.787507Z

I’d keep track of those for a particular change, which is basically an undoable thing.

cfleming 2017-06-15T04:37:32.790487Z

This is trickier in IntelliJ than in most editors, since something like a rename can affect a lot of locations in the file, or even across multiple files.

cfleming 2017-06-15T04:39:26.802268Z

The difficulty tracking modified ranges is that each new change creates a new document “co-ordinate space”, so if I want to get an sexp range from the original document which was affected by a series of deltas, I have to map them all back through the previous changes to get the correct range in the original doc affected by each change.

cfleming 2017-06-15T04:40:00.805719Z

Then, once I have those ranges I can work out the sexp ranges which cover them all, and then I have to map that forward to get the correct range in the resulting doc.

shaunlebron 2017-06-15T04:40:35.809781Z

makes sense, yeah

shaunlebron 2017-06-15T04:40:44.810742Z

😕

shaunlebron 2017-06-15T04:41:27.815304Z

on keypress => any change, would be a fair mapping I think

shaunlebron 2017-06-15T04:41:38.816399Z

not sure about others

cfleming 2017-06-15T04:41:42.816930Z

Yeah, pretty much - it’s actually a hard problem, especially to do it efficiently - it’s quadratic in the number of changes, and for something like a file reformat that can be a lot.

cfleming 2017-06-15T04:42:22.820738Z

Not sure if I can special case reformat, and just process the whole file at that point.

cfleming 2017-06-15T04:46:01.843617Z

Well, keypress is just an action, and some keypresses are more complicated than others and can lead to reformatting changes (tab, backspace, delete, enter)

shaunlebron 2017-06-15T04:47:03.850297Z

well, it should really reformat on any keypress

cfleming 2017-06-15T04:47:53.855516Z

I mean that the IntelliJ action will format things, before I get to see it.

cfleming 2017-06-15T04:48:13.857528Z

Or at least, the resulting reformatting will be part of the changes communicated to me via document events.

shaunlebron 2017-06-15T04:50:26.871853Z

oh, yeah, that’s not good

cfleming 2017-06-15T04:53:57.894404Z

I’m actually curious how this works in e.g. Emacs. A lot of the complexity in the IntelliJ integration is around making it work in a very general way, since I can’t anticipate all the changes that either IntelliJ or any installed plugins might make.

cfleming 2017-06-15T04:54:38.898640Z

But the same must apply to Emacs if someone is using clj-refactor - a particular action can cause a lot of changes to be made in multiple places/files.

cfleming 2017-06-15T04:55:39.904994Z

And people extend Emacs such that a particular action does crazy things all the time. Are those people just not using parinfer?

shaunlebron 2017-06-15T05:02:16.949011Z

@cfleming: it was recently added to spacemacs as a core plugin I think

shaunlebron 2017-06-15T05:03:26.956542Z

https://github.com/syl20bnr/spacemacs/issues/5574

cfleming 2017-06-15T05:10:22.001757Z

So it looks like the Emacs integration only runs on one of a hard-coded set of commands.

cfleming 2017-06-15T05:11:30.008896Z

Unless I’m missing something, my elisp is not great.

shaunlebron 2017-06-15T15:09:41.282811Z

i can’t tell by skimming right now

shaunlebron 2017-06-15T15:11:09.318073Z

looks like it’s only executed from these keys though: https://github.com/DogLooksGood/parinfer-mode/blob/master/parinfer.el#L1078-L1101

mattly 2017-06-15T18:15:35.455923Z

I use parinfer in spacemacs/main (that PR is still in develop), setting it up was fairly straightforward

mattly 2017-06-15T18:16:22.472738Z

I use it alongside smartparens and paredit

shaunlebron 2017-06-15T19:42:38.271816Z

@mattly: cool, does it work well?

mattly 2017-06-15T19:46:47.353465Z

@shaunlebron for me it does. I've been slowly moving off of spacemacs (though I still use spacemacs for work) and I just setup parinfer by itself and it feels off

mattly 2017-06-15T19:47:23.365221Z

I'd link my config but for whatever reason the slack electron app decided to stop interacting with my system clipboard

shaunlebron 2017-06-15T19:56:42.550689Z

@mattly it might feel off due to lack of structural editing stuff

shaunlebron 2017-06-15T19:56:55.555347Z

but it was always my hope that it would be compatible if you want add those layers, so glad it’s fitting okay

mattly 2017-06-15T19:56:56.555444Z

yeah, paredit is next on my list of things to setup

mattly 2017-06-15T19:58:46.593758Z

parinfer has been a helpful sell to my lisp-phobic co-workers that come and pair with me though

shaunlebron 2017-06-15T20:00:00.619361Z

🙂!

shaunlebron 2017-06-15T20:00:41.635076Z

what type of lisp are you using? and how are you introducing it to your project? (kind of interested in how folks do this)

mattly 2017-06-15T20:02:33.673644Z

it's.. a bit odd, really; Clojure/Script, in a group that's otherwise Rails/Ember/Elixir

mattly 2017-06-15T20:03:35.694727Z

my project is somewhat alien compared to what everything else is, it's a free-from analytics tool for asking questions from a variety of HIPAA-protected data sources

mattly 2017-06-15T20:04:10.706164Z

whereas all the other projects in the group are closed-ended tools for accomplishing specific tasks

mattly 2017-06-15T20:04:57.722027Z

before I came on, one of the other senior devs had tried prototyping this project in rails/ember and it was a mess

mattly 2017-06-15T20:06:48.759299Z

my specialty is this sort of thing – interfaces for doing data analysis – and I had enough trust from the dev team (most of whom I've known for a while) to make a strong case for doing this in clojure/script, and it's been a huge success in that regard

mattly 2017-06-15T20:07:33.774158Z

the original prototype centered around a single type of query from a single datasource, and it had like 2000 lines of string concatenation in ruby to construct a sequel query

mattly 2017-06-15T20:07:50.779823Z

I boiled that down to 20 lines of logic and 100 lines of data in clojure

mattly 2017-06-15T20:08:03.784236Z

and that got people interested

shaunlebron 2017-06-15T20:08:50.799516Z

🎉

shaunlebron 2017-06-15T20:09:22.810221Z

trust + direct comparison to show benefit

mattly 2017-06-15T20:10:18.828362Z

yeah

mattly 2017-06-15T20:10:48.838031Z

I've gotten one or two of the fronend people on another project interested in re-frame

mattly 2017-06-15T20:11:05.843684Z

they're both using Atom, so of course I set them up with parinfer

shaunlebron 2017-06-15T20:12:06.863839Z

yeah? what do you think their general impression is?

mattly 2017-06-15T20:12:34.873051Z

they think it's neat but have a hard time understanding how to build something complex in it

mattly 2017-06-15T20:12:44.876311Z

oh, of parinfer, not re-frame

mattly 2017-06-15T20:13:18.887010Z

one of them said, "ok, so you were right, the parens aren't really that big of a deal"

shaunlebron 2017-06-15T20:15:08.922806Z

sweet!

shaunlebron 2017-06-15T20:16:35.951712Z

I tried getting david to make the cljs repo compatible with parinfer, but it was kind of a big ask to add so many whitespace changes without some kind of evidence that newcomers are using parinfer

shaunlebron 2017-06-15T20:17:24.967560Z

I’m going to setup some kind of survey asking for people to share stories like this to help build a better case

mattly 2017-06-15T20:19:13.002642Z

cool deal

dominicm 2017-06-15T20:20:03.018925Z

@shaunlebron biggest use for me in parlinter was just identifying dumb indentation mistakes.

shaunlebron 2017-06-15T20:21:39.050901Z

@dominicm yeah, your point about revealing “confusing indentation” made it into the parlinter readme, i thought that was a good way to say that

shaunlebron 2017-06-15T20:22:36.069538Z

we actually caught an accidental expression nesting in the cljs repo using it

dominicm 2017-06-15T20:23:15.082287Z

My #1 comment about parinfer is always: > Parinfer puts parentheses where they look like they should be. I've found so many bugs by locating the indent button in people's editors. Parinfer solves this

shaunlebron 2017-06-15T20:26:33.147144Z

maybe a good example of this—the mistake caught in cljs repo:

;; before
(is (= nil (s/index-of sb "z" 100))
(is (= nil (s/index-of sb "z" -10))))))

;; after
(is (= nil (s/index-of sb "z" 100))
 (is (= nil (s/index-of sb "z" -10))))))

shaunlebron 2017-06-15T20:27:17.161223Z

yeah, indentation was wrong

mattly 2017-06-15T20:27:18.161649Z

I've had a few instances of that as well

dominicm 2017-06-15T20:27:29.165270Z

That's a perfect example.

shaunlebron 2017-06-15T20:31:05.236964Z

when parens are inferred, i think the question most people ask is—so why are they even there?

shaunlebron 2017-06-15T20:32:11.260056Z

i showed the project to jeremy ashkenas before i had a fancy website for it, and his reaction was “…so i guess the next step is to remove the parens”

shaunlebron 2017-06-15T20:35:13.320380Z

i kind of got a blank stare when i tried to explain the benefits of explicitness and consistency, but I think it remains the second half of the problem of introducting lisp—that parinfer only elucidates the how of parens rather than the why

✅ 1
mattly 2017-06-15T20:36:58.355229Z

... oh god

mattly 2017-06-15T20:37:22.362912Z

fleeing from coffeescript's indecisiveness is what drove me to lisp

shaunlebron 2017-06-15T20:39:38.406527Z

it’s definitely what drove me back to js

shaunlebron 2017-06-15T20:40:52.430079Z

i think it was a great experiment that took philosophy of implied behavior to its extreme, and taught me that it’s not a very good thing for a language to have

mattly 2017-06-15T20:41:03.433719Z

agreed

shaunlebron 2017-06-15T20:43:11.475496Z

it also taught me how to market a new idea in a very straightforward way

shaunlebron 2017-06-15T20:43:21.478933Z

that website was so good

dominicm 2017-06-15T21:10:14.997886Z

https://srfi.schemers.org/srfi-49/srfi-49.html

dominicm 2017-06-15T21:10:22.000278Z

RE "why are they even there"

dominicm 2017-06-15T21:10:49.008495Z

https://srfi.schemers.org/srfi-110/srfi-110.html also interesting

shaunlebron 2017-06-15T21:31:52.372836Z

I’d be interested in reading why those never caught on