replete-repl / replete-ios

ClojureScript REPL iOS app
Eclipse Public License 1.0
395 stars 25 forks source link

Investigate using Parinfer for form entry #73

Closed mfikes closed 8 years ago

mfikes commented 8 years ago

Parinfer is here.

Rationale:

  1. It is difficult to type on a mobile keyboard so the heavy inference could reduce explicit keystrokes for balancing parens, etc.
  2. Using key combinations (like paredit) would probably make things more difficult if we went down that path. (You'd probably need explicit barf/slurp buttons—maybe Parinfer makes much of this moot)
  3. This would provide a nice way to auto-indent forms as entered, which Replete currently does not do.

Implementation ideas:

• Replace the existing input text field with a small web view that has Parinfer hooked up to it. • Sort out how to make the input web view automatically grow and shrink vertically. • Make sure Parinfer can work in self-host / bootstrapped mode (if it needs to use the reader, analyzer, etc.)

shaunlebron commented 8 years ago

Alternatively, you can keep the single-line text field, and still take advantage of auto-paredit. You just need a pure function of your input text, which does the following:

parinfer has its own simplified reader, btw, which seemed to work against all the core clojure repos I could throw at it.

mfikes commented 8 years ago

@shaunlebron Replete actually has a multi-line input field which dynamically adjusts vertical height to grow or shrink to accommodate the s-expression.

shaunlebron commented 8 years ago

@mfikes just tried out the multi-line input field, great!

Just published [parinfer "0.1.0"] which you can use from ClojureScript. You can just transform the input field with indent-mode/format-text after every keystroke. details

mfikes commented 8 years ago

@shaunlebron cool. I may give it a try. Doesn't sound difficult.

shaunlebron commented 8 years ago

I can put together a PR if you want to decide whether it's enabled by default or not, and how to enable if not.

mfikes commented 8 years ago

Initial hook is in place now. It is working.

https://github.com/mfikes/replete/commit/8fd5bd2fae6d170a85bde3850d3594892dbac220

This gets us into a position where we can experiment with ergonomics, caret positioning, etc.

shaunlebron commented 8 years ago

sweet! :+1:

mfikes commented 8 years ago

parinfer-replete

mfikes commented 8 years ago

@shaunlebron In the parinfer branch, I've updated the code so it correctly supplies :cursor-x and :cursor-line hints. But, when hitting return, things don't behave like on the Parinfer web page. For example, if typing (+ 2) and then hitting return, and then 3, you instead get (+ 2)3 with a trailing newline. I have a question: Does Parinfer assume that something else is auto-indenting prior to feeding text to it? Or does it doe the indenting? (I'm thinking this may explain the difference.)

shaunlebron commented 8 years ago

right, parinfer doesnt do any auto-indenting when pressing enter since it doesnt know anything about the last character pressed. i can see about adding a 'pressed-enter?' option

On Saturday, November 21, 2015, Mike Fikes notifications@github.com wrote:

@shaunlebron https://github.com/shaunlebron In the parinfer branch, I've updated the code so it correctly supplies :cursor-x and :cursor-line hints. But, when hitting return, things don't behave like on the Parinfer web page. For example, if typing (+ 2) and then hitting return, and then 3, you instead get (+ 2)3 with a trailing newline. I have a question: Does Parinfer assume that something else is auto-indenting prior to feeding text to it? Or does it doe the indenting? (I'm thinking this may explain the difference.)

— Reply to this email directly or view it on GitHub https://github.com/mfikes/replete/issues/73#issuecomment-158659268.

mfikes commented 8 years ago

@shaunlebron Ahh interesting. I need to make sure that the "re-set cursor position after putting text in field" logic is right. An interesting philosophical aspect I'm seeing is that perhaps Paredit is geared towards editing source files (where you may have a sequence of forms), while REPLs want the user to enter a single form. I'll play around with it more to gain a better understanding of its behavior, design philosophy, etc.

shaunlebron commented 8 years ago

if you're referring to your logic here, that is how I handled it in CodeMirror as well. And actually, my pressed-enter? option wouldn't work unless I returned a cursor position from format-text, which I will do eventually.

I think Paredit is still useful inside a single top-level form, given all the nested expressions you can transform inside.

mfikes commented 8 years ago

@shaunlebron Yeah. I was also pondering the concept of cursor position being returned from format-text as well, motivated by the case where (+ 2\n) gets transformed to (+ 2)\n, which effectively moves the cursor, while the UI doesn't know to do so. :)

I agree, Paredit is proving extremely useful for a single form. I think the consequences of hitting return is the only corner case.

mfikes commented 8 years ago

@shaunlebron Ahh... I think I've confirmed my suspicion: the Parinfer page is using CodeMirror's Clojure mode. So hitting return does more than inserting "\n" into the text. CodeMirror adds some spaces. If I can figure out how to do the same, I think I can replicate the experience on the Parinfer demo pages.

shaunlebron commented 8 years ago

Well, Paren Mode already corrects dedented lines of text, albeit with just a one-space indentation. So we could just process the text with Paren Mode (instead of Indent Mode) when pressing enter. For example, pressing enter right before b here:

(def foo [a b])

will result in:

(def foo [a 
b])

which Paren Mode would correct to be:

(def foo [a 
          b])

I'll have to finish https://github.com/shaunlebron/parinfer/issues/54 for this to work when pressing enter before a close-paren though.

mfikes commented 8 years ago

@shaunlebron Ahh. Cool. Sounds like a promising plan. Of course, don't rush—all of this is in an experimental branch of Replete where it can take its time to mature.

shaunlebron commented 8 years ago

cool, I'll write a note here when it's done.

shaunlebron commented 8 years ago

released parinfer 0.2.0. When pressing enter:

mfikes commented 8 years ago

@shaunlebron Updated and looks great:

indent-return