Skip to content

Commit 8c53778

Browse files
committedNov 3, 2021
Capture help tests
1 parent 4f46bc6 commit 8c53778

14 files changed

+270
-144
lines changed
 

‎index.js

+36-35
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import meta from '@thebespokepixel/meta';
88
import { createSelector } from '@thebespokepixel/n-selector';
99
import _ from 'lodash';
1010
import { simple, palette } from 'trucolor';
11+
import { Buffer } from 'node:buffer';
1112
import { statSync, readFileSync } from 'node:fs';
1213
import ansiRegex from 'ansi-regex';
1314

@@ -20,7 +21,7 @@ const newlineRegex$1 = /\n/g;
2021
class Tokeniser {
2122
/**
2223
* Create a new tokeniser
23-
* @param {Regexp} tokenisingRegex - The regex that forms the word boundaries.
24+
* @param {RegExp} tokenisingRegex - The regex that forms the word boundaries.
2425
*/
2526
constructor(tokenisingRegex) {
2627
this.tokenisingRegex = tokenisingRegex || (function () {
@@ -48,8 +49,8 @@ class Tokeniser {
4849
}
4950
/**
5051
* Reconstruct the line, flushing any remaining tokens
51-
* @param {String} source - Line to process
52-
* @return {String} - Process line
52+
* @param {string} source - Line to process
53+
* @return {string} - Process line
5354
*/
5455
restore(source) {
5556
return source
@@ -60,7 +61,7 @@ class Tokeniser {
6061
/**
6162
* Creates a tokeniser.
6263
* @private
63-
* @param {<type>} tokenisingRegex The tokenising regular expression
64+
* @param {RegExp} tokenisingRegex The tokenising regular expression
6465
* @see {@link Tokeniser}
6566
* @return {Tokeniser} { A tokeniser instance. }
6667
*/
@@ -103,7 +104,7 @@ class LineFitter {
103104
/**
104105
* Add a token to the line.
105106
* @param {string} token The word token to add.
106-
* @returns {Boolean} Causes newline.
107+
* @returns {boolean} Causes newline.
107108
*/
108109
add(token) {
109110
if (newlineRegex.test(token)) {
@@ -161,9 +162,9 @@ class LineFitter {
161162
/**
162163
* Creates a line fitter - a new line of wrapped text..
163164
* @private
164-
* @param {String} margin The left margin, made up of spaces
165-
* @param {Number} width The width the line can take up
166-
* @param {Number} tabWidth Desired TAB width
165+
* @param {string} margin The left margin, made up of spaces
166+
* @param {number} width The width the line can take up
167+
* @param {number} tabWidth Desired TAB width
167168
* @return {LineFitter} The line fitter.
168169
*/
169170
function createLineFitter(margin, width, tabWidth) {
@@ -178,9 +179,9 @@ class WrapTool {
178179
/**
179180
* Create a new line wrapping tool.
180181
* @param {options} $0 - The supplied options
181-
* @param {Number} $0.left - The left margins
182-
* @param {Number} $0.width - The width of the view, in chars
183-
* @param {Regex} $0.tokenRegex - An optional regex passed to the Tokeniser
182+
* @param {number} $0.left - The left margins
183+
* @param {number} $0.width - The width of the view, in chars
184+
* @param {RegExp} $0.tokenRegex - An optional regex passed to the Tokeniser
184185
*/
185186
constructor({
186187
left,
@@ -195,8 +196,8 @@ class WrapTool {
195196
}
196197
/**
197198
* Apply instance settings to source text.
198-
* @param {String} text - The text that require wrapping to the view.
199-
* @return {String} - Text with wrapping applied.
199+
* @param {string} text - The text that require wrapping to the view.
200+
* @return {string} - Text with wrapping applied.
200201
*/
201202
wrap(text) {
202203
this.lines = [];
@@ -221,7 +222,7 @@ class WrapTool {
221222
/**
222223
* Creates a wrap tool.
223224
* @private
224-
* @param {Object} options The options
225+
* @param {object} options The options
225226
* @return {WrapTool} The wrap tool.
226227
*/
227228
function createWrapTool(options) {
@@ -231,11 +232,11 @@ function createWrapTool(options) {
231232
const clr = _.merge(
232233
simple({format: 'sgr'}),
233234
palette({format: 'sgr'},
234-
{
235-
title: 'bold #9994D1',
236-
bright: 'bold rgb(255,255,255)',
237-
dark: '#333',
238-
}),
235+
{
236+
title: 'bold #9994D1',
237+
bright: 'bold rgb(255,255,255)',
238+
dark: '#333',
239+
}),
239240
);
240241
const colorReplacer = new TemplateTag(
241242
replaceSubstitutionTransformer(
@@ -257,9 +258,9 @@ class Image {
257258
* @param {string} $0.file - The filename of the image.
258259
* @param {string} $0.name - The name of the image
259260
* [will be taken from image if missing]
260-
* @param {String} $0.width - Can be X(chars), Xpx(pixels),
261+
* @param {string} $0.width - Can be X(chars), Xpx(pixels),
261262
* X%(% width of window) or 'auto'
262-
* @param {String} $0.height - Can be Y(chars), Ypx(pixels),
263+
* @param {string} $0.height - Can be Y(chars), Ypx(pixels),
263264
* Y%(% width of window) or 'auto'
264265
*/
265266
constructor({
@@ -291,29 +292,29 @@ class Image {
291292
}
292293
/**
293294
* Load and render the image into the CLI
294-
* @param {Object} options - The options to set
295+
* @param {object} options - The options to set
295296
* @property {number} align - The line count needed to realign the cursor.
296-
* @property {Boolean} stretch - Do we stretch the image to match the width
297+
* @property {boolean} stretch - Do we stretch the image to match the width
297298
* and height.
298-
* @property {Boolean} nobreak - Do we clear the image with a newline?
299+
* @property {boolean} nobreak - Do we clear the image with a newline?
299300
* @return {string} The string to insert into the output buffer, with base64
300301
* encoded image.
301302
*/
302303
render(options) {
303-
const {align, stretch = false, nobreak} = options;
304+
const {align, stretch = false, nobreak, spacing = ''} = options;
304305
const content = Buffer.from(readFileSync(this.filePath));
305306
const aspect = stretch ? 'preserveAspectRatio=0;' : '';
306307
const linebreak = nobreak ? '' : '\n';
307308
const newline = align > 1 ? `\u001BH\u001B[${align}A` : linebreak;
308309
return `${prefix}${aspect}size=${content.length}${this.config}:${
309310
content.toString('base64')
310-
}${suffix}${newline}`
311+
}${suffix}${newline}${spacing}`
311312
}
312313
}
313314
/**
314315
* Creates an image.
315316
* @private
316-
* @param {String} source The source
317+
* @param {string} source The source
317318
* @return {Image} A configured (but not yet loaded) image.
318319
*/
319320
function createImage(source) {
@@ -325,7 +326,7 @@ function createImage(source) {
325326
* @private
326327
* @param {string} buffer_ Input plain text.
327328
* @param {string} delimiter_ Field delimiter.
328-
* @param {Number} width_ Panel width.
329+
* @param {number} width_ Panel width.
329330
* @return {object} The columnify configuration.
330331
*/
331332
function panel(buffer_, delimiter_, width_) {
@@ -428,7 +429,7 @@ function truwrap({
428429
if (outStream.isTTY) {
429430
return outStream.columns || outStream.getWindowSize()[0]
430431
}
431-
return Infinity
432+
return 120
432433
})();
433434
const viewWidth = (function () {
434435
if (ttyWidth - left - right > 1) {
@@ -468,15 +469,15 @@ function truwrap({
468469
/**
469470
* Fetch the width in characters of the wrapping view.
470471
* @function
471-
* @return {Number} wrapping width
472+
* @return {number} wrapping width
472473
*/
473474
getWidth: unimplemented,
474475
/**
475476
* Create a multicolumn panel within this view
476477
* @function
477478
* @param {panelObject} content - Object for columnify
478-
* @param {Object} configuration - Configuration for columnify
479-
* @return {String} - The rendered panel.
479+
* @param {object} configuration - Configuration for columnify
480+
* @return {string} - The rendered panel.
480481
*/
481482
panel(content, configuration) {
482483
if (outStream._isStdio) {
@@ -487,7 +488,7 @@ function truwrap({
487488
/**
488489
* Generate linebreaks within this view
489490
* @function
490-
* @param {Number} newlines - number of new lines to add.
491+
* @param {number} newlines - number of new lines to add.
491492
* @return {api} has side effect of writing to stream.
492493
*/
493494
break(newlines = 1) {
@@ -506,7 +507,7 @@ function truwrap({
506507
/**
507508
* Write text via the wrapping logic
508509
* @function
509-
* @param {String} text - The raw, unwrapped test to wrap.
510+
* @param {string} text - The raw, unwrapped test to wrap.
510511
* @return {api} has side effect of writing to stream.
511512
*/
512513
write(text) {
@@ -516,7 +517,7 @@ function truwrap({
516517
};
517518
switch (true) {
518519
case !ttyActive:
519-
console.info(colorReplacer`${'yellow|Non-TTY'}: width: Infinity`);
520+
console.info(colorReplacer`${'yellow|Non-TTY'}: width: 120`);
520521
/**
521522
* @name noTTY
522523
* @private

‎src/cli/help.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ const images = (function () {
3535
/**
3636
* Render help when asked for.
3737
* @param {yargs} yargsInstance - yargs object defined in cli
38-
* @return {undefined} Writes help to stdout.
38+
* @return {null} Writes help to stdout.
3939
*/
4040
export default async function help(yargsInstance) {
4141
const header = () => stripIndent(colorReplacer)`
42-
${`title| ${metadata.name}`}
42+
${`title|${metadata.name}`}
4343
${images.space}${metadata.description}
4444
${images.space}${`grey|${metadata.version(3)}`}
4545
`
@@ -75,6 +75,7 @@ export default async function help(yargsInstance) {
7575
container.write(images.cc.render({
7676
nobreak: false,
7777
align: 2,
78+
spacing: ' ',
7879
}))
7980
container.write(header()).break()
8081
container.write(`${clr.dark}${'—'.repeat(windowWidth)}${clr.dark.out}`).break()

‎src/cli/index.js

+31-34
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/* ────────────╮
22
│ truwrap CLI │
33
╰─────────────┴─────────────────────────────────────────────────────────────── */
4-
/* eslint unicorn/no-process-exit:0,quotes:0 */
54

65
import {format} from 'util'
76

@@ -156,43 +155,41 @@ if (!(process.env.USER === 'root' && process.env.SUDO_USER !== process.env.USER)
156155
if (argv.help) {
157156
(async () => {
158157
await help(yargsInstance)
159-
process.exit(0)
160158
})()
161-
}
162-
163-
const viewSettings = {
164-
left: argv.left,
165-
right: argv.right,
166-
mode: argv.mode,
167-
tabWidth: argv.tab,
168-
outStream
169-
}
170-
171-
if (argv.regex) {
172-
viewSettings.tokenRegex = new RegExp(argv.regex, 'g')
173-
}
159+
} else {
160+
const viewSettings = {
161+
left: argv.left,
162+
right: argv.right,
163+
mode: argv.mode,
164+
tabWidth: argv.tab,
165+
outStream
166+
}
174167

175-
if (argv.width) {
176-
viewSettings.width = argv.width
177-
}
168+
if (argv.regex) {
169+
viewSettings.tokenRegex = new RegExp(argv.regex, 'g')
170+
}
178171

179-
const renderer = truwrap(viewSettings)
172+
if (argv.width) {
173+
viewSettings.width = argv.width
174+
}
180175

181-
if (argv.stamp) {
182-
renderer.write(format(...argv._))
183-
process.exit(0)
184-
}
176+
const renderer = truwrap(viewSettings)
185177

186-
getStdin().then(input => {
187-
if (argv.panel) {
188-
const panel = parsePanel(input, argv.delimiter, renderer.getWidth())
189-
renderer.panel(panel.content, {
190-
maxLineWidth: renderer.getWidth(),
191-
showHeaders: false,
192-
truncate: argv.truncate,
193-
config: panel.configuration
194-
})
178+
if (argv.stamp) {
179+
renderer.write(format(...argv._))
195180
} else {
196-
renderer.write(input)
181+
getStdin().then(input => {
182+
if (argv.panel) {
183+
const panel = parsePanel(input, argv.delimiter, renderer.getWidth())
184+
renderer.panel(panel.content, {
185+
maxLineWidth: renderer.getWidth(),
186+
showHeaders: false,
187+
truncate: argv.truncate,
188+
config: panel.configuration
189+
})
190+
} else {
191+
renderer.write(input)
192+
}
193+
})
197194
}
198-
})
195+
}

‎src/index.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export function truwrap({
6969
return outStream.columns || outStream.getWindowSize()[0]
7070
}
7171

72-
return Infinity
72+
return 120
7373
})()
7474

7575
const viewWidth = (function () {
@@ -116,16 +116,16 @@ export function truwrap({
116116
/**
117117
* Fetch the width in characters of the wrapping view.
118118
* @function
119-
* @return {Number} wrapping width
119+
* @return {number} wrapping width
120120
*/
121121
getWidth: unimplemented,
122122

123123
/**
124124
* Create a multicolumn panel within this view
125125
* @function
126126
* @param {panelObject} content - Object for columnify
127-
* @param {Object} configuration - Configuration for columnify
128-
* @return {String} - The rendered panel.
127+
* @param {object} configuration - Configuration for columnify
128+
* @return {string} - The rendered panel.
129129
*/
130130
panel(content, configuration) {
131131
if (outStream._isStdio) {
@@ -138,7 +138,7 @@ export function truwrap({
138138
/**
139139
* Generate linebreaks within this view
140140
* @function
141-
* @param {Number} newlines - number of new lines to add.
141+
* @param {number} newlines - number of new lines to add.
142142
* @return {api} has side effect of writing to stream.
143143
*/
144144
break(newlines = 1) {
@@ -159,7 +159,7 @@ export function truwrap({
159159
/**
160160
* Write text via the wrapping logic
161161
* @function
162-
* @param {String} text - The raw, unwrapped test to wrap.
162+
* @param {string} text - The raw, unwrapped test to wrap.
163163
* @return {api} has side effect of writing to stream.
164164
*/
165165
write(text) {
@@ -170,7 +170,7 @@ export function truwrap({
170170

171171
switch (true) {
172172
case !ttyActive:
173-
console.info(colorReplacer`${'yellow|Non-TTY'}: width: Infinity`)
173+
console.info(colorReplacer`${'yellow|Non-TTY'}: width: 120`)
174174

175175
/**
176176
* @name noTTY

‎src/lib/classes/image.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ class Image {
2222
* @param {string} $0.file - The filename of the image.
2323
* @param {string} $0.name - The name of the image
2424
* [will be taken from image if missing]
25-
* @param {String} $0.width - Can be X(chars), Xpx(pixels),
25+
* @param {string} $0.width - Can be X(chars), Xpx(pixels),
2626
* X%(% width of window) or 'auto'
27-
* @param {String} $0.height - Can be Y(chars), Ypx(pixels),
27+
* @param {string} $0.height - Can be Y(chars), Ypx(pixels),
2828
* Y%(% width of window) or 'auto'
2929
*/
3030
constructor({
@@ -61,16 +61,16 @@ class Image {
6161

6262
/**
6363
* Load and render the image into the CLI
64-
* @param {Object} options - The options to set
64+
* @param {object} options - The options to set
6565
* @property {number} align - The line count needed to realign the cursor.
66-
* @property {Boolean} stretch - Do we stretch the image to match the width
66+
* @property {boolean} stretch - Do we stretch the image to match the width
6767
* and height.
68-
* @property {Boolean} nobreak - Do we clear the image with a newline?
68+
* @property {boolean} nobreak - Do we clear the image with a newline?
6969
* @return {string} The string to insert into the output buffer, with base64
7070
* encoded image.
7171
*/
7272
render(options) {
73-
const {align, stretch = false, nobreak} = options
73+
const {align, stretch = false, nobreak, spacing = ''} = options
7474

7575
const content = Buffer.from(readFileSync(this.filePath))
7676

@@ -80,14 +80,14 @@ class Image {
8080

8181
return `${prefix}${aspect}size=${content.length}${this.config}:${
8282
content.toString('base64')
83-
}${suffix}${newline}`
83+
}${suffix}${newline}${spacing}`
8484
}
8585
}
8686

8787
/**
8888
* Creates an image.
8989
* @private
90-
* @param {String} source The source
90+
* @param {string} source The source
9191
* @return {Image} A configured (but not yet loaded) image.
9292
*/
9393
export default function createImage(source) {

‎src/lib/classes/line-fitter.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class LineFitter {
4545
/**
4646
* Add a token to the line.
4747
* @param {string} token The word token to add.
48-
* @returns {Boolean} Causes newline.
48+
* @returns {boolean} Causes newline.
4949
*/
5050
add(token) {
5151
if (newlineRegex.test(token)) {
@@ -113,9 +113,9 @@ class LineFitter {
113113
/**
114114
* Creates a line fitter - a new line of wrapped text..
115115
* @private
116-
* @param {String} margin The left margin, made up of spaces
117-
* @param {Number} width The width the line can take up
118-
* @param {Number} tabWidth Desired TAB width
116+
* @param {string} margin The left margin, made up of spaces
117+
* @param {number} width The width the line can take up
118+
* @param {number} tabWidth Desired TAB width
119119
* @return {LineFitter} The line fitter.
120120
*/
121121
export default function createLineFitter(margin, width, tabWidth) {

‎src/lib/classes/panel.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import _ from 'lodash'
1010
* @private
1111
* @param {string} buffer_ Input plain text.
1212
* @param {string} delimiter_ Field delimiter.
13-
* @param {Number} width_ Panel width.
13+
* @param {number} width_ Panel width.
1414
* @return {object} The columnify configuration.
1515
*/
1616
export default function panel(buffer_, delimiter_, width_) {

‎src/lib/classes/tokeniser.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const newlineRegex = /\n/g
1616
class Tokeniser {
1717
/**
1818
* Create a new tokeniser
19-
* @param {Regexp} tokenisingRegex - The regex that forms the word boundaries.
19+
* @param {RegExp} tokenisingRegex - The regex that forms the word boundaries.
2020
*/
2121
constructor(tokenisingRegex) {
2222
this.tokenisingRegex = tokenisingRegex || (function () {
@@ -46,8 +46,8 @@ class Tokeniser {
4646

4747
/**
4848
* Reconstruct the line, flushing any remaining tokens
49-
* @param {String} source - Line to process
50-
* @return {String} - Process line
49+
* @param {string} source - Line to process
50+
* @return {string} - Process line
5151
*/
5252
restore(source) {
5353
return source
@@ -59,7 +59,7 @@ class Tokeniser {
5959
/**
6060
* Creates a tokeniser.
6161
* @private
62-
* @param {<type>} tokenisingRegex The tokenising regular expression
62+
* @param {RegExp} tokenisingRegex The tokenising regular expression
6363
* @see {@link Tokeniser}
6464
* @return {Tokeniser} { A tokeniser instance. }
6565
*/

‎src/lib/classes/wrap-tool.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ class WrapTool {
1414
/**
1515
* Create a new line wrapping tool.
1616
* @param {options} $0 - The supplied options
17-
* @param {Number} $0.left - The left margins
18-
* @param {Number} $0.width - The width of the view, in chars
19-
* @param {Regex} $0.tokenRegex - An optional regex passed to the Tokeniser
17+
* @param {number} $0.left - The left margins
18+
* @param {number} $0.width - The width of the view, in chars
19+
* @param {RegExp} $0.tokenRegex - An optional regex passed to the Tokeniser
2020
*/
2121
constructor({
2222
left,
@@ -32,8 +32,8 @@ class WrapTool {
3232

3333
/**
3434
* Apply instance settings to source text.
35-
* @param {String} text - The text that require wrapping to the view.
36-
* @return {String} - Text with wrapping applied.
35+
* @param {string} text - The text that require wrapping to the view.
36+
* @return {string} - Text with wrapping applied.
3737
*/
3838
wrap(text) {
3939
this.lines = []
@@ -62,7 +62,7 @@ class WrapTool {
6262
/**
6363
* Creates a wrap tool.
6464
* @private
65-
* @param {Object} options The options
65+
* @param {object} options The options
6666
* @return {WrapTool} The wrap tool.
6767
*/
6868
export default function createWrapTool(options) {

‎test-out

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
]1337;File=inline=1;size=8717width=auto;height=3;name=bG9nbw==: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H truwrap
3+
Smarter terminal text wrapping (handles 24bit color)
4+
v2.0.4
5+
————————————————————————————————————————————————————————————————————————————————
6+
Synopsis:
7+
cat inputFile | truwrap [options]
8+
9+
Options:
10+
-h, --help Display this help.
11+
-v, --version Return the current version on stdout. -vv Return name & versi
12+
on. [count]
13+
-V, --verbose Be verbose. -VV Be loquacious. [count]
14+
-o, --stderr Use stderr rather than stdout [boolean] [default: false]
15+
-l, --left Left margin [default: 2]
16+
-r, --right Right margin [default: 2]
17+
-w, --width Set total width. Overrides terminal window’s width.
18+
-t, --tab Set tab width. [default: 2]
19+
-m, --mode Wrapping mode
20+
[choices: "hard", "soft", "keep", "container"] [default: "soft"]
21+
-s, --stamp Print arguments rather than stdin. printf-style options suppo
22+
rted. [boolean]
23+
-p, --panel Render a tabular panel into the available console width.
24+
[boolean]
25+
-c, --truncate Truncate panel cells. [boolean]
26+
-d, --delimiter The column delimiter when reading data for a panel.
27+
[default: "|"]
28+
-x, --regex Character run selection regex.
29+
--color Force color depth --color=256|16m. Disable with --no-color
30+
31+
Usage:
32+
Reads unformatted text from stdin and typographically applies paragraph wrapping it for the currently active tty.
33+
34+
————————————————————————————————————————————————————————————————————————————————truwrap ©2021 The Bespoke Pixel. Released under the MIT License.
35+
An Open Source component from ByteTree.com's terminal visualisation toolkit
36+
Issues?: https://github.com/thebespokepixel/truwrap/issues

‎test/cli.js

+10
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,13 @@ test(`Module name/version is '${pkg.name} v${expectedVersion}'.`, async t => {
1111
const {stdout} = await execPromise('./truwrap.js -vv')
1212
t.is(stdout.trim(), `${pkg.name} v${expectedVersion}`)
1313
})
14+
15+
test('Module help with image', async t => {
16+
const {stderr} = await execPromise('./truwrap.js --help --color=256')
17+
t.snapshot(stderr)
18+
})
19+
20+
test('Module help, no color', async t => {
21+
const {stderr} = await execPromise('./truwrap.js --help --no-color')
22+
t.snapshot(stderr)
23+
})

‎test/snapshots/cli.js.md

+79
Large diffs are not rendered by default.

‎test/snapshots/cli.js.snap

9.59 KB
Binary file not shown.

‎truwrap.js

+45-43
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,17 @@ import { createConsole } from 'verbosity';
1818
import meta from '@thebespokepixel/meta';
1919
import { createSelector } from '@thebespokepixel/n-selector';
2020
import ansiRegex from 'ansi-regex';
21+
import { Buffer } from 'node:buffer';
2122
import { statSync, readFileSync } from 'node:fs';
2223

2324
const clr = _.merge(
2425
simple({format: 'sgr'}),
2526
palette({format: 'sgr'},
26-
{
27-
title: 'bold #9994D1',
28-
bright: 'bold rgb(255,255,255)',
29-
dark: '#333',
30-
}),
27+
{
28+
title: 'bold #9994D1',
29+
bright: 'bold rgb(255,255,255)',
30+
dark: '#333',
31+
}),
3132
);
3233
const colorReplacer = new TemplateTag(
3334
replaceSubstitutionTransformer(
@@ -209,14 +210,14 @@ class Image {
209210
})();
210211
}
211212
render(options) {
212-
const {align, stretch = false, nobreak} = options;
213+
const {align, stretch = false, nobreak, spacing = ''} = options;
213214
const content = Buffer.from(readFileSync(this.filePath));
214215
const aspect = stretch ? 'preserveAspectRatio=0;' : '';
215216
const linebreak = nobreak ? '' : '\n';
216217
const newline = align > 1 ? `\u001BH\u001B[${align}A` : linebreak;
217218
return `${prefix}${aspect}size=${content.length}${this.config}:${
218219
content.toString('base64')
219-
}${suffix}${newline}`
220+
}${suffix}${newline}${spacing}`
220221
}
221222
}
222223
function createImage(source) {
@@ -305,7 +306,7 @@ function truwrap({
305306
if (outStream.isTTY) {
306307
return outStream.columns || outStream.getWindowSize()[0]
307308
}
308-
return Infinity
309+
return 120
309310
})();
310311
const viewWidth = (function () {
311312
if (ttyWidth - left - right > 1) {
@@ -355,7 +356,7 @@ function truwrap({
355356
};
356357
switch (true) {
357358
case !ttyActive:
358-
console.info(colorReplacer`${'yellow|Non-TTY'}: width: Infinity`);
359+
console.info(colorReplacer`${'yellow|Non-TTY'}: width: 120`);
359360
return Object.assign(Object.create(api), {
360361
getWidth: () => ttyWidth
361362
})
@@ -404,7 +405,7 @@ const images = (function () {
404405
})();
405406
async function help(yargsInstance) {
406407
const header = () => stripIndent(colorReplacer)`
407-
${`title| ${metadata.name}`}
408+
${`title|${metadata.name}`}
408409
${images.space}${metadata.description}
409410
${images.space}${`grey|${metadata.version(3)}`}
410411
`;
@@ -418,7 +419,7 @@ async function help(yargsInstance) {
418419
`;
419420
const epilogue = stripIndent(colorReplacer)`
420421
${`title|${metadata.name}`} ${`white|${metadata.copyright}`}. ${`grey|Released under the ${metadata.license} License.`}
421-
${`grey|An Open Source component from ByteTree.com's terminal visualisation toolkit.`}
422+
${'grey|An Open Source component from ByteTree.com\'s terminal visualisation toolkit'}
422423
${`grey|Issues?: ${metadata.bugs}`}
423424
`;
424425
const container = truwrap({
@@ -436,6 +437,7 @@ async function help(yargsInstance) {
436437
container.write(images.cc.render({
437438
nobreak: false,
438439
align: 2,
440+
spacing: ' ',
439441
}));
440442
container.write(header()).break();
441443
container.write(`${clr.dark}${'—'.repeat(windowWidth)}${clr.dark.out}`).break();
@@ -578,37 +580,37 @@ if (!(process.env.USER === 'root' && process.env.SUDO_USER !== process.env.USER)
578580
if (argv.help) {
579581
(async () => {
580582
await help(yargsInstance);
581-
process.exit(0);
582583
})();
583-
}
584-
const viewSettings = {
585-
left: argv.left,
586-
right: argv.right,
587-
mode: argv.mode,
588-
tabWidth: argv.tab,
589-
outStream
590-
};
591-
if (argv.regex) {
592-
viewSettings.tokenRegex = new RegExp(argv.regex, 'g');
593-
}
594-
if (argv.width) {
595-
viewSettings.width = argv.width;
596-
}
597-
const renderer = truwrap(viewSettings);
598-
if (argv.stamp) {
599-
renderer.write(format(...argv._));
600-
process.exit(0);
601-
}
602-
getStdin().then(input => {
603-
if (argv.panel) {
604-
const panel$1 = panel(input, argv.delimiter, renderer.getWidth());
605-
renderer.panel(panel$1.content, {
606-
maxLineWidth: renderer.getWidth(),
607-
showHeaders: false,
608-
truncate: argv.truncate,
609-
config: panel$1.configuration
610-
});
611-
} else {
612-
renderer.write(input);
584+
} else {
585+
const viewSettings = {
586+
left: argv.left,
587+
right: argv.right,
588+
mode: argv.mode,
589+
tabWidth: argv.tab,
590+
outStream
591+
};
592+
if (argv.regex) {
593+
viewSettings.tokenRegex = new RegExp(argv.regex, 'g');
613594
}
614-
});
595+
if (argv.width) {
596+
viewSettings.width = argv.width;
597+
}
598+
const renderer = truwrap(viewSettings);
599+
if (argv.stamp) {
600+
renderer.write(format(...argv._));
601+
process.exit(0);
602+
}
603+
getStdin().then(input => {
604+
if (argv.panel) {
605+
const panel$1 = panel(input, argv.delimiter, renderer.getWidth());
606+
renderer.panel(panel$1.content, {
607+
maxLineWidth: renderer.getWidth(),
608+
showHeaders: false,
609+
truncate: argv.truncate,
610+
config: panel$1.configuration
611+
});
612+
} else {
613+
renderer.write(input);
614+
}
615+
});
616+
}

0 commit comments

Comments
 (0)
Please sign in to comment.