252 lines
5.8 KiB
JavaScript
Raw Normal View History

2025-02-25 13:59:26 +01:00
import path from "path";
import inquirer from "inquirer";
import boxen from "boxen";
import chalk from "chalk";
import fs from "fs";
import { filesystemSync } from "fs-filesystem";
2025-02-17 15:13:47 +01:00
function showMsg(msg) {
2025-02-25 13:59:26 +01:00
console.log(
boxen(chalk.white(msg), {
padding: 1,
margin: 1,
borderStyle: "round",
borderColor: "white",
titleAlignment: "center",
}),
);
2025-02-17 15:13:47 +01:00
}
2025-02-20 10:04:58 +01:00
function getAvailableRoots() {
const devices = filesystemSync();
var mountPoints = [];
2025-02-25 13:59:26 +01:00
Object.keys(devices).forEach(function (key) {
var val = devices[key];
val.volumes.forEach(function (volume) {
mountPoints.push(volume.mountPoint);
2025-02-20 10:04:58 +01:00
});
2025-02-25 13:59:26 +01:00
});
2025-02-20 10:04:58 +01:00
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 = [];
2025-02-25 13:59:26 +01:00
parts.forEach(function (part) {
2025-02-19 14:56:22 +01:00
if (part.length > 0) {
result.push(part);
}
2025-02-25 13:59:26 +01:00
});
2025-02-19 14:56:22 +01:00
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(
2025-02-25 13:59:26 +01:00
"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-20 09:23:18 +01:00
);
}
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;
2025-02-25 13:59:26 +01:00
roots.forEach(function (root) {
2025-02-20 10:04:58 +01:00
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);
2025-02-25 13:59:26 +01:00
const { choice } = await inquirer
.prompt([
{
type: "list",
name: "choice",
message: "Select an option:",
2025-02-17 15:13:47 +01:00
choices: [
2025-02-25 13:59:26 +01:00
"1. Enter path",
"2. Go up one",
"3. Go down one",
"4. Create new folder here",
"5. Select this path",
"6. Cancel",
2025-02-17 15:13:47 +01:00
],
pageSize: 6,
2025-02-25 13:59:26 +01:00
loop: true,
},
])
.catch(() => {
handleExit();
return { choice: "6" };
});
2025-02-17 15:13:47 +01:00
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-25 13:59:26 +01:00
switch (choice.split(".")[0]) {
case "1":
newCurrentPath = await enterPath(currentPath, pathMustExist);
break;
case "2":
newCurrentPath = upOne(currentPath);
break;
case "3":
newCurrentPath = await downOne(currentPath);
break;
case "4":
newCurrentPath = await createSubDir(currentPath, pathMustExist);
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-25 13:59:26 +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([
{
2025-02-25 13:59:26 +01:00
type: "input",
name: "path",
message: "Enter Path:",
},
]);
2025-02-17 15:13:47 +01:00
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;
2025-02-25 13:59:26 +01:00
entries.forEach(function (entry) {
2025-02-17 15:13:47 +01:00
if (isSubDir(currentPath, entry)) {
2025-02-25 13:59:26 +01:00
result.push(counter + ". " + entry);
2025-02-20 10:04:58 +01:00
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;
}
2025-02-25 13:59:26 +01:00
const { choice } = await inquirer
.prompt([
{
type: "list",
name: "choice",
message: "Select an subdir:",
2025-02-17 15:13:47 +01:00
choices: options,
pageSize: options.length,
2025-02-25 13:59:26 +01:00
loop: true,
},
])
.catch(() => {
return currentPath;
});
2025-02-17 15:13:47 +01:00
2025-02-25 13:59:26 +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([
{
2025-02-25 13:59:26 +01:00
type: "input",
name: "name",
message: "Enter name:",
},
]);
2025-02-17 15:13:47 +01:00
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];
}