GithubHelp home page GithubHelp logo

parinfer / parinfer.js Goto Github PK

View Code? Open in Web Editor NEW
1.7K 35.0 40.0 10.44 MB

Let's simplify the way we write Lisp

Home Page: https://shaunlebron.github.io/parinfer

License: MIT License

Shell 2.02% JavaScript 97.98%

parinfer.js's Issues

strip trailing delimiters on current line after cursor

It's a bit strange to dedent this line and not see the change until leaving the line:

 <[:div]
   [:h1 "title"]

Since we only prevent stripping delimiters on the current line to allow us to insert tokens after them, I think we only need to prevent stripping ones appearing after the cursor.

special cases for repositioning cursor

if change is insertion, place cursor after the first occurrence of that character starting at the previous cursor position

  • prevents advancing cursor forward when inserting bad delimiters
  • prevents backshifting when inserting a semicolon behind a trailing delimiter

allow typing unmatched delims

I think this will be good for giving the user freedom to create a closing paren before an open paren if they want. We can just highlight it red until they match it, like editors will commonly do.

Problem with quoted semicolons

I've been working with hiccup this week and I found a problem in insert mode that keeps biting me. I'm not sure if #49 is describing existing bugs or just trying to find a better way of handling this stuff, but I wanted to raise an issue for this because it's coming up so often in my codebase.

Here's the test-case

in

(for [col columns]
  "|
  [:div.td {:style "max-width: 500px;"}])

out

(for [col columns]
  "
  [:div.td {:style "max-width: 500px;"}])

The test error is

expected----------------------------------
(for [col columns]
  "
  [:div.td {:style "max-width: 500px;"}])
actual------------------------------------
(for [col columns]
  "
  [:div.td {:style "max-width: 500px);"}])
expected: "(for [col columns]\n  \"\n  [:div.td {:style \"max-width: 500px;\"}])"
  actual: "(for [col columns]\n  \"\n  [:div.td {:style \"max-width: 500px);\"}])"
    diff: - "(for [col columns]\n  \"\n  [:div.td {:style \"max-width: 500px;\"}])"
          + "(for [col columns]\n  \"\n  [:div.td {:style \"max-width: 500px);\"}])"

multiple cursors

supporting this can have an effect on #39, in that we might have to just handle changes sequentially

Separate Parinfer as a library

Starting this issue to track separation of "Parinfer the library" from "Parinfer the website".

Specifically, I'm looking for a library version of Parinfer in order to create an Atom editor plugin that will allow it's use.

editors waiting on this:

  • Replete
  • Light Table
  • Atom
  • Gorilla REPL
  • Neovim

space and shift+space

when multiple lines are selected:

  • space - indent one space
  • shift+space - dedent one space

Dim trailing delims

this will signal to the user that these are not in stone, and can be reposition by indented lines

will have to implement a new clojure mode in CodeMirror to highlight them differently

return cursor position

the API may have to return the corrected cursor position under the following circumstances:

  • not allowed to insert paren
  • not allowed to remove paren
  • commenting an inferred paren

we can add this to the test case output blocks with a pipe |.

handling auto-indent

There are two extra features related to auto-indentation that Parinfer users are starting to expect. Parinfer may grow in scope to handle these cases somehow, or we will have to detail how this can be handled external to it:

  1. position of cursor after pressing enter (auto-indentation of newlines)
  2. auto-indenting a region of text according to specific rules (realigning according to conventions)

Specifically, @snoe and @SevereOverfl0w expect the following from item 1: when pressing enter at the end of the last line:

(defn foo [a b]
  (let [x (+ a b)]
    x))|

They expect the cursor to be at the following position:

(defn foo [a b]
  (let [x (+ a b)]
    x))
   |

This behavior is handled in vim by using a mode called autoindent (seen here), which trivially copies the indentation of the previous line.

The behavior for item 2 can be handled by vim-clojure-static, which defines configurable rules for how to indent forms.

These two modes conflict with each other inside vim, so a solution to this problem must combine them when appropriate.

new plugin: emacs-parinfer

Hi Shaun, I've decided this will be a great way to work on my elisp chops so I'm working on emacs-parinfer which is planned to be a minor mode for emacs. Depending on how much work I get done over the coming holiday I might be at a point of making code public in a week or so. Thanks for all the work you have done so far!
Roger

keeping exprs intact

There seems to a necessity for a separate mode when performing certain edits. Given this:

(defn foo [a b]
  (+ a b))

Prepending the first line with an ignore form macro in infer-mode, gives this:

#_(defn foo [a b])
  (+ a b)

whereas, we want this instead:

#_(defn foo [a b]
    (+ a b))

I think this is the job for the prep function during live editing. We will have to extend the prep function to accept a cursor position and cursor delta (maybe just previous cursor position to compute delta). The delta is required so we can preserve relative indentation of expressions after the cursor (we can just add the cursor delta to the indent-delta line data at the cursor). This could get tricky for selection-based editing. Just keep it simple with cursor for now.

Add a sockets API?

I'd be interested in making a Parinfer bundle for Howl, but Howl's written in MoonScript and can't interface easily with Clojure. Would it be possible to have a sockets-based API to allow other editors to access Parinfer?

Inserting a quote can cause loss of information

If I have the following string:

"]"

And I insert a quote at the beginning of this line, I end up with this:

"""

This happens because it considers ] to be code now. And since we disallow unmatched closing delims, it is erased.

I am not sure how to solve this problem:

  • we can't use the mechanics of indentation to auto-wrap/splice like we can with parens
  • even if we could, placing a quote before another completely changes the meaning of the latter, which can erase previously fine characters
  • we could restrict quotes to be inserted in pairs
    • would have to restrict deleting in pairs too
    • would have to auto-correct pasted code

introducing this extra complexity may result in the antithesis of my objective for an approachable lisp.

unified change api for both modes

We can describe all text changes with this model: https://github.com/shaunlebron/parinfer/blob/master/test-cases/text-change.md

but right now, the parinfer api requires us to specify changes differently depending on the mode:

  • indent mode - line numbers to replace, new lines to insert
  • paren mode - specify a cursor-dx position indicating how far the cursor has moved

this requires a lot of manual work on the api user, so if we simply accept a change object described by the above link (which I think most editors expose on change events), we can offload this work to the modes themselves.

This should be done before #24 (creating the standalone parinfer-lib)

Plugin for Light Table

This would be fantastic for Light Table and all of the Lispy languages our users use.

Light Table uses Code Mirror internally so maybe this isn't too hard.

new sections needed

  • usage for single line REPLs
  • pasting code (indent mode and paren mode)
  • how paren-mode preserves indentation
  • where parinfer breaks down

proposals for better quote-handling

I waited too long to write these down and it's not fresh on my mind anymore, but here are some suggestions from clojure conj folks:

  • @SVMBrown suggests a new two-step process. Upon loading a file, fix unclosed quotes in all comments. And then enforce all subsequent additions of quotes in comments are balanced or escaped.
  • @jteneycke suggests explicitly treating the jsdoc comments as special and untouchable (since escaping quotes would result in invalid jsdocs), while correcting all other comments.

But I'm now recalling a goal which seems to prevent these from working: we want to preserve reversibility. Imagine commenting and uncommenting a line of code. In my mind, the resulting line shouldn't be different (i.e. 1 and 4 below should be the same):

  1. We have a line with a quote:

    "foo
  2. We comment it out:

    ; "foo
  3. Quote fixer escapes it

    ; \"foo
  4. Uncomment

    \"foo

We also talked about how the source of the problem is that quotes are non-directional, and how their meaning is dependent on the number of quotes before it, allowing strings to be turned inside out when parity changes. svmbrown proposed that we imagine how chaotic this would be if parens were non-directional.

return only changed lines?

each format function returns the full text, but we may want to return only an index of lines that have changed

faster cutoff for detecting imbalanced strings

right now, process-text-change will process until the end of the file if an imbalanced quote is inserted. we could probably track the number of unescaped quotes (in both code and comment) per line to cutoff processing. not sure though

multiple editors not working

possible that we need to share a cm instance:

  • second editor allows normal text input (without formatting correctly)
  • first editor does not allow moving of the cursor, inserting text at front (appending correct formatting)

License

It would be nice to know the license for this through a LICENSE file or at least in the README.md. If there's a license in the source I haven't found it yet.

throw away quick-look anim for something better

don't use the editor for the quick look. it doesn't communicate the essence of the idea. we need to show the parens actually moving with css transitions. We can do that by scripting a simple css animation.

consider escape state when testing chars

\,))

is being transformed to this

\)),

whitespace? function doesn't consider that \, is a literal character not the whitespace comma.

problem is that escape state can be checked prior to push-char, but not after.

need a lot of ecape char tests

only skip the cursor forward for semicolon

I only want to do two things with the cursor:

  • do not move it if an unmatched right-paren was attempted
  • move cursor to inserted semicolon if commenting out inferred parens

bugs

This:

((a ) ;

Produces:

((a  ;))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.