1- import kleur from 'kleur'
21import { parseArgs } from 'util'
32import { either , type Either } from '../../adts.js'
4- import { withPhantomData } from '../../phantom-data.js'
5- import { type Molecule } from '../parsing.js'
6- import { type Canonicalized , type SyntaxTree } from '../parsing/syntax-tree.js'
3+ import { type SyntaxTree } from '../parsing/syntax-tree.js'
4+ import { unparse , type Notation } from '../unparsing.js'
5+ import { prettyJson } from '../unparsing/pretty-json.js'
6+ import { prettyPlz } from '../unparsing/pretty-plz.js'
77
88export const handleOutput = async (
99 process : NodeJS . Process ,
@@ -16,91 +16,54 @@ export const handleOutput = async (
1616 'output-format' : { type : 'string' } ,
1717 } ,
1818 } )
19- if ( args . values [ 'output-format' ] === undefined ) {
19+ const outputFormat = args . values [ 'output-format' ]
20+ if ( outputFormat === undefined ) {
2021 throw new Error ( 'Missing required option: --output-format' )
21- } else if ( args . values [ 'output-format' ] !== 'json' ) {
22- throw new Error (
23- `Unsupported output format: "${ args . values [ 'output-format' ] } "` ,
24- )
2522 } else {
23+ let notation : Notation
24+ if ( outputFormat === 'json' ) {
25+ notation = prettyJson
26+ } else if ( outputFormat === 'plz' ) {
27+ notation = prettyPlz
28+ } else {
29+ throw new Error ( `Unsupported output format: "${ outputFormat } "` )
30+ }
31+
2632 const result = await command ( )
2733 return either . match ( result , {
2834 left : error => {
2935 throw new Error ( error . message ) // TODO: Improve error reporting.
3036 } ,
3137 right : output => {
32- writeJSON ( process . stdout , output )
38+ writeOutput ( process . stdout , notation , output )
3339 return undefined
3440 } ,
3541 } )
3642 }
3743}
3844
39- export const writeJSON = (
45+ export const writeOutput = (
4046 writeStream : NodeJS . WritableStream ,
47+ notation : Notation ,
4148 output : SyntaxTree ,
4249) : void => {
43- writeStream . write ( stringifyAsPrettyJSON ( output ) )
44-
45- // Writing a newline ensures that output is flushed before terminating, otherwise nothing may be
46- // printed to the console. See:
47- // - <https://github.com/nodejs/node/issues/6379>
48- // - <https://github.com/nodejs/node/issues/6456>
49- // - <https://github.com/nodejs/node/issues/2972>
50- // - …and many other near-duplicate issues
51- //
52- // I've tried other workarounds such as explicitly terminating via `process.exit`, passing a
53- // callback to `writeStream.write` (ensuring the returned `Promise` is not resolved until it is
54- // called), and explicitly calling `writeStream.end`/`writeStream.uncork` and so far this is the
55- // only workaround which reliably results in the desired behavior.
56- writeStream . write ( '\n' )
57- }
58-
59- const indent = ( spaces : number , textToIndent : string ) => {
60- const indentation = ' ' . repeat ( spaces )
61- return ( indentation + textToIndent ) . replace ( / ( \r ? \n ) / g, `$1${ indentation } ` )
62- }
63-
64- const quote = kleur . dim ( '"' )
65- const colon = kleur . dim ( ':' )
66- const comma = kleur . dim ( ',' )
67- const openBrace = kleur . dim ( '{' )
68- const closeBrace = kleur . dim ( '}' )
69-
70- const escapeStringContents = ( value : string ) =>
71- value . replace ( '\\' , '\\\\' ) . replace ( '"' , '\\"' )
72-
73- const key = ( value : string ) : string =>
74- quote + kleur . bold ( escapeStringContents ( value ) ) + quote
75-
76- const string = ( value : string ) : string =>
77- quote +
78- escapeStringContents (
79- / ^ @ [ ^ @ ] / . test ( value ) ? kleur . bold ( kleur . underline ( value ) ) : value ,
80- ) +
81- quote
82-
83- const object = ( value : Molecule ) : string => {
84- const entries = Object . entries ( value )
85- if ( entries . length === 0 ) {
86- return openBrace + closeBrace
50+ const outputAsString = unparse ( output , notation )
51+ if ( either . isLeft ( outputAsString ) ) {
52+ throw new Error ( outputAsString . value . message )
8753 } else {
88- const keyValuePairs : string = Object . entries ( value )
89- . map (
90- ( [ propertyKey , propertyValue ] ) =>
91- key ( propertyKey ) +
92- colon +
93- ' ' +
94- stringifyAsPrettyJSON (
95- withPhantomData < Canonicalized > ( ) ( propertyValue ) ,
96- ) ,
97- )
98- . join ( comma + '\n' )
54+ writeStream . write ( outputAsString . value )
9955
100- return openBrace + '\n' + indent ( 2 , keyValuePairs ) + '\n' + closeBrace
56+ // Writing a newline ensures that output is flushed before terminating, otherwise nothing may be
57+ // printed to the console. See:
58+ // - <https://github.com/nodejs/node/issues/6379>
59+ // - <https://github.com/nodejs/node/issues/6456>
60+ // - <https://github.com/nodejs/node/issues/2972>
61+ // - …and many other near-duplicate issues
62+ //
63+ // I've tried other workarounds such as explicitly terminating via `process.exit`, passing a
64+ // callback to `writeStream.write` (ensuring the returned `Promise` is not resolved until it is
65+ // called), and explicitly calling `writeStream.end`/`writeStream.uncork` and so far this is the
66+ // only workaround which reliably results in the desired behavior.
67+ writeStream . write ( '\n' )
10168 }
10269}
103-
104- const stringifyAsPrettyJSON = ( output : SyntaxTree ) => {
105- return typeof output === 'string' ? string ( output ) : object ( output )
106- }
0 commit comments