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 09:23:18 +01:00
|
|
|
// function getAvailableRoots() {
|
|
|
|
|
// const platform = os.platform();
|
|
|
|
|
// if (platform === 'win32') {
|
|
|
|
|
// const result = await runCommand('for /f "delims=" %a in (\'curl -s --ssl-reqd ip.codex.storage\') do @echo %a');
|
|
|
|
|
// nat = result.trim();
|
|
|
|
|
// } else {
|
|
|
|
|
// nat = await runCommand('curl -s https://ip.codex.storage');
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
var currentPath = splitPath(startingPath);
|
2025-02-17 15:13:47 +01:00
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
const choice = await showMain(currentPath);
|
|
|
|
|
|
|
|
|
|
switch (choice.split('.')[0]) {
|
|
|
|
|
case '1':
|
2025-02-19 14:56:22 +01:00
|
|
|
currentPath = await enterPath(currentPath, pathMustExist);
|
2025-02-17 15:13:47 +01:00
|
|
|
break;
|
|
|
|
|
case '2':
|
|
|
|
|
currentPath = upOne(currentPath);
|
|
|
|
|
break;
|
|
|
|
|
case '3':
|
|
|
|
|
currentPath = await downOne(currentPath);
|
|
|
|
|
break;
|
|
|
|
|
case '4':
|
2025-02-19 14:56:22 +01:00
|
|
|
currentPath = 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-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);
|
|
|
|
|
currentPath.forEach(function(part) {
|
|
|
|
|
console.log("part: '" + part + "'");
|
|
|
|
|
});
|
|
|
|
|
console.log("current: '" + fullPath + "'");
|
|
|
|
|
const entries = fs.readdirSync(fullPath);
|
2025-02-17 15:13:47 +01:00
|
|
|
var result = [];
|
|
|
|
|
var counter = 1;
|
|
|
|
|
entries.forEach(function(entry) {
|
2025-02-19 14:56:22 +01:00
|
|
|
console.log("entry: " + entry);
|
2025-02-17 15:13:47 +01:00
|
|
|
if (isSubDir(currentPath, entry)) {
|
|
|
|
|
result.push(counter + ". " + entry);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
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;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const subDir = choice.slice(3);
|
|
|
|
|
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];
|
|
|
|
|
}
|