├── .gitignore
├── .travis.yml
├── CHANGES.md
├── LICENSE
├── README.md
├── fixtures
├── bad.clj
├── good.clj
└── untrimmed.clj
├── package.json
├── parlinter.js
├── sync.sh
├── test.sh
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | fixtures/actual.clj
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "7.4"
4 |
--------------------------------------------------------------------------------
/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.3.0
2 |
3 | - fix `--list-different` option (see [#4](https://github.com/shaunlebron/parlinter/pull/4), thanks [@zhanjing1214](https://github.com/zhanjing1214))
4 | - only prints filenames of those unformatted
5 | - returns correct exit code (1 for unformatted file is found, 0 otherwise)
6 |
7 | # 1.2.0
8 |
9 | - update to Parinfer 3.9.0
10 | - shift comment indentation when parent forms are shifted
11 | - [extend indentation contraints](https://github.com/shaunlebron/parinfer/blob/master/lib/test/cases/paren-mode.md#extending-indentation-constraints) for better stability
12 |
13 | # 1.1.0
14 |
15 | - update to Parinfer 2.2.1
16 | - fix: do not process if unmatched close-parens found anywhere
17 |
18 | # 1.0.1
19 |
20 | - fix `parlinter` binary publish
21 |
22 | # 1.0.0
23 |
24 | - Public release (readme changes)
25 | - `--trim` removes lines that become empty after linting
26 |
27 | # 0.1.0
28 |
29 | - Initial early release
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Shaun Williams and contributors
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Parlinter
2 |
3 | A low-friction linter for Lisp that finally allows your team members to use [Parinfer].
4 |
5 | Unlike full pretty-printers, it preserves as much of the original source as
6 | possible, only fixing _confusing indentation_ and _dangling close-parens_. But
7 | it's still flexible, allowing any-space indentation within thresholds.
8 |
9 | Adopt Parlinter to make your project Parinfer friendly!
10 |
11 |  [](https://travis-ci.org/shaunlebron/parlinter)
12 |
13 | ## Want a Quick Look?
14 |
15 | - See concrete examples of [Common Lint Results in Clojure].
16 | - See the only [Two Rules] it follows.
17 | - [Try it out on your project] then check `git diff -w` to verify the minor changes.
18 |
19 | [Common Lint Results in Clojure]:#common-lint-results-in-clojure
20 | [Two Rules]:#two-rules
21 | [Try it out on your project]:#install
22 |
23 | ## Two Rules
24 |
25 | Parlinter performs minimal source transformation in order to satisfy two rules:
26 |
27 | ### Rule #1 - no dangling close-parens
28 |
29 | Close-parens at the beginning of a line are moved to the end of its previous
30 | token:
31 |
32 | ```clj
33 | ;; bad
34 | (foo (bar
35 | ) baz
36 | ) ^
37 | ^
38 |
39 | ;; fixed
40 | (foo (bar)
41 | baz) ^
42 | ^
43 | ```
44 |
45 | > __Conventional Formatters__ comply with Rule #1 for all cases except to allow
46 | > [close-parens after a comment]. Parlinter does NOT make this exception.
47 |
48 | [close-parens after a comment]:#2-close-parens-after-comments
49 |
50 | ### Rule #2 - ordered indentation
51 |
52 | Newlines must be indented to the right of their parent open-paren:
53 |
54 | ```clj
55 | (foo (bar)
56 | |
57 | |
58 | >
59 | bar) ;; must be indented to the right of the point above: ✔️
60 | ^
61 | ```
62 |
63 | But they cannot extend too far right into another open-paren:
64 |
65 | ```clj
66 | (foo (bar)
67 | |
68 | |
69 | <
70 | bar) ;; must be indented to the left of the point above: ✔️
71 | ^
72 | ```
73 |
74 | To fix, indentation is clamped to these points:
75 |
76 | ```clj
77 | ;; bad
78 | (foo (bar)
79 | baz)
80 |
81 | ;; fixed
82 | (foo (bar)
83 | baz) ;; <-- nudged to the right
84 | ```
85 |
86 | ```clj
87 | ;; bad
88 | (foo (bar)
89 | baz)
90 |
91 | ;; fixed
92 | (foo (bar)
93 | baz) ;; <-- nudged to the left
94 | ```
95 |
96 | > __Conventional formatters__ comply with Rule #2 for all cases, except
97 | > [clojure.pprint] and older versions of [clojure-mode], which cause extra indentation
98 | > of [multi-arity function bodies].
99 |
100 | [Compatibility]:#compatibility
101 | [multi-arity function bodies]:#1-multi-arity-function-bodies
102 |
103 | ## Install
104 |
105 | ```
106 | npm install -g parlinter
107 | or
108 | yarn global add parlinter
109 | ```
110 |
111 | > Want to use as a plugin in your build environment instead? (e.g. lein, boot) Help wanted! Please [create an issue].
112 |
113 | [create an issue]:https://github.com/shaunlebron/parlinter/issues/new
114 |
115 | ## Usage
116 |
117 | ```
118 | $ parlinter
119 |
120 | Usage: parlinter [opts] [filename|glob ...]
121 |
122 | Available options:
123 | --write Edit the file in-place. (Beware!)
124 | --trim Remove lines that become empty after linting.
125 | --list-different or -l Print filenames of files that are different from Parlinter formatting.
126 | --stdin Read input from stdin.
127 | --version or -v Print Parlinter version.
128 | ```
129 |
130 | [Glob patterns](https://github.com/isaacs/node-glob#glob-primer) must be quoted.
131 |
132 | ## Examples
133 |
134 | Format all clojure files:
135 |
136 | ```
137 | parlinter --trim --write "**/*.{clj,cljs,cljc,edn}"
138 | ```
139 |
140 | Verify non-whitespace changes below for peace-of-mind: (AST not changed)
141 |
142 | ```
143 | git diff -w
144 | ```
145 |
146 | Check if all clojure files are properly formatted (non-zero exit code if not):
147 |
148 | ```
149 | $ parlinter -l "**/*.{clj,cljs,cljc,edn}"
150 | ```
151 |
152 | ## Performance
153 |
154 | It takes ~0.5s to run against ~40k lines. (tested on the [Clojure] and [ClojureScript] project repos)
155 |
156 | It was heavily optimized to allow [Parinfer] to run at 60hz on a ~3k line file
157 | while typing.
158 |
159 | [Clojure]:https://github.com/clojure/clojure
160 | [ClojureScript]:https://github.com/clojure/clojurescript
161 |
162 | ## Compatibility
163 |
164 | _Syntactically_ compatible with Clojure, Racket, Scheme, and other Lisps that follow this syntax:
165 |
166 | - delimiters `(`, `{`, `[`
167 | - strings `"`
168 | - characters `\`
169 | - comments `;`
170 |
171 | _Culturally_ compatible with standard Lisp styles\*:
172 |
173 | - [Lisp Indentation]
174 | - [Clojure Style Guide]
175 | - [Google Common Lisp Style Guide]
176 | - [Racket Style Guide]
177 |
178 | > _\* some allow close-parens on their own line, but still allow them to be
179 | removed as Parlinter does_
180 |
181 | [Lisp Indentation]:http://wiki.c2.com/?LispIndentation
182 | [Racket Style Guide]:http://docs.racket-lang.org/style/Textual_Matters.html
183 | [Google Common Lisp Style Guide]:https://google.github.io/styleguide/lispguide.xml
184 |
185 | ## Common Lint Results in Clojure
186 |
187 | A collection of common changes performed by Parlinter on Clojure code—the
188 | Lisp I am most familiar with.
189 |
190 | ### 1. Multi-arity function bodies
191 |
192 | Sometimes function bodies for multi-arity functions are indented past the
193 | function params.
194 |
195 | ```clj
196 | ;; bad
197 | (defn foo
198 | "I have two arities."
199 | ([x]
200 | (foo x 1))
201 | ([x y]
202 | (+ x y)))
203 |
204 | ;; fixed
205 | (defn foo
206 | "I have two arities."
207 | ([x]
208 | (foo x 1))
209 | ([x y]
210 | (+ x y)))
211 | ```
212 |
213 | ### 2. Close-parens after comments
214 |
215 | Since close-parens cannot be at the beginning of a line, they cannot come after
216 | comments.
217 |
218 | ```clj
219 | ;; bad
220 | (-> 10
221 | (foo 20)
222 | (bar 30)
223 | ;; my comment
224 | )
225 |
226 | ;; fixed
227 | (-> 10
228 | (foo 20)
229 | (bar 30))
230 | ;; my comment
231 | ```
232 |
233 | ### 3. Lines inside strings are not touched
234 |
235 | Indentation of lines inside multi-line strings is significant, so it is not
236 | modified:
237 |
238 | ```clj
239 | ;; bad
240 | (foo (bar
241 | "Hello
242 | world"))
243 |
244 | ;; fixed
245 | (foo (bar
246 | "Hello
247 | world")) ;; <-- not nudged
248 | ```
249 |
250 | ### 4. Recessed function bodies
251 |
252 | Function bodies are sometimes indented to its grandparent form rather than its
253 | parent:
254 |
255 | ```clj
256 | ;; bad
257 | (foo bar (fn [a]
258 | (println a)))
259 |
260 | ;; fixed
261 | (foo bar (fn [a]
262 | (println a))) ;; <-- nudged to be inside "(fn"
263 | ```
264 |
265 | ### 5. Recessed lines after JSON-style `{`
266 |
267 | It is sometimes common to use JSON-style indentation in a top-level EDN config:
268 |
269 | ```clj
270 | ;; bad
271 | :cljsbuild {
272 | :builds [...]
273 | }
274 |
275 | ;; fixed
276 | :cljsbuild {
277 | :builds [...]} ;; <-- nudged to be inside "{"
278 |
279 | ;; fine (but not automated)
280 | :cljsbuild {:builds [...]}
281 |
282 | ;; fine (but not automated)
283 | :cljsbuild
284 | {:builds [...]}
285 | ```
286 |
287 | ### 6. Recessed lines after `#_` and `comment`
288 |
289 | Comment and ignore forms are commonly added retroactively without adjusting
290 | indentation:
291 |
292 | ```clj
293 | ;; bad
294 | #_(defn foo []
295 | (bar baz))
296 |
297 | ;; fixed
298 | #_(defn foo []
299 | (bar baz))
300 | ```
301 |
302 | ```clj
303 | ;; bad
304 | (comment
305 | (defn foo []
306 | (bar baz))
307 | )
308 |
309 | ;; fixed
310 | (comment
311 | (defn foo []
312 | (bar baz)))
313 | ```
314 |
315 | ### 7. Vertically-aligned comments
316 |
317 | Linting may throw off the alignment of comments, due to paren movement:
318 |
319 | ```clj
320 | ;; bad
321 | (let [foo 1 ; this is number one
322 | bar 2 ; this is number two
323 | ]
324 | (+ foo bar))
325 |
326 | ;; fixed
327 | (let [foo 1 ; this is number one
328 | bar 2] ; this is number two
329 | (+ foo bar))
330 | ```
331 |
332 | ## Motivation
333 |
334 | Though [Parinfer] was designed to lower the barrier for newcomers, it faced a
335 | problem of practicality by not allowing them to collaborate smoothly with people
336 | who didn't use it. This friction was not part of the intended experience.
337 |
338 | Parlinter was designed as an answer to this problem, since there now seems to be
339 | a growing acceptance of linters and even full-formatters like [Prettier],
340 | [refmt], and [gofmt] from other language communities.
341 |
342 | Thus, I hope that Parlinter at least spurs some thoughts on what is an
343 | acceptable amount of process around linting in Lisp, whether or not Parinfer is
344 | worth linting for, and how else we can help newcomers get into Lisp easier.
345 |
346 | (It may also open the door for some exciting next-gen things I'm not yet ready
347 | to talk about.)
348 |
349 | Written for Lisp with <3
350 |
351 | [Prettier]:https://github.com/prettier/prettier
352 | [refmt]:https://facebook.github.io/reason/tools.html#tools-command-line-utilities-refmt
353 | [gofmt]:https://golang.org/cmd/gofmt/
354 |
355 | [clojure.pprint]:https://clojure.github.io/clojure/clojure.pprint-api.html
356 | [clojure-mode]:https://github.com/clojure-emacs/clojure-mode
357 | [fipp]:https://github.com/brandonbloom/fipp
358 | [cljfmt]:https://github.com/weavejester/cljfmt
359 | [zprint]:https://github.com/kkinnear/zprint
360 |
361 |
362 | [Clojure Style Guide]:https://github.com/bbatsov/clojure-style-guide
363 | [Parinfer]:http://shaunlebron.github.io/parinfer/
364 |
--------------------------------------------------------------------------------
/fixtures/bad.clj:
--------------------------------------------------------------------------------
1 |
2 | (foo
3 | bar
4 | )
5 |
6 |
--------------------------------------------------------------------------------
/fixtures/good.clj:
--------------------------------------------------------------------------------
1 |
2 | (foo
3 | bar)
4 |
5 |
--------------------------------------------------------------------------------
/fixtures/untrimmed.clj:
--------------------------------------------------------------------------------
1 |
2 | (foo
3 | bar)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parlinter",
3 | "version": "1.3.0",
4 | "description": "A minimal formatting linter for Lisp code (using Parinfer)",
5 | "main": "parlinter.js",
6 | "repository": "https://github.com/shaunlebron/parlinter",
7 | "author": "Shaun Lebron ",
8 | "license": "MIT",
9 | "bin": {
10 | "parlinter": "parlinter.js"
11 | },
12 | "scripts": {
13 | "test": "./test.sh"
14 | },
15 | "files": [
16 | "README.md",
17 | "CHANGES.md",
18 | "parlinter.js"
19 | ],
20 | "dependencies": {
21 | "chalk": "^1.1.3",
22 | "get-stdin": "^5.0.1",
23 | "glob": "^7.1.2",
24 | "minimist": "^1.2.0",
25 | "parinfer": "^3.9.0",
26 | "readline": "^1.3.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/parlinter.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // Parlinter 1.3.0
4 |
5 | // Source copied from Prettier's CLI! (MIT License)
6 | // https://github.com/prettier/prettier/blob/master/bin/prettier.js
7 |
8 | "use strict";
9 |
10 | const fs = require("fs");
11 | const getStdin = require("get-stdin");
12 | const glob = require("glob");
13 | const chalk = require("chalk");
14 | const minimist = require("minimist");
15 | const readline = require("readline");
16 | const parinfer = require("parinfer");
17 |
18 | const version = "1.3.0";
19 |
20 | const argv = minimist(process.argv.slice(2), {
21 | boolean: ["write", "trim", "stdin", "help", "version", "list-different"],
22 | alias: { help: "h", version: "v", "list-different": "l" },
23 | unknown: param => {
24 | if (param.startsWith("-")) {
25 | console.warn("Ignored unknown option: " + param + "\n");
26 | return false;
27 | }
28 | }
29 | });
30 |
31 | if (argv["version"]) {
32 | console.log(
33 | "Parlinter " + version + " (using Parinfer " + parinfer.version + ")"
34 | );
35 | process.exit(0);
36 | }
37 |
38 | const filepatterns = argv["_"];
39 | const write = argv["write"];
40 | const trim = argv["trim"];
41 | const stdin = argv["stdin"] || (!filepatterns.length && !process.stdin.isTTY);
42 | const globOptions = {
43 | dot: true
44 | };
45 |
46 | function getLineEnding(text) {
47 | // NOTE: We assume that if the CR char "\r" is used anywhere,
48 | // then we should use CRLF line-endings after every line.
49 | var i = text.search("\r");
50 | if (i !== -1) {
51 | return "\r\n";
52 | }
53 | return "\n";
54 | }
55 |
56 | function trimOutput(input, output) {
57 | const inLines = input.split(/\r?\n/);
58 | const outLines = output.split(/\r?\n/);
59 | const trimLines = [];
60 | const empty = /^\s*$/;
61 | for (let i = 0; i < outLines.length; i++) {
62 | const emptyAfterLinting = !empty.test(inLines[i]) && empty.test(outLines[i]);
63 | if (!emptyAfterLinting) {
64 | trimLines.push(outLines[i]);
65 | }
66 | }
67 | return trimLines.join(getLineEnding(output));
68 | }
69 |
70 | function format(input) {
71 | const result = parinfer.parenMode(input);
72 | if (result.error) {
73 | throw result.error;
74 | }
75 | const output = result.text;
76 | return trim ? trimOutput(input, output) : output;
77 | }
78 |
79 | function handleError(filename, e) {
80 | console.error(
81 | filename + ":" + (e.lineNo + 1) + ":" + e.x + " - " + e.message
82 | );
83 |
84 | // Don't exit the process if one file failed
85 | process.exitCode = 2;
86 | }
87 |
88 | if (argv["help"] || (!filepatterns.length && !stdin)) {
89 | console.log(
90 | "\n" +
91 | "Usage: parlinter [opts] [filename ...]\n" +
92 | "\n" +
93 | "A minimal formatting linter for Lisp code (using Parinfer)\n" +
94 | "\n" +
95 | "Available options:\n" +
96 | " --write Edit the file in-place. (Beware!)\n" +
97 | " --trim Remove lines that become empty after linting.\n" +
98 | " --list-different or -l Print filenames of files that are different from Parlinter formatting.\n" +
99 | " --stdin Read input from stdin.\n" +
100 | " --version or -v Print Parlinter version.\n" +
101 | "\n"
102 | );
103 | process.exit(argv["help"] ? 0 : 1);
104 | }
105 |
106 | if (stdin) {
107 | getStdin().then(input => {
108 | try {
109 | writeOutput(format(input));
110 | } catch (e) {
111 | handleError("stdin", e);
112 | return;
113 | }
114 | });
115 | } else {
116 | eachFilename(filepatterns, filename => {
117 | if (write) {
118 | // Don't use `console.log` here since we need to replace this line.
119 | process.stdout.write(filename);
120 | }
121 |
122 | let input;
123 | try {
124 | input = fs.readFileSync(filename, "utf8");
125 | } catch (e) {
126 | // Add newline to split errors from filename line.
127 | process.stdout.write("\n");
128 |
129 | console.error("Unable to read file: " + filename + "\n" + e);
130 | // Don't exit the process if one file failed
131 | process.exitCode = 2;
132 | return;
133 | }
134 |
135 | const start = Date.now();
136 |
137 | let output;
138 |
139 | try {
140 | output = format(input);
141 | } catch (e) {
142 | // Add newline to split errors from filename line.
143 | process.stdout.write("\n");
144 |
145 | handleError(filename, e);
146 | return;
147 | }
148 |
149 | if (argv["list-different"]) {
150 | if (output !== input) {
151 | if (!write) {
152 | console.log(filename);
153 | }
154 | process.exitCode = 1;
155 | }
156 | }
157 |
158 | if (write) {
159 | // Remove previously printed filename to log it with duration.
160 | readline.clearLine(process.stdout, 0);
161 | readline.cursorTo(process.stdout, 0, null);
162 |
163 | // Don't write the file if it won't change in order not to invalidate
164 | // mtime based caches.
165 | if (output === input) {
166 | if (!argv["list-different"]) {
167 | console.log(chalk.grey("%s %dms"), filename, Date.now() - start);
168 | }
169 | } else {
170 | if (argv["list-different"]) {
171 | console.log(filename);
172 | } else {
173 | console.log("%s %dms", filename, Date.now() - start);
174 | }
175 |
176 | try {
177 | fs.writeFileSync(filename, output, "utf8");
178 | } catch (err) {
179 | console.error("Unable to write file: " + filename + "\n" + err);
180 | // Don't exit the process if one file failed
181 | process.exitCode = 2;
182 | }
183 | }
184 | } else if (!argv["list-different"]) {
185 | writeOutput(output);
186 | }
187 | });
188 | }
189 |
190 | function writeOutput(text) {
191 | // Don't use `console.log` here since it adds an extra newline at the end.
192 | process.stdout.write(text);
193 | }
194 |
195 | function eachFilename(patterns, callback) {
196 | patterns.forEach(pattern => {
197 | if (!glob.hasMagic(pattern)) {
198 | callback(pattern);
199 | return;
200 | }
201 |
202 | glob(pattern, globOptions, (err, filenames) => {
203 | if (err) {
204 | console.error("Unable to expand glob pattern: " + pattern + "\n" + err);
205 | // Don't exit the process if one pattern failed
206 | process.exitCode = 2;
207 | return;
208 | }
209 |
210 | filenames.forEach(filename => {
211 | callback(filename);
212 | });
213 | });
214 | });
215 | }
216 |
--------------------------------------------------------------------------------
/sync.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ## Sync dependent files with each other:
4 | ## - package.json version => parlinter.js
5 |
6 | jsfile=parlinter.js
7 |
8 | ##----------------------------------------------------------------------------
9 | ## Version sync
10 | ##----------------------------------------------------------------------------
11 |
12 | # Get package.json version.
13 | version=$(perl -n -e'/"version": "(.+)"/ && print "$1"' package.json)
14 |
15 | # Sync version
16 | sed -i.bak "s|^// Parlinter .*|// Parlinter $version|" $jsfile
17 | sed -i.bak "s|^const version = .*|const version = \"$version\";|" $jsfile
18 | rm ${jsfile}.bak
19 |
20 | echo "Updated $jsfile with package.json version $version"
21 | echo
22 |
--------------------------------------------------------------------------------
/test.sh:
--------------------------------------------------------------------------------
1 |
2 | bad=fixtures/bad.clj
3 | good=fixtures/good.clj
4 | untrimmed=fixtures/untrimmed.clj
5 | temp=fixtures/temp.clj
6 | actual=fixtures/actual.clj
7 |
8 | # default
9 | node parlinter.js $bad > $temp
10 | restore() {
11 | rm $temp
12 | }
13 | if ! diff $temp $untrimmed > /dev/null; then
14 | echo "Test Failed for --write : expected $bad to be corrected to match $untrimmed."
15 | echo "Check $actual for actual output."
16 | cp $temp $actual
17 | restore
18 | exit 1
19 | fi
20 | restore
21 |
22 |
23 | # --write
24 | cp $bad $temp
25 | node parlinter.js --write $bad > /dev/null
26 | restore() {
27 | cp $temp $bad
28 | rm $temp
29 | }
30 | if ! diff $bad $untrimmed > /dev/null; then
31 | echo "Test Failed for --write : expected $bad to be corrected to match $good."
32 | echo "Check $actual for actual output."
33 | cp $bad $actual
34 | restore
35 | exit 1
36 | fi
37 | restore
38 |
39 | # --trim
40 | node parlinter.js --trim $bad > $temp
41 | restore() {
42 | rm $temp
43 | }
44 | if ! diff $temp $good > /dev/null; then
45 | echo "Test Failed for --trim : expected $bad to trim down to $good."
46 | echo "Check $actual for actual output."
47 | cp $temp $actual
48 | restore
49 | exit 1
50 | fi
51 | restore
52 |
53 | # --list different
54 | if node parlinter.js -l $bad > /dev/null; then
55 | echo "Test Failed for --list-different : expected $bad to be listed"
56 | exit 1
57 | fi
58 | if ! node parlinter.js -l $good > /dev/null; then
59 | echo "Test Failed for --list-different : expected $good to not be listed"
60 | exit 1
61 | fi
62 | if ! node parlinter.js -l $untrimmed > /dev/null; then
63 | echo "Test Failed for --list-different : expected $untrimmed to not be listed"
64 | exit 1
65 | fi
66 |
67 | echo "TESTS PASSED."
68 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | ansi-regex@^2.0.0:
6 | version "2.1.1"
7 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
8 |
9 | ansi-styles@^2.2.1:
10 | version "2.2.1"
11 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
12 |
13 | balanced-match@^0.4.1:
14 | version "0.4.2"
15 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
16 |
17 | brace-expansion@^1.1.7:
18 | version "1.1.7"
19 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
20 | dependencies:
21 | balanced-match "^0.4.1"
22 | concat-map "0.0.1"
23 |
24 | chalk@^1.1.3:
25 | version "1.1.3"
26 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
27 | dependencies:
28 | ansi-styles "^2.2.1"
29 | escape-string-regexp "^1.0.2"
30 | has-ansi "^2.0.0"
31 | strip-ansi "^3.0.0"
32 | supports-color "^2.0.0"
33 |
34 | concat-map@0.0.1:
35 | version "0.0.1"
36 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
37 |
38 | escape-string-regexp@^1.0.2:
39 | version "1.0.5"
40 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
41 |
42 | fs.realpath@^1.0.0:
43 | version "1.0.0"
44 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
45 |
46 | get-stdin@^5.0.1:
47 | version "5.0.1"
48 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
49 |
50 | glob@^7.1.2:
51 | version "7.1.2"
52 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
53 | dependencies:
54 | fs.realpath "^1.0.0"
55 | inflight "^1.0.4"
56 | inherits "2"
57 | minimatch "^3.0.4"
58 | once "^1.3.0"
59 | path-is-absolute "^1.0.0"
60 |
61 | has-ansi@^2.0.0:
62 | version "2.0.0"
63 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
64 | dependencies:
65 | ansi-regex "^2.0.0"
66 |
67 | inflight@^1.0.4:
68 | version "1.0.6"
69 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
70 | dependencies:
71 | once "^1.3.0"
72 | wrappy "1"
73 |
74 | inherits@2:
75 | version "2.0.3"
76 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
77 |
78 | minimatch@^3.0.4:
79 | version "3.0.4"
80 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
81 | dependencies:
82 | brace-expansion "^1.1.7"
83 |
84 | minimist@^1.2.0:
85 | version "1.2.0"
86 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
87 |
88 | once@^1.3.0:
89 | version "1.4.0"
90 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
91 | dependencies:
92 | wrappy "1"
93 |
94 | parinfer@^3.9.0:
95 | version "3.9.0"
96 | resolved "https://registry.yarnpkg.com/parinfer/-/parinfer-3.9.0.tgz#22f7d1d1fbcac347d46f3864181f546e103b8830"
97 |
98 | path-is-absolute@^1.0.0:
99 | version "1.0.1"
100 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
101 |
102 | readline@^1.3.0:
103 | version "1.3.0"
104 | resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c"
105 |
106 | strip-ansi@^3.0.0:
107 | version "3.0.1"
108 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
109 | dependencies:
110 | ansi-regex "^2.0.0"
111 |
112 | supports-color@^2.0.0:
113 | version "2.0.0"
114 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
115 |
116 | wrappy@1:
117 | version "1.0.2"
118 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
119 |
--------------------------------------------------------------------------------