From 357792ec7d25773762ae52a53a0fb9b221d7c35f Mon Sep 17 00:00:00 2001 From: Prozilla Date: Mon, 29 Apr 2024 23:18:55 +0200 Subject: [PATCH] Implemented command options with input values --- docs/features/apps/terminal/README.md | 2 +- package-lock.json | 25 ++++ src/components/apps/terminal/Terminal.jsx | 29 +++- src/features/apps/terminal/command.js | 44 ++++-- src/features/apps/terminal/commands.js | 64 ++------- src/features/apps/terminal/commands/cat.js | 2 +- src/features/apps/terminal/commands/cd.js | 2 +- src/features/apps/terminal/commands/clear.js | 2 +- .../apps/terminal/commands/compgen.js | 2 +- src/features/apps/terminal/commands/cowsay.js | 2 +- src/features/apps/terminal/commands/dir.js | 2 +- src/features/apps/terminal/commands/echo.js | 2 +- src/features/apps/terminal/commands/exit.js | 2 +- .../apps/terminal/commands/fortune.js | 136 +++++++----------- src/features/apps/terminal/commands/help.js | 2 +- .../apps/terminal/commands/hostname.js | 2 +- src/features/apps/terminal/commands/ls.js | 2 +- src/features/apps/terminal/commands/make.js | 2 +- src/features/apps/terminal/commands/man.js | 2 +- src/features/apps/terminal/commands/mkdir.js | 2 +- .../apps/terminal/commands/neofetch.js | 2 +- src/features/apps/terminal/commands/pwd.js | 2 +- src/features/apps/terminal/commands/reboot.js | 2 +- src/features/apps/terminal/commands/rev.js | 9 ++ src/features/apps/terminal/commands/rm.js | 2 +- src/features/apps/terminal/commands/rmdir.js | 2 +- src/features/apps/terminal/commands/sl.js | 101 +++++++++---- src/features/apps/terminal/commands/touch.js | 2 +- src/features/apps/terminal/commands/uptime.js | 2 +- src/features/apps/terminal/commands/whatis.js | 2 +- src/features/apps/terminal/commands/whoami.js | 2 +- 31 files changed, 246 insertions(+), 210 deletions(-) create mode 100644 src/features/apps/terminal/commands/rev.js diff --git a/docs/features/apps/terminal/README.md b/docs/features/apps/terminal/README.md index 1ac2a58..7b7fa6b 100644 --- a/docs/features/apps/terminal/README.md +++ b/docs/features/apps/terminal/README.md @@ -19,7 +19,7 @@ See [features/apps/terminal/commands.js](../../../../src/features/apps/terminal/ ```js // features/apps/terminal/commands/touch.js -export const touch = new Command("touch") +export const touch = new Command() .setRequireArgs(true) .setManual({ purpose: "Change file timestamps", diff --git a/package-lock.json b/package-lock.json index 52ac75b..44d9925 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "babel-plugin-wildcard": "^7.0.0", "eslint-plugin-jsdoc": "^46.4.6", "gh-pages": "^5.0.0" } @@ -5636,6 +5637,30 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" }, + "node_modules/babel-plugin-wildcard": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-wildcard/-/babel-plugin-wildcard-7.0.0.tgz", + "integrity": "sha512-3duaRaULzxmmgr+YO9EPEE3m/irVyOWKvXCOz2S41tlp0g2UarSEtpM++D3IS+asK205OOqW1ajnjFeoRRqfZg==", + "dev": true, + "dependencies": { + "rimraf": "^2.6.2" + }, + "bin": { + "bpwc": "index.js" + } + }, + "node_modules/babel-plugin-wildcard/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", diff --git a/src/components/apps/terminal/Terminal.jsx b/src/components/apps/terminal/Terminal.jsx index 5676b5c..89d425b 100644 --- a/src/components/apps/terminal/Terminal.jsx +++ b/src/components/apps/terminal/Terminal.jsx @@ -106,16 +106,30 @@ export function Terminal({ startPath, setTitle, close: exit, active }) { // Get options const options = []; - args.filter((arg) => arg.startsWith("-")).forEach((option) => { + const inputs = {}; + args.filter((arg) => arg.startsWith("-")).forEach((option, index) => { + const addOption = (key) => { + if (options.includes(key)) + return; + + options.push(key); + + const commandOption = command.getOption(options[options.length - 1]); + + if (commandOption?.isInput) { + const optionInput = args[args.indexOf(option) + 1]; + inputs[commandOption.short] = optionInput; + removeFromArray(optionInput, args); + } + }; + if (option.startsWith("--")) { const longOption = option.substring(2).toLowerCase(); - if (!options.includes(longOption)) - options.push(longOption); + addOption(longOption); } else { const shortOptions = option.substring(1).split(""); shortOptions.forEach((shortOption) => { - if (!options.includes(shortOption)) - options.push(shortOption); + addOption(shortOption); }); } @@ -143,7 +157,8 @@ export function Terminal({ startPath, setTitle, close: exit, active }) { hostname: HOSTNAME, rawInputValue, options, - exit + exit, + inputs }); if (response == null) @@ -214,8 +229,10 @@ export function Terminal({ startPath, setTitle, close: exit, active }) { submitInput(value); setInputKey((previousKey) => previousKey + 1); } else if (key === "ArrowUp") { + event.preventDefault(); updateHistoryIndex(1); } else if (key === "ArrowDown") { + event.preventDefault(); updateHistoryIndex(-1); } else if (!stream && (event.ctrlKey || event.metaKey) && key === "c") { setInputValue((value) => value + "^C"); diff --git a/src/features/apps/terminal/command.js b/src/features/apps/terminal/command.js index e925413..75a773a 100644 --- a/src/features/apps/terminal/command.js +++ b/src/features/apps/terminal/command.js @@ -15,25 +15,27 @@ import { VirtualRoot } from "../../virtual-drive/root/virtualRoot.js"; * @param {string} options.rawInputValue * @param {string[]} options.options * @param {Function} options.exit + * @param {[]} options.inputs * @returns {string|{ blank: boolean }} */ +/** + * @typedef {object} optionType + * @property {string} long + * @property {string} short + * @property {boolean} isInput + */ + export default class Command { /** @type {string} */ name; + /** @type {optionType[]} */ + options = []; + /** @type {executeType} */ execute = () => {}; - /** - * @param {string} name - * @param {executeType} execute - */ - constructor(name, execute) { - this.name = name; - this.execute = execute; - } - /** * @param {string} name * @returns {Command} @@ -78,4 +80,28 @@ export default class Command { this.manual = { purpose, usage, description, options }; return this; } + + /** + * @param {optionType} option + * @returns {Command} + */ + addOption({ short, long, isInput }) { + this.options.push({ short, long, isInput }); + return this; + } + + /** + * @param {string} key + * @returns {optionType} + */ + getOption(key) { + let matchingOption = null; + + this.options.forEach((option) => { + if (option.short === key || option.long === key) + matchingOption = option; + }); + + return matchingOption; + } } \ No newline at end of file diff --git a/src/features/apps/terminal/commands.js b/src/features/apps/terminal/commands.js index fea3595..9f4c8d9 100644 --- a/src/features/apps/terminal/commands.js +++ b/src/features/apps/terminal/commands.js @@ -1,29 +1,15 @@ import Command from "./command.js"; -import { cat } from "./commands/cat.js"; -import { cd } from "./commands/cd.js"; -import { clear } from "./commands/clear.js"; -import { compgen } from "./commands/compgen.js"; -import { cowsay } from "./commands/cowsay.js"; -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 { pwd } from "./commands/pwd.js"; -import { reboot } from "./commands/reboot.js"; -import { rm } from "./commands/rm.js"; -import { rmdir } from "./commands/rmdir.js"; -import { sl } from "./commands/sl.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"; + +// Dynamically import commands +const context = require.context("./commands", false, /\.js$/); +const commands = []; +context.keys().forEach((key) => { + const commandModule = context(key); + const commandName = Object.keys(commandModule)[0]; + const command = commandModule[commandName]; + command.setName(commandName.toLowerCase()); + commands.push(command); +}); export default class CommandsManager { /** @@ -52,31 +38,5 @@ export default class CommandsManager { return matches; } - static COMMANDS = [ - echo, - clear, - ls, - cd, - dir, - pwd, - touch, - mkdir, - rm, - rmdir, - hostname, - neofetch, - fortune, - cowsay, - make, - cat, - man, - reboot, - compgen, - whoami, - whatis, - exit, - help, - uptime, - sl, - ]; + static COMMANDS = commands; } \ No newline at end of file diff --git a/src/features/apps/terminal/commands/cat.js b/src/features/apps/terminal/commands/cat.js index ed1ac8b..402929b 100644 --- a/src/features/apps/terminal/commands/cat.js +++ b/src/features/apps/terminal/commands/cat.js @@ -1,7 +1,7 @@ import { VirtualFile } from "../../../virtual-drive/file/virtualFile.js"; import Command from "../command.js"; -export const cat = new Command("cat") +export const cat = new Command() .setRequireArgs(true) .setManual({ purpose: "Concetenate files and display on the terminal screen", diff --git a/src/features/apps/terminal/commands/cd.js b/src/features/apps/terminal/commands/cd.js index 6429bee..2d4e039 100644 --- a/src/features/apps/terminal/commands/cd.js +++ b/src/features/apps/terminal/commands/cd.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const cd = new Command("cd") +export const cd = new Command() .setManual({ purpose: "Change the current directory", usage: "cd path", diff --git a/src/features/apps/terminal/commands/clear.js b/src/features/apps/terminal/commands/clear.js index 88afbad..7f3d8e2 100644 --- a/src/features/apps/terminal/commands/clear.js +++ b/src/features/apps/terminal/commands/clear.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const clear = new Command("clear") +export const clear = new Command() .setManual({ purpose: "Clear terminal screen", usage: "clear", diff --git a/src/features/apps/terminal/commands/compgen.js b/src/features/apps/terminal/commands/compgen.js index 4cd5094..3c50c57 100644 --- a/src/features/apps/terminal/commands/compgen.js +++ b/src/features/apps/terminal/commands/compgen.js @@ -1,7 +1,7 @@ import Command from "../command.js"; import CommandsManager from "../commands.js"; -export const compgen = new Command("compgen") +export const compgen = new Command() .setRequireOptions(true) .setExecute(function(args, { options }) { if (options.includes("c")) { diff --git a/src/features/apps/terminal/commands/cowsay.js b/src/features/apps/terminal/commands/cowsay.js index bf5b852..92c802a 100644 --- a/src/features/apps/terminal/commands/cowsay.js +++ b/src/features/apps/terminal/commands/cowsay.js @@ -8,7 +8,7 @@ const COW = ` ||----w | || ||`; -export const cowsay = new Command("cowsay") +export const cowsay = new Command() .setRequireArgs(true) .setManual({ purpose: "Show a cow saying something", diff --git a/src/features/apps/terminal/commands/dir.js b/src/features/apps/terminal/commands/dir.js index 0f86d32..611af40 100644 --- a/src/features/apps/terminal/commands/dir.js +++ b/src/features/apps/terminal/commands/dir.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const dir = new Command("dir") +export const dir = new Command() .setManual({ purpose: "List all directories in the current directory" }) diff --git a/src/features/apps/terminal/commands/echo.js b/src/features/apps/terminal/commands/echo.js index 49ab477..aa587eb 100644 --- a/src/features/apps/terminal/commands/echo.js +++ b/src/features/apps/terminal/commands/echo.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const echo = new Command("echo") +export const echo = new Command() .setManual({ purpose: "Display text on the terminal screen" }) diff --git a/src/features/apps/terminal/commands/exit.js b/src/features/apps/terminal/commands/exit.js index bb95e92..90a6841 100644 --- a/src/features/apps/terminal/commands/exit.js +++ b/src/features/apps/terminal/commands/exit.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const exit = new Command("exit") +export const exit = new Command() .setManual({ purpose: "Quit terminal interface" }) diff --git a/src/features/apps/terminal/commands/fortune.js b/src/features/apps/terminal/commands/fortune.js index 421021f..6945b60 100644 --- a/src/features/apps/terminal/commands/fortune.js +++ b/src/features/apps/terminal/commands/fortune.js @@ -5,96 +5,56 @@ import Command from "../command.js"; * Source: https://github.com/shlomif/fortune-mod/blob/master/fortune-mod/datfiles/fortunes */ const FORTUNES = [ - "A day for firm decisions!!!!! Or is it?", - "Just to have it is enough.", - "Keep emotionally active. Cater to your favorite neurosis.", - "Keep it short for pithy sake.", - "Lady Luck brings added income today. Lady friend takes it away tonight.", - "Learn to pause -- or nothing worthwhile can catch up to you.", - "Let me put it this way: today is going to be a learning experience.", - "Life is to you a dashing and bold adventure.", - "\"Life, loathe it or ignore it, you can't like it.\"\n\n -- Marvin, \"Hitchhiker's Guide to the Galaxy\"", - "Live in a world of your own, but always welcome visitors.", - "Living your life is a task so difficult, it has never been attempted before.", - "Long life is in store for you.", - "Look afar and see the end from the beginning.", - "Love is in the offing. Be affectionate to one who adores you.", - "Make a wish, it might come true.", - "Many changes of mind and mood; do not hesitate too long.", - "Never be led astray onto the path of virtue.", - "Never commit yourself! Let someone else commit you.", - "Never give an inch!", - "Never look up when dragons fly overhead.", - "Never reveal your best argument.", - "Next Friday will not be your lucky day. As a matter of fact, you don't have a lucky day this year.", - "Of course you have a purpose -- to find a purpose.", - "People are beginning to notice you. Try dressing before you leave the house.", - "Perfect day for scrubbing the floor and other exciting things.", - "Questionable day.\n\nAsk somebody something.", - "Reply hazy, ask again later.", - "Save energy: be apathetic.", - "Ships are safe in harbor, but they were never meant to stay there.", - "Slow day. Practice crawling.", - "Snow Day -- stay home.", - "So this is it. We're going to die.", - "So you're back... about time...", - "Someone is speaking well of you.", - "Someone is speaking well of you.\n\nHow unusual!", - "Someone whom you reject today, will reject you tomorrow.", - "Stay away from flying saucers today.", - "Stay away from hurricanes for a while.", - "Stay the curse.", - "That secret you've been guarding, isn't.", - "The time is right to make new friends.", - "The whole world is a tuxedo and you are a pair of brown shoes.\n\n -- George Gobel", - "There is a 20% chance of tomorrow.", - "There is a fly on your nose.", - "There was a phone call for you.", - "You're not my type. For that matter, you're not even my species!!!", - "You're ugly and your mother dresses you funny.", - "You're working under a slight handicap. You happen to be human.", - "You've been leading a dog's life. Stay off the furniture.", - "Your aim is high and to the right.", - "Your aims are high, and you are capable of much.", - "Your analyst has you mixed up with another patient. Don't believe a thing he tells you.", - "Your best consolation is the hope that the things you failed to get weren't really worth having.", - "Your boss climbed the corporate ladder, wrong by wrong.", - "Your boss is a few sandwiches short of a picnic.", - "Your boyfriend takes chocolate from strangers.", - "Your business will assume vast proportions.", - "Your business will go through a period of considerable expansion.", - "Your depth of comprehension may tend to make you lax in worldly ways.", - "Your domestic life may be harmonious.", - "Your fly might be open (but don't check it just now).", - "Your goose is cooked. (Your current chick is burned up too!)", - "Your heart is pure, and your mind clear, and your soul devout.", - "Your ignorance cramps my conversation.", - "Your life would be very empty if you had nothing to regret.", - "Your love life will be happy and harmonious.", - "Your love life will be... interesting.", - "Your lover will never wish to leave you.", - "Your lucky color has faded.", - "Your lucky number has been disconnected.", - "Your lucky number is 3552664958674928. Watch for it everywhere.", - "Your mode of life will be changed for the better because of good news soon.", - "Your mode of life will be changed for the better because of new developments.", - "Your motives for doing whatever good deed you may have in mind will be misinterpreted by somebody.", - "Your nature demands love and your happiness depends on it.", - "Your object is to save the world, while still leading a pleasant life.", - "Your own qualities will help prevent your advancement in the world.", - "Your present plans will be successful.", - "Your reasoning is excellent -- it's only your basic assumptions that are wrong.", - "Your reasoning powers are good, and you are a fairly good planner.", - "Your sister swims out to meet troop ships.", - "Your society will be sought by people of taste and refinement.", - "Your step will soil many countries.", - "Your supervisor is thinking about you.", - "Your talents will be recognized and suitably rewarded.", - "Your temporary financial embarrassment will be relieved in a surprising manner.", - "Your true value depends entirely on what you are compared with.", + "Do not be afraid of competition.", + "An exciting opportunity lies ahead of you.", + "You love peace.", + "Get your mind set…confidence will lead you on.", + "You will always be surrounded by true friends.", + "Sell your ideas-they have exceptional merit.", + "You should be able to undertake and complete anything.", + "You are kind and friendly.", + "You are wise beyond your years.", + "Your ability to juggle many tasks will take you far.", + "A routine task will turn into an enchanting adventure.", + "Beware of all enterprises that require new clothes.", + "Be true to your work, your word, and your friend.", + "Goodness is the only investment that never fails.", + "A journey of a thousand miles begins with a single step.", + "Forget injuries; never forget kindnesses.", + "Respect yourself and others will respect you.", + "A man cannot be comfortable without his own approval.", + "Always do right. This will gratify some people and astonish the rest.", + "It is easier to stay out than to get out.", + "Sing everyday and chase the mean blues away.", + "You will receive money from an unexpected source.", + "Attitude is a little thing that makes a big difference.", + "Plan for many pleasures ahead.", + "Experience is the best teacher.", + "You will be happy with your spouse.", + "Expect the unexpected.", + "Stay healthy. Walk a mile.", + "The family that plays together stays together.", + "Eat chocolate to have a sweeter life.", + "Once you make a decision the universe conspires to make it happen.", + "Make yourself necessary to someone.", + "The only way to have a friend is to be one.", + "Nothing great was ever achieved without enthusiasm.", + "Dance as if no one is watching.", + "Live this day as if it were your last.", + "Your life will be happy and peaceful.", + "Reach for joy and all else will follow.", + "Move in the direction of your dreams.", + "Bloom where you are planted.", + "Appreciate. Appreciate. Appreciate.", + "Happy News is on its way.", + "A closed mouth gathers no feet.", + "He who throws dirt is losing ground.", + "Borrow money from a pessimist. They don't expect it back.", + "Life is what happens to you while you are busy making other plans.", + "Help! I'm being held prisoner in a fortune cookie factory.", ]; -export const fortune = new Command("fortune") +export const fortune = new Command() .setManual({ purpose: "Tell fortune" }) diff --git a/src/features/apps/terminal/commands/help.js b/src/features/apps/terminal/commands/help.js index 5954737..406baee 100644 --- a/src/features/apps/terminal/commands/help.js +++ b/src/features/apps/terminal/commands/help.js @@ -1,7 +1,7 @@ import Command from "../command.js"; import CommandsManager from "../commands.js"; -export const help = new Command("help") +export const help = new Command() .setExecute((args) => { if (args.length === 0) { return CommandsManager.COMMANDS.map((command) => { diff --git a/src/features/apps/terminal/commands/hostname.js b/src/features/apps/terminal/commands/hostname.js index e54fe5e..8dffc0f 100644 --- a/src/features/apps/terminal/commands/hostname.js +++ b/src/features/apps/terminal/commands/hostname.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const hostname = new Command("hostname") +export const hostname = new Command() .setManual({ purpose: "Display the hostname" }) diff --git a/src/features/apps/terminal/commands/ls.js b/src/features/apps/terminal/commands/ls.js index dda79dd..f61bd99 100644 --- a/src/features/apps/terminal/commands/ls.js +++ b/src/features/apps/terminal/commands/ls.js @@ -1,7 +1,7 @@ import { ANSI } from "../../../../config/apps/terminal.config.js"; import Command from "../command.js"; -export const ls = new Command("ls") +export const ls = new Command() .setManual({ purpose: "List directory contents", usage: "ls [OPTION]... [FILE]...", diff --git a/src/features/apps/terminal/commands/make.js b/src/features/apps/terminal/commands/make.js index ed72339..4e13102 100644 --- a/src/features/apps/terminal/commands/make.js +++ b/src/features/apps/terminal/commands/make.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const make = new Command("make") +export const make = new Command() .setRequireArgs(true) .setExecute(function(args) { if (args[0] === "love") diff --git a/src/features/apps/terminal/commands/man.js b/src/features/apps/terminal/commands/man.js index 2be9059..f6a270f 100644 --- a/src/features/apps/terminal/commands/man.js +++ b/src/features/apps/terminal/commands/man.js @@ -3,7 +3,7 @@ import CommandsManager from "../commands.js"; const MARGIN = 5; -export const man = new Command("man") +export const man = new Command() .setRequireArgs(true) .setManual({ purpose: "Show system reference manuals", diff --git a/src/features/apps/terminal/commands/mkdir.js b/src/features/apps/terminal/commands/mkdir.js index 2b9b1a2..8df0690 100644 --- a/src/features/apps/terminal/commands/mkdir.js +++ b/src/features/apps/terminal/commands/mkdir.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const mkdir = new Command("mkdir") +export const mkdir = new Command() .setManual({ purpose: "Create directory" }) diff --git a/src/features/apps/terminal/commands/neofetch.js b/src/features/apps/terminal/commands/neofetch.js index d97c1f0..db15d51 100644 --- a/src/features/apps/terminal/commands/neofetch.js +++ b/src/features/apps/terminal/commands/neofetch.js @@ -6,7 +6,7 @@ import { formatRelativeTime } from "../../../_utils/date.utils.js"; import AppsManager from "../../appsManager.js"; import Command from "../command.js"; -export const neofetch = new Command("neofetch") +export const neofetch = new Command() .setManual({ purpose: "Fetch system information" }) diff --git a/src/features/apps/terminal/commands/pwd.js b/src/features/apps/terminal/commands/pwd.js index 5f1d55f..6193479 100644 --- a/src/features/apps/terminal/commands/pwd.js +++ b/src/features/apps/terminal/commands/pwd.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const pwd = new Command("pwd") +export const pwd = new Command() .setManual({ purpose: "Display path of the current directory" }) diff --git a/src/features/apps/terminal/commands/reboot.js b/src/features/apps/terminal/commands/reboot.js index 1bce6cf..12ca09c 100644 --- a/src/features/apps/terminal/commands/reboot.js +++ b/src/features/apps/terminal/commands/reboot.js @@ -1,7 +1,7 @@ import { reloadViewport } from "../../../_utils/browser.utils.js"; import Command from "../command.js"; -export const reboot = new Command("reboot") +export const reboot = new Command() .setManual({ purpose: "Reboot the system" }) diff --git a/src/features/apps/terminal/commands/rev.js b/src/features/apps/terminal/commands/rev.js new file mode 100644 index 0000000..4197366 --- /dev/null +++ b/src/features/apps/terminal/commands/rev.js @@ -0,0 +1,9 @@ +import Command from "../command.js"; + +export const rev = new Command() + .setManual({ + purpose: "Reverses text." + }) + .setExecute((args, { rawInputValue }) => { + return rawInputValue.split("").reverse().join(""); + }); \ No newline at end of file diff --git a/src/features/apps/terminal/commands/rm.js b/src/features/apps/terminal/commands/rm.js index f3fc12b..2ea971f 100644 --- a/src/features/apps/terminal/commands/rm.js +++ b/src/features/apps/terminal/commands/rm.js @@ -1,7 +1,7 @@ import { VirtualFile } from "../../../virtual-drive/file/virtualFile.js"; import Command from "../command.js"; -export const rm = new Command("rm") +export const rm = new Command() .setRequireArgs(true) .setManual({ purpose: "Remove a file" diff --git a/src/features/apps/terminal/commands/rmdir.js b/src/features/apps/terminal/commands/rmdir.js index 9528d53..6df7ea9 100644 --- a/src/features/apps/terminal/commands/rmdir.js +++ b/src/features/apps/terminal/commands/rmdir.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const rmdir = new Command("rmdir") +export const rmdir = new Command() .setRequireArgs(true) .setManual({ purpose: "Remove a directory" diff --git a/src/features/apps/terminal/commands/sl.js b/src/features/apps/terminal/commands/sl.js index faacb01..acc8ba4 100644 --- a/src/features/apps/terminal/commands/sl.js +++ b/src/features/apps/terminal/commands/sl.js @@ -11,7 +11,7 @@ const LOCOMOTIVE_SMOKE = [ " (@@@)", ], [ - " ( ) (@@) ( ) (@) () @@ o @ o", + " ( ) (@@) ( ) (@) () @@ o @ o @", " (@@@)", " ( )", " (@@@@)", @@ -21,55 +21,76 @@ const LOCOMOTIVE_SMOKE = [ ]; const LOCOMOTIVE_TOP = [ - " ==== ________ ___________ ", - " _D _| |_______/ \\__I_I_____===__|_________| ", - " |(_)--- | H\\________/ | | =|___ ___| ", - " / | | H | | | | ||_| |_|| ", - " | | | H |__--------------------| [___] | ", - " | ________|___H__/__|_____/[][]~\\_______| | ", - " |/ | |-----------I_____I [][] [] D |=======|__ ", + " ==== ________ ___________", + " _D _| |_______/ \\__I_I_____===__|_________|", + " |(_)--- | H\\________/ | | =|___ ___| ", + " / | | H | | | | ||_| |_|| ", + " | | | H |__--------------------| [___] | ", + " | ________|___H__/__|_____/[][]~\\_______| | ", + " |/ | |-----------I_____I [][] [] D |=======|__", ]; const LOCOMOTIVE_BOTTOM = [ [ - "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ", - " |/-=|___|= || || || |_____/~\\___/ ", - " \\_/ \\O=====O=====O=====O_/ \\_/ ", + "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__", + " |/-=|___|= || || || |_____/~\\___/ ", + " \\_/ \\O=====O=====O=====O_/ \\_/ ", ], [ - "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ", - " |/-=|___|=O=====O=====O=====O |_____/~\\___/ ", - " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", + "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__", + " |/-=|___|=O=====O=====O=====O |_____/~\\___/ ", + " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", ], [ - "__/ =| o |=-O=====O=====O=====O \\ ____Y___________|__ ", - " |/-=|___|= || || || |_____/~\\___/ ", - " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", + "__/ =| o |=-O=====O=====O=====O \\ ____Y___________|__", + " |/-=|___|= || || || |_____/~\\___/ ", + " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", ], [ - "__/ =| o |=-~O=====O=====O=====O\\ ____Y___________|__ ", - " |/-=|___|= || || || |_____/~\\___/ ", - " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", + "__/ =| o |=-~O=====O=====O=====O\\ ____Y___________|__", + " |/-=|___|= || || || |_____/~\\___/ ", + " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", ], [ - "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ", - " |/-=|___|= O=====O=====O=====O|_____/~\\___/ ", - " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", + "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__", + " |/-=|___|= O=====O=====O=====O|_____/~\\___/ ", + " \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ", ], [ - "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ", - " |/-=|___|= || || || |_____/~\\___/ ", - " \\_/ \\_O=====O=====O=====O/ \\_/ ", + "__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__", + " |/-=|___|= || || || |_____/~\\___/ ", + " \\_/ \\_O=====O=====O=====O/ \\_/ ", ] ].reverse(); -function getLocomotive(frame) { +const WAGON = [ + " _________________ ", + " _| \\_____A ", + " =| | ", + " -| | ", + "__|________________________|_", + "|__________________________|_", + " |_D__D__D_| |_D__D__D_| ", + " \\_/ \\_/ \\_/ \\_/ ", +]; + +function getLocomotive(frame, wagonCount = 1) { + const smokeHeight = LOCOMOTIVE_SMOKE[0].length; + const locomotiveHeight = LOCOMOTIVE_TOP.length + LOCOMOTIVE_BOTTOM[0].length; + const wagonHeight = WAGON.length; + + const wagonStart = smokeHeight + locomotiveHeight - wagonHeight; + const smoke = LOCOMOTIVE_SMOKE[Math.round(frame / 6) % LOCOMOTIVE_SMOKE.length]; const top = LOCOMOTIVE_TOP; const bottom = LOCOMOTIVE_BOTTOM[frame % LOCOMOTIVE_BOTTOM.length]; const distance = 50 - frame; - const locomotive = smoke.concat(top, bottom).map((line) => { + const locomotive = smoke.concat(top, bottom).map((line, index) => { + if (index >= wagonStart && wagonCount > 0) { + line += WAGON[index - wagonStart].repeat(wagonCount); + } + if (distance === 0) { return line; } else if (distance > 0) { @@ -83,13 +104,31 @@ function getLocomotive(frame) { return `\n${locomotive}\n`; } -export const sl = new Command("sl") - .setExecute(function() { +export const sl = new Command() + .setManual({ + purpose: "Displays animations aimed to correct users who accidentally enter sl instead of ls. SL stands for Steam Locomotive." + }) + .addOption({ + short: "w", + long: "wagons", + isInput: true + }) + .setExecute((args, { inputs }) => { + let wagonCount = 1; + + if (inputs?.w) { + wagonCount = parseInt(inputs.w); + + if (!wagonCount || wagonCount < 0) { + return `${this.name}: Please specify a valid amount of wagons`; + } + } + const stream = new Stream(); let frame = 0; const interval = setInterval(() => { - const text = getLocomotive(frame); + const text = getLocomotive(frame, wagonCount); stream.send(text); frame++; diff --git a/src/features/apps/terminal/commands/touch.js b/src/features/apps/terminal/commands/touch.js index bea5caa..50ef012 100644 --- a/src/features/apps/terminal/commands/touch.js +++ b/src/features/apps/terminal/commands/touch.js @@ -1,7 +1,7 @@ import { VirtualFile } from "../../../virtual-drive/file/virtualFile.js"; import Command from "../command.js"; -export const touch = new Command("touch") +export const touch = new Command() .setRequireArgs(true) .setManual({ purpose: "Change file timestamps", diff --git a/src/features/apps/terminal/commands/uptime.js b/src/features/apps/terminal/commands/uptime.js index fe59b4b..6e5fe4e 100644 --- a/src/features/apps/terminal/commands/uptime.js +++ b/src/features/apps/terminal/commands/uptime.js @@ -3,7 +3,7 @@ import { formatRelativeTime } from "../../../_utils/date.utils.js"; import Command from "../command.js"; -export const uptime = new Command("uptime") +export const uptime = new Command() .setManual({ purpose: "Displays the current uptime of the system" }) diff --git a/src/features/apps/terminal/commands/whatis.js b/src/features/apps/terminal/commands/whatis.js index edfe2d2..06c2224 100644 --- a/src/features/apps/terminal/commands/whatis.js +++ b/src/features/apps/terminal/commands/whatis.js @@ -1,7 +1,7 @@ import Command from "../command.js"; import CommandsManager from "../commands.js"; -export const whatis = new Command("whatis") +export const whatis = new Command() .setRequireArgs(true) .setManual({ purpose: "Show information about a command" diff --git a/src/features/apps/terminal/commands/whoami.js b/src/features/apps/terminal/commands/whoami.js index 9810883..8807d86 100644 --- a/src/features/apps/terminal/commands/whoami.js +++ b/src/features/apps/terminal/commands/whoami.js @@ -1,6 +1,6 @@ import Command from "../command.js"; -export const whoami = new Command("whoami") +export const whoami = new Command() .setManual({ purpose: "Display the username" })