-
Notifications
You must be signed in to change notification settings - Fork 0
/
nav.js
116 lines (103 loc) · 3.52 KB
/
nav.js
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
115
116
const fs = require('fs');
const inquirer = require('inquirer');
const path = require('path');
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'));
// show files (non directories)
let showFiles = false;
// show hidden files and directories
let showHidden = false;
// exit process gracefully when receiving a SIGINT event
process.on('SIGINT', function() {
process.exit();
});
// exit process gracefully when pressing the ESC key
process.stdin.on('keypress', function (chunk, key) {
if (key.name === 'escape') {
process.exit();
}
});
// update the cwd file, holding the absolute path of the current working directory
function updateCurrentWorkingDirectory() {
fs.writeFileSync(path.join(__dirname, 'cwd'), process.cwd());
}
// prefix the choice with an icon, depending of its type (file or directory)
function iconize(choice) {
const isDirectory = fs.lstatSync(path.join(process.cwd(), choice)).isDirectory();
return `${isDirectory ? '📂' : '📄'} ${choice}`;
}
// remove the icon prefix from the choice
function deiconize(choice) {
return choice.substr(3);
}
// gets the choices for the supported commands, given the current configuration
function getCommandChoices(input) {
return [
showFiles ? '/hideFiles' : '/showFiles',
showHidden ? '/hideHidden' : '/showHidden',
].filter(choice => choice.includes(input));
}
// gets the choices for the available navigation options, given the current working directory
function getNavigationChoices(input) {
// the available choices include the parent directory (..) and the children of the current working directory
let choices = ['..'].concat(fs.readdirSync(process.cwd()));
if (!showFiles) {
// filter choices to have only directories
choices = choices.filter(choice => fs.lstatSync(path.join(process.cwd(), choice)).isDirectory());
}
if (!showHidden) {
// filter choices to have only non hidden files and directories
choices = choices.filter(choice => choice === '..' || !choice.startsWith('.'));
}
return choices.filter(choice => choice.includes(input)).map(choice => iconize(choice));
}
// provides the choice list that should be shown to the user, depending on the current input
function getPromptSource(answers, input) {
input = input || '';
return Promise.resolve(input.startsWith('/') ? getCommandChoices(input) : getNavigationChoices(input));
}
// handle the provided answer
function handleAnswer(value) {
// switch through the supported commands
switch (value) {
case '/hideFiles':
showFiles = false;
return;
case '/showFiles':
showFiles = true;
return;
case '/hideHidden':
showHidden = false;
return;
case '/showHidden':
showHidden = true;
return;
}
// the answer is not a command
const absolutePath = path.join(process.cwd(), deiconize(value));
if (fs.lstatSync(absolutePath).isDirectory()) {
// trigger the directory change
process.chdir(deiconize(value));
} else {
// log the file absolute path
console.log(absolutePath);
}
}
// trigger a prompt that allows the user to change the current working directory or issue a command
function prompt() {
// persist the current working directory
updateCurrentWorkingDirectory();
inquirer.prompt([{
type: 'autocomplete',
name: 'value',
message: process.cwd(),
pageSize: 20,
source: getPromptSource,
}]).then((answer) => {
// handle the answer appropriately
handleAnswer(answer.value);
// relaunch the prompt
prompt();
});
}
// launch the prompt
prompt();