mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-01-11 07:47:33 +01:00
Add simple glob support to nano/vim usage
This commit is contained in:
parent
d8a5f5b03c
commit
74ba063772
@ -1,9 +1,12 @@
|
||||
import { ITerminal } from "../../ITerminal";
|
||||
import { removeLeadingSlash, removeTrailingSlash } from '../../DirectoryHelpers'
|
||||
import { IRouter, ScriptEditorRouteOptions } from "../../../ui/Router";
|
||||
import { IPlayer } from "../../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../../Script/isScriptFilename";
|
||||
import { CursorPositions } from "../../../ScriptEditor/CursorPositions";
|
||||
import { Script } from "../../../Script/Script";
|
||||
import { isEmpty } from "lodash";
|
||||
|
||||
interface EditorParameters {
|
||||
terminal: ITerminal;
|
||||
@ -22,6 +25,74 @@ export async function main(ns) {
|
||||
|
||||
}`;
|
||||
|
||||
interface ISimpleScriptGlob {
|
||||
glob: string;
|
||||
preGlob: string;
|
||||
postGlob: string;
|
||||
globError: string;
|
||||
globMatches: string[];
|
||||
globAgainst: Script[];
|
||||
}
|
||||
|
||||
function containsSimpleGlob(filename: string): boolean {
|
||||
return filename.includes("*");
|
||||
}
|
||||
|
||||
function detectSimpleScriptGlob(
|
||||
args: EditorParameters["args"],
|
||||
player: IPlayer,
|
||||
terminal: ITerminal,
|
||||
): ISimpleScriptGlob | null {
|
||||
if (args.length == 1 && containsSimpleGlob(`${args[0]}`)) {
|
||||
const filename = `${args[0]}`;
|
||||
const scripts = player.getCurrentServer().scripts;
|
||||
const parsedGlob = parseSimpleScriptGlob(filename, scripts, terminal);
|
||||
return parsedGlob;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseSimpleScriptGlob(globString: string, globDatabase: Script[], terminal: ITerminal): ISimpleScriptGlob {
|
||||
const parsedGlob: ISimpleScriptGlob = {
|
||||
glob: globString,
|
||||
preGlob: "",
|
||||
postGlob: "",
|
||||
globError: "",
|
||||
globMatches: [],
|
||||
globAgainst: globDatabase,
|
||||
};
|
||||
|
||||
// Ensure deep globs are minified to simple globs, which act as deep globs in this impl
|
||||
globString = globString.replace("**", "*");
|
||||
|
||||
// Ensure only a single glob is present
|
||||
if (globString.split("").filter((c) => c == "*").length !== 1) {
|
||||
parsedGlob.globError = "Only a single glob is supported per command.\nexample: `nano my-dir/*.js`";
|
||||
return parsedGlob;
|
||||
}
|
||||
|
||||
// Split arg around glob, normalize preGlob path
|
||||
[parsedGlob.preGlob, parsedGlob.postGlob] = globString.split("*");
|
||||
parsedGlob.preGlob = removeLeadingSlash(parsedGlob.preGlob);
|
||||
|
||||
// Add CWD to preGlob path
|
||||
const cwd = removeTrailingSlash(terminal.cwd())
|
||||
parsedGlob.preGlob = `${cwd}/${parsedGlob.preGlob}`
|
||||
|
||||
// For every script on the current server, filter matched scripts per glob values & persist
|
||||
globDatabase.forEach((script) => {
|
||||
const filename = script.filename.startsWith('/') ? script.filename : `/${script.filename}`
|
||||
if (filename.startsWith(parsedGlob.preGlob) && filename.endsWith(parsedGlob.postGlob)) {
|
||||
parsedGlob.globMatches.push(filename);
|
||||
}
|
||||
});
|
||||
|
||||
// Rebuild glob for potential error reporting
|
||||
parsedGlob.glob = `${parsedGlob.preGlob}*${parsedGlob.postGlob}`
|
||||
|
||||
return parsedGlob;
|
||||
}
|
||||
|
||||
export function commonEditor(
|
||||
command: string,
|
||||
{ terminal, router, player, args }: EditorParameters,
|
||||
@ -32,8 +103,15 @@ export function commonEditor(
|
||||
return;
|
||||
}
|
||||
|
||||
let filesToLoadOrCreate = args;
|
||||
try {
|
||||
const files = args.map((arg) => {
|
||||
const globSearch = detectSimpleScriptGlob(args, player, terminal);
|
||||
if (globSearch) {
|
||||
if (isEmpty(globSearch.globError) === false) throw new Error(globSearch.globError);
|
||||
filesToLoadOrCreate = globSearch.globMatches;
|
||||
}
|
||||
|
||||
const files = filesToLoadOrCreate.map((arg) => {
|
||||
const filename = `${arg}`;
|
||||
|
||||
if (isScriptFilename(filename)) {
|
||||
@ -55,12 +133,18 @@ export function commonEditor(
|
||||
if (filename.endsWith(".txt")) {
|
||||
const filepath = terminal.getFilepath(filename);
|
||||
const txt = terminal.getTextFile(player, filename);
|
||||
return [filepath, txt == null ? "" : txt.text];
|
||||
return [filepath, txt === null ? "" : txt.text];
|
||||
}
|
||||
|
||||
throw new Error(`Invalid file. Only scripts (.script, .ns, .js), or text files (.txt) can be edited with ${command}`);
|
||||
throw new Error(
|
||||
`Invalid file. Only scripts (.script, .ns, .js), or text files (.txt) can be edited with ${command}`,
|
||||
);
|
||||
});
|
||||
|
||||
if (globSearch && files.length === 0) {
|
||||
throw new Error(`Could not find any valid files to open with ${command} using glob: \`${globSearch.glob}\``)
|
||||
}
|
||||
|
||||
router.toScriptEditor(Object.fromEntries(files), scriptEditorRouteOptions);
|
||||
} catch (e) {
|
||||
terminal.error(`${e}`);
|
||||
|
Loading…
Reference in New Issue
Block a user