UNPKG

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