Skip to content

Commit 870b44c

Browse files
authored
Merge pull request #199 from parinfer/oakmac-merge
Oakmac merge
2 parents 9a4197f + 423ed3f commit 870b44c

File tree

446 files changed

+5749
-86228
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

446 files changed

+5749
-86228
lines changed

.gitignore

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,2 @@
1-
pom.xml
2-
pom.xml.asc
3-
*jar
4-
classes/
5-
out/
6-
target/
7-
.lein-deps-sum
8-
.lein-repl-history
9-
.lein-failures
10-
.lein-plugins/
11-
.repl
12-
.nrepl-port
13-
*.swp
14-
figwheel_server.log
15-
1+
node_modules/
162
*.diff
17-
todo
18-
19-
node_modules

.travis.yml

Lines changed: 0 additions & 7 deletions
This file was deleted.

lib/CHANGES.md renamed to CHANGES.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 3.13.1 - 2020-09-08
2+
3+
- update the `.version` property to return the correct version
4+
5+
## 3.13.0 - 2020-09-06
6+
7+
- add support for comment characters other than semicolon - [Issue #11](https://github.com/oakmac/parinfer/issues/11)
8+
- first release from @oakmac fork
9+
- apply standardjs linter to the codebase (ie: this release has a large code diff, but minimal logic change from 3.12.0)
10+
111
## 3.12.0 - 2018-01-04
212

313
- make Smart Mode work better when inputting multiple changes. See [#181]
@@ -25,7 +35,7 @@
2535

2636
[#147]:https://github.com/shaunlebron/parinfer/issues/147
2737

28-
## 3.9.0 - 2017-07-26
38+
## 3.9.0 - 2017-07-26
2939

3040
- add: return `tabStops` in Paren Mode (see [#156](https://github.com/shaunlebron/parinfer/issues/156))
3141
- add: return `argX` for Tab Stops (see [#157](https://github.com/shaunlebron/parinfer/issues/157))
@@ -39,11 +49,11 @@
3949

4050
- add: return non-empty `parenTrails` so editors can dim/mark them (see [Paren Trails](https://github.com/shaunlebron/parinfer/blob/master/lib/doc/code.md#paren-trail))
4151

42-
## 3.6.0 - 2017-07-22
52+
## 3.6.0 - 2017-07-22
4353

4454
- add: fix indentation in Smart Mode after cursor leaves the end of a Paren Trail (see [#147](https://github.com/shaunlebron/parinfer/issues/147))
4555

46-
## 3.5.0 - 2017-07-21
56+
## 3.5.0 - 2017-07-21
4757

4858
- add: fix indentation in Smart Mode after cursor leaves a holding area, preventing
4959
unintended line adoption (see [#143](https://github.com/shaunlebron/parinfer/issues/143))
@@ -79,7 +89,7 @@ stability in Indent Mode and Smart Mode
7989

8090
- enhancement: publish separate test API
8191

82-
## 3.0.1 - 2017-07-11
92+
## 3.0.1 - 2017-07-11
8393

8494
- fix: make deleted unbalanced parens influence shifted expressions (when `forceBalance` is true)
8595

@@ -99,7 +109,7 @@ stability in Indent Mode and Smart Mode
99109

100110
- fix: comment lines are shifted when indented inside shifted collections (see end of [this section](doc/code.md#preserving-relative-indentation-while-typing))
101111

102-
## 2.5.1 - 2017-07-09
112+
## 2.5.1 - 2017-07-09
103113

104114
- fix: dedenting an open-paren with `cursorDx` in Indent Mode will properly adopt new child lines
105115

README.md

Lines changed: 227 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,249 @@
1-
# Parinfer
1+
# Parinfer.js
22

3-
_parentheses inference for Lisp_
3+
> Pronounced "par-in-fur". "par" rhymes with car and star; "fur" rhymes with blur and stir
44
5-
<img src="http://zippy.gfycat.com/WeirdOddBluefintuna.gif" width="400">
6-
7-
---
8-
9-
<em>See the __[Parinfer Home Page]__ for a complete exploration.</em>
5+
<em>See the __[Parinfer Home Page]__ for the original animated demo page.</em>
106

117
__Parinfer__ is a proof-of-concept editor mode for Lisp programming languages.
128
It simplifies the way we write Lisp by auto-adjusting parens when indentation
139
changes and vice versa. The hope is to make basic Lisp-editing easier for
1410
newcomers and experts alike, while still allowing existing plugins like Paredit
1511
to satisfy the need for more advanced operations.
1612

17-
This project is split into two parts:
13+
## npm package
14+
15+
This library is published on npm under the package name [`parinfer`](https://www.npmjs.com/package/parinfer)
16+
17+
```sh
18+
## using npm
19+
npm install parinfer
20+
21+
## using yarn
22+
yarn add parinfer
23+
```
24+
25+
## Usage
26+
27+
Parinfer consists of a couple pure functions of your text, returning new text with
28+
corrected parens or indentation.
29+
30+
```js
31+
// 'parinfer' is a global object if not used as Node module.
32+
var parinfer = require('parinfer');
33+
34+
// Run Indent Mode on the given text:
35+
var result = parinfer.indentMode("(def foo [a b");
36+
console.log(result.text);
37+
// prints:
38+
// (def foo [a b])
39+
40+
// Run Paren Mode on the given text:
41+
var result = parinfer.parenMode("(def foo\n[a b\nc])");
42+
console.log(result.text);
43+
// prints:
44+
// (def foo
45+
// [a b
46+
// c])
47+
```
48+
49+
## Integrating with an Editor or REPL
50+
51+
_See [integrating.md]_
52+
53+
<!-- file links need to be full path to make them work for the NPM readme -->
54+
[integrating.md]:https://github.com/parinfer/parinfer.js/blob/master/doc/integrating.md
55+
56+
## API
57+
58+
##### `smartMode(text[, options])`
59+
##### `indentMode(text[, options])`
60+
##### `parenMode(text[, options])`
61+
62+
Runs
63+
[Indent Mode](http://shaunlebron.github.io/parinfer/#indent-mode)
64+
or
65+
[Paren Mode](http://shaunlebron.github.io/parinfer/#paren-mode)
66+
on the given text. Smart Mode is currently something in between.
67+
68+
Arguments:
69+
70+
- `text` is the full text input.
71+
- `options` is an object with the following properties:
72+
- `commentChars` - a character (ie: string of length 1) or array of characters that should be considered comments in the code (defaults to `[";"]`)
73+
- `cursorLine` - zero-based line number of the cursor
74+
- `cursorX` - zero-based x-position of the cursor
75+
- `prevCursorLine` and `prevCursorX` is required by Smart Mode (previous cursor position)
76+
- `selectionStartLine` - first line of the current selection
77+
- `changes` - ordered array of change objects with the following:
78+
- `lineNo` - starting line number of the change
79+
- `x` - starting x of the change
80+
- `oldText` - original text that was replaced
81+
- `newText` - new text that replaced the original text
82+
- `forceBalance` - employ the aggressive paren-balancing rules from v1 (defaults to false)
83+
- `partialResult` - return partially processed text/cursor if an error occurs (defaults to false)
84+
85+
Returns an object with the following properties:
86+
87+
- `success` is a boolean indicating if the input was properly formatted enough to create a valid result
88+
- `text` is the full text output (if `success` is false, returns original text unless `partialResult` is enabled)
89+
- `cursorX`/`cursorLine` is the new position of the cursor (since parinfer may shift it around)
90+
- `error` is an object populated if `success` is false:
91+
- `name` is the name of the error, which will be any of the following:
92+
- `"quote-danger"`
93+
- `"eol-backslash"`
94+
- `"unclosed-quote"`
95+
- `"unclosed-paren"`
96+
- `"unmatched-close-paren"`
97+
- `"unhandled"`
98+
- `message` is a message describing the error
99+
- `lineNo` is a zero-based line number where the error occurred
100+
- `x` is a zero-based column where the error occurred
101+
- `extra` has lineNo and x of open-paren for `unmatched-close-paren`
102+
- `tabStops` is an array of objects representing [Tab stops], which is
103+
populated if a cursor position or selection is supplied. We identify tab
104+
stops at relevant open-parens, and supply the following extra information so
105+
you may compute extra tab stops for one-space or two-space indentation
106+
conventions based on the type of open-paren.
107+
- `x` is a zero-based x-position of the tab stop
108+
- `argX` position of the first argument after `x` (e.g. position of bar in `(foo bar`)
109+
- `lineNo` is a zero-based line number of the open-paren responsible for the tab stop
110+
- `ch` is the character of the open-paren responsible for the tab stop (e.g. `(`,`[`,`{`)
111+
- `parenTrails` is an array of object representing the [Paren Trails] at the end
112+
of each line that Parinfer may move
113+
- `lineNo` is a zero-based line number
114+
- `startX` is a zero-based x-position of the first close-paren
115+
- `endX` is a zero-based x-position after the last close-paren
116+
117+
[Tab stops]:https://en.wikipedia.org/wiki/Tab_stop
118+
119+
## Test API
120+
121+
You can use our testing API for a fast, visual way to specify options and verify
122+
results. This allows all metadata required by and returned from Parinfer to be
123+
specified inside the text using our annotation syntax.
124+
125+
__[See here for Annotation Syntax details][annotation syntax]__
126+
127+
```js
128+
// Currently only supported in Node
129+
var parinferTest = require('parinfer/test');
130+
```
131+
132+
### Test Example
133+
134+
The following code is a quick way to verify behavior of Indent Mode.
135+
The `|` is parsed as the cursor and removed from the text before processing.
136+
137+
```js
138+
parinterTest.indentMode(`
139+
(def foo
140+
"|
141+
"(a b)
142+
c")
143+
`);
144+
```
145+
146+
This returns the processed text below, with `|` reinserted to show cursor
147+
result, and an `^ error` annotation line since a string was not closed:
148+
149+
```
150+
(def foo
151+
"|
152+
"(a b)
153+
c")
154+
^ error: unclosed-quote
155+
```
156+
157+
### Test Usage
158+
159+
```js
160+
parinferTest.smartMode(inputText, extras); // returns string
161+
parinferTest.indentMode(inputText, extras); // returns string
162+
parinferTest.parenMode(inputText, extras); // returns string
163+
```
164+
165+
`extras` allows us to specify options for which there is no annotation syntax yet:
166+
167+
- `forceBalance`
168+
- `partialResult`
169+
- `printTabStops`
170+
171+
You can also use the input/output functions directly:
172+
173+
```js
174+
parinferTest.parseInput(inputText, extras); // returns {text, options}
175+
parinferTest.parseOutput(inputText, extras); // returns result
176+
177+
parinferTest.printOutput(result, extras); // returns string
178+
179+
// `result` is returned by main indentMode or parenMode functions
180+
```
181+
182+
## Development
183+
184+
__Code__: [`parinfer.js`] is implemented in ECMAScript 5 for easy speed and portability. Also:
185+
186+
__Documentation__: Code is documented in [`code.md`].
187+
188+
__Performance__: To run a performance stress test:
189+
190+
```
191+
node test/perf.js
192+
```
193+
194+
__Testing__: See [`test/cases/`] directory for testing details. Or just run the following:
195+
196+
```
197+
npm install
198+
npm test
199+
```
200+
201+
<!-- file links need to be full path to make them work for the NPM readme -->
202+
[`parinfer.js`]:https://github.com/parinfer/parinfer.js/blob/master/parinfer.js
203+
[`code.md`]:https://github.com/parinfer/parinfer.js/blob/master/doc/code.md
204+
[`test/cases/`]:https://github.com/parinfer/parinfer.js/tree/master/test/cases
205+
[annotation syntax]:https://github.com/parinfer/parinfer.js/tree/master/test/cases#annotations
206+
[Paren Trails]:https://github.com/parinfer/parinfer.js/blob/master/doc/code.md#paren-trail
18207

19-
- __[Parinfer Lib](https://github.com/shaunlebron/parinfer/tree/master/lib)__ - the _editor-agnostic_ library
20-
- __[Parinfer Site](https://github.com/shaunlebron/parinfer/tree/master/site)__ - the code for the website
208+
## A stable core for editor plugins
21209

22-
## How to Use It!
210+
> __Want to use Parinfer on a team?__ Introduce [Parlinter] as your project's linter!
23211
24-
<em>See the __[Parinfer Demo Editor]__ to try the latest version online.</em>
212+
[Parlinter]:https://github.com/shaunlebron/parlinter
25213

26-
[Parinfer Demo Editor]:http://shaunlebron.github.io/parinfer/demo
214+
The behavior and implementation of the Parinfer library is stable and
215+
canonicalized. To allow different editors to use it, we have ported the
216+
implementation to the languages required by the plugin
217+
APIs of most major text editors. All language ports pass the same
218+
comprehensive test suite to help ensure consistent behavior.
27219

28-
Parinfer is still in early development. Several people have started
29-
integrating it into code editors at various stages of development.
220+
| implemented in | link | relevant editor |
221+
|:---------------|:-------------------|:-------------------------|
222+
| JavaScript | parinfer.js (here) | Atom, VSCode, LightTable |
223+
| Rust | [parinfer-rust] | Vim |
224+
| Python | [parinfer.py] | Sublime Text |
225+
| Kotlin (JVM) | [parinfer-jvm] | Cursive IDE, Nightcode |
226+
| Emacs Lisp | [parinfer-elisp] | Emacs |
227+
| Vim Script | [parinfer-viml] | Vim |
228+
| Lua | [parinfer-lua] | TextAdept |
30229

31-
- [atom-parinfer] for [Atom]
32-
- [parinfer-rust] for [Vim] and [Neovim]
33-
- [nvim-parinfer.js] for [Neovim]
34-
- [vim-parinfer] for [Vim]
35-
- [vscode-parinfer] for [Visual Studio Code]
36-
- [sublime-text-parinfer] for [Sublime Text]
37-
- [parinfer-mode] for [Emacs]
38-
- [Parinfer layer] for [Spacemacs] - _in progress_
39-
- [parinfer-codemirror] for [CodeMirror] - _used on Parinfer's homepage_
40-
- [lt_parinfer] for [Light Table]
41-
- native support in [Nightcode]
230+
[parinfer-rust]:https://github.com/eraserhd/parinfer-rust
231+
[parinfer.py]:https://github.com/oakmac/parinfer.py
232+
[parinfer-jvm]:https://github.com/oakmac/parinfer-jvm
233+
[parinfer-elisp]:https://github.com/oakmac/parinfer-elisp
234+
[parinfer-viml]:https://github.com/oakmac/parinfer-viml
235+
[parinfer-lua]:https://github.com/oakmac/parinfer-lua
42236

43-
Parinfer will soon be available for some REPL environments as well:
237+
## Status Update 2019 (Smart Mode)
44238

45-
- [Replete] for iOS
46-
- [Dirac DevTools] for Google Chrome
47-
- [Reepl] for the browser
239+
**Smart Mode** (available in [demo]) was an experiment to eliminate switching between Indent Mode and Paren Mode—by looking at a change and determining whether to run Indent Mode or Paren Mode. It is well tested and worked great in our sandboxes, but we found that the majority of editor APIs do not allow us to integrate Smart Mode's rules _safely_.
48240

49-
<em>__[Let me know]__ if you're working on a plugin, or check the [lib readme] for extra guidance. Thanks!</em>
241+
For example, if we don't catch a search/replace change in multiple locations of your document, but we infer from the next typing operation that we should run Indent Mode, then Smart Mode will make its decision without knowing the previous search/replace operation took place—thereby breaking its promise of choosing the best mode, and unsafely modifying your code.
50242

51-
[Let me know]:https://github.com/shaunlebron/parinfer/issues/new?title=new%20plugin
52-
[lib readme]:lib
243+
The larger problem is that Smart Mode requires the synchronous interception of _every type of change_ coming from the editor. It must decide the right thing to do for input changes at single/multiple cursors, search/replace, copy/paste, advanced macro operations, buffer refreshes from changes on disk, and maybe some others we haven't thought of yet. The interface for receiving these kinds of changes from the editor are not consistent—they either come in asynchronously or sychronously or _not at all_. This forces us to resort to computing diffs, a lossy mapping from _changes_ to _patches_.
53244

54-
[parinfer-rust]:https://github.com/eraserhd/parinfer-rust
55-
[atom-parinfer]:https://github.com/oakmac/atom-parinfer
56-
[Atom]:https://atom.io/
57-
[nvim-parinfer.js]:https://github.com/snoe/nvim-parinfer.js
58-
[Neovim]:https://neovim.io/
59-
[vscode-parinfer]:https://github.com/narma/vscode-parinfer
60-
[Visual Studio Code]:https://code.visualstudio.com/
61-
[sublime-text-parinfer]:https://github.com/oakmac/sublime-text-parinfer
62-
[Sublime Text]:http://www.sublimetext.com/
63-
[parinfer-mode]:https://github.com/DogLooksGood/parinfer-mode
64-
[Emacs]:https://www.gnu.org/software/emacs/
65-
[vim-parinfer]:https://github.com/bhurlow/vim-parinfer
66-
[Vim]:http://www.vim.org/
67-
[parinfer-codemirror]:https://github.com/shaunlebron/parinfer-codemirror
68-
[CodeMirror]:https://codemirror.net/
69-
[lt_parinfer]:https://github.com/mauricioszabo/lt_parinfer
70-
[Light Table]:http://lighttable.com/
71-
[Nightcode]:https://github.com/oakes/Nightcode
72-
[Parinfer layer]:https://github.com/syl20bnr/spacemacs/issues/5574
73-
[Spacemacs]:http://spacemacs.org/
74-
75-
[Replete]:https://github.com/mfikes/replete
76-
[Dirac DevTools]:https://github.com/binaryage/dirac
77-
[Reepl]:http://jaredforsyth.com/reepl/
78-
79-
[Paredit]:http://danmidwood.com/content/2014/11/21/animated-paredit.html
80-
[Parinfer Home Page]:http://shaunlebron.github.io/parinfer/
81-
82-
---
245+
We have made separate attempts to implement Smart Mode in Cursive, Vim, Atom, and Emacs through some wrangling that made integration very difficult and delicate, and ultimately incomplete. _Editors simply are not yet designed to allow an ideal version of Parinfer to exist_—probably because nothing like Parinfer has demanded them before. The practicality of requesting these (likely non-trivial) changes on the editor is to be determined.
246+
247+
## License
83248

84249
[MIT License](LICENSE.md)
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)