Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework wrap to have simpler usage pattern #1395

Merged
merged 1 commit into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,11 @@ class Help {
const termWidth = helper.padWidth(cmd, helper);
const columns = helper.columns || 80;
const itemIndentWidth = 2;
const itemSeparatorWidth = 2;
// itemIndent term itemSeparator description
const descriptionWidth = columns - termWidth - itemIndentWidth - itemSeparatorWidth;
const itemSeparatorWidth = 2; // between term and description
function formatItem(term, description) {
if (description) {
return term.padEnd(termWidth + itemSeparatorWidth) + helper.wrap(description, descriptionWidth, termWidth + itemSeparatorWidth);
const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
return helper.wrap(fullText, columns - itemIndentWidth, termWidth + itemSeparatorWidth);
}
return term;
};
Expand Down Expand Up @@ -311,32 +310,36 @@ class Help {
};

/**
* Optionally wrap the given str to a max width of width characters per line
* while indenting with indent spaces. Do not wrap if insufficient width or
* string is manually formatted.
* Wrap the given string to width characters per line, with lines after the first indented.
* Do not wrap if insufficient room for wrapping, or string is manually formatted.
*
* @param {string} str
* @param {number} width
* @param {number} indent
* @return {string}
*
*/

wrap(str, width, indent) {
// Detect manually wrapped and indented strings by searching for line breaks
// followed by multiple spaces/tabs.
if (str.match(/[\n]\s+/)) return str;
// Do not wrap to narrow columns (or can end up with a word per line).
const minWidth = 40;
if (width < minWidth) return str;
// Do not wrap if not enough room for a wrapped column of text (as could end up with a word per line).
const columnWidth = width - indent;
const minColumnWidth = 40;
if (columnWidth < minColumnWidth) return str;

const leadingStr = str.substr(0, indent);
const columnText = str.substr(indent);

const indentString = ' '.repeat(indent);
const regex = new RegExp('.{1,' + (width - 1) + '}([\\s\u200B]|$)|[^\\s\u200B]+?([\\s\u200B]|$)', 'g');
const lines = str.match(regex) || [];
return lines.map((line, i) => {
const regex = new RegExp('.{1,' + (columnWidth - 1) + '}([\\s\u200B]|$)|[^\\s\u200B]+?([\\s\u200B]|$)', 'g');
const lines = columnText.match(regex) || [];
return leadingStr + lines.map((line, i) => {
if (line.slice(-1) === '\n') {
line = line.slice(0, line.length - 1);
}
return ((i > 0 && indent) ? indentString : '') + line.trimRight();
return ((i > 0) ? indentString : '') + line.trimRight();
}).join('\n');
}
}
Expand Down
10 changes: 5 additions & 5 deletions tests/help.wrap.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ ${' '.repeat(10)}${'a '.repeat(5)}a`);
});

test('when text has line breaks then respect and indent', () => {
const text = 'foo\nbar';
const text = 'term description\nanother line';
const helper = new commander.Help();
const wrapped = helper.wrap(text, 50, 3);
expect(wrapped).toEqual('foo\n bar');
const wrapped = helper.wrap(text, 78, 5);
expect(wrapped).toEqual('term description\n another line');
});

test('when text already formatted with line breaks and indent then do not touch', () => {
const text = 'a '.repeat(25) + '\n ' + 'a '.repeat(25) + 'a';
const text = 'term a '.repeat(25) + '\n ' + 'a '.repeat(25) + 'a';
const helper = new commander.Help();
const wrapped = helper.wrap(text, 39, 0);
const wrapped = helper.wrap(text, 78, 5);
expect(wrapped).toEqual(text);
});
});
Expand Down
5 changes: 2 additions & 3 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,8 @@ declare namespace commander {
padWidth(cmd: Command, helper: Help): number;

/**
* Optionally wrap the given str to a max width of width characters per line
* while indenting with indent spaces. Do not wrap if insufficient width or
* string is manually formatted.
* Wrap the given string to width characters per line, with lines after the first indented.
* Do not wrap if insufficient room for wrapping, or string is manually formatted.
*/
wrap(str: string, width: number, indent: number): string;

Expand Down