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:
parent
6d4473324f
commit
78a9a27e6f
4 changed files with 213 additions and 10 deletions
|
@ -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:
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
8
prettier/testdata/echox.ts
vendored
Normal 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));
|
Loading…
Reference in a new issue