UNPKG

7.39 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3const fs = require('fs');
4const fn = require('funclib');
5const path = require('path');
6const program = require('commander');
7const package = require('../package.json');
8const parser = require('../src/dir-parser');
9
10program.version(package.version)
11 .option('-v, --version', 'output the version number')
12 .option('-c, --config [config]', 'config file, Optional.')
13 .option('-i, --input <input>', 'target directory', './')
14 .option('-o, --output <output>', 'output path', './')
15 .option('-d, --depth <depth>', 'depth of a parse process, 0 means no limit', 0)
16 .option('-l, --lineType <lineType>', 'line type of tree, "dash" or "solid"', 'solid')
17 .option('-e, --excludes <excludes..>', 'exclude some directories or files by name.')
18 .option('-x, --excPaths <excPaths..>', 'exclude directories or files by path.')
19 .option('-p, --patterns <patterns...>', 'filter directories or files by RegExp.')
20 .option('-g, --generate [fileName]', 'generate a dir-info file to the output path, "dir-info.txt" is default.')
21 .option('-r, --reverse', 'reverse the parsed dir-tree nodes.')
22 .option('-s, --silent', 'not show the parsed dir-tree in terminal.')
23 .option('-f, --fileFirst', 'print files first, before directories.')
24 .option('-F, --fileOnly', 'pase files only.')
25 .option('-D, --dirOnly', 'pase directories only, and it only takes effect when fileOnly is false.')
26 .option('-I, --ignores <ignores..>', 'ignore some directories or files by name.')
27 .option('-N, --no-dirInfo', 'hide file and directory number info on the result top.')
28 .option('-G, --glob <glob>', 'filter files with glob patterns.')
29 .option('--paths <paths..>', 'filter directories or files by path.')
30 .option('--includes <includes..>', 'filter directories or files by name.')
31 .option('--excPatterns <excPatterns...>', 'exclude directories or files by RegExp.')
32 .option('-H, --Help', 'output chinese usage information.(打印中文帮助信息.)')
33 .parse(process.argv);
34
35if (program.Help) {
36 console.log(`用例: parser [参数options]
37
38参数 Options:
39 -V, --version 打印输出版本号。
40 -v, --version 打印输出版本号。
41 -c, --config [config] 根据配置文件解析,可选。
42 -i, --input <input> 指定个目标文件夹,(默认: "./")。
43 -o, --output <output> 解析结果输出目录,(默认: "./")。
44 -d, --depth <depth> 解析深度,0表示不限制。(默认: 0)。
45 -l, --lineType <lineType> 生成的文件树线型, "dash" 或 "solid",(默认: "solid")。
46 -e, --excludes <excludes..> 根据名称排除文件夹或文件。
47 -x, --excPaths <excPaths..> 根据路径排除文件夹或文件。
48 -p, --patterns <patterns...> 根据正则解析文件夹或文件。
49 -g, --generate [fileName] 生成一个解析结果的文件,默认文件名为"dir-info.txt"。
50 -r, --reverse 生成节点逆序的文件树。
51 -s, --silent 静默解析,不在控制台输出解析结果。
52 -f, --fileFirst 先输出文件节点,先于文件夹节点。
53 -F, --fileOnly 只解析文件。
54 -D, --dirOnly 只解析文件夹,只有当fileOnly为false时才生效。
55 -I, --ignores <ignores..> 根据名称忽略一些文件夹或文件。
56 -N, --no-dirInfo 不在解析结果中显示文件夹和文件的数量信息。
57 -G, --glob <glob> 使用glob语法过虑文件.
58 --paths <paths..> 根据路径解析文件夹或文件。
59 --includes <includes..> 根据名称解析文件夹或文件。
60 --excPatterns <excPatterns...> 根据正则排队文件夹或文件。
61 -H, --Help 打印中文帮助信息。
62 -h, --help 打印英语帮助信息。(output usage information)`);
63 return process.exit(0);
64}
65
66let config = {};
67if (program.config) {
68 config = require(path.resolve(program.config));
69}
70
71const target = rmQuote(program.input || fn.get(config, 'input', 'str') || path.resolve('./'));
72const output = rmQuote(program.output || fn.get(config, 'output', 'str') || path.resolve('./'));
73const lineType = program.lineType || fn.get(config, 'lineType', 'str') || 'solid';
74const depth = parseInt(program.depth) || parseInt(fn.get(config, 'depth', 'str')) || 0;
75const excludes = matchHandler(program.excludes || fn.get(config, 'excludes', 'arr') || [], 'excludes');
76const excPaths = matchHandler(program.excPaths || fn.get(config, 'excPaths', 'arr') || [], 'excPaths');
77const excPatterns = matchHandler(program.excPatterns || fn.get(config, 'excPatterns', 'arr') || [], 'excPatterns');
78const ignores = matchHandler(program.ignores || fn.get(config, 'ignores', 'arr') || [], 'ignores');
79const includes = matchHandler(program.includes || fn.get(config, 'includes', 'arr') || [], 'includes');
80const paths = matchHandler(program.paths || fn.get(config, 'paths', 'arr') || [], 'paths');
81const patterns = matchHandler(program.patterns || fn.get(config, 'patterns', 'arr') || [], 'patterns');
82const glob = program.glob || fn.get(config, 'glob', 'str') || '';
83const generate = program.generate || fn.get(config, 'generate');
84const reverse = program.reverse || fn.get(config, 'reverse', 'bol');
85const silent = program.silent || fn.get(config, 'silent', 'bol');
86const fileFirst = program.fileFirst || fn.get(config, 'fileFirst', 'bol');
87const fileOnly = program.fileOnly || fn.get(config, 'fileOnly', 'bol');
88const dirOnly = program.dirOnly || fn.get(config, 'dirOnly', 'bol');
89const dInfo = program.dirInfo || fn.get(config, 'dirInfo', 'bol');
90const dirInfo = fn.isBol(dInfo) ? dInfo : true;
91const outputName = fn.isStr(generate) && generate || 'dir-info.txt';
92
93if (!fs.statSync(target).isDirectory()) {
94 throw new Error('Target must be a directory!')
95}
96const outputStat = fs.statSync(output);
97if (!outputStat.isDirectory() && !outputStat.isFile()) {
98 throw new Error('Output must be a file or a directory!')
99}
100if (outputStat.isDirectory()) {
101 outputFile = path.join(output, outputName)
102}
103// excPaths.push(outputFile);
104
105/**
106 * Format the target and output
107 */
108function rmQuote(str) {
109 return str.replace(/^['"`]|['"`]$/mg, '');
110}
111
112/**
113 * Format the matchs
114 */
115function matchHandler(match, type_) {
116 if (fn.typeOf(match, 'str')) {
117 match = rmQuote(match);
118 if (match.startsWith('[')) {
119 try {
120 eval('match =' + match);
121 } catch (e) {
122 match = fn.get(config, type_, 'arr') || [];
123 }
124 } else {
125 match = match.replace(/,/mg, ' ').split(' ');
126 }
127 }
128 return fn.toArr(match);
129}
130
131/**
132 * Log the parameters
133 */
134// fn.log({
135// target, output, depth, lineType, excludes, excPaths, excPatterns, ignores, includes,
136// paths, patterns, reverse, silent, generate, dirInfo, fileFirst, fileOnly, dirOnly,
137// }, '#Cmd Params');
138
139/**
140 * Parse target dir by options
141 */
142parser(target, {
143 depth, reverse, lineType, excludes, excPaths, excPatterns, ignores,
144 includes, paths, patterns, dirInfo, fileFirst, fileOnly, dirOnly, glob,
145}).then(
146 parsed => {
147 if (!silent) console.log(parsed.dirTree);
148 if (generate || silent) fn.wt(outputFile, parsed.dirTree);
149 },
150 error => {
151 console.log(fn.chalk(error.message, 'red'));
152 }
153);