Skip to content

Instantly share code, notes, and snippets.

@Qix-
Last active May 9, 2019 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Qix-/996fc50c5b2ab254a989 to your computer and use it in GitHub Desktop.
Save Qix-/996fc50c5b2ab254a989 to your computer and use it in GitHub Desktop.
Justifies text to a certain width (usually for console text or source code text)
// Get width
const width = parseInt(process.argv[2] || '80');
// Read STDIN
let buffer = Buffer.alloc(0);
process.stdin.resume();
process.stdin.on('data', function(data) {
buffer = Buffer.concat([buffer, data]);
});
const resultLines = [];
process.stdin.on('end', function() {
process.stdin.pause();
const str = buffer.toString();
const paragraphs = str.split(/\n\n*/g); // Don't know why (\r?\n)+ doesn't work.
const title = paragraphs.shift();
center(title);
paragraphs.forEach(p => split(p));
console.log(resultLines.map(l => l.replace(/\s*$/, '')).join('\n').replace(/[\s\r\n]*$/, ''));
});
function center(str) {
const padding = Math.floor((width - str.length) / 2);
resultLines.push(' '.repeat(padding) + str, '');
}
function split(str) {
const [_, initialIndent, rawLine] = str.match(/^(\s*(?:[a-z]+\.\s+)?)(.*)$/);
const words = rawLine.split(/\s+/g);
const indent = initialIndent.replace('\t', ' ').length - 1;
const lines = [];
const whiteIndent = initialIndent.replace(/./g, ' ');
let lineLength = indent;
let lastLine = [];
words.forEach(word => {
if (lineLength + word.length + 1 > width) {
lines.push([lineLength, lastLine]);
lineLength = indent;
lastLine = [];
}
lastLine.push(word);
lineLength += word.length + 1;
});
let indentString = initialIndent;
for (const [length, line] of lines) {
const leftover = width - length;
let content;
let curLength = length;
let cur = 0;
const hit = new Set();
let count = 0;
while (curLength < width) {
do {
cur += Math.floor((Math.random() * 2) + (line.length / leftover));
cur = cur % line.length;
} while (cur === 0
|| (hit.has(cur)
&& ++count < 100));
hit.add(cur);
line[cur] = ' ' + line[cur];
++curLength;
}
content = line.join(' ');
resultLines.push(indentString + content);
indentString = whiteIndent;
}
if (lastLine.length > 0) {
resultLines.push(indentString + lastLine.join(' '));
}
resultLines.push('');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment