Skip to content

Commit

Permalink
New: Add --depth flag to pair with --tasks flag
Browse files Browse the repository at this point in the history
  • Loading branch information
sttk authored and phated committed Dec 21, 2017
1 parent 12f2e3f commit 3e0fc18
Show file tree
Hide file tree
Showing 15 changed files with 313 additions and 58 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ __Some flags only work with gulp 4 and will be ignored when invoked against gulp
<td>-T</td>
<td>Print the task dependency tree for the loaded gulpfile.</td>
</tr>
<tr>
<td>--depth [number]</td>
<td></td>
<td>Specify the depth of the task dependency tree to print.</td>
</tr>
<tr>
<td>--tasks-simple</td>
<td></td>
Expand Down
6 changes: 6 additions & 0 deletions lib/shared/cliOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ module.exports = {
desc: chalk.gray(
'Print the task dependency tree for the loaded gulpfile.'),
},
depth: {
type: 'number',
requiresArg: true,
desc: chalk.gray(
'Specify the depth of the task dependency tree.'),
},
'tasks-simple': {
type: 'boolean',
desc: chalk.gray(
Expand Down
201 changes: 174 additions & 27 deletions lib/shared/log/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,187 @@
var archy = require('archy');
var chalk = require('chalk');
var log = require('gulplog');
var sortBy = require('lodash.sortby');

function isString(val) {
return typeof val === 'string';
}

function isObject(val) {
return typeof val === 'object' && !Array.isArray(val);
}

function logTasks(tree, depth, getTask) {
depth = (typeof depth !== 'number') ? null : ((depth < 1) ? 1 : depth);

var lineInfos = [];
var entryObserver = getLineInfoCollector(lineInfos);

tree = copyTree(tree, depth, getTask, entryObserver);

var spacer = getSpacerForLineIndents(tree, lineInfos);
var lines = getLinesContainingOnlyBranches(tree);

log.info(tree.label);
printTreeList(lines, spacer, lineInfos);
}

function getLineInfoCollector(lineInfos) {
return {
topTask: function(node) {
lineInfos.push({
name: node.label,
desc: node.desc,
type: 'top',
});
},
option: function(opt) {
lineInfos.push({
name: opt.label,
desc: opt.desc,
type: 'option',
});
},
childTask: function(node) {
lineInfos.push({
name: node.label,
type: 'child',
});
},
};
}

function copyTree(tree, depth, getTask, entryObserver) {
var newTree = {
label: tree.label,
nodes: [],
};

sortBy(tree.nodes, sorter).forEach(visit);

function sorter(node) {
return node.label;
}

function visit(node) {
var task = getTask(node.label) || {};

var newNode = {
label: node.label,
desc: isString(task.description) ? task.description : '',
opts: [],
nodes: [],
};
entryObserver.topTask(newNode);
newTree.nodes.push(newNode);

if (isObject(task.flags)) {
Object.keys(task.flags).sort().forEach(function(flag) {
if (flag.length === 0) {
return;
}
var opt = {
label: flag,
desc: isString(task.flags[flag]) ? task.flags[flag] : '',
};
entryObserver.option(opt);
newNode.opts.push(opt);
newNode.label += '\n' + opt.label; // The way of archy for options.
});
}

if (!depth || depth > 1) {
var fn = function(child, maxDepth, nowDepth, newParent) {
var newChild = {
label: child.label,
nodes: [],
};
entryObserver.childTask(newChild);
newChild.label = ''; // Because don't use child tasks to calc indents.
newParent.nodes.push(newChild);
if (!maxDepth || maxDepth > nowDepth) {
forEachNode(child.nodes, fn, maxDepth, nowDepth + 1, newChild);
}
};
forEachNode(node.nodes, fn, depth, 2, newNode);
}
}

return newTree;
}

function forEachNode(nodes, fn) {
if (!Array.isArray(nodes)) {
return;
}

var args = [].slice.call(arguments, 2);

for (var i = 0, n = nodes.length; i < n; i++) {
fn.apply(nodes[i], [nodes[i]].concat(args));
}
}

function getSpacerForLineIndents(tree, lineInfos) {
var maxSize = 0;
var sizes = [];

function logTasks(tree, getDescription) {
var padding = 0;
var rdependency = /[ │] [├└]/;
archy(tree)
.split('\n')
.filter(function(v, i) {
// Log first line as is
if (i === 0) {
log.info(v);
return false;
.slice(1, -1)
.forEach(function(line, index) {
var info = lineInfos[index];
if (info.type === 'top' || info.type === 'option') {
maxSize = Math.max(maxSize, line.length);
sizes.push(line.length);
} else {
sizes.push(0);
}
// Search for longest line
if (v.length > padding) {
padding = v.length;
});

maxSize += 3;

return function(index) {
return Array(maxSize - sizes[index]).join(' ');
};
}

function getLinesContainingOnlyBranches(tree) {
tree.nodes.forEach(function(node) {
node.label = '';
node.opts.forEach(function() {
node.label += '\n';
});
});

return archy(tree)
.split('\n')
.slice(1, -1);
}

function printTreeList(lines, spacer, lineInfos) {
lines.forEach(function(branch, index) {
var info = lineInfos[index];

var line = chalk.white(branch);

if (info.type === 'top') {
line += chalk.cyan(info.name);
if (info.desc.length > 0) {
line += spacer(index) + chalk.white(info.desc);
}
return v.trim().length !== 0;
}).forEach(function(v) {
var line = v.split(' ');
var task = line.slice(1).join(' ');

// Log dependencies as is
if (rdependency.test(v)) {
log.info(v);
return;
} else if (info.type === 'option') {
line += chalk.magenta(info.name);
if (info.desc.length > 0) {
line += spacer(index) + chalk.white('…' + info.desc);
}
} else { // If (info.type === 'child') {
line += chalk.white(info.name);
}

// Pretty task with optional description
log.info(
line[0] + ' ' + chalk.cyan(task) +
Array(padding + 3 - v.length).join(' ') +
(getDescription(task) || '')
);
});
log.info(line);
});
}

module.exports = logTasks;

4 changes: 2 additions & 2 deletions lib/versioned/^3.7.0/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ function execute(opts, env) {
if (opts.tasks) {
var tree = taskTree(gulpInst.tasks);
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
return logTasks(tree, function(task) {
return gulpInst.tasks[task].fn.description;
return logTasks(tree, opts.depth, function(task) {
return gulpInst.tasks[task].fn;
});
}
gulpInst.start.apply(gulpInst, toRun);
Expand Down
23 changes: 14 additions & 9 deletions lib/versioned/^3.7.0/taskTree.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
'use strict';

module.exports = function(tasks) {
return Object.keys(tasks)
.reduce(function(prev, task) {
prev.nodes.push({
label: task,
nodes: tasks[task].dep,
});
return prev;
}, {
nodes: [],
var map = {};
var arr = [];
Object.keys(tasks).forEach(function(taskname) {
var task = { label: taskname, nodes: [], };
map[taskname] = task;
arr.push(task);
});
Object.keys(tasks).forEach(function(taskname) {
var task = map[taskname];
tasks[taskname].dep.forEach(function(childname) {
var child = map[childname] || { label: childname, nodes: [], };
task.nodes.push(child);
});
});
return { label: 'Tasks', nodes: arr, };
};
4 changes: 2 additions & 2 deletions lib/versioned/^4.0.0-alpha.1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ function execute(opts, env) {
label: 'Tasks for ' + chalk.magenta(tildify(env.configPath)),
nodes: gulpInst.tree({ deep: true }),
};
return logTasks(tree, function(task) {
return gulpInst.task(task).description;
return logTasks(tree, opts.depth, function(taskname) {
return gulpInst.task(taskname);
});
}
if (opts.tasksJson) {
Expand Down
4 changes: 2 additions & 2 deletions lib/versioned/^4.0.0-alpha.2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ function execute(opts, env) {
tree = gulpInst.tree({ deep: true });
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));

return logTasks(tree, function(task) {
return gulpInst.task(task).description;
return logTasks(tree, opts.depth, function(taskname) {
return gulpInst.task(taskname);
});
}
if (opts.tasksJson) {
Expand Down
4 changes: 2 additions & 2 deletions lib/versioned/^4.0.0/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ function execute(opts, env) {
tree = gulpInst.tree({ deep: true });
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));

return logTasks(tree, function(task) {
return gulpInst.task(task).description;
return logTasks(tree, opts.depth, function(taskname) {
return gulpInst.task(taskname);
});
}
if (opts.tasksJson) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"gulplog": "^1.0.0",
"interpret": "^1.0.0",
"liftoff": "^2.1.0",
"lodash.sortby": "^4.0.1",
"matchdep": "^1.0.0",
"mute-stdout": "^1.0.0",
"pretty-hrtime": "^1.0.0",
Expand Down
1 change: 1 addition & 0 deletions test/expected/flags-help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Options:
--cwd Manually set the CWD. The search for the gulpfile, as well as the relativity of all requires will be from here. [string]
--verify Will verify plugins referenced in project's package.json against the plugins blacklist.
--tasks, -T Print the task dependency tree for the loaded gulpfile. [boolean]
--depth Specify the depth of the task dependency tree.
--tasks-simple Print a plaintext list of tasks for the loaded gulpfile. [boolean]
--tasks-json Print the task dependency tree, in JSON format, for the loaded gulpfile.
--color Will force gulp and gulp plugins to display colors, even when no color support is detected. [boolean]
Expand Down
22 changes: 22 additions & 0 deletions test/expected/flags-tasks-with-desc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
gulp-cli/test
├─┬ build Build all the things!
│ │ --dev …un-minified
│ │ --production …compressed into single bundle
│ └─┬ <series>
│ ├── clean
│ ├── scripts
│ └── styles
├── clean Delete dist folder
├─┬ default Build and watch for changes
│ └─┬ <series>
│ ├─┬ build
│ │ └─┬ <series>
│ │ ├── clean
│ │ ├── scripts
│ │ └── styles
│ └── watch
├── scripts Bundles JavaScript
├── serve Serves files reloading
│ --lr …with live reloading
├── styles Compiles and bundles CSS
└── watch Watch files and build on change
24 changes: 12 additions & 12 deletions test/expected/flags-tasks.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
gulp-cli/test
├─┬ default
│ └─┬ <series>
│ ├─┬ test1
│ │ └─┬ <series>
│ │ └── noop
│ ├─┬ test3
│ │ └─┬ <series>
│ │ └── described
│ └── noop
├─┬ test1
│ └─┬ <series>
│ └── noop
Expand All @@ -11,16 +20,7 @@ gulp-cli/test
├─┬ test3
│ └─┬ <series>
│ └── described
├─┬ test4
│ └─┬ <series>
│ ├── errorFunction
│ └── anon
└─┬ default
└─┬ test4
└─┬ <series>
├─┬ test1
│ └─┬ <series>
│ └── noop
├─┬ test3
│ └─┬ <series>
│ └── described
└── noop
├── errorFunction
└── anon
Loading

0 comments on commit 3e0fc18

Please sign in to comment.