From adc4b96f0be6bc69cb7bbd9be78c3b61050daba3 Mon Sep 17 00:00:00 2001 From: Morten Siebuhr Date: Thu, 13 Mar 2014 15:07:32 +0100 Subject: [PATCH 1/3] oconf-tree: Initial take on helper for pretty-printing include-chains. --- bin/oconf-tree | 143 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100755 bin/oconf-tree diff --git a/bin/oconf-tree b/bin/oconf-tree new file mode 100755 index 0000000..cf44f10 --- /dev/null +++ b/bin/oconf-tree @@ -0,0 +1,143 @@ +#!/usr/bin/env node +// ex: filetype=javascript + +var oconf = require('../lib/index'), + util = require('util'), + path = require('path'), + cjson = require('cjson'), + optimist = require('optimist'); + +var argv = optimist + .demand(1) + .usage('$0 ') + .options('b', { + alias: 'bottom-up', + default: false, + description: 'Show from the root up' + }) + /*.options('t', { + alias: 'top-down', + default: true, + description: 'Show from the top down' + })*/ + .boolean('t', 'b') + .argv; + +function shortestFilename(name) { + var rel = path.relative(process.cwd(), name), + abs = path.resolve(process.cwd(), name); + + return rel.length > abs.length ? abs : rel; +} + +var fileList = argv._.map(function (filename) { + return shortestFilename(filename); +}); + +var filesToLookAt = fileList, + filesLookedAt = []; + +function discoverIncludes(obj, currentFile, loadedFiles) { + //console.warn("→ discoverIncludes(" + i(obj) + ", " + currentFile + ", " + loadedFiles + ")"); + var includes = []; + + if (Array.isArray(obj)) { + obj.forEach(function (element) { + discoverIncludes(element, currentFile, loadedFiles).forEach(function (n) { + includes.push(n); + }); + }); + /* + includes = obj.map(function (element) { + return discoverIncludes(element, currentFile, loadedFiles); + }); + */ + } else if (typeof obj === 'object' && obj !== null) { + // If there's any data to mix in, we do that. + if (obj['#include'] !== undefined) { + (Array.isArray(obj['#include']) ? obj['#include'].reverse() : [obj['#include']]).forEach(function (include) { + // Figure out the target filename. + var dirname = path.dirname(currentFile), + newFilename = shortestFilename(path.resolve(dirname, include)); + includes.push(newFilename); + + // Should we look at this new file? + if ( + filesToLookAt.indexOf(newFilename) === -1 && + filesLookedAt.indexOf(newFilename) === -1 + ) { + filesToLookAt.push(newFilename); + } + }); + } + + // Discover any and all sub-includes + Object.keys(obj).forEach(function (key) { + discoverIncludes(obj[key], currentFile, loadedFiles).forEach(function (newInclude) { + includes.push(newInclude); + }); + }); + } + + //console.warn("← discoverIncludes(" + i(includes) + ")"); + return includes; +} + +// Lookup-tables for resolving includes +var includes = {}, + included = {}; + +// Load all the given oconf files and record what they are supposed to load +while(filesToLookAt.length > 0) { + var filename = filesToLookAt.pop(); + filesLookedAt.push(filename); + + //var fullFilename = path.normalize(path.resolve(filename)); + var fullFilename = path.relative(process.cwd(), filename); + + var data = cjson.load(fullFilename), + inc = discoverIncludes(data, filename, []); + + //console.log("%s\tincludes %s", fullFilename, inc); + + inc.forEach(function (i) { + // Note what this file includes + if (filename in includes) { includes[filename].push(i) } + else { includes[filename] = [i] } + + // Reverse lookups + if (i in included) { included[i].push(filename) } + else { included[i] = [filename] } + }); +} + + +// OUTPUT +function printTree(indent, branch, childLookup) { + console.log("%s%s", Array(indent).join(" "), branch) + childLookup(branch).sort().forEach(function (child) { + printTree(indent + 2, child, childLookup); + }); +} + +// Print bottom-up tree +if (argv['bottom-up']) { + //console.log(included) + filesLookedAt.filter(function (filename) { + return !(filename in includes); + }).sort().forEach(function (filename) { + printTree(1, filename, function (branch) { + return included[branch] || []; + }); + }); +} else { + // Print top-down tree + //console.log(includes); + filesLookedAt.filter(function (filename) { + return !(filename in included); + }).sort().forEach(function (filename) { + printTree(1, filename, function (branch) { + return includes[branch] || []; + }); + }); +} From 73177b6aeacf7e332ecbee1e77cf592b32b09cb0 Mon Sep 17 00:00:00 2001 From: Morten Siebuhr Date: Thu, 13 Mar 2014 15:43:23 +0100 Subject: [PATCH 2/3] oconf-tree: Code + UI cleanup. --- bin/oconf-tree | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/bin/oconf-tree b/bin/oconf-tree index cf44f10..fb43f78 100755 --- a/bin/oconf-tree +++ b/bin/oconf-tree @@ -10,10 +10,10 @@ var oconf = require('../lib/index'), var argv = optimist .demand(1) .usage('$0 ') - .options('b', { - alias: 'bottom-up', + .options('r', { + alias: 'reverse', default: false, - description: 'Show from the root up' + description: 'Start at the root (needs to include all files on command-line)' }) /*.options('t', { alias: 'top-down', @@ -47,11 +47,6 @@ function discoverIncludes(obj, currentFile, loadedFiles) { includes.push(n); }); }); - /* - includes = obj.map(function (element) { - return discoverIncludes(element, currentFile, loadedFiles); - }); - */ } else if (typeof obj === 'object' && obj !== null) { // If there's any data to mix in, we do that. if (obj['#include'] !== undefined) { @@ -120,8 +115,8 @@ function printTree(indent, branch, childLookup) { }); } -// Print bottom-up tree -if (argv['bottom-up']) { +// Print reversen tree +if (argv['reverse']) { //console.log(included) filesLookedAt.filter(function (filename) { return !(filename in includes); From 8fc7af3a809ab11937b54de18216ce07ef4fe517 Mon Sep 17 00:00:00 2001 From: Morten Siebuhr Date: Thu, 13 Mar 2014 15:43:51 +0100 Subject: [PATCH 3/3] oconf-tree: Don't show full paths all over. --- bin/oconf-tree | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/bin/oconf-tree b/bin/oconf-tree index fb43f78..b3ac932 100755 --- a/bin/oconf-tree +++ b/bin/oconf-tree @@ -23,9 +23,20 @@ var argv = optimist .boolean('t', 'b') .argv; -function shortestFilename(name) { - var rel = path.relative(process.cwd(), name), - abs = path.resolve(process.cwd(), name); +/* shortestFilename([base,] name) + */ +function shortestFilename(base, name) { + if (arguments.length === 1) { + name = base; + base = process.cwd(); + } + var rel = path.relative(base, name), + abs = path.resolve(base, name); + + // Ensure rel has ./ prefixed if nothing else + if (path.basename(rel) === rel) { + rel = './' + rel; + } return rel.length > abs.length ? abs : rel; } @@ -108,10 +119,14 @@ while(filesToLookAt.length > 0) { // OUTPUT -function printTree(indent, branch, childLookup) { - console.log("%s%s", Array(indent).join(" "), branch) +function printTree(indent, branch, parentPath, childLookup) { + console.log( + "%s%s", + Array(indent).join(" "), + shortestFilename(parentPath, branch) + ) childLookup(branch).sort().forEach(function (child) { - printTree(indent + 2, child, childLookup); + printTree(indent + 2, child, path.dirname(branch), childLookup); }); } @@ -121,7 +136,7 @@ if (argv['reverse']) { filesLookedAt.filter(function (filename) { return !(filename in includes); }).sort().forEach(function (filename) { - printTree(1, filename, function (branch) { + printTree(1, filename, process.cwd(), function (branch) { return included[branch] || []; }); }); @@ -131,7 +146,7 @@ if (argv['reverse']) { filesLookedAt.filter(function (filename) { return !(filename in included); }).sort().forEach(function (filename) { - printTree(1, filename, function (branch) { + printTree(1, filename, process.cwd(), function (branch) { return includes[branch] || []; }); });