feat: Add vim terminal command

This commit is contained in:
Billy Vong 2021-12-17 12:48:34 -05:00
parent 009bae5870
commit d30edc7f59
9 changed files with 107 additions and 48 deletions

@ -44,7 +44,7 @@ interface IProps {
hostname: string; hostname: string;
player: IPlayer; player: IPlayer;
router: IRouter; router: IRouter;
vim?: boolean; vim: boolean;
} }
// TODO: try to removve global symbols // TODO: try to removve global symbols

@ -40,6 +40,7 @@ export const TerminalHelpText: string[] = [
"tail [script] [args...] Displays dynamic logs for the specified script", "tail [script] [args...] Displays dynamic logs for the specified script",
"top Displays all running scripts and their RAM usage", "top Displays all running scripts and their RAM usage",
"unalias [alias name] Deletes the specified alias", "unalias [alias name] Deletes the specified alias",
"vim [file] Text editor - Open up and edit a script or text file in vim mode",
"weaken [server] Reduce the security of a server", "weaken [server] Reduce the security of a server",
"wget [url] [target file] Retrieves code/text from a web server", "wget [url] [target file] Retrieves code/text from a web server",
]; ];
@ -402,6 +403,13 @@ export const HelpTexts: IMap<string[]> = {
" ", " ",
"It is not necessary to differentiate between global and non-global aliases when using 'unalias'", "It is not necessary to differentiate between global and non-global aliases when using 'unalias'",
], ],
vim: [
"vim [file name]",
" ",
"Opens up the specified file in the Text Editor in vim mode. Only scripts (.script) or text files (.txt) can be ",
"edited using the Text Editor. If the file does not already exist, then a new, empty one ",
"will be created",
],
weaken: [ weaken: [
"weaken", "weaken",
"", "",

@ -67,6 +67,7 @@ import { sudov } from "./commands/sudov";
import { tail } from "./commands/tail"; import { tail } from "./commands/tail";
import { top } from "./commands/top"; import { top } from "./commands/top";
import { unalias } from "./commands/unalias"; import { unalias } from "./commands/unalias";
import { vim } from "./commands/vim";
import { weaken } from "./commands/weaken"; import { weaken } from "./commands/weaken";
import { wget } from "./commands/wget"; import { wget } from "./commands/wget";
import { hash } from "../hash/hash"; import { hash } from "../hash/hash";
@ -789,6 +790,7 @@ export class Terminal implements ITerminal {
tail: tail, tail: tail,
top: top, top: top,
unalias: unalias, unalias: unalias,
vim: vim,
weaken: weaken, weaken: weaken,
wget: wget, wget: wget,
}; };

@ -0,0 +1,65 @@
import { ITerminal } from "../../ITerminal";
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";
interface EditorParameters {
terminal: ITerminal;
router: IRouter;
player: IPlayer;
server: BaseServer;
args: (string | number | boolean)[];
}
export function commonEditor(command: string, {
terminal,
router,
player,
server,
args,
}: EditorParameters, scriptEditorRouteOptions?: ScriptEditorRouteOptions): void {
if (args.length !== 1) {
terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`);
return;
}
try {
const filename = args[0] + "";
if (isScriptFilename(filename)) {
const filepath = terminal.getFilepath(filename);
const script = terminal.getScript(player, filename);
if (script == null) {
let code = "";
if (filename.endsWith(".ns") || filename.endsWith(".js")) {
code = `/** @param {NS} ns **/
export async function main(ns) {
}`;
}
CursorPositions.saveCursor(filename, {
row: 3,
column: 5,
});
router.toScriptEditor(filepath, code, scriptEditorRouteOptions);
} else {
router.toScriptEditor(filepath, script.code, scriptEditorRouteOptions);
}
} else if (filename.endsWith(".txt")) {
const filepath = terminal.getFilepath(filename);
const txt = terminal.getTextFile(player, filename);
if (txt == null) {
router.toScriptEditor(filepath, "", scriptEditorRouteOptions);
} else {
router.toScriptEditor(filepath, txt.text, scriptEditorRouteOptions);
}
} else {
terminal.error("Invalid file. Only scripts (.script, .ns, .js), or text files (.txt) can be edited with vim");
return;
}
} catch (e) {
terminal.error(e + "");
}
}

@ -2,8 +2,8 @@ import { ITerminal } from "../ITerminal";
import { IRouter } from "../../ui/Router"; import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
import { isScriptFilename } from "../../Script/isScriptFilename";
import { CursorPositions } from "../../ScriptEditor/CursorPositions"; import {commonEditor} from './common/editor';
export function nano( export function nano(
terminal: ITerminal, terminal: ITerminal,
@ -12,45 +12,5 @@ export function nano(
server: BaseServer, server: BaseServer,
args: (string | number | boolean)[], args: (string | number | boolean)[],
): void { ): void {
if (args.length !== 1) { return commonEditor('nano', {terminal, router, player, server, args});
terminal.error("Incorrect usage of nano command. Usage: nano [scriptname]");
return;
}
try {
const filename = args[0] + "";
if (isScriptFilename(filename)) {
const filepath = terminal.getFilepath(filename);
const script = terminal.getScript(player, filename);
if (script == null) {
let code = "";
if (filename.endsWith(".ns") || filename.endsWith(".js")) {
code = `/** @param {NS} ns **/
export async function main(ns) {
}`;
}
CursorPositions.saveCursor(filename, {
row: 3,
column: 5,
});
router.toScriptEditor(filepath, code);
} else {
router.toScriptEditor(filepath, script.code);
}
} else if (filename.endsWith(".txt")) {
const filepath = terminal.getFilepath(filename);
const txt = terminal.getTextFile(player, filename);
if (txt == null) {
router.toScriptEditor(filepath);
} else {
router.toScriptEditor(filepath, txt.text);
}
} else {
terminal.error("Invalid file. Only scripts (.script, .ns, .js), or text files (.txt) can be edited with nano");
return;
}
} catch (e) {
terminal.error(e + "");
}
} }

@ -0,0 +1,16 @@
import { ITerminal } from "../ITerminal";
import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { BaseServer } from "../../Server/BaseServer";
import {commonEditor} from './common/editor';
export function vim(
terminal: ITerminal,
router: IRouter,
player: IPlayer,
server: BaseServer,
args: (string | number | boolean)[],
): void {
return commonEditor('vim', {terminal, router, player, server, args}, {vim: true});
}

@ -49,6 +49,7 @@ const commands = [
"tail", "tail",
"theme", "theme",
"top", "top",
"vim",
"weaken", "weaken",
]; ];
@ -265,7 +266,7 @@ export async function determineAllPossibilitiesForTabCompletion(
return allPos; return allPos;
} }
if (isCommand("nano")) { if (isCommand("nano") || isCommand("vim")) {
addAllScripts(); addAllScripts();
addAllTextFiles(); addAllTextFiles();
addAllDirectories(); addAllDirectories();

@ -33,7 +33,7 @@ import createStyles from "@mui/styles/createStyles";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { Page, IRouter } from "./Router"; import { Page, IRouter, ScriptEditorRouteOptions } from "./Router";
import { Overview } from "./React/Overview"; import { Overview } from "./React/Overview";
import { SidebarRoot } from "../Sidebar/ui/SidebarRoot"; import { SidebarRoot } from "../Sidebar/ui/SidebarRoot";
import { AugmentationsRoot } from "../Augmentation/ui/AugmentationsRoot"; import { AugmentationsRoot } from "../Augmentation/ui/AugmentationsRoot";
@ -97,6 +97,7 @@ const useStyles = makeStyles((theme: Theme) =>
let filename = ""; let filename = "";
let code = ""; let code = "";
let vim = false;
export let Router: IRouter = { export let Router: IRouter = {
page: () => { page: () => {
@ -246,9 +247,10 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
toHacknetNodes: () => setPage(Page.Hacknet), toHacknetNodes: () => setPage(Page.Hacknet),
toMilestones: () => setPage(Page.Milestones), toMilestones: () => setPage(Page.Milestones),
toResleeves: () => setPage(Page.Resleeves), toResleeves: () => setPage(Page.Resleeves),
toScriptEditor: (fn: string, c: string) => { toScriptEditor: (fn: string, c: string, options?: ScriptEditorRouteOptions) => {
filename = fn; filename = fn;
code = c; code = c;
vim = !!options?.vim;
setPage(Page.ScriptEditor); setPage(Page.ScriptEditor);
}, },
toSleeves: () => setPage(Page.Sleeves), toSleeves: () => setPage(Page.Sleeves),
@ -335,6 +337,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
hostname={player.getCurrentServer().hostname} hostname={player.getCurrentServer().hostname}
player={player} player={player}
router={Router} router={Router}
vim={vim}
/> />
) : page === Page.ActiveScripts ? ( ) : page === Page.ActiveScripts ? (
<ActiveScriptsRoot workerScripts={workerScripts} /> <ActiveScriptsRoot workerScripts={workerScripts} />

@ -38,6 +38,10 @@ export enum Page {
Recovery, Recovery,
} }
export interface ScriptEditorRouteOptions {
vim: boolean;
}
/** /**
* This class keeps track of player navigation/routing within the game. * This class keeps track of player navigation/routing within the game.
*/ */
@ -66,7 +70,7 @@ export interface IRouter {
toJob(): void; toJob(): void;
toMilestones(): void; toMilestones(): void;
toResleeves(): void; toResleeves(): void;
toScriptEditor(filename?: string, code?: string): void; toScriptEditor(filename?: string, code?: string, options?: ScriptEditorRouteOptions): void;
toSleeves(): void; toSleeves(): void;
toStockMarket(): void; toStockMarket(): void;
toTerminal(): void; toTerminal(): void;