1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 16:42:21 -05:00

prettier: support reading code from stdin (denoland/deno_std#498)

Original: 85db520b60
This commit is contained in:
Axetroy 2019-06-30 23:10:00 +08:00 committed by Ryan Dahl
parent 6d4473324f
commit 78a9a27e6f
4 changed files with 213 additions and 10 deletions

View file

@ -6,22 +6,31 @@ Prettier APIs and tools for deno
To formats the source files, run:
```console
```bash
deno --allow-read --allow-write https://deno.land/std/prettier/main.ts
```
You can format only specific files by passing the arguments.
```console
```bash
deno --allow-read --allow-write https://deno.land/std/prettier/main.ts path/to/script.ts
```
You can format files on specific directory by passing the directory's path.
```console
```bash
deno --allow-read --allow-write https://deno.land/std/prettier/main.ts path/to/script.ts
```
You can format the input plain text stream. default parse it as typescript code.
```bash
cat path/to/script.ts | deno https://deno.land/std/prettier/main.ts
cat path/to/script.js | deno https://deno.land/std/prettier/main.ts --stdin-parser=babel
cat path/to/config.json | deno https://deno.land/std/prettier/main.ts --stdin-parser=json
cat path/to/README.md | deno https://deno.land/std/prettier/main.ts --stdin-parser=markdown
```
## Use API
You can use APIs of prettier as the following:

View file

@ -23,7 +23,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// This script formats the given source files. If the files are omitted, it
// formats the all files in the repository.
const { args, exit, readFile, writeFile, stdout } = Deno;
const { args, exit, readFile, writeFile, stdout, stdin, readAll } = Deno;
import { glob, isGlob, GlobOptions } from "../fs/glob.ts";
import { walk, WalkInfo } from "../fs/walk.ts";
import { parse } from "../flags/mod.ts";
@ -41,6 +41,15 @@ Options:
it will output to stdout, Defaults to
false.
--ignore <path> Ignore the given path(s).
--stdin Specifies to read the code from stdin.
If run the command in a pipe, you do not
need to specify this flag.
Defaults to false.
--stdin-parser <typescript|babel|markdown|json>
If set --stdin flag, then need specify a
parser for stdin. available parser:
typescript/babel/markdown/json. Defaults
to typescript.
JS/TS Styling Options:
--print-width <int> The line length where Prettier will try
@ -76,6 +85,14 @@ Example:
deno run prettier/main.ts script1.ts
Print the formatted code to stdout
cat script1.ts | deno run prettier/main.ts
Read the typescript code from stdin and
output formatted code to stdout.
cat config.json | deno run prettier/main.ts --stdin-parser=json
Read the JSON string from stdin and
output formatted code to stdout.
`;
// Available parsers
@ -237,6 +254,39 @@ async function formatSourceFiles(
exit(0);
}
/**
* Format source code
*/
function format(
text: string,
parser: ParserLabel,
prettierOpts: PrettierOptions
): string {
const formatted: string = prettier.format(text, {
...prettierOpts,
parser: parser,
plugins: prettierPlugins
});
return formatted;
}
/**
* Format code from stdin and output to stdout
*/
async function formatFromStdin(
parser: ParserLabel,
prettierOpts: PrettierOptions
): Promise<void> {
const byte = await readAll(stdin);
const formattedCode = format(
new TextDecoder().decode(byte),
parser,
prettierOpts
);
await stdout.write(new TextEncoder().encode(formattedCode));
}
/**
* Get the files to format.
* @param selectors The glob patterns to select the files.
@ -329,14 +379,21 @@ async function main(opts): Promise<void> {
options
);
const tty = Deno.isTTY();
const shouldReadFromStdin =
(!tty.stdin && (tty.stdout || tty.stderr)) || !!opts["stdin"];
try {
if (check) {
if (shouldReadFromStdin) {
await formatFromStdin(opts["stdin-parser"], prettierOpts);
} else if (check) {
await checkSourceFiles(files, prettierOpts);
} else {
await formatSourceFiles(files, prettierOpts);
}
} catch (e) {
console.log(e);
console.error(e);
exit(1);
}
}
@ -350,7 +407,8 @@ main(
"trailing-comma",
"arrow-parens",
"prose-wrap",
"end-of-line"
"end-of-line",
"stdin-parser"
],
boolean: [
"check",
@ -359,7 +417,8 @@ main(
"use-tabs",
"single-quote",
"bracket-spacing",
"write"
"write",
"stdin"
],
default: {
ignore: [],
@ -373,7 +432,9 @@ main(
"arrow-parens": "avoid",
"prose-wrap": "preserve",
"end-of-line": "auto",
write: false
write: false,
stdin: false,
"stdin-parser": "typescript"
},
alias: {
H: "help"

View file

@ -2,7 +2,7 @@
import { join } from "../fs/path.ts";
import { EOL } from "../fs/path/constants.ts";
import { assertEquals } from "../testing/asserts.ts";
import { test } from "../testing/mod.ts";
import { test, runIfMain } from "../testing/mod.ts";
import { xrun } from "./util.ts";
import { copy, emptyDir } from "../fs/mod.ts";
const { readAll, execPath } = Deno;
@ -233,3 +233,128 @@ test(async function testPrettierPrintToStdout(): Promise<void> {
emptyDir(tempDir);
});
test(async function testPrettierReadFromStdin(): Promise<void> {
interface TestCase {
stdin: string;
stdout: string;
stderr: string;
code: number;
success: boolean;
parser?: string;
}
async function readFromStdinAssertion(
stdin: string,
expectedStdout: string,
expectedStderr: string,
expectedCode: number,
expectedSuccess: boolean,
parser?: string
): Promise<void> {
const inputCode = stdin;
const p1 = Deno.run({
args: [execPath, "./prettier/testdata/echox.ts", `${inputCode}`],
stdout: "piped"
});
const p2 = Deno.run({
args: [
execPath,
"run",
"./prettier/main.ts",
"--stdin",
...(parser ? ["--stdin-parser", parser] : [])
],
stdin: "piped",
stdout: "piped",
stderr: "piped"
});
const n = await Deno.copy(p2.stdin!, p1.stdout!);
assertEquals(n, new TextEncoder().encode(stdin).length);
const status1 = await p1.status();
assertEquals(status1.code, 0);
assertEquals(status1.success, true);
p2.stdin!.close();
const status2 = await p2.status();
assertEquals(status2.code, expectedCode);
assertEquals(status2.success, expectedSuccess);
const decoder = new TextDecoder("utf-8");
assertEquals(
decoder.decode(await Deno.readAll(p2.stdout!)),
expectedStdout
);
assertEquals(
decoder.decode(await Deno.readAll(p2.stderr!)).split(EOL)[0],
expectedStderr
);
p2.close();
p1.close();
}
const testCases: TestCase[] = [
{
stdin: `console.log("abc" )`,
stdout: `console.log("abc");\n`,
stderr: ``,
code: 0,
success: true
},
{
stdin: `console.log("abc" )`,
stdout: `console.log("abc");\n`,
stderr: ``,
code: 0,
success: true,
parser: "babel"
},
{
stdin: `{\"a\":\"b\"}`,
stdout: `{ "a": "b" }\n`,
stderr: ``,
code: 0,
success: true,
parser: "json"
},
{
stdin: `## test`,
stdout: `## test\n`,
stderr: ``,
code: 0,
success: true,
parser: "markdown"
},
{
stdin: `invalid typescript code##!!@@`,
stdout: ``,
stderr: `SyntaxError: ';' expected. (1:9)`,
code: 1,
success: false
},
{
stdin: `console.log("foo");`,
stdout: ``,
stderr:
'Error: Couldn\'t resolve parser "invalid_parser". ' +
"Parsers must be explicitly added to the standalone bundle.",
code: 1,
success: false,
parser: "invalid_parser"
}
];
for (const t of testCases) {
await readFromStdinAssertion(
t.stdin,
t.stdout,
t.stderr,
t.code,
t.success,
t.parser
);
}
});
runIfMain(import.meta);

8
prettier/testdata/echox.ts vendored Normal file
View file

@ -0,0 +1,8 @@
async function echox(args: string[]) {
for (const arg of args) {
await Deno.stdout.write(new TextEncoder().encode(arg));
}
Deno.exit(0);
}
echox(Deno.args.slice(1));