244 lines
5.7 KiB
JavaScript
Raw Normal View History

2025-02-17 15:13:47 +01:00
import path from 'path';
import inquirer from 'inquirer';
import boxen from 'boxen';
import chalk from 'chalk';
import fs from 'fs';
2025-02-20 09:23:18 +01:00
import { filesystemSync } from 'fs-filesystem';
2025-02-17 15:13:47 +01:00
function showMsg(msg) {
console.log(boxen(chalk.white(msg), {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'white',
titleAlignment: 'center'
}));
}
2025-02-20 10:04:58 +01:00
function getAvailableRoots() {
const devices = filesystemSync();
var mountPoints = [];
Object.keys(devices).forEach(function(key) {
var val = devices[key];
val.volumes.forEach(function(volume) {
mountPoints.push(volume.mountPoint);
});
});
if (mountPoints.length < 1) {
throw new Error("Failed to detect file system devices.");
}
return mountPoints;
}
2025-02-20 09:23:18 +01:00
2025-02-17 15:13:47 +01:00
function splitPath(str) {
return str.replaceAll("\\", "/").split("/");
}
2025-02-19 14:56:22 +01:00
function dropEmptyParts(parts) {
var result = [];
parts.forEach(function(part) {
if (part.length > 0) {
result.push(part);
}
})
return result;
}
function combine(parts) {
const toJoin = dropEmptyParts(parts);
if (toJoin.length == 1) return toJoin[0];
return path.join(...toJoin);
}
function combineWith(parts, extra) {
const toJoin = dropEmptyParts(parts);
if (toJoin.length == 1) return path.join(toJoin[0], extra);
return path.join(...toJoin, extra);
}
2025-02-17 15:13:47 +01:00
function showCurrent(currentPath) {
const len = currentPath.length;
2025-02-19 14:56:22 +01:00
showMsg(`Current path: [${len}]\n` + combine(currentPath));
2025-02-20 09:23:18 +01:00
if (len < 2) {
showMsg(
'Warning - Known issue:\n' +
'Path selection does not work in root paths on some platforms.\n' +
'Use "Enter path" or "Create new folder" to navigate and create folders\n' +
'if this is the case for you.'
);
}
2025-02-17 15:13:47 +01:00
}
2025-02-20 10:04:58 +01:00
function hasValidRoot(roots, checkPath) {
if (checkPath.length < 1) return false;
var result = false;
roots.forEach(function(root) {
if (root.toLowerCase() == checkPath[0].toLowerCase()) {
console.log("valid root: " + combine(checkPath));
result = true;
}
});
if (!result) console.log("invalid root: " + combine(checkPath));
return result;
}
2025-02-17 15:13:47 +01:00
async function showMain(currentPath) {
showCurrent(currentPath);
const { choice } = await inquirer.prompt([
{
type: 'list',
name: 'choice',
message: 'Select an option:',
choices: [
'1. Enter path',
'2. Go up one',
'3. Go down one',
2025-02-19 14:56:22 +01:00
'4. Create new folder here',
'5. Select this path',
'6. Cancel'
2025-02-17 15:13:47 +01:00
],
pageSize: 6,
loop: true
}
]).catch(() => {
handleExit();
return { choice: '6' };
});
return choice;
}
2025-02-19 14:56:22 +01:00
export async function showPathSelector(startingPath, pathMustExist) {
2025-02-20 10:04:58 +01:00
const roots = getAvailableRoots();
2025-02-19 14:56:22 +01:00
var currentPath = splitPath(startingPath);
2025-02-20 10:04:58 +01:00
if (!hasValidRoot(roots, currentPath)) {
currentPath = [roots[0]];
}
2025-02-17 15:13:47 +01:00
while (true) {
const choice = await showMain(currentPath);
2025-02-20 10:04:58 +01:00
var newCurrentPath = currentPath;
2025-02-17 15:13:47 +01:00
switch (choice.split('.')[0]) {
case '1':
2025-02-20 10:04:58 +01:00
newCurrentPath = await enterPath(currentPath, pathMustExist);
2025-02-17 15:13:47 +01:00
break;
case '2':
2025-02-20 10:04:58 +01:00
newCurrentPath = upOne(currentPath);
2025-02-17 15:13:47 +01:00
break;
case '3':
2025-02-20 10:04:58 +01:00
newCurrentPath = await downOne(currentPath);
2025-02-17 15:13:47 +01:00
break;
case '4':
2025-02-20 10:04:58 +01:00
newCurrentPath = await createSubDir(currentPath, pathMustExist);
2025-02-17 15:13:47 +01:00
break;
case '5':
2025-02-19 14:56:22 +01:00
if (pathMustExist && !isDir(combine(currentPath))) {
2025-02-17 15:13:47 +01:00
console.log("Current path does not exist.");
2025-02-19 14:56:22 +01:00
break;
2025-02-17 15:13:47 +01:00
} else {
2025-02-19 14:56:22 +01:00
return combine(currentPath);
2025-02-17 15:13:47 +01:00
}
2025-02-19 14:56:22 +01:00
case '6':
return combine(currentPath);
2025-02-17 15:13:47 +01:00
}
2025-02-20 10:04:58 +01:00
if (hasValidRoot(roots, newCurrentPath)) {
currentPath = newCurrentPath;
} else {
console.log("Selected path has no valid root.");
}
2025-02-17 15:13:47 +01:00
}
}
2025-02-19 14:56:22 +01:00
async function enterPath(currentPath, pathMustExist) {
2025-02-17 15:13:47 +01:00
const response = await inquirer.prompt([
{
type: 'input',
name: 'path',
message: 'Enter Path:'
}]);
2025-02-19 14:56:22 +01:00
const newPath = response.path;
if (pathMustExist && !isDir(newPath)) {
console.log("The entered path does not exist.");
return currentPath;
}
2025-02-17 15:13:47 +01:00
return splitPath(response.path);
}
function upOne(currentPath) {
return currentPath.slice(0, currentPath.length - 1);
}
2025-02-19 14:56:22 +01:00
export function isDir(dir) {
try {
return fs.lstatSync(dir).isDirectory();
} catch {
return false;
}
2025-02-17 15:13:47 +01:00
}
function isSubDir(currentPath, entry) {
2025-02-19 14:56:22 +01:00
const newPath = combineWith(currentPath, entry);
2025-02-17 15:13:47 +01:00
return isDir(newPath);
}
function getSubDirOptions(currentPath) {
2025-02-19 14:56:22 +01:00
const fullPath = combine(currentPath);
const entries = fs.readdirSync(fullPath);
2025-02-17 15:13:47 +01:00
var result = [];
var counter = 1;
entries.forEach(function(entry) {
if (isSubDir(currentPath, entry)) {
2025-02-20 10:04:58 +01:00
result.push(counter + '. ' + entry);
counter = counter + 1;
2025-02-17 15:13:47 +01:00
}
});
return result;
}
async function downOne(currentPath) {
const options = getSubDirOptions(currentPath);
if (options.length == 0) {
console.log("There are no subdirectories here.");
return currentPath;
}
const { choice } = await inquirer.prompt([
{
type: 'list',
name: 'choice',
message: 'Select an subdir:',
choices: options,
pageSize: options.length,
loop: true
}
]).catch(() => {
return currentPath;
});
2025-02-20 10:04:58 +01:00
const subDir = choice.split('. ')[1];
2025-02-17 15:13:47 +01:00
return [...currentPath, subDir];
}
2025-02-19 14:56:22 +01:00
async function createSubDir(currentPath, pathMustExist) {
2025-02-17 15:13:47 +01:00
const response = await inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Enter name:'
}]);
const name = response.name;
if (name.length < 1) return;
2025-02-19 14:56:22 +01:00
const fullDir = combineWith(currentPath, name);
if (pathMustExist && !isDir(fullDir)) {
fs.mkdirSync(fullDir);
}
2025-02-17 15:13:47 +01:00
return [...currentPath, name];
}