Updated terminal app

This commit is contained in:
Prozilla 2023-12-19 11:42:51 +01:00
parent d20c1f6b80
commit ed80c17dfa
No known key found for this signature in database
GPG key ID: 5858DFE71CAF31EE
26 changed files with 209 additions and 139 deletions

View file

@ -6,7 +6,6 @@ import { faCaretLeft, faCaretRight, faHome, faRotateRight } from "@fortawesome/f
import { HOME_URL, SEARCH_URL } from "../../../constants/applications/browser.js";
import { isValidUrl } from "../../../features/utils/browser.js";
import { useHistory } from "../../../hooks/utils/history.js";
import { TITLE_SEPARATOR } from "../../../constants/windows.js";
/** @type {import("../../windows/WindowView.jsx").windowProps} */
export function Browser({ startUrl, focus }) {

View file

@ -134,7 +134,7 @@ export function Terminal({ setTitle, close: exit }) {
});
if (output)
promptOutput(output);
promptOutput(`${output}\n`);
};
const updateHistoryIndex = (delta) => {

View file

@ -1,5 +1,4 @@
import Command from "./command.js";
import { blow } from "./commands/blow.js";
import { cat } from "./commands/cat.js";
import { cd } from "./commands/cd.js";
import { clear } from "./commands/clear.js";
@ -9,21 +8,21 @@ import { dir } from "./commands/dir.js";
import { echo } from "./commands/echo.js";
import { exit } from "./commands/exit.js";
import { fortune } from "./commands/fortune.js";
import { help } from "./commands/help.js";
import { hostname } from "./commands/hostname.js";
import { ls } from "./commands/ls.js";
import { make } from "./commands/make.js";
import { man } from "./commands/man.js";
import { mkdir } from "./commands/mkdir.js";
import { neofetch } from "./commands/neofetch.js";
import { nice } from "./commands/nice.js";
import { pwd } from "./commands/pwd.js";
import { reboot } from "./commands/reboot.js";
import { rm } from "./commands/rm.js";
import { rmdir } from "./commands/rmdir.js";
import { touch } from "./commands/touch.js";
import { uptime } from "./commands/uptime.js";
import { whatis } from "./commands/whatis.js";
import { whoami } from "./commands/whoami.js";
import { world } from "./commands/world.js";
export default class CommandsManager {
/**
@ -67,9 +66,6 @@ export default class CommandsManager {
neofetch,
fortune,
cowsay,
world,
nice,
blow,
make,
cat,
man,
@ -78,5 +74,7 @@ export default class CommandsManager {
whoami,
whatis,
exit,
help,
uptime,
];
}

View file

@ -1,6 +0,0 @@
import Command from "../command.js";
export const blow = new Command("%blow")
.setExecute(function() {
return `fg: ${this.name}: No such job`;
});

View file

@ -3,7 +3,7 @@ import Command from "../command.js";
export const cat = new Command("cat")
.setRequireArgs(true)
.setManual({
purpose: "Concetenate files and print on the standard output",
purpose: "Concetenate files and display on the terminal screen",
usage: "cat [OPTION]... [FILE]...",
description: "Concetenate FILE(s) to standard output."
})

View file

@ -3,7 +3,7 @@ import Command from "../command.js";
export const cd = new Command("cd")
.setRequireArgs(true)
.setManual({
purpose: "Change directory",
purpose: "Change the current directory",
usage: "cd path",
description: "Change working directory to given path (the home directory by default)."
})

View file

@ -1,10 +1,14 @@
import Command from "../command.js";
export const dir = new Command("dir", (args, { currentDirectory }) => {
const folderNames = currentDirectory.subFolders.map((folder) => folder.id);
if (folderNames.length === 0)
return { blank: true };
return folderNames.sort((nameA, nameB) => nameA.localeCompare(nameB)).join(" ");
});
export const dir = new Command("dir")
.setManual({
purpose: "List all directories in the current directory"
})
.setExecute((args, { currentDirectory }) => {
const folderNames = currentDirectory.subFolders.map((folder) => folder.id);
if (folderNames.length === 0)
return { blank: true };
return folderNames.sort((nameA, nameB) => nameA.localeCompare(nameB)).join(" ");
});

View file

@ -1,5 +1,9 @@
import Command from "../command.js";
export const echo = new Command("echo", (args, { rawInputValue }) => {
return rawInputValue;
});
export const echo = new Command("echo")
.setManual({
purpose: "Display text on the terminal screen"
})
.setExecute((args, { rawInputValue }) => {
return rawInputValue;
});

View file

@ -1,6 +1,10 @@
import Command from "../command.js";
export const exit = new Command("exit", (args, { exit }) => {
exit();
return { blank: true };
});
export const exit = new Command("exit")
.setManual({
purpose: "Quit terminal interface"
})
.setExecute((args, { exit }) => {
exit();
return { blank: true };
});

View file

@ -94,6 +94,10 @@ const FORTUNES = [
"Your true value depends entirely on what you are compared with.",
];
export const fortune = new Command("fortune", () => {
return randomFromArray(FORTUNES);
});
export const fortune = new Command("fortune")
.setManual({
purpose: "Tell fortune"
})
.setExecute(() => {
return randomFromArray(FORTUNES);
});

View file

@ -0,0 +1,26 @@
import Command from "../command.js";
import CommandsManager from "../commands.js";
export const help = new Command("help")
.setExecute((args) => {
if (args.length === 0) {
return CommandsManager.COMMANDS.map((command) => {
if (command.manual?.purpose) {
return `${command.name} - ${command.manual.purpose}`;
} else {
return command.name;
}
}).sort().join("\n");
}
const commandName = args[0].toLowerCase();
const command = CommandsManager.find(commandName);
if (!command)
return `${this.name}: ${commandName}: Command not found`;
if (!command.manual?.purpose)
return `${this.name}: ${commandName}: No manual found`;
return command.manual.purpose;
});

View file

@ -1,5 +1,9 @@
import Command from "../command.js";
export const hostname = new Command("hostname", (args, { hostname }) => {
return hostname;
});
export const hostname = new Command("hostname")
.setManual({
purpose: "Display the hostname"
})
.setExecute((args, { hostname }) => {
return hostname;
});

View file

@ -2,10 +2,9 @@ import Command from "../command.js";
export const ls = new Command("ls")
.setManual({
purpose: "list directory contents",
purpose: "List directory contents",
usage: "ls [OPTION]... [FILE]...",
description: "List information about the FILEs (the current directory by default).\n"
+ "Sort entries alphabetically if none of -cftuvSUX nor --sort is specified."
description: "List information about the FILEs (the current directory by default)."
})
.setExecute(function(args, { currentDirectory }) {
let directory = currentDirectory;

View file

@ -1,6 +1,7 @@
import Command from "../command.js";
export const make = new Command("make")
.setRequireArgs(true)
.setExecute(function(args) {
if (args[0] === "love")
return `${this.name}: *** No rule to make target 'love'. Stop.`;

View file

@ -18,14 +18,14 @@ export const man = new Command("man")
.setExecute(function(args, { options }) {
// Search function
if (options.includes("k")) {
const commands = CommandsManager.search(args[0]);
const commands = CommandsManager.search(args[0].toLowerCase());
return commands.map((command) => {
if (command.manual?.purpose) {
return `${command.name} - ${command.manual.purpose}`;
} else {
return command.name;
}
}).join("\n");
}).sort().join("\n");
}
const commandName = args[0].toLowerCase();

View file

@ -1,11 +1,16 @@
import Command from "../command.js";
export const mkdir = new Command("mkdir", (args, { currentDirectory }) => {
const name = args[0];
if (currentDirectory.findSubFolder(name))
export const mkdir = new Command("mkdir")
.setManual({
purpose: "Create directory"
})
.setRequireArgs(true)
.setExecute((args, { currentDirectory }) => {
const name = args[0];
if (currentDirectory.findSubFolder(name))
return { blank: true };
currentDirectory.createFolder(name);
return { blank: true };
currentDirectory.createFolder(name);
return { blank: true };
}).setRequireArgs(true);
});

View file

@ -5,53 +5,57 @@ import { formatRelativeTime } from "../../../utils/date.js";
import AppsManager from "../../applications.js";
import Command from "../command.js";
export const neofetch = new Command("neofetch", (args, { username, hostname }) => {
const leftColumn = ASCII_LOGO.split("\n");
const rightColumnWidth = username.length + hostname.length + 1;
export const neofetch = new Command("neofetch")
.setManual({
purpose: "Fetch system information"
})
.setExecute((args, { username, hostname }) => {
const leftColumn = ASCII_LOGO.split("\n");
const rightColumnWidth = username.length + hostname.length + 1;
const userAgent = navigator.userAgent;
const userAgent = navigator.userAgent;
// Check for the browser name using regular expressions
let browserName;
if (userAgent.match(/Firefox\//)) {
browserName = "Mozilla Firefox";
} else if (userAgent.match(/Edg\//)) {
browserName = "Microsoft Edge";
} else if (userAgent.match(/Chrome\//)) {
browserName = "Google Chrome";
} else if (userAgent.match(/Safari\//)) {
browserName = "Apple Safari";
} else {
browserName = "Unknown";
}
const rightColumn = [
`${username}@${hostname}`,
"-".repeat(rightColumnWidth),
`OS: ${NAME}`,
`UPTIME: ${formatRelativeTime(START_DATE, 2, false)}`,
`RESOLUTION: ${window.innerWidth}x${window.innerHeight}`,
"THEME: default",
"ICONS: Font Awesome",
`TERMINAL: ${AppsManager.getApp(APPS.TERMINAL)?.name ?? "Unknown"}`,
`BROWSER: ${browserName}`,
`PLATFORM: ${navigator.platform}`,
`LANGUAGE: ${navigator.language}`,
];
const combined = [];
for (let i = 1; i < leftColumn.length; i++) {
let line = `${leftColumn[i]} `;
if (i <= rightColumn.length) {
line += rightColumn[i - 1];
// Check for the browser name using regular expressions
let browserName;
if (userAgent.match(/Firefox\//)) {
browserName = "Mozilla Firefox";
} else if (userAgent.match(/Edg\//)) {
browserName = "Microsoft Edge";
} else if (userAgent.match(/Chrome\//)) {
browserName = "Google Chrome";
} else if (userAgent.match(/Safari\//)) {
browserName = "Apple Safari";
} else {
// This fixes a weird display bug on Safari mobile
line += " ".repeat(rightColumnWidth);
browserName = "Unknown";
}
combined.push(line);
}
const rightColumn = [
`${username}@${hostname}`,
"-".repeat(rightColumnWidth),
`OS: ${NAME}`,
`UPTIME: ${formatRelativeTime(START_DATE, 2, false)}`,
`RESOLUTION: ${window.innerWidth}x${window.innerHeight}`,
"THEME: default",
"ICONS: Font Awesome",
`TERMINAL: ${AppsManager.getApp(APPS.TERMINAL)?.name ?? "Unknown"}`,
`BROWSER: ${browserName}`,
`PLATFORM: ${navigator.platform}`,
`LANGUAGE: ${navigator.language}`,
];
return combined.join("\n");
});
const combined = [];
for (let i = 1; i < leftColumn.length; i++) {
let line = `${leftColumn[i]} `;
if (i <= rightColumn.length) {
line += rightColumn[i - 1];
} else {
// This fixes a weird display bug on Safari mobile
line += " ".repeat(rightColumnWidth);
}
combined.push(line);
}
return combined.join("\n");
});

View file

@ -1,7 +0,0 @@
import Command from "../command.js";
export const nice = new Command("nice")
.setExecute(function(args) {
if (args[0] === "man" && args[1] === "woman")
return `${this.name}: No manual entry for woman`;
});

View file

@ -1,9 +1,13 @@
import Command from "../command.js";
export const pwd = new Command("pwd", (args, { currentDirectory }) => {
if (currentDirectory.root) {
return "/";
} else {
return currentDirectory.absolutePath;
}
});
export const pwd = new Command("pwd")
.setManual({
purpose: "Display path of the current directory"
})
.setExecute((args, { currentDirectory }) => {
if (currentDirectory.root) {
return "/";
} else {
return currentDirectory.absolutePath;
}
});

View file

@ -1,7 +1,11 @@
import { reloadViewport } from "../../../utils/browser.js";
import Command from "../command.js";
export const reboot = new Command("reboot", () => {
reloadViewport();
return { blank: true };
});
export const reboot = new Command("reboot")
.setManual({
purpose: "Reboot the system"
})
.setExecute(() => {
reloadViewport();
return { blank: true };
});

View file

@ -1,12 +1,17 @@
import Command from "../command.js";
export const rm = new Command("rm", (args, { currentDirectory }) => {
const [name, extension] = args[0].split(".");
const file = currentDirectory.findFile(name, extension);
if (!file)
return `${this.name}: ${args[0]}: No such file`;
export const rm = new Command("rm")
.setRequireArgs(true)
.setManual({
purpose: "Remove a file"
})
.setExecute((args, { currentDirectory }) => {
const [name, extension] = args[0].split(".");
const file = currentDirectory.findFile(name, extension);
file.delete();
return { blank: true };
}).setRequireArgs(true);
if (!file)
return `${this.name}: ${args[0]}: No such file`;
file.delete();
return { blank: true };
});

View file

@ -1,12 +1,17 @@
import Command from "../command.js";
export const rmdir = new Command("rmdir", (args, { currentDirectory }) => {
const name = args[0];
const folder = currentDirectory.findSubFolder(name);
if (!folder)
return `${this.name}: ${args[0]}: No such directory`;
export const rmdir = new Command("rmdir")
.setRequireArgs(true)
.setManual({
purpose: "Remove a directory"
})
.setExecute((args, { currentDirectory }) => {
const name = args[0];
const folder = currentDirectory.findSubFolder(name);
folder.delete();
return { blank: true };
}).setRequireArgs(true);
if (!folder)
return `${this.name}: ${args[0]}: No such directory`;
folder.delete();
return { blank: true };
});

View file

@ -0,0 +1,12 @@
import { START_DATE } from "../../../../index.js";
import { formatRelativeTime } from "../../../utils/date.js";
import Command from "../command.js";
export const uptime = new Command("uptime")
.setManual({
purpose: "Displays the current uptime of the system"
})
.setExecute(() => {
return `Uptime: ${formatRelativeTime(START_DATE, 2, false)}`;
});

View file

@ -3,6 +3,9 @@ import CommandsManager from "../commands.js";
export const whatis = new Command("whatis")
.setRequireArgs(true)
.setManual({
purpose: "Show information about a command"
})
.setExecute(function(args) {
const commandName = args[0].toLowerCase();
const command = CommandsManager.find(commandName);

View file

@ -1,5 +1,9 @@
import Command from "../command.js";
export const whoami = new Command("whoami", (args, { username }) => {
return username;
});
export const whoami = new Command("whoami")
.setManual({
purpose: "Display the username"
})
.setExecute((args, { username }) => {
return username;
});

View file

@ -1,6 +0,0 @@
import Command from "../command.js";
export const world = new Command("world")
.setExecute(function() {
return `${this.name}: Not found`;
});