view-ignored 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -20
- package/out/browser/binds/index.js +16 -4
- package/out/browser/binds/plugins/git.js +8 -3
- package/out/browser/binds/plugins/jsr.js +17 -6
- package/out/browser/binds/plugins/npm.js +12 -4
- package/out/browser/binds/plugins/vsce.js +12 -4
- package/out/browser/binds/plugins/yarn.js +8 -2
- package/out/browser/binds/scanner.js +6 -2
- package/out/browser/filtering.js +2 -1
- package/out/browser/fs/directory.d.ts +1 -1
- package/out/browser/fs/directory.js +21 -7
- package/out/browser/fs/file-info.js +12 -5
- package/out/browser/fs/source-info.js +1 -1
- package/out/browser/lib.d.ts +1 -1
- package/out/browser/sorting.js +7 -1
- package/out/browser/styling.d.ts +2 -2
- package/out/browser/styling.js +11 -5
- package/out/cli.d.ts +1 -2
- package/out/cli.js +104 -98
- package/out/config.d.ts +4 -1
- package/out/config.js +29 -8
- package/package.json +113 -113
package/README.md
CHANGED
|
@@ -5,14 +5,25 @@
|
|
|
5
5
|
[](https://github.com/Mopsgamer/view-ignored)
|
|
6
6
|
[](https://github.com/Mopsgamer/view-ignored/issues)
|
|
7
7
|
|
|
8
|
-
Retrieve list of files ignored/included by Git, NPM, Yarn, JSR, VSCE or other
|
|
8
|
+
Retrieve list of files ignored/included by Git, NPM, Yarn, JSR, VSCE or other
|
|
9
|
+
tools.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
Requires Node.js vXX or later.
|
|
9
14
|
|
|
10
15
|
## Highlights
|
|
11
16
|
|
|
12
|
-
- **Multi-target.** Get list of included files
|
|
13
|
-
|
|
14
|
-
- **
|
|
15
|
-
|
|
17
|
+
- **Multi-target.** Get a list of included files using configuration file
|
|
18
|
+
readers, not command-line wrappers.
|
|
19
|
+
- **Use in browser.** view-ignored can run in the browser using a file system
|
|
20
|
+
adapter.
|
|
21
|
+
- **Command-line.** Supports no-color and multiple output styles (tree, list,
|
|
22
|
+
parsable, etc.), including
|
|
23
|
+
[Nerd Fonts](https://github.com/ryanoasis/nerd-fonts).
|
|
24
|
+
- **Plugins.** view-ignored allows you to add new [targets](#targets)
|
|
25
|
+
programmatically. Command-line interface supports plugins through `--plugins`
|
|
26
|
+
option.
|
|
16
27
|
|
|
17
28
|
## Install
|
|
18
29
|
|
|
@@ -20,10 +31,14 @@ Retrieve list of files ignored/included by Git, NPM, Yarn, JSR, VSCE or other to
|
|
|
20
31
|
npm i view-ignored
|
|
21
32
|
```
|
|
22
33
|
|
|
34
|
+
TypeScript types are included.
|
|
35
|
+
|
|
23
36
|
## Usage
|
|
24
37
|
|
|
25
38
|
### Command-line
|
|
26
39
|
|
|
40
|
+
After installing globally, you can use the following commands:
|
|
41
|
+
|
|
27
42
|
```bash
|
|
28
43
|
# get started
|
|
29
44
|
npm i -g view-ignored
|
|
@@ -31,26 +46,27 @@ viewig --help
|
|
|
31
46
|
view-ignored --help
|
|
32
47
|
|
|
33
48
|
# scan: git (default) and npm
|
|
34
|
-
viewig scan
|
|
35
|
-
viewig scan
|
|
36
|
-
viewig scan
|
|
49
|
+
viewig scan
|
|
50
|
+
viewig scan --target=npm
|
|
51
|
+
viewig scan --parsable
|
|
37
52
|
|
|
38
53
|
# scan: plugins (space, comma or pipe separated)
|
|
39
54
|
# all built-in plugins loaded automatically
|
|
40
|
-
|
|
41
|
-
viewig scan
|
|
42
|
-
viewig scan
|
|
43
|
-
viewig scan
|
|
55
|
+
# Replace example1/example2 with real plugin names
|
|
56
|
+
viewig scan --plugins="example1, example2"
|
|
57
|
+
viewig scan --plugins="example1 example2"
|
|
58
|
+
viewig scan --plugins example1 example2
|
|
59
|
+
viewig scan --plugins example1, example2
|
|
44
60
|
|
|
45
61
|
# config: print configuration entries
|
|
46
62
|
viewig config get
|
|
47
63
|
viewig config get --real
|
|
48
64
|
# config: set npm as default target and scan for npm
|
|
49
65
|
viewig config set target=npm
|
|
50
|
-
viewig scan
|
|
66
|
+
viewig scan
|
|
51
67
|
# config: always use nerdfonts
|
|
52
68
|
viewig config set style=tree
|
|
53
|
-
# config: always use
|
|
69
|
+
# config: always use Nerd Fonts for decoration
|
|
54
70
|
viewig config set decor=nerdfonts
|
|
55
71
|
# config: always use plugins
|
|
56
72
|
viewig config set plugins=example1,example2
|
|
@@ -58,7 +74,7 @@ viewig config set plugins=example1,example2
|
|
|
58
74
|
|
|
59
75
|
### Programmatically
|
|
60
76
|
|
|
61
|
-
|
|
77
|
+
To use programmatically:
|
|
62
78
|
|
|
63
79
|
```js
|
|
64
80
|
import * as vign from "view-ignored"; // or "view-ignored/browser"
|
|
@@ -68,12 +84,20 @@ await vign.Plugins.loadBuiltIns(); // load all built-in plugins
|
|
|
68
84
|
await vign.Plugins.loadPlugins(["example"]); // load third-party plugins
|
|
69
85
|
|
|
70
86
|
// scan - options available
|
|
71
|
-
const fileInfoList = await vign.scan(".", {
|
|
72
|
-
|
|
87
|
+
const fileInfoList = await vign.scan(".", {
|
|
88
|
+
target: "git",
|
|
89
|
+
cwd: process.cwd(),
|
|
90
|
+
});
|
|
91
|
+
const fileInfoList2 = await vign.scan(["./path/to/file"], {
|
|
92
|
+
target: "git",
|
|
93
|
+
cwd: process.cwd(),
|
|
94
|
+
});
|
|
73
95
|
|
|
74
96
|
// use results
|
|
75
|
-
|
|
97
|
+
for (const fileInfo of fileInfoList) {
|
|
98
|
+
if (fileInfo.ignored) {
|
|
76
99
|
superCodeEditor.explorer.colorFile(fileInfo.relativePath, "gray");
|
|
100
|
+
}
|
|
77
101
|
}
|
|
78
102
|
```
|
|
79
103
|
|
|
@@ -81,14 +105,38 @@ if (fileInfo.ignored) {
|
|
|
81
105
|
|
|
82
106
|
```js
|
|
83
107
|
const sorter = vign.Sorting.firstFolders;
|
|
84
|
-
const fileInfoList = await vign.scan(".", {target: "npm"});
|
|
85
|
-
const fileInfoSorted = fileInfoList.sort((a, b) =>
|
|
108
|
+
const fileInfoList = await vign.scan(".", { target: "npm" });
|
|
109
|
+
const fileInfoSorted = fileInfoList.sort((a, b) =>
|
|
110
|
+
sorter(String(a), String(b))
|
|
111
|
+
);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### Plugin export example
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const bind: Plugins.TargetBind = {
|
|
118
|
+
id,
|
|
119
|
+
icon,
|
|
120
|
+
name,
|
|
121
|
+
testCommand,
|
|
122
|
+
scanOptions: {
|
|
123
|
+
target: methodologyGitignoreLike(".gitignore"),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
const git: Plugins.PluginExport = { viewignored: { addTargets: [bind] } };
|
|
127
|
+
export default git;
|
|
86
128
|
```
|
|
87
129
|
|
|
88
130
|
### Targets
|
|
89
131
|
|
|
132
|
+
The following built-in plugins are available:
|
|
133
|
+
|
|
90
134
|
- `git`
|
|
91
135
|
- `npm` (compatible with Bun, PNPM, and others)
|
|
92
136
|
- `yarn`
|
|
93
137
|
- `vsce`
|
|
94
138
|
- `jsr` (compatible with Deno)
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT License. See [LICENSE.txt](LICENSE.txt) for details.
|
|
@@ -26,7 +26,8 @@ export function isPluginExport(value) {
|
|
|
26
26
|
}
|
|
27
27
|
const vign = value.viewignored;
|
|
28
28
|
return (vign?.constructor === Object)
|
|
29
|
-
&& 'addTargets' in vign && Array.isArray(vign.addTargets)
|
|
29
|
+
&& 'addTargets' in vign && Array.isArray(vign.addTargets)
|
|
30
|
+
&& vign.addTargets.every(v => isTargetBind(v));
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* Imports the plugin's exported data.
|
|
@@ -43,8 +44,15 @@ export function importPlugin(exportData) {
|
|
|
43
44
|
*/
|
|
44
45
|
export async function loadPlugin(modulePath, useImport = false) {
|
|
45
46
|
try {
|
|
46
|
-
const exports = useImport
|
|
47
|
-
|
|
47
|
+
const exports = useImport
|
|
48
|
+
? Object.getOwnPropertyDescriptor(await import(modulePath), 'default')
|
|
49
|
+
?.value
|
|
50
|
+
: await load(modulePath);
|
|
51
|
+
const result = {
|
|
52
|
+
resource: modulePath,
|
|
53
|
+
isLoaded: true,
|
|
54
|
+
exports,
|
|
55
|
+
};
|
|
48
56
|
if (isPluginExport(exports)) {
|
|
49
57
|
importPlugin(exports);
|
|
50
58
|
}
|
|
@@ -56,7 +64,11 @@ export async function loadPlugin(modulePath, useImport = false) {
|
|
|
56
64
|
if (r?.code === 'ERR_MODULE_NOT_FOUND') {
|
|
57
65
|
reason = r.message;
|
|
58
66
|
}
|
|
59
|
-
const fail = {
|
|
67
|
+
const fail = {
|
|
68
|
+
resource: modulePath,
|
|
69
|
+
isLoaded: false,
|
|
70
|
+
exports: reason,
|
|
71
|
+
};
|
|
60
72
|
return fail;
|
|
61
73
|
}
|
|
62
74
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { icons } from '@m234/nerd-fonts';
|
|
2
|
-
import {
|
|
2
|
+
import { Directory, File, InvalidPatternError, NoSourceError, SourceInfo, } from '../../index.js';
|
|
3
3
|
import { ScannerGitignore } from '../scanner.js';
|
|
4
4
|
const id = 'git';
|
|
5
5
|
const name = 'Git';
|
|
@@ -41,7 +41,8 @@ export const methodologyGitignoreLike = (base) => function (tree, o) {
|
|
|
41
41
|
}
|
|
42
42
|
for (const sourceFile of sourceList) {
|
|
43
43
|
const scanner = new ScannerGitignore({ exclude: matcherExclude });
|
|
44
|
-
const content = o.modules.fs.readFileSync(sourceFile.absolutePath)
|
|
44
|
+
const content = o.modules.fs.readFileSync(sourceFile.absolutePath)
|
|
45
|
+
.toString();
|
|
45
46
|
const pattern = content;
|
|
46
47
|
if (!scanner.isValid(pattern)) {
|
|
47
48
|
throw new InvalidPatternError(sourceFile, pattern);
|
|
@@ -52,7 +53,11 @@ export const methodologyGitignoreLike = (base) => function (tree, o) {
|
|
|
52
53
|
return map;
|
|
53
54
|
};
|
|
54
55
|
const bind = {
|
|
55
|
-
id,
|
|
56
|
+
id,
|
|
57
|
+
icon,
|
|
58
|
+
name,
|
|
59
|
+
testCommand,
|
|
60
|
+
scanOptions: {
|
|
56
61
|
target: methodologyGitignoreLike('.gitignore'),
|
|
57
62
|
},
|
|
58
63
|
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { icons } from '@m234/nerd-fonts';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { Directory, InvalidPatternError,
|
|
3
|
+
import { BadSourceError, Directory, InvalidPatternError, } from '../../index.js';
|
|
4
4
|
import { ScannerGitignore } from '../scanner.js';
|
|
5
5
|
import * as git from './git.js';
|
|
6
6
|
const id = 'jsr';
|
|
7
7
|
const name = 'JSR';
|
|
8
|
-
const icon = {
|
|
8
|
+
const icon = {
|
|
9
|
+
...icons['nf-ple-pixelated_squares_big'],
|
|
10
|
+
color: '#F5DD1E',
|
|
11
|
+
};
|
|
9
12
|
/**
|
|
10
13
|
* @internal
|
|
11
14
|
*/
|
|
@@ -61,7 +64,8 @@ export const sourceSearch = (priority, scanner) => function (tree, o) {
|
|
|
61
64
|
throw new BadSourceError(sourceFile, 'Must have \'name\', \'version\'.');
|
|
62
65
|
}
|
|
63
66
|
const { exclude, include, publish } = manifest;
|
|
64
|
-
if (exclude === undefined && include === undefined
|
|
67
|
+
if (exclude === undefined && include === undefined
|
|
68
|
+
&& publish === undefined) {
|
|
65
69
|
continue;
|
|
66
70
|
}
|
|
67
71
|
const pattern = publish?.include ?? include;
|
|
@@ -75,7 +79,8 @@ export const sourceSearch = (priority, scanner) => function (tree, o) {
|
|
|
75
79
|
}
|
|
76
80
|
}
|
|
77
81
|
else {
|
|
78
|
-
const content = o.modules.fs.readFileSync(sourceFile.absolutePath)
|
|
82
|
+
const content = o.modules.fs.readFileSync(sourceFile.absolutePath)
|
|
83
|
+
.toString();
|
|
79
84
|
const pattern = content;
|
|
80
85
|
if (!scanner.isValid(pattern)) {
|
|
81
86
|
throw new InvalidPatternError(sourceFile, pattern);
|
|
@@ -88,8 +93,14 @@ export const sourceSearch = (priority, scanner) => function (tree, o) {
|
|
|
88
93
|
return useChildren(tree, map, child => sourceSearch(priority, scanner)(child, o));
|
|
89
94
|
};
|
|
90
95
|
const bind = {
|
|
91
|
-
id,
|
|
92
|
-
|
|
96
|
+
id,
|
|
97
|
+
icon,
|
|
98
|
+
name,
|
|
99
|
+
scanOptions: {
|
|
100
|
+
target: sourceSearch(['deno.json', 'deno.jsonc', 'jsr.json', 'jsr.jsonc'], new ScannerGitignore({
|
|
101
|
+
exclude: matcherExclude,
|
|
102
|
+
include: matcherInclude,
|
|
103
|
+
})),
|
|
93
104
|
},
|
|
94
105
|
};
|
|
95
106
|
const npm = { viewignored: { addTargets: [bind] } };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { icons } from '@m234/nerd-fonts';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { Directory, InvalidPatternError,
|
|
3
|
+
import { BadSourceError, Directory, InvalidPatternError, NoSourceError, } from '../../index.js';
|
|
4
4
|
import { ScannerGitignore } from '../scanner.js';
|
|
5
5
|
import * as git from './git.js';
|
|
6
6
|
const id = 'npm';
|
|
@@ -89,7 +89,8 @@ export const sourceSearch = (priority, scanner) => function (tree, o) {
|
|
|
89
89
|
scanner.pattern = pattern;
|
|
90
90
|
}
|
|
91
91
|
else {
|
|
92
|
-
const content = o.modules.fs.readFileSync(sourceFile.absolutePath)
|
|
92
|
+
const content = o.modules.fs.readFileSync(sourceFile.absolutePath)
|
|
93
|
+
.toString();
|
|
93
94
|
const pattern = content;
|
|
94
95
|
if (!scanner.isValid(pattern)) {
|
|
95
96
|
throw new InvalidPatternError(sourceFile, pattern);
|
|
@@ -128,8 +129,15 @@ export const methodologyManifestNpmLike = (priority, scanner) => function (tree,
|
|
|
128
129
|
return sourceSearch(priority, scanner)(tree, o);
|
|
129
130
|
};
|
|
130
131
|
const bind = {
|
|
131
|
-
id,
|
|
132
|
-
|
|
132
|
+
id,
|
|
133
|
+
icon,
|
|
134
|
+
name,
|
|
135
|
+
testCommand,
|
|
136
|
+
scanOptions: {
|
|
137
|
+
target: methodologyManifestNpmLike(['package.json', '.npmignore', '.gitignore'], new ScannerGitignore({
|
|
138
|
+
exclude: matcherExclude,
|
|
139
|
+
include: matcherInclude,
|
|
140
|
+
})),
|
|
133
141
|
},
|
|
134
142
|
};
|
|
135
143
|
const npm = { viewignored: { addTargets: [bind] } };
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { icons } from '@m234/nerd-fonts';
|
|
2
|
-
import {
|
|
2
|
+
import { BadSourceError, File, NoSourceError, } from '../../index.js';
|
|
3
3
|
import * as git from './git.js';
|
|
4
4
|
const id = 'vsce';
|
|
5
5
|
const name = 'VSCE';
|
|
6
|
-
const icon = {
|
|
6
|
+
const icon = {
|
|
7
|
+
...icons['nf-md-microsoft_visual_studio_code'],
|
|
8
|
+
color: '#23A9F1',
|
|
9
|
+
};
|
|
7
10
|
const testCommand = 'vsce ls';
|
|
8
11
|
/**
|
|
9
12
|
* @internal
|
|
@@ -36,7 +39,8 @@ export const methodologyManifestVsce = function (tree, o) {
|
|
|
36
39
|
if (packageJson === undefined) {
|
|
37
40
|
throw new NoSourceError('package.json');
|
|
38
41
|
}
|
|
39
|
-
const packageJsonContent = o.modules.fs.readFileSync(packageJson.absolutePath)
|
|
42
|
+
const packageJsonContent = o.modules.fs.readFileSync(packageJson.absolutePath)
|
|
43
|
+
.toString();
|
|
40
44
|
let manifest;
|
|
41
45
|
try {
|
|
42
46
|
manifest = JSON.parse(packageJsonContent);
|
|
@@ -53,7 +57,11 @@ export const methodologyManifestVsce = function (tree, o) {
|
|
|
53
57
|
return git.methodologyGitignoreLike('.vscodeignore')(tree, o);
|
|
54
58
|
};
|
|
55
59
|
const bind = {
|
|
56
|
-
id,
|
|
60
|
+
id,
|
|
61
|
+
icon,
|
|
62
|
+
name,
|
|
63
|
+
testCommand,
|
|
64
|
+
scanOptions: {
|
|
57
65
|
target: methodologyManifestVsce,
|
|
58
66
|
},
|
|
59
67
|
};
|
|
@@ -19,8 +19,14 @@ export const matcherInclude = [
|
|
|
19
19
|
...npm.matcherInclude,
|
|
20
20
|
];
|
|
21
21
|
const bind = {
|
|
22
|
-
id,
|
|
23
|
-
|
|
22
|
+
id,
|
|
23
|
+
icon,
|
|
24
|
+
name,
|
|
25
|
+
scanOptions: {
|
|
26
|
+
target: npm.methodologyManifestNpmLike(['package.json', '.yarnignore', '.npmignore', '.gitignore'], new ScannerGitignore({
|
|
27
|
+
exclude: matcherExclude,
|
|
28
|
+
include: matcherInclude,
|
|
29
|
+
})),
|
|
24
30
|
},
|
|
25
31
|
};
|
|
26
32
|
const yarn = { viewignored: { addTargets: [bind] } };
|
|
@@ -79,7 +79,10 @@ export class ScannerMinimatch {
|
|
|
79
79
|
if (Array.isArray(argument) || typeof argument === 'string') {
|
|
80
80
|
argument = ArrayPatternToString(argument);
|
|
81
81
|
}
|
|
82
|
-
const minimatchOptions = {
|
|
82
|
+
const minimatchOptions = {
|
|
83
|
+
dot: true,
|
|
84
|
+
matchBase: true,
|
|
85
|
+
};
|
|
83
86
|
let check;
|
|
84
87
|
if (typeof argument === 'string') {
|
|
85
88
|
check = this.isMatch(path, argument, minimatchOptions);
|
|
@@ -104,7 +107,8 @@ export class ScannerMinimatch {
|
|
|
104
107
|
export class ScannerGitignore extends ScannerMinimatch {
|
|
105
108
|
static gitignoreToMinimatch(argument) {
|
|
106
109
|
if (typeof argument === 'string') {
|
|
107
|
-
return ScannerGitignore.gitignoreToMinimatch(argument.split(/\r?\n/))
|
|
110
|
+
return ScannerGitignore.gitignoreToMinimatch(argument.split(/\r?\n/))
|
|
111
|
+
.join('\n');
|
|
108
112
|
}
|
|
109
113
|
return argument
|
|
110
114
|
.map(p => p.replaceAll(/(#.+$|(?<!\\) )/gm, ''))
|
package/out/browser/filtering.js
CHANGED
|
@@ -6,5 +6,6 @@ export const filterNameList = ['ignored', 'included', 'all'];
|
|
|
6
6
|
* Checks if the value is the {@link FilterName}.
|
|
7
7
|
*/
|
|
8
8
|
export function isFilterName(value) {
|
|
9
|
-
return typeof value === 'string'
|
|
9
|
+
return typeof value === 'string'
|
|
10
|
+
&& filterNameList.includes(value);
|
|
10
11
|
}
|
|
@@ -119,7 +119,7 @@ export declare class Directory implements ParsedPath {
|
|
|
119
119
|
*/
|
|
120
120
|
toString(): string;
|
|
121
121
|
get<T extends string>(key: T): (T extends `${string}/` ? Directory : File) | undefined;
|
|
122
|
-
set<T extends string>(key: T, value:
|
|
122
|
+
set<T extends string>(key: T, value: T extends `${string}/` ? Directory : File): typeof this.children;
|
|
123
123
|
/**
|
|
124
124
|
* @returns The cache for each file of the directory with last time edited number.
|
|
125
125
|
* @see {@link modified}.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join, parse, relative
|
|
1
|
+
import { join, parse, relative } from 'node:path';
|
|
2
2
|
import EventEmitter from 'node:events';
|
|
3
3
|
import * as FSP from 'node:fs/promises';
|
|
4
4
|
import process from 'node:process';
|
|
@@ -20,7 +20,10 @@ export class Directory {
|
|
|
20
20
|
*/
|
|
21
21
|
static async deepCount(directoryPath, options) {
|
|
22
22
|
const { modules, cwd, concurrency, progress = {
|
|
23
|
-
current: 0,
|
|
23
|
+
current: 0,
|
|
24
|
+
total: 0,
|
|
25
|
+
files: 0,
|
|
26
|
+
directories: 0,
|
|
24
27
|
}, } = options;
|
|
25
28
|
const limit = pLimit(concurrency);
|
|
26
29
|
const readdir = modules.fs.promises.readdir ?? FSP.readdir;
|
|
@@ -53,9 +56,15 @@ export class Directory {
|
|
|
53
56
|
});
|
|
54
57
|
});
|
|
55
58
|
controller.run = async function () {
|
|
56
|
-
const data = await Directory.deepStreamNested(directoryPath, {
|
|
59
|
+
const data = await Directory.deepStreamNested(directoryPath, {
|
|
60
|
+
...optionsReal,
|
|
61
|
+
controller,
|
|
62
|
+
});
|
|
57
63
|
const { progress, target } = data;
|
|
58
|
-
const dataRoot = {
|
|
64
|
+
const dataRoot = {
|
|
65
|
+
progress,
|
|
66
|
+
tree: target,
|
|
67
|
+
};
|
|
59
68
|
controller.emit('end', dataRoot);
|
|
60
69
|
return dataRoot;
|
|
61
70
|
};
|
|
@@ -111,8 +120,10 @@ export class Directory {
|
|
|
111
120
|
*/
|
|
112
121
|
static async deepStreamNested(directoryPath, options) {
|
|
113
122
|
const { modules, cwd, concurrency, parent } = options;
|
|
114
|
-
const controller = options.controller
|
|
115
|
-
|
|
123
|
+
const controller = options.controller
|
|
124
|
+
?? new EventEmitter();
|
|
125
|
+
const progress = options.progress
|
|
126
|
+
?? await Directory.deepCount(directoryPath, options);
|
|
116
127
|
controller.emit('progress', progress);
|
|
117
128
|
const limit = pLimit(concurrency);
|
|
118
129
|
const readdir = modules.fs.promises.readdir ?? FSP.readdir;
|
|
@@ -126,7 +137,10 @@ export class Directory {
|
|
|
126
137
|
const relativePath = modules.path.relative(cwd, absolutePath);
|
|
127
138
|
if (entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
128
139
|
const data = await Directory.deepStreamNested(relativePath, {
|
|
129
|
-
...options,
|
|
140
|
+
...options,
|
|
141
|
+
controller,
|
|
142
|
+
progress,
|
|
143
|
+
parent,
|
|
130
144
|
});
|
|
131
145
|
++progress.current;
|
|
132
146
|
controller.emit('progress', progress);
|
|
@@ -42,19 +42,25 @@ export class FileInfo extends File {
|
|
|
42
42
|
* @returns Relative file path. Optionally formatted.
|
|
43
43
|
*/
|
|
44
44
|
toString(options) {
|
|
45
|
-
const { fileIcon, chalk, usePrefix = false, source: useSource = false, entire = true, posix = false } = options ?? {};
|
|
45
|
+
const { fileIcon, chalk, usePrefix = false, source: useSource = false, entire = true, posix = false, } = options ?? {};
|
|
46
46
|
const patha = posix ? PATH.posix : PATH;
|
|
47
47
|
const parsed = PATH.parse(this.relativePath);
|
|
48
48
|
const glyph = nf.Seti.fromParsedPath(parsed);
|
|
49
49
|
const fIcon = fileIcon
|
|
50
50
|
? decorCondition(fileIcon, {
|
|
51
51
|
ifEmoji: '📄',
|
|
52
|
-
ifNerd: chalk && glyph.color !== undefined
|
|
52
|
+
ifNerd: chalk && glyph.color !== undefined
|
|
53
|
+
? chalk.hex(glyph.color)(glyph.value)
|
|
54
|
+
: glyph.value,
|
|
53
55
|
postfix: ' ',
|
|
54
56
|
})
|
|
55
57
|
: '';
|
|
56
|
-
let prefix = usePrefix && this.status !== 'non-target'
|
|
57
|
-
|
|
58
|
+
let prefix = usePrefix && this.status !== 'non-target'
|
|
59
|
+
? (this.status === 'ignored' ? '!' : '+')
|
|
60
|
+
: '';
|
|
61
|
+
let postfix = useSource && this.source !== undefined
|
|
62
|
+
? ' < ' + this.source.toString()
|
|
63
|
+
: '';
|
|
58
64
|
if (chalk) {
|
|
59
65
|
prefix = chalk.dim(prefix);
|
|
60
66
|
postfix = chalk.dim(postfix);
|
|
@@ -64,7 +70,8 @@ export class FileInfo extends File {
|
|
|
64
70
|
if (entire) {
|
|
65
71
|
return fIcon + clr(prefix + this.relativePath + postfix);
|
|
66
72
|
}
|
|
67
|
-
return parsed.dir + patha.sep + fIcon
|
|
73
|
+
return parsed.dir + patha.sep + fIcon
|
|
74
|
+
+ clr(prefix + parsed.base + postfix);
|
|
68
75
|
}
|
|
69
76
|
if (entire) {
|
|
70
77
|
return prefix + this.relativePath + postfix;
|
package/out/browser/lib.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as PATH from 'node:path';
|
|
2
2
|
import * as FS from 'node:fs';
|
|
3
|
-
import { Directory, File, FileInfo, type
|
|
3
|
+
import { type DeepStreamEventEmitter, Directory, File, FileInfo, type SourceInfo } from './fs/index.js';
|
|
4
4
|
import { type FilterName } from './filtering.js';
|
|
5
5
|
export * from './errors.js';
|
|
6
6
|
export * from './fs/index.js';
|
package/out/browser/sorting.js
CHANGED
|
@@ -2,7 +2,13 @@ import path from 'node:path';
|
|
|
2
2
|
/**
|
|
3
3
|
* Contains all file sort names.
|
|
4
4
|
*/
|
|
5
|
-
export const sortNameList = [
|
|
5
|
+
export const sortNameList = [
|
|
6
|
+
'firstFolders',
|
|
7
|
+
'firstFiles',
|
|
8
|
+
'type',
|
|
9
|
+
'mixed',
|
|
10
|
+
'modified',
|
|
11
|
+
];
|
|
6
12
|
/**
|
|
7
13
|
* Checks if the value is the {@link SortName}.
|
|
8
14
|
*/
|
package/out/browser/styling.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export type FormatFilesOptions = {
|
|
|
8
8
|
* resolved UNC forms, eg instead of `'C:\\foo\\bar'`, it would return
|
|
9
9
|
* `'//?/C:/foo/bar'`
|
|
10
10
|
* @default false
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
* @returns `/` delimited paths, even on Windows.
|
|
12
|
+
*/
|
|
13
13
|
posix?: boolean;
|
|
14
14
|
/**
|
|
15
15
|
* @default false
|
package/out/browser/styling.js
CHANGED
|
@@ -11,7 +11,11 @@ export function formatFiles(files, options) {
|
|
|
11
11
|
const patha = posix ? PATH.posix : PATH;
|
|
12
12
|
const isPaths = style === 'paths';
|
|
13
13
|
const paths = files.map(f => f.toString({
|
|
14
|
-
fileIcon: decor,
|
|
14
|
+
fileIcon: decor,
|
|
15
|
+
usePrefix: true,
|
|
16
|
+
chalk,
|
|
17
|
+
source: showSources,
|
|
18
|
+
entire: isPaths,
|
|
15
19
|
}));
|
|
16
20
|
if (isPaths) {
|
|
17
21
|
return paths.join('\n') + '\n';
|
|
@@ -29,7 +33,8 @@ export const styleNameList = ['tree', 'paths'];
|
|
|
29
33
|
* Checks if the value is the {@link StyleName}.
|
|
30
34
|
*/
|
|
31
35
|
export function isStyleName(value) {
|
|
32
|
-
return typeof value === 'string'
|
|
36
|
+
return typeof value === 'string'
|
|
37
|
+
&& styleNameList.includes(value);
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
* Contains all decor names.
|
|
@@ -39,7 +44,8 @@ export const decorNameList = ['normal', 'emoji', 'nerdfonts'];
|
|
|
39
44
|
* Checks if the value is the {@link DecorName}.
|
|
40
45
|
*/
|
|
41
46
|
export function isDecorName(value) {
|
|
42
|
-
return typeof value === 'string'
|
|
47
|
+
return typeof value === 'string'
|
|
48
|
+
&& decorNameList.includes(value);
|
|
43
49
|
}
|
|
44
50
|
/**
|
|
45
51
|
* Formats the string for specific style types.
|
|
@@ -63,13 +69,13 @@ export function decorCondition(decor, condition) {
|
|
|
63
69
|
* Make a message in a red box. Or without color.
|
|
64
70
|
*/
|
|
65
71
|
export function boxError(message, options) {
|
|
66
|
-
let result =
|
|
72
|
+
let result = '\n' + boxen(message, {
|
|
67
73
|
titleAlignment: 'left',
|
|
68
74
|
padding: { left: 2, right: 2 },
|
|
69
75
|
borderColor: 'redBright',
|
|
70
76
|
borderStyle: 'round',
|
|
71
77
|
...options,
|
|
72
|
-
})
|
|
78
|
+
});
|
|
73
79
|
if (options?.noColor) {
|
|
74
80
|
result = stripVTControlCharacters(result);
|
|
75
81
|
}
|
package/out/cli.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Argument,
|
|
1
|
+
import { Argument, Command, Option } from 'commander';
|
|
2
2
|
import * as Config from './config.js';
|
|
3
3
|
import { type DecorName, type StyleName } from './browser/styling.js';
|
|
4
4
|
import { type SortName } from './browser/sorting.js';
|
|
@@ -57,7 +57,6 @@ export declare const argumentConfigKey: Argument;
|
|
|
57
57
|
export declare const cfgRealOption: Option;
|
|
58
58
|
export declare const cfgTypesOption: Option;
|
|
59
59
|
export declare function parseArgumentArrayString(argument: string): string[];
|
|
60
|
-
export declare function parseArgumentBoolean(argument: string): boolean;
|
|
61
60
|
export declare function parseArgumentInteger(argument: string): number;
|
|
62
61
|
export declare function createArgumentParserStringLiteral(choices: string[]): (argument: string) => string;
|
|
63
62
|
export declare function parseArgumentKey(key: string): string;
|
package/out/cli.js
CHANGED
|
@@ -2,15 +2,15 @@ import { format } from 'node:util';
|
|
|
2
2
|
import * as process from 'node:process';
|
|
3
3
|
import { icons } from '@m234/nerd-fonts';
|
|
4
4
|
import { Chalk } from 'chalk';
|
|
5
|
-
import { Argument, InvalidArgumentError, Option
|
|
6
|
-
import { Listr } from 'listr2';
|
|
5
|
+
import { Argument, Command, InvalidArgumentError, Option } from 'commander';
|
|
7
6
|
import * as Config from './config.js';
|
|
8
|
-
import {
|
|
7
|
+
import { loadBuiltIns, loadPlugins, targetGet, targetList, } from './browser/binds/index.js';
|
|
9
8
|
import { decorCondition, formatFiles, } from './browser/styling.js';
|
|
10
9
|
import { sortNameList } from './browser/sorting.js';
|
|
11
10
|
import { boxError, decorNameList, highlight, stringTime, styleNameList, } from './styling.js';
|
|
12
|
-
import { Directory,
|
|
11
|
+
import { Directory, makeOptionsReal, package_, scan, Sorting, ViewIgnoredError, } from './lib.js';
|
|
13
12
|
import { filterNameList } from './browser/filtering.js';
|
|
13
|
+
import { oraPromise } from 'ora';
|
|
14
14
|
/**
|
|
15
15
|
* @internal
|
|
16
16
|
*/
|
|
@@ -23,14 +23,17 @@ export function logError(message, options) {
|
|
|
23
23
|
*/
|
|
24
24
|
export async function programInit() {
|
|
25
25
|
try {
|
|
26
|
-
const { configManager, configDefault, configValueArray, configValueString, configValueLiteral } = Config;
|
|
26
|
+
const { configManager, configDefault, configValueArray, configValueString, configValueLiteral, } = Config;
|
|
27
27
|
const flags = program.optsWithGlobals();
|
|
28
28
|
const chalk = new Chalk();
|
|
29
29
|
configManager.keySetValidator('plugins', configDefault.plugins, configValueArray(configValueString()));
|
|
30
30
|
const loadResultConfig = configManager.load();
|
|
31
31
|
const builtInPlugins = await loadBuiltIns();
|
|
32
32
|
const configPlugins = configManager.get('plugins');
|
|
33
|
-
const loadResultPlugins = [
|
|
33
|
+
const loadResultPlugins = [
|
|
34
|
+
...(flags.plugins ? await loadPlugins(flags.plugins) : []),
|
|
35
|
+
...builtInPlugins,
|
|
36
|
+
];
|
|
34
37
|
for (const loadResult of loadResultPlugins) {
|
|
35
38
|
if (loadResult.isLoaded) {
|
|
36
39
|
continue;
|
|
@@ -47,9 +50,15 @@ export async function programInit() {
|
|
|
47
50
|
configManager.keySetValidator('target', configDefault.target, configValueLiteral(targets));
|
|
48
51
|
{
|
|
49
52
|
const title = 'view-ignored - Configuration loading failed.';
|
|
50
|
-
const infoSymbol = decorCondition(flags.decor, {
|
|
53
|
+
const infoSymbol = decorCondition(flags.decor, {
|
|
54
|
+
ifEmoji: 'ℹ️',
|
|
55
|
+
ifNerd: icons['nf-seti-info'].value,
|
|
56
|
+
postfix: ' ',
|
|
57
|
+
});
|
|
51
58
|
const errorIcon = decorCondition(flags.decor, {
|
|
52
|
-
ifNerd: icons['nf-seti-error'].value,
|
|
59
|
+
ifNerd: icons['nf-seti-error'].value,
|
|
60
|
+
ifEmoji: '⚠️',
|
|
61
|
+
postfix: ' ',
|
|
53
62
|
});
|
|
54
63
|
const footer = `\n\n${chalk.blue(infoSymbol)}Configuration path: ${Config.configManager.path}`;
|
|
55
64
|
if (typeof loadResultConfig === 'string') {
|
|
@@ -58,25 +67,31 @@ export async function programInit() {
|
|
|
58
67
|
}
|
|
59
68
|
if (loadResultConfig && loadResultConfig?.size > 0) {
|
|
60
69
|
const propertiesErrors = [...loadResultConfig.entries()].map(([key, message]) => {
|
|
61
|
-
const pair = Config.configManager.getPairString(key, {
|
|
70
|
+
const pair = Config.configManager.getPairString(key, {
|
|
71
|
+
chalk,
|
|
72
|
+
types: false,
|
|
73
|
+
real: true,
|
|
74
|
+
});
|
|
62
75
|
return `${pair} - ${chalk.red(errorIcon)}${message}`;
|
|
63
76
|
}).join('\n');
|
|
64
|
-
logError(`Invalid properties:\n${propertiesErrors}${footer}`, {
|
|
77
|
+
logError(`Invalid properties:\n${propertiesErrors}${footer}`, {
|
|
78
|
+
title,
|
|
79
|
+
});
|
|
65
80
|
process.exit(1);
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
83
|
program.version('v' + package_.version, '-v');
|
|
69
|
-
configManager.setOption('noColor', program, new Option('--no-color', 'force disable colors')
|
|
70
|
-
configManager.setOption('posix', program, new Option('--posix', 'use unix path separator')
|
|
84
|
+
configManager.setOption('noColor', program, new Option('--no-color', 'force disable colors'));
|
|
85
|
+
configManager.setOption('posix', program, new Option('--posix', 'use unix path separator'));
|
|
71
86
|
configManager.setOption('plugins', program, new Option('--plugins <modules...>', 'import modules to modify behavior'), parseArgumentArrayString);
|
|
72
87
|
configManager.setOption('decor', program, new Option('--decor <decor>', 'the interface decorations'), createArgumentParserStringLiteral([...decorNameList]));
|
|
73
|
-
configManager.setOption('parsable', program, new Option('-p, --parsable
|
|
88
|
+
configManager.setOption('parsable', program, new Option('-p, --parsable', 'print parsable text'));
|
|
74
89
|
configManager.setOption('target', scanProgram, new Option('-t, --target <ignorer>', 'the scan target'), createArgumentParserStringLiteral(targets));
|
|
75
90
|
configManager.setOption('filter', scanProgram, new Option('--filter <filter>', 'filter results'), createArgumentParserStringLiteral([...filterNameList]));
|
|
76
91
|
configManager.setOption('sort', scanProgram, new Option('--sort <sorter>', 'sort results'), createArgumentParserStringLiteral([...sortNameList]));
|
|
77
92
|
configManager.setOption('style', scanProgram, new Option('--style <style>', 'results view mode'), createArgumentParserStringLiteral([...styleNameList]));
|
|
78
93
|
configManager.setOption('depth', scanProgram, new Option('--depth <depth>', 'the max results depth'), parseArgumentInteger);
|
|
79
|
-
configManager.setOption('showSources', scanProgram, new Option('--show-sources
|
|
94
|
+
configManager.setOption('showSources', scanProgram, new Option('--show-sources', 'show scan sources'));
|
|
80
95
|
configManager.setOption('concurrency', scanProgram, new Option('--concurrency [limit]', 'the limit for the signgle directory operations'), parseArgumentInteger);
|
|
81
96
|
program.parse();
|
|
82
97
|
}
|
|
@@ -140,13 +155,6 @@ cfgProgram
|
|
|
140
155
|
export function parseArgumentArrayString(argument) {
|
|
141
156
|
return argument.split(/[ ,|]/).filter(Boolean);
|
|
142
157
|
}
|
|
143
|
-
export function parseArgumentBoolean(argument) {
|
|
144
|
-
const errorMessage = Config.configValueSwitch()(argument);
|
|
145
|
-
if (errorMessage !== undefined) {
|
|
146
|
-
throw new InvalidArgumentError(errorMessage);
|
|
147
|
-
}
|
|
148
|
-
return Config.switchTrueValues.includes(argument);
|
|
149
|
-
}
|
|
150
158
|
export function parseArgumentInteger(argument) {
|
|
151
159
|
const value = Number.parseInt(argument, 10);
|
|
152
160
|
const errorMessage = Config.configValueInteger()(value);
|
|
@@ -205,7 +213,10 @@ export async function actionScan() {
|
|
|
205
213
|
logError(format(`Bad target '${flags.target}'. Registered targets: ${targetList().join(', ')}.`), { title: 'view-ignored - Fatal error.' });
|
|
206
214
|
process.exit(1);
|
|
207
215
|
}
|
|
208
|
-
const optionsReal = makeOptionsReal({
|
|
216
|
+
const optionsReal = makeOptionsReal({
|
|
217
|
+
posix: flags.posix || flags.parsable,
|
|
218
|
+
concurrency: flags.concurrency,
|
|
219
|
+
});
|
|
209
220
|
const stream = Directory.deepStream('.', {
|
|
210
221
|
concurrency: optionsReal.concurrency,
|
|
211
222
|
cwd: optionsReal.cwd,
|
|
@@ -218,17 +229,18 @@ export async function actionScan() {
|
|
|
218
229
|
filter: flags.filter,
|
|
219
230
|
maxDepth: flags.depth,
|
|
220
231
|
});
|
|
221
|
-
console.log(fileInfoList.map(fileInfo => fileInfo.relativePath + (flags.showSources && fileInfo.source !== undefined
|
|
232
|
+
console.log(fileInfoList.map(fileInfo => fileInfo.relativePath + (flags.showSources && fileInfo.source !== undefined
|
|
233
|
+
? '<' + (fileInfo.source.relativePath)
|
|
234
|
+
: '')).join(','));
|
|
222
235
|
}
|
|
223
236
|
else {
|
|
224
|
-
let name = decorCondition(flags.decor, { ifNerd: bind.icon?.value, postfix: ' ' })
|
|
237
|
+
let name = decorCondition(flags.decor, { ifNerd: bind.icon?.value, postfix: ' ' })
|
|
238
|
+
+ bind.name;
|
|
225
239
|
if (bind.icon?.color !== undefined) {
|
|
226
240
|
name = chalk.hex('#' + bind.icon.color)(name);
|
|
227
241
|
}
|
|
228
242
|
const context = {
|
|
229
|
-
|
|
230
|
-
files: 0, directories: 0, current: 0, total: 0,
|
|
231
|
-
},
|
|
243
|
+
progress: { current: 0, directories: 0, files: 0, total: 0 },
|
|
232
244
|
fileInfoList: [],
|
|
233
245
|
stream,
|
|
234
246
|
message: '',
|
|
@@ -238,76 +250,61 @@ export async function actionScan() {
|
|
|
238
250
|
});
|
|
239
251
|
}),
|
|
240
252
|
};
|
|
241
|
-
const progress = new Listr([
|
|
242
|
-
{
|
|
243
|
-
title: `${name} ${chalk.hex('#73A7DE')(flags.filter)} ${cwd}`,
|
|
244
|
-
async task(context, task) {
|
|
245
|
-
return task.newListr([
|
|
246
|
-
{
|
|
247
|
-
title: 'Preparing',
|
|
248
|
-
async task() {
|
|
249
|
-
const { progress } = await context.reading;
|
|
250
|
-
Object.assign(context.count, progress);
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
title: 'Scanning',
|
|
255
|
-
async task() {
|
|
256
|
-
context.fileInfoList = await scan(context.stream, {
|
|
257
|
-
...optionsReal,
|
|
258
|
-
target: flags.target,
|
|
259
|
-
filter: flags.filter,
|
|
260
|
-
maxDepth: flags.depth,
|
|
261
|
-
});
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
|
-
{
|
|
265
|
-
title: 'Printing',
|
|
266
|
-
async task() {
|
|
267
|
-
const sorter = Sorting[flags.sort];
|
|
268
|
-
const cache = new Map();
|
|
269
|
-
if (flags.sort === 'modified') {
|
|
270
|
-
const { tree } = await context.reading;
|
|
271
|
-
await tree.deepModifiedTime(cache, optionsReal);
|
|
272
|
-
}
|
|
273
|
-
const time = Date.now() - start;
|
|
274
|
-
const fileInfoListSorted = context.fileInfoList.sort((a, b) => sorter(String(a), String(b), cache));
|
|
275
|
-
const files = formatFiles(fileInfoListSorted, {
|
|
276
|
-
chalk,
|
|
277
|
-
posix: flags.posix,
|
|
278
|
-
style: flags.style,
|
|
279
|
-
decor: flags.decor,
|
|
280
|
-
showSources: flags.showSources,
|
|
281
|
-
});
|
|
282
|
-
const fastSymbol = decorCondition(flags.decor, { ifEmoji: '⚡', ifNerd: icons['nf-md-lightning_bolt'].value });
|
|
283
|
-
const infoSymbol = decorCondition(flags.decor, { ifEmoji: 'ℹ️', ifNerd: icons['nf-seti-info'].value, postfix: ' ' });
|
|
284
|
-
let message = '';
|
|
285
|
-
message += files;
|
|
286
|
-
message += '\n';
|
|
287
|
-
message += `Done in ${time < 2000 ? chalk.yellow(fastSymbol) : ''}${stringTime(time, chalk)}.`;
|
|
288
|
-
message += '\n';
|
|
289
|
-
message += `Listed ${highlight(String(context.fileInfoList.length), chalk)} files.`;
|
|
290
|
-
message += '\n';
|
|
291
|
-
message += `Processed ${highlight(String(context.count.files), chalk)} files and ${highlight(String(context.count.directories), chalk)} directories.`;
|
|
292
|
-
message += '\n';
|
|
293
|
-
if (bind.testCommand) {
|
|
294
|
-
message += '\n';
|
|
295
|
-
message += `${chalk.blue(infoSymbol)}You can use ${highlight(`'${bind.testCommand}'`, chalk)} to check if the list is valid.`;
|
|
296
|
-
}
|
|
297
|
-
message += '\n';
|
|
298
|
-
context.message = message;
|
|
299
|
-
},
|
|
300
|
-
},
|
|
301
|
-
]);
|
|
302
|
-
},
|
|
303
|
-
},
|
|
304
|
-
], {
|
|
305
|
-
ctx: context,
|
|
306
|
-
exitOnError: true,
|
|
307
|
-
});
|
|
308
253
|
try {
|
|
309
254
|
context.stream.run();
|
|
310
|
-
|
|
255
|
+
console.log(`${name} ${chalk.hex('#73A7DE')(flags.filter)} ${cwd}`);
|
|
256
|
+
await oraPromise(async (spinner) => {
|
|
257
|
+
const proc = scan(context.stream, {
|
|
258
|
+
...optionsReal,
|
|
259
|
+
target: flags.target,
|
|
260
|
+
filter: flags.filter,
|
|
261
|
+
maxDepth: flags.depth,
|
|
262
|
+
});
|
|
263
|
+
context.stream.on('progress', (progress) => {
|
|
264
|
+
spinner.text = `Scanning ${progress.current}/${progress.total}`;
|
|
265
|
+
context.progress = progress;
|
|
266
|
+
});
|
|
267
|
+
context.fileInfoList = await proc;
|
|
268
|
+
}, 'Scanning');
|
|
269
|
+
const sorter = Sorting[flags.sort];
|
|
270
|
+
const cache = new Map();
|
|
271
|
+
if (flags.sort === 'modified') {
|
|
272
|
+
const { tree } = await context.reading;
|
|
273
|
+
await tree.deepModifiedTime(cache, optionsReal);
|
|
274
|
+
}
|
|
275
|
+
const time = Date.now() - start;
|
|
276
|
+
const fileInfoListSorted = context.fileInfoList.sort((a, b) => sorter(String(a), String(b), cache));
|
|
277
|
+
const files = formatFiles(fileInfoListSorted, {
|
|
278
|
+
chalk,
|
|
279
|
+
posix: flags.posix,
|
|
280
|
+
style: flags.style,
|
|
281
|
+
decor: flags.decor,
|
|
282
|
+
showSources: flags.showSources,
|
|
283
|
+
});
|
|
284
|
+
const fastSymbol = decorCondition(flags.decor, {
|
|
285
|
+
ifEmoji: '⚡',
|
|
286
|
+
ifNerd: icons['nf-md-lightning_bolt'].value,
|
|
287
|
+
});
|
|
288
|
+
const infoSymbol = decorCondition(flags.decor, {
|
|
289
|
+
ifEmoji: 'ℹ️',
|
|
290
|
+
ifNerd: icons['nf-seti-info'].value,
|
|
291
|
+
postfix: ' ',
|
|
292
|
+
});
|
|
293
|
+
let message = '';
|
|
294
|
+
message += files;
|
|
295
|
+
message += '\n';
|
|
296
|
+
message += `Done in ${time < 2000 ? chalk.yellow(fastSymbol) : ''}${stringTime(time, chalk)}.`;
|
|
297
|
+
message += '\n';
|
|
298
|
+
message += `Listed ${highlight(String(context.fileInfoList.length), chalk)} files.`;
|
|
299
|
+
message += '\n';
|
|
300
|
+
message += `Processed ${highlight(String(context.progress.files), chalk)} files and ${highlight(String(context.progress.directories), chalk)} directories.`;
|
|
301
|
+
message += '\n';
|
|
302
|
+
if (bind.testCommand) {
|
|
303
|
+
message += '\n';
|
|
304
|
+
message += `${chalk.blue(infoSymbol)}You can use ${highlight(`'${bind.testCommand}'`, chalk)} to check if the list is valid.`;
|
|
305
|
+
}
|
|
306
|
+
message += '\n';
|
|
307
|
+
context.message = message;
|
|
311
308
|
}
|
|
312
309
|
catch (error) {
|
|
313
310
|
if (!(error instanceof ViewIgnoredError)) {
|
|
@@ -341,7 +338,10 @@ export function actionCfgSet(pair, options) {
|
|
|
341
338
|
const chalk = new Chalk();
|
|
342
339
|
Config.configManager.save();
|
|
343
340
|
console.log(Config.configManager.getPairString(key, {
|
|
344
|
-
chalk,
|
|
341
|
+
chalk,
|
|
342
|
+
real: options.real,
|
|
343
|
+
types: options.types,
|
|
344
|
+
parsable: flags.parsable,
|
|
345
345
|
}));
|
|
346
346
|
}
|
|
347
347
|
/**
|
|
@@ -355,7 +355,10 @@ export function actionCfgUnset(key, options) {
|
|
|
355
355
|
const chalk = new Chalk();
|
|
356
356
|
Config.configManager.unset(key).save();
|
|
357
357
|
console.log(Config.configManager.getPairString(key, {
|
|
358
|
-
chalk,
|
|
358
|
+
chalk,
|
|
359
|
+
real: options.real,
|
|
360
|
+
types: options.types,
|
|
361
|
+
parsable: flags.parsable,
|
|
359
362
|
}));
|
|
360
363
|
}
|
|
361
364
|
/**
|
|
@@ -365,6 +368,9 @@ export function actionCfgGet(key, options) {
|
|
|
365
368
|
const flags = scanProgram.optsWithGlobals();
|
|
366
369
|
const chalk = new Chalk();
|
|
367
370
|
console.log(Config.configManager.getPairString(key, {
|
|
368
|
-
chalk,
|
|
371
|
+
chalk,
|
|
372
|
+
real: options.real,
|
|
373
|
+
types: options.types,
|
|
374
|
+
parsable: flags.parsable,
|
|
369
375
|
}));
|
|
370
376
|
}
|
package/out/config.d.ts
CHANGED
|
@@ -22,7 +22,10 @@ export declare function isShowSources(value: unknown): value is ShowSourcesType;
|
|
|
22
22
|
/**
|
|
23
23
|
* Represents array with the key nad the value.
|
|
24
24
|
*/
|
|
25
|
-
export type ConfigPair<KeyT extends ConfigKey = ConfigKey> = [
|
|
25
|
+
export type ConfigPair<KeyT extends ConfigKey = ConfigKey> = [
|
|
26
|
+
key: KeyT,
|
|
27
|
+
value: ConfigValue<KeyT>
|
|
28
|
+
];
|
|
26
29
|
/**
|
|
27
30
|
* Command-line configuration structure.
|
|
28
31
|
* @see {@link configKeyList} Before adding new properties.
|
package/out/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as os from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { existsSync, readFileSync, rmSync, writeFileSync
|
|
3
|
+
import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { format } from 'node:util';
|
|
5
5
|
import * as yaml from 'yaml';
|
|
6
6
|
import { decorNameList, highlight, styleNameList, } from './styling.js';
|
|
@@ -81,8 +81,24 @@ export const configValueLiteral = (choices) => {
|
|
|
81
81
|
validator.typeName = choices.map(choice => format('%o', choice)).join('|');
|
|
82
82
|
return validator;
|
|
83
83
|
};
|
|
84
|
-
export const switchTrueValues = [
|
|
85
|
-
|
|
84
|
+
export const switchTrueValues = [
|
|
85
|
+
'true',
|
|
86
|
+
'on',
|
|
87
|
+
'yes',
|
|
88
|
+
'y',
|
|
89
|
+
'enable',
|
|
90
|
+
'enabled',
|
|
91
|
+
'1',
|
|
92
|
+
];
|
|
93
|
+
export const switchFalseValues = [
|
|
94
|
+
'false',
|
|
95
|
+
'off',
|
|
96
|
+
'no',
|
|
97
|
+
'n',
|
|
98
|
+
'disable',
|
|
99
|
+
'disabled',
|
|
100
|
+
'0',
|
|
101
|
+
];
|
|
86
102
|
export const booleanValues = [...switchTrueValues, ...switchFalseValues];
|
|
87
103
|
export const configValueSwitch = () => {
|
|
88
104
|
const validator = (value) => {
|
|
@@ -136,7 +152,8 @@ export const configValueNumber = () => {
|
|
|
136
152
|
};
|
|
137
153
|
export const configValueInteger = () => {
|
|
138
154
|
const validator = (value) => {
|
|
139
|
-
if (typeof value === 'number'
|
|
155
|
+
if (typeof value === 'number'
|
|
156
|
+
&& (Number.isSafeInteger(value) || Math.abs(value) === Infinity)) {
|
|
140
157
|
return;
|
|
141
158
|
}
|
|
142
159
|
return 'The value should be an integer.';
|
|
@@ -242,7 +259,9 @@ export class ConfigManager {
|
|
|
242
259
|
* @returns The error message for each invalid property.
|
|
243
260
|
*/
|
|
244
261
|
load() {
|
|
245
|
-
const parsed = existsSync(this.path)
|
|
262
|
+
const parsed = existsSync(this.path)
|
|
263
|
+
? yaml.parse(readFileSync(this.path).toString())
|
|
264
|
+
: undefined;
|
|
246
265
|
if (parsed === undefined) {
|
|
247
266
|
return;
|
|
248
267
|
}
|
|
@@ -294,7 +313,9 @@ export class ConfigManager {
|
|
|
294
313
|
* @returns An array of properties which defined in the configuration file.
|
|
295
314
|
*/
|
|
296
315
|
keyList(real = true) {
|
|
297
|
-
const keys = real
|
|
316
|
+
const keys = real
|
|
317
|
+
? [...this.configValidation.keys()]
|
|
318
|
+
: Object.keys(this.data);
|
|
298
319
|
return keys;
|
|
299
320
|
}
|
|
300
321
|
get(key, options) {
|
|
@@ -332,8 +353,8 @@ export class ConfigManager {
|
|
|
332
353
|
const type = this.getType(key);
|
|
333
354
|
const pad = keyMaxLength - key.length;
|
|
334
355
|
const line = types
|
|
335
|
-
? format(`${' '.repeat(pad)}%s ${highlight('=', chalk)} %s${highlight(':', chalk)} %s`,
|
|
336
|
-
: format(`${' '.repeat(pad)}%s ${highlight('=', chalk)} %s`,
|
|
356
|
+
? format(`${' '.repeat(pad)}%s ${highlight('=', chalk)} %s${highlight(':', chalk)} %s`, chalk ? chalk.hex('#FFBC42')(key) : key, chalk ? highlight(value, chalk) : value, chalk ? chalk.dim(highlight(type, chalk)) : type)
|
|
357
|
+
: format(`${' '.repeat(pad)}%s ${highlight('=', chalk)} %s`, chalk ? chalk.hex('#FFBC42')(key) : key, chalk ? highlight(value, chalk) : value);
|
|
337
358
|
return line;
|
|
338
359
|
}).join('\n');
|
|
339
360
|
}
|
package/package.json
CHANGED
|
@@ -1,115 +1,115 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
2
|
+
"name": "view-ignored",
|
|
3
|
+
"version": "0.4.4",
|
|
4
|
+
"description": "Retrieve list of files ignored/included by Git, NPM, Yarn, JSR, VSCE or other tools.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"viewig": "./bin/viewig",
|
|
8
|
+
"view-ignored": "./bin/viewig"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"prerelease": "bun run build:pub && bun run lint",
|
|
12
|
+
"test": "bun run node --test out/**/*.test.js",
|
|
13
|
+
"build": "bun run build:clean && bun run tsc -p src",
|
|
14
|
+
"build:pub": "bun run build:clean && bun run tsc -p src --sourceMap false && rm **/*.test.d.ts",
|
|
15
|
+
"build:watch": "bun run build:clean && bun run tsc -p src --watch",
|
|
16
|
+
"build:clean": "rm -rf out",
|
|
17
|
+
"lint": "bun run eslint .",
|
|
18
|
+
"release:major": "bun run release-it --increment=major",
|
|
19
|
+
"release:minor": "bun run release-it --increment=minor",
|
|
20
|
+
"release:patch": "bun run release-it --increment=patch"
|
|
21
|
+
},
|
|
22
|
+
"author": "Mopsgamer",
|
|
23
|
+
"license": "ISC",
|
|
24
|
+
"main": "./out/src/index.js",
|
|
25
|
+
"files": [
|
|
26
|
+
"/bin",
|
|
27
|
+
"/out",
|
|
28
|
+
"!**/*.test.js"
|
|
29
|
+
],
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/Mopsgamer/view-ignored.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/Mopsgamer/view-ignored/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/Mopsgamer/view-ignored",
|
|
38
|
+
"exports": {
|
|
39
|
+
".": {
|
|
40
|
+
"default": "./out/index.js",
|
|
41
|
+
"types": "./out/index.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"./browser": {
|
|
44
|
+
"default": "./out/browser/index.js",
|
|
45
|
+
"types": "./out/browser/index.d.ts"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"release-it": {
|
|
49
|
+
"hooks": {
|
|
50
|
+
"before:init": "bun prerelease"
|
|
51
|
+
},
|
|
52
|
+
"plugins": {
|
|
53
|
+
"@release-it/keep-a-changelog": {
|
|
54
|
+
"filename": "CHANGELOG.md"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"github": {
|
|
58
|
+
"release": true,
|
|
59
|
+
"draft": false,
|
|
60
|
+
"releaseName": "${version}"
|
|
61
|
+
},
|
|
62
|
+
"npm": {
|
|
63
|
+
"publish": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"directories": {
|
|
70
|
+
"lib": "out"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
|
|
74
|
+
"@m234/nerd-fonts": "^0.3.1",
|
|
75
|
+
"ansi-regex": "^6.1.0",
|
|
76
|
+
"boxen": "^8.0.1",
|
|
77
|
+
"chalk": "^5.4.1",
|
|
78
|
+
"commander": "^14.0.0",
|
|
79
|
+
"jsonify-paths": "^1.1.0",
|
|
80
|
+
"load-plugin": "^6.0.3",
|
|
81
|
+
"minimatch": "^10.0.3",
|
|
82
|
+
"ora": "^8.2.0",
|
|
83
|
+
"p-limit": "^6.2.0",
|
|
84
|
+
"treeify": "^1.1.0",
|
|
85
|
+
"yaml": "^2.8.0",
|
|
86
|
+
"zod": "^3.25.75"
|
|
87
|
+
},
|
|
88
|
+
"devDependencies": {
|
|
89
|
+
"@eslint/js": "^9.30.1",
|
|
90
|
+
"@release-it/keep-a-changelog": "^7.0.0",
|
|
91
|
+
"@stylistic/eslint-plugin": "^5.1.0",
|
|
92
|
+
"@types/node": "^24.0.10",
|
|
93
|
+
"@types/treeify": "^1.0.3",
|
|
94
|
+
"eslint": "^9.30.1",
|
|
95
|
+
"fs-fixture": "^2.8.1",
|
|
96
|
+
"globals": "^16.3.0",
|
|
97
|
+
"release-it": "^19.0.3",
|
|
98
|
+
"typescript": "^5.8.3",
|
|
99
|
+
"typescript-eslint": "^8.36.0"
|
|
100
|
+
},
|
|
101
|
+
"keywords": [
|
|
102
|
+
"tree",
|
|
103
|
+
"ls-tree",
|
|
104
|
+
"ignore",
|
|
105
|
+
"gitignore",
|
|
106
|
+
"npmignore",
|
|
107
|
+
"vscodeignore",
|
|
108
|
+
"cli",
|
|
109
|
+
"fs",
|
|
110
|
+
"file-system",
|
|
111
|
+
"output",
|
|
112
|
+
"project",
|
|
113
|
+
"migration"
|
|
114
|
+
]
|
|
115
115
|
}
|