Skip to content

Commit 0a600e5

Browse files
committed
New: --print-name option (fixes #35)
1 parent 00f674a commit 0a600e5

File tree

11 files changed

+216
-58
lines changed

11 files changed

+216
-58
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ Usage: npm-run-all [...tasks] [OPTIONS]
4646
-l, --print-label Set the flag to print the task name as a prefix
4747
on each line of output, to the current group of
4848
tasks.
49+
-n, --print-name Set the flag to print the task name before
50+
running each task, to the current group of
51+
tasks.
4952
--silent Set "silent" to the log level of npm.
5053
5154
-p, --parallel [...tasks] Run a group of tasks in parallel.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"cross-spawn-async": "^2.1.9",
2727
"minimatch": "^3.0.0",
2828
"ps-tree": "^1.0.1",
29+
"read-pkg": "^1.1.0",
2930
"shell-quote": "^1.4.3",
3031
"string.prototype.padend": "^3.0.0"
3132
},

src/bin/help.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Usage: npm-run-all [...tasks] [OPTIONS]
2626
-l, --print-label Set the flag to print the task name as a prefix
2727
on each line of output, to the current group of
2828
tasks.
29+
-n, --print-name Set the flag to print the task name before
30+
running each task, to the current group of
31+
tasks.
2932
--silent Set "silent" to the log level of npm.
3033
3134
-p, --parallel [...tasks] Run a group of tasks in parallel.

src/bin/main.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ function parse(args) {
6666
parallel: false,
6767
continueOnError: false,
6868
printLabel: false,
69+
printName: false,
6970
patterns: []
7071
}];
7172

@@ -81,6 +82,7 @@ function parse(args) {
8182
parallel: false,
8283
continueOnError: arg === "-S",
8384
printLabel: false,
85+
printName: false,
8486
patterns: []
8587
});
8688
break;
@@ -92,6 +94,7 @@ function parse(args) {
9294
parallel: true,
9395
continueOnError: arg === "-P",
9496
printLabel: false,
97+
printName: false,
9598
patterns: []
9699
});
97100
break;
@@ -106,6 +109,13 @@ function parse(args) {
106109
groups[groups.length - 1].printLabel = true;
107110
break;
108111

112+
case "-n":
113+
case "--print-name":
114+
groups[groups.length - 1].printName = true;
115+
break;
116+
117+
case "--color":
118+
case "--no-color":
109119
case "--silent":
110120
// do nothing.
111121
break;
@@ -153,7 +163,16 @@ export default function npmRunAll(args, stdout, stderr) {
153163
const {groups, packageConfig} = parse(args);
154164

155165
return groups.reduce(
156-
(prev, {patterns, parallel, continueOnError, printLabel}) => {
166+
(
167+
prev,
168+
{
169+
patterns,
170+
parallel,
171+
continueOnError,
172+
printLabel,
173+
printName
174+
}
175+
) => {
157176
if (patterns.length === 0) {
158177
return prev;
159178
}
@@ -166,6 +185,7 @@ export default function npmRunAll(args, stdout, stderr) {
166185
parallel,
167186
continueOnError,
168187
printLabel,
188+
printName,
169189
packageConfig,
170190
silent
171191
}

src/lib/create-header.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* @author Toru Nagashima
3+
* @copyright 2016 Toru Nagashima. All rights reserved.
4+
* See LICENSE file in root directory for full license.
5+
*/
6+
7+
//------------------------------------------------------------------------------
8+
// Requirements
9+
//------------------------------------------------------------------------------
10+
11+
import chalk from "chalk";
12+
13+
//------------------------------------------------------------------------------
14+
// Public Interface
15+
//------------------------------------------------------------------------------
16+
17+
/**
18+
* Creates the header text for a given task.
19+
*
20+
* @param {string} nameAndArgs - A task name and arguments.
21+
* @param {object} packageInfo - A package.json's information.
22+
* @param {object} packageInfo.body - A package.json's JSON object.
23+
* @param {string} packageInfo.path - A package.json's file path.
24+
* @param {boolean} isTTY - The flag to color the header.
25+
* @returns {string} The header of a given task.
26+
*/
27+
export default function createHeader(nameAndArgs, packageInfo, isTTY) {
28+
if (!packageInfo) {
29+
return `\n> ${nameAndArgs}\n\n`;
30+
}
31+
32+
const index = nameAndArgs.indexOf(" ");
33+
const name = (index === -1) ? nameAndArgs : nameAndArgs.slice(0, index);
34+
const args = (index === -1) ? "" : nameAndArgs.slice(index + 1);
35+
const {
36+
body: {
37+
name: packageName,
38+
version: packageVersion,
39+
scripts: {
40+
[name]: scriptBody
41+
}
42+
},
43+
path: packagePath
44+
} = packageInfo || {};
45+
const color = isTTY ? chalk.styles.gray : {open: "", close: ""};
46+
47+
return `
48+
${color.open}> ${packageName}@${packageVersion} ${name} ${packagePath}${color.close}
49+
${color.open}> ${scriptBody} ${args}${color.close}
50+
51+
`;
52+
}

src/lib/npm-run-all.js

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* See LICENSE file in root directory for full license.
55
*/
66
import matchTasks from "./match-tasks";
7-
import readTasks from "./read-tasks";
7+
import readPackageJson from "./read-package-json";
88
import runTasksInParallel from "./run-tasks-in-parallel";
99
import runTasksInSequencial from "./run-tasks-in-sequencial";
1010

@@ -104,6 +104,9 @@ function maxLength(length, name) {
104104
* @param {boolean} options.printLabel -
105105
* The flag to print task names at the head of each line.
106106
* Default is `false`.
107+
* @param {boolean} options.printName -
108+
* The flag to print task names before running each task.
109+
* Default is `false`.
107110
* @returns {Promise}
108111
* A promise object which becomes fullfilled when all npm-scripts are completed.
109112
*/
@@ -118,7 +121,8 @@ export default function npmRunAll(
118121
packageConfig = null,
119122
silent = false,
120123
continueOnError = false,
121-
printLabel = false
124+
printLabel = false,
125+
printName = false
122126
} = {}
123127
) {
124128
try {
@@ -138,22 +142,34 @@ export default function npmRunAll(
138142
prefixOptions.push(...toOverwriteOptions(packageConfig));
139143
}
140144

141-
const tasks = matchTasks(taskList || readTasks(), patterns);
142-
const labelWidth = tasks.reduce(maxLength, 0);
143-
const runTasks = parallel ? runTasksInParallel : runTasksInSequencial;
144-
return runTasks(tasks, {
145-
stdin,
146-
stdout,
147-
stderr,
148-
prefixOptions,
149-
continueOnError,
150-
labelState: {
151-
enabled: printLabel,
152-
width: labelWidth,
153-
lastPrefix: null,
154-
lastIsLinebreak: true
155-
}
156-
});
145+
return Promise.resolve(taskList)
146+
.then(taskList => { // eslint-disable-line no-shadow
147+
if (taskList != null) {
148+
return {taskList, packageInfo: null};
149+
}
150+
return readPackageJson();
151+
})
152+
.then(({taskList, packageInfo}) => { // eslint-disable-line no-shadow
153+
const tasks = matchTasks(taskList, patterns);
154+
const labelWidth = tasks.reduce(maxLength, 0);
155+
const runTasks = parallel ? runTasksInParallel : runTasksInSequencial;
156+
157+
return runTasks(tasks, {
158+
stdin,
159+
stdout,
160+
stderr,
161+
prefixOptions,
162+
continueOnError,
163+
labelState: {
164+
enabled: printLabel,
165+
width: labelWidth,
166+
lastPrefix: null,
167+
lastIsLinebreak: true
168+
},
169+
printName,
170+
packageInfo
171+
});
172+
});
157173
}
158174
catch (err) {
159175
return Promise.reject(new Error(err.message));

src/lib/read-package-json.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @author Toru Nagashima
3+
* @copyright 2016 Toru Nagashima. All rights reserved.
4+
* See LICENSE file in root directory for full license.
5+
*/
6+
7+
//------------------------------------------------------------------------------
8+
// Requirements
9+
//------------------------------------------------------------------------------
10+
11+
import {join as joinPath} from "path";
12+
import readPkg from "read-pkg";
13+
14+
//------------------------------------------------------------------------------
15+
// Public Interface
16+
//------------------------------------------------------------------------------
17+
18+
/**
19+
* Reads the package.json in the current directory.
20+
*
21+
* @returns {object} package.json's information.
22+
*/
23+
export default function readPackageJson() {
24+
const path = joinPath(process.cwd(), "package.json");
25+
return readPkg(path).then(body => ({
26+
taskList: Object.keys(body.scripts || {}),
27+
packageInfo: {path, body}
28+
}));
29+
}

src/lib/read-tasks.js

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/lib/run-task.js

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,29 @@
1111
import chalk from "chalk";
1212
import {parse as parseArgs} from "shell-quote";
1313
import padEnd from "string.prototype.padend";
14+
import createHeader from "./create-header";
1415
import createPrefixTransform from "./create-prefix-transform-stream";
1516
import spawn from "./spawn";
1617

1718
//------------------------------------------------------------------------------
1819
// Helpers
1920
//------------------------------------------------------------------------------
2021

21-
/**
22-
* Pass through the argument.
23-
*
24-
* @param {string} s - An argument.
25-
* @returns {string} The argument.
26-
*/
27-
function identity(s) {
28-
return s;
29-
}
30-
3122
/**
3223
* Wraps stdout/stderr with a transform stream to add the task name as prefix.
3324
*
3425
* @param {string} taskName - The task name.
3526
* @param {stream.Writable} source - An output stream to be wrapped.
36-
* @param {stream.Writable} std - process.stdout/process.stderr.
3727
* @param {object} labelState - An label state for the transform stream.
3828
* @returns {stream.Writable} `source` or the created wrapped stream.
3929
*/
40-
function wrapLabeling(taskName, source, std, labelState) {
30+
function wrapLabeling(taskName, source, labelState) {
4131
if (source == null || !labelState.enabled) {
4232
return source;
4333
}
4434

4535
const label = padEnd(taskName, labelState.width);
46-
const color = (source === std) ? chalk.gray : identity;
36+
const color = source.isTTY ? chalk.gray : (x) => x;
4737
const prefix = color(`[${label}] `);
4838
const stream = createPrefixTransform(prefix, labelState);
4939

@@ -97,6 +87,7 @@ function detectStreamKind(stream, std) {
9787
* @param {string[]} options.prefixOptions -
9888
* An array of options which are inserted before the task name.
9989
* @param {object} options.labelState - A state object for printing labels.
90+
* @param {boolean} options.printName - The flag to print task names before running each task.
10091
* @returns {Promise}
10192
* A promise object which becomes fullfilled when the npm-script is completed.
10293
* This promise object has an extra method: `abort()`.
@@ -109,17 +100,24 @@ export default function runTask(
109100
stdout: sourceStdout,
110101
stderr: sourceStderr,
111102
prefixOptions,
112-
labelState
103+
labelState,
104+
printName,
105+
packageInfo
113106
}
114107
) {
115108
let cp = null;
116109
const promise = new Promise((resolve, reject) => {
117-
const stdout = wrapLabeling(task, sourceStdout, process.stdout, labelState);
118-
const stderr = wrapLabeling(task, sourceStderr, process.stderr, labelState);
110+
const stdout = wrapLabeling(task, sourceStdout, labelState);
111+
const stderr = wrapLabeling(task, sourceStderr, labelState);
119112
const stdinKind = detectStreamKind(stdin, process.stdin);
120113
const stdoutKind = detectStreamKind(stdout, process.stdout);
121114
const stderrKind = detectStreamKind(stderr, process.stderr);
122115

116+
// Print task name.
117+
if (printName && stdout != null) {
118+
stdout.write(createHeader(task, packageInfo, sourceStdout.isTTY));
119+
}
120+
123121
// Execute.
124122
cp = spawn(
125123
"npm",

test/print-label.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ describe("[print-label] npm-run-all", () => {
4444
assert.equal(stdout.value, EXPECTED_TEXT);
4545
});
4646
});
47+
48+
it("command version (shorthand)", () => {
49+
const stdout = new BufferStream();
50+
return command(["test-task:echo abc", "--silent", "-l"], stdout)
51+
.then(() => {
52+
assert.equal(stdout.value, EXPECTED_TEXT);
53+
});
54+
});
4755
});
4856

4957
describe("should print all labels with the same width:", () => {

0 commit comments

Comments
 (0)