From 3494d577abb51bdb96095a8bf7e39bfe14753b6c Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 16:44:43 +0530 Subject: [PATCH 01/29] Update .gitignore to exclude additional files Added various file types and IDE directories to .gitignore to prevent them from being tracked. --- .gitignore | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f97022..b7aab31 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,47 @@ -target/ \ No newline at end of file + +*.class + + +*.log + + +*.ctxt + + +.mtj.tmp/ + + +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# IntelliJ / VS Code / Eclipse +.idea/ +.vscode/ +*.iml +.project +.classpath +.settings/ + + +target/ +out/ + + +.mvn/wrapper/maven-wrapper.jar + + +.DS_Store +Thumbs.db + + +javafx_cache/ + + +launcher/*.exe +launcher/*.lnk +installer/output/ From a8ddefc3a061e598bde995cda129273443a920f5 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 16:53:06 +0530 Subject: [PATCH 02/29] Refactor pom.xml for MyCMD-GUI project Updated project details and dependencies for MyCMD-GUI. --- pom.xml | 88 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/pom.xml b/pom.xml index 5d226e0..7b4ff9f 100644 --- a/pom.xml +++ b/pom.xml @@ -1,76 +1,80 @@ + + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 com.mycmd - MyCMD - 1.0 - jar - - MyCMD - A custom CMD shell written in Java + MyCMD-GUI + 1.0.0 + MyCMD-GUI + Dark futuristic JavaFX shell for MyCMD + UTF-8 17 17 + 21 + - org.projectlombok - lombok - 1.18.42 - provided + org.openjfx + javafx-controls + ${javafx.version} + + + org.openjfx + javafx-fxml + ${javafx.version} + + org.apache.maven.plugins maven-compiler-plugin - 3.14.1 + 3.10.1 ${maven.compiler.source} ${maven.compiler.target} - - - org.projectlombok - lombok - 1.18.42 - - - + + - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 + org.openjfx + javafx-maven-plugin + ${javafx.version} - - - com.mycmd.App - - + com.mycmd.gui.MainApp - - com.diffplug.spotless - spotless-maven-plugin - 3.0.0 - - - - 1.17.0 - - - - + org.apache.maven.plugins + maven-shade-plugin + 3.3.0 + + + package + + shade + + + + + com.mycmd.gui.MainApp + + + + + - \ No newline at end of file + From e506d4a85d46ee7478fb11776926f63ef52d5b7a Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:00:55 +0530 Subject: [PATCH 03/29] Refactor App to launch JavaFX GUI instead of CLI Removed command-line interface code and added JavaFX GUI launch. --- src/main/java/com/mycmd/App.java | 238 ++----------------------------- 1 file changed, 13 insertions(+), 225 deletions(-) diff --git a/src/main/java/com/mycmd/App.java b/src/main/java/com/mycmd/App.java index bc99d3f..4608f28 100644 --- a/src/main/java/com/mycmd/App.java +++ b/src/main/java/com/mycmd/App.java @@ -1,234 +1,22 @@ package com.mycmd; -import com.mycmd.commands.*; -import java.util.*; -import java.util.Scanner; +import com.mycmd.gui.MainApp; +import javafx.application.Application; +/** + * Entry point for MyCMD-GUI. + */ public class App { public static void main(String[] args) { - ShellContext context = new ShellContext(); - - // Register commands - Map commands = new HashMap<>(); - registerCommands(commands); - - System.out.println("MyCMD [Version 1.0]"); - System.out.println("(c) 2025 MyCMD Organization. All rights reserved."); - - Scanner sc = new Scanner(System.in); - - while (true) { - System.out.print(context.getCurrentDir().getAbsolutePath() + ">"); - String input = sc.nextLine().trim(); - if (input.isEmpty()) continue; - - // Resolve aliases before processing - input = resolveAliases(input, context); - - String[] parts = input.split("\\s+"); - String cmd = parts[0].toLowerCase(); - String[] cmdArgs = Arrays.copyOfRange(parts, 1, parts.length); - - Command command = commands.get(cmd); - if (command != null) { - try { - command.execute(cmdArgs, context); - // Add to history after successful execution - context.addToHistory(input); - } catch (Exception e) { - System.out.println("Error: " + e.getMessage()); - } - } else { - // Single, clear not-recognized message + optional suggestion - System.out.println( - "Unknown command: '" - + cmd - + "'. Enter '" - + CommandNames.HELP - + "' to list all available commands."); - - // compute suggestion safely - try { - List validCommands = new ArrayList<>(commands.keySet()); - String suggestion = StringUtils.findClosest(cmd, validCommands); - if (suggestion != null && !suggestion.equalsIgnoreCase(cmd)) { - System.out.println("Did you mean '" + suggestion + "'?"); - } - } catch (Exception ex) { - // don't let suggestion errors break the shell - } - } + // Security check to prevent CMD access + String launchedFrom = System.getenv("MYCMD_LAUNCHED"); + if (launchedFrom == null || !launchedFrom.equalsIgnoreCase("true")) { + System.out.println("❌ MyCMD-GUI cannot be run directly from CMD."); + System.out.println("➡️ Please use the official launcher (MyCMD.bat)."); + return; } - } - - private static String resolveAliases(String input, ShellContext context) { - String[] parts = input.split("\\s+", 2); - String cmd = parts[0]; - String rest = parts.length > 1 ? parts[1] : ""; - - // Check if the command is an alias - if (context.hasAlias(cmd)) { - String aliasCommand = context.getAlias(cmd); - // Replace the alias with its command, preserving arguments - return rest.isEmpty() ? aliasCommand : aliasCommand + " " + rest; - } - - return input; - } - - private static final class CommandNames { - private CommandNames() {} - - private static final String ALIAS = "alias"; - private static final String ARP = "arp"; - private static final String ASSOC = "assoc"; - private static final String ATTRIB = "attrib"; - private static final String CD = "cd"; - private static final String CHKDSK = "chkdsk"; - private static final String CHOICE = "choice"; - private static final String CLEARHISTORY = "clearhistory"; - private static final String CLIP = "clip"; - private static final String CLS = "cls"; - private static final String COLOR = "color"; - private static final String COMPACT = "compact"; - private static final String COPY = "copy"; - private static final String DATE = "date"; - private static final String DEL = "del"; - private static final String DIR = "dir"; - private static final String DRIVERQUERY = "driverquery"; - private static final String ECHO = "echo"; - private static final String EXIT = "exit"; - private static final String FC = "fc"; - private static final String FIND = "find"; - private static final String FINDSTR = "findstr"; - private static final String FORFILES = "forfiles"; - private static final String FSUTIL = "fsutil"; - private static final String FTYPE = "ftype"; - private static final String GETMAC = "getmac"; - private static final String HELP = "help"; - private static final String HISTORY = "history"; - private static final String HOSTNAME = "hostname"; - private static final String IPCONFIG = "ipconfig"; - private static final String LABEL = "label"; - private static final String LS = "ls"; - private static final String MKDIR = "mkdir"; - private static final String MORE = "more"; - private static final String MOVE = "move"; - private static final String MSG = "msg"; - private static final String NET = "net"; - private static final String NETSH = "netsh"; - private static final String NETSTAT = "netstat"; - private static final String NSLOOKUP = "nslookup"; - private static final String PATH = "path"; - private static final String PAUSE = "pause"; - private static final String PING = "ping"; - private static final String PWD = "pwd"; - private static final String REM = "rem"; - private static final String RENAME = "rename"; - private static final String REPLACE = "replace"; - private static final String RMDIR = "rmdir"; - private static final String ROBOCOPY = "robocopy"; - private static final String ROUTE = "route"; - private static final String SET = "set"; - private static final String SFC = "sfc"; - private static final String SHUTDOWN = "shutdown"; - private static final String SORT = "sort"; - private static final String START = "start"; - private static final String SYSTEMINFO = "systeminfo"; - private static final String TASKKILL = "taskkill"; - private static final String TASKLIST = "tasklist"; - private static final String TELNET = "telnet"; - private static final String TIME = "time"; - private static final String TIMEOUT = "timeout"; - private static final String TITLE = "title"; - private static final String TOUCH = "touch"; - private static final String TRACERT = "tracert"; - private static final String TREE = "tree"; - private static final String TYPE = "type"; - private static final String UNALIAS = "unalias"; - private static final String UPTIME = "uptime"; - private static final String VER = "ver"; - private static final String VERIFY = "verify"; - private static final String VOL = "vol"; - private static final String WHOAMI = "whoami"; - private static final String WMIC = "wmic"; - private static final String XCOPY = "xcopy"; - } - private static void registerCommands(Map commands) { - commands.put(CommandNames.ALIAS, new AliasCommand()); - commands.put(CommandNames.ARP, new ArpCommand()); - commands.put(CommandNames.ASSOC, new AssocCommand()); - commands.put(CommandNames.ATTRIB, new AttribCommand()); - commands.put(CommandNames.CD, new CdCommand()); - commands.put(CommandNames.CHKDSK, new ChkdskCommand()); - commands.put(CommandNames.CHOICE, new ChoiceCommand()); - commands.put(CommandNames.CLEARHISTORY, new ClearHistoryCommand()); - commands.put(CommandNames.CLIP, new ClipCommand()); - commands.put(CommandNames.CLS, new ClsCommand()); - commands.put(CommandNames.COLOR, new ColorCommand()); - commands.put(CommandNames.COMPACT, new CompactCommand()); - commands.put(CommandNames.COPY, new CopyCommand()); - commands.put(CommandNames.DATE, new DateCommand()); - commands.put(CommandNames.DEL, new DelCommand()); - commands.put(CommandNames.DIR, new DirCommand()); - commands.put(CommandNames.DRIVERQUERY, new DriverqueryCommand()); - commands.put(CommandNames.ECHO, new EchoCommand()); - commands.put(CommandNames.EXIT, new ExitCommand()); - commands.put(CommandNames.FC, new FcCommand()); - commands.put(CommandNames.FIND, new FindCommand()); - commands.put(CommandNames.FINDSTR, new FindstrCommand()); - commands.put(CommandNames.FORFILES, new ForfilesCommand()); - commands.put(CommandNames.FSUTIL, new FsutilCommand()); - commands.put(CommandNames.FTYPE, new FtypeCommand()); - commands.put(CommandNames.GETMAC, new GetmacCommand()); - commands.put(CommandNames.HELP, new HelpCommand(commands)); - commands.put(CommandNames.HISTORY, new HistoryCommand()); - commands.put(CommandNames.HOSTNAME, new HostnameCommand()); - commands.put(CommandNames.IPCONFIG, new IpConfig()); - commands.put(CommandNames.LABEL, new LabelCommand()); - commands.put(CommandNames.LS, new LsCommand()); - commands.put(CommandNames.MKDIR, new MkdirCommand()); - commands.put(CommandNames.MORE, new MoreCommand()); - commands.put(CommandNames.MOVE, new MoveCommand()); - commands.put(CommandNames.MSG, new MsgCommand()); - commands.put(CommandNames.NET, new NetCommand()); - commands.put(CommandNames.NETSH, new NetshCommand()); - commands.put(CommandNames.NETSTAT, new NetstatCommand()); - commands.put(CommandNames.NSLOOKUP, new NslookupCommand()); - commands.put(CommandNames.PATH, new PathCommand()); - commands.put(CommandNames.PAUSE, new PauseCommand()); - commands.put(CommandNames.PING, new PingCommand()); - commands.put(CommandNames.PWD, new PwdCommand()); - commands.put(CommandNames.REM, new RemCommand()); - commands.put(CommandNames.RENAME, new RenameCommand()); - commands.put(CommandNames.REPLACE, new ReplaceCommand()); - commands.put(CommandNames.RMDIR, new RmdirCommand()); - commands.put(CommandNames.ROBOCOPY, new RobocopyCommand()); - commands.put(CommandNames.ROUTE, new RouteCommand()); - commands.put(CommandNames.SET, new SetCommand()); - commands.put(CommandNames.SFC, new SfcCommand()); - commands.put(CommandNames.SHUTDOWN, new ShutdownCommand()); - commands.put(CommandNames.SORT, new SortCommand()); - commands.put(CommandNames.START, new StartCommand()); - commands.put(CommandNames.SYSTEMINFO, new SysteminfoCommand()); - commands.put(CommandNames.TASKKILL, new TaskkillCommand()); - commands.put(CommandNames.TASKLIST, new TasklistCommand()); - commands.put(CommandNames.TELNET, new TelnetCommand()); - commands.put(CommandNames.TIME, new TimeCommand()); - commands.put(CommandNames.TIMEOUT, new TimeoutCommand()); - commands.put(CommandNames.TITLE, new TitleCommand()); - commands.put(CommandNames.TOUCH, new TouchCommand()); - commands.put(CommandNames.TRACERT, new TracertCommand()); - commands.put(CommandNames.TREE, new TreeCommand()); - commands.put(CommandNames.TYPE, new TypeCommand()); - commands.put(CommandNames.UNALIAS, new UnaliasCommand()); - commands.put(CommandNames.UPTIME, new UptimeCommand()); - commands.put(CommandNames.VER, new VersionCommand()); - commands.put(CommandNames.VERIFY, new VerifyCommand()); - commands.put(CommandNames.VOL, new VolCommand()); - commands.put(CommandNames.WHOAMI, new WhoamiCommand()); - commands.put(CommandNames.WMIC, new WmicCommand()); - commands.put(CommandNames.XCOPY, new XcopyCommand()); + // Launch JavaFX GUI + Application.launch(MainApp.class, args); } } From a7c6e584f94cdd75eb2e928eb3f560929ef9366c Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:03:19 +0530 Subject: [PATCH 04/29] Update Command interface with description and usage methods Refactor Command interface to define description and usage methods. --- src/main/java/com/mycmd/Command.java | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/mycmd/Command.java b/src/main/java/com/mycmd/Command.java index ce67f47..fac7b07 100644 --- a/src/main/java/com/mycmd/Command.java +++ b/src/main/java/com/mycmd/Command.java @@ -3,29 +3,11 @@ import java.io.IOException; /** - * Represents a shell command that can be executed inside the MyCMD shell. Implementations perform - * their operation when {@link #execute(String[], ShellContext)} is called. + * Interfaace for all commands. + * Every command impleements this */ public interface Command { - /** - * Execute the command. - * - * @param args command-line style arguments passed to the command. May be empty but will not be - * null. - * @param context current shell context containing state such as the current working directory. - * @throws IOException if the command cannot complete successfully. - */ void execute(String[] args, ShellContext context) throws IOException; - - /** - * Short description of the command. Default is empty so existing implementations do not break. - */ - default String description() { - return ""; - } - - /** Usage string for the command. Default is empty. */ - default String usage() { - return ""; - } + String description(); + String usage(); } From 3ada1eb459cab78ec13ca0e397a12ef15fc4ab29 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:05:00 +0530 Subject: [PATCH 05/29] Refactor ShellContext by removing unused code Removed unused methods and variables related to command history and environment variables. Simplified alias management. --- src/main/java/com/mycmd/ShellContext.java | 134 +++------------------- 1 file changed, 16 insertions(+), 118 deletions(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 502e59c..90b8e7f 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -1,142 +1,40 @@ package com.mycmd; -import java.io.*; -import java.time.Instant; -import java.util.*; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; +import java.io.File; +import java.util.HashMap; +import java.util.Map; -@Getter(AccessLevel.PUBLIC) -public class ShellContext { - - @Setter @NonNull private File currentDir; - private List history; - private Map aliases; - private static final String ALIAS_FILE = ".mycmd_aliases"; - private static final int MAX_HISTORY = 100; - - private final List commandHistory; - private final Instant startTime; +public class ShellContext { - private final Map envVars = new HashMap<>(); + private File currentDir; + private final Map aliases; public ShellContext() { this.currentDir = new File(System.getProperty("user.dir")); - this.history = new ArrayList<>(); this.aliases = new HashMap<>(); - this.commandHistory = new ArrayList<>(); - this.startTime = Instant.now(); - loadAliases(); } - public void addToHistory(String command) { - history.add(command); - commandHistory.add(command); - if (history.size() > MAX_HISTORY) { - history.remove(0); - } + public File getCurrentDir() { + return currentDir; } - /** RETAINED FOR SAFETY: Returns a DEFENSIVE COPY instead of the raw Map. */ - public List getHistory() { - return new ArrayList<>(history); + public void setCurrentDir(File dir) { + if (dir != null && dir.exists() && dir.isDirectory()) { + this.currentDir = dir; + } } public Map getAliases() { - return new HashMap<>(aliases); - } - - public Map getEnvVars() { - return new HashMap<>(envVars); - } - - public void clearHistory() { - history.clear(); + return aliases; } public void addAlias(String name, String command) { aliases.put(name, command); - saveAliases(); - } - - public void removeAlias(String name) { - aliases.remove(name); - saveAliases(); - } - - public String getAlias(String name) { - return aliases.get(name); - } - - public boolean hasAlias(String name) { - return aliases.containsKey(name); } - public void setEnvVar(String key, String value) { - envVars.put(key, value); - } - - public String getEnvVar(String key) { - return envVars.get(key); - } - - private void loadAliases() { - File aliasFile = new File(System.getProperty("user.home"), ALIAS_FILE); - // ... (method body remains the same) - if (!aliasFile.exists()) { - return; - } - - try (BufferedReader reader = new BufferedReader(new FileReader(aliasFile))) { - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (line.isEmpty() || line.startsWith("#")) { - continue; - } - String[] parts = line.split("=", 2); - if (parts.length == 2) { - String name = parts[0].trim(); - String command = parts[1].trim(); - aliases.put(name, command); - } - } - } catch (IOException e) { - System.err.println("Warning: Could not load aliases: " + e.getMessage()); - } - } - - private void saveAliases() { - File aliasFile = new File(System.getProperty("user.home"), ALIAS_FILE); - // ... (method body remains the same) - try (BufferedWriter writer = new BufferedWriter(new FileWriter(aliasFile))) { - writer.write("# MyCMD Aliases Configuration\n"); - writer.write("# Format: aliasName=command\n\n"); - for (Map.Entry entry : aliases.entrySet()) { - writer.write(entry.getKey() + "=" + entry.getValue() + "\n"); - } - } catch (IOException e) { - System.err.println("Warning: Could not save aliases: " + e.getMessage()); - } - } - - /** - * Resolve the given path (absolute or relative) to a File using the current directory. If the - * provided path is absolute, returns it directly; otherwise returns a File rooted at - * currentDir. - */ - public File resolvePath(String path) { - if (path == null || path.trim().isEmpty()) { - return currentDir; - } - File f = new File(path); - if (f.isAbsolute()) { - return f; - } else { - return new File(currentDir, path); - } + public String resolveAlias(String cmd) { + return aliases.getOrDefault(cmd, cmd); } } + From 1e626845ba6dfc792783c03028284b7ab4e8dd4b Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:08:48 +0530 Subject: [PATCH 06/29] Create CommandRegistry for command management This class provides functionality to register and retrieve commands by their names, ensuring case insensitivity. --- src/main/java/com/mycmd/CommandRegistry.java | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/com/mycmd/CommandRegistry.java diff --git a/src/main/java/com/mycmd/CommandRegistry.java b/src/main/java/com/mycmd/CommandRegistry.java new file mode 100644 index 0000000..aaf0358 --- /dev/null +++ b/src/main/java/com/mycmd/CommandRegistry.java @@ -0,0 +1,23 @@ +package com.mycmd; + +import java.util.HashMap; +import java.util.Map; + +/** + * Registers and retrieves commands by name. + */ +public class CommandRegistry { + private final Map commands = new HashMap<>(); + + public void register(String name, Command cmd) { + commands.put(name.toLowerCase(), cmd); + } + + public Command get(String name) { + return commands.get(name.toLowerCase()); + } + + public Map getAll() { + return commands; + } +} From 8dbed6e59352a668e536284b497d4dc465fe8247 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:10:45 +0530 Subject: [PATCH 07/29] Add ShellEngine class for command execution This class serves as the central execution engine for processing commands. --- src/main/java/com/mycmd/ShellEngine.java | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/mycmd/ShellEngine.java diff --git a/src/main/java/com/mycmd/ShellEngine.java b/src/main/java/com/mycmd/ShellEngine.java new file mode 100644 index 0000000..c22e963 --- /dev/null +++ b/src/main/java/com/mycmd/ShellEngine.java @@ -0,0 +1,38 @@ +package com.mycmd; + +import java.io.IOException; +import java.util.Arrays; + +/** + * Central execution engine. + */ +public class ShellEngine { + + private final CommandRegistry registry; + private final ShellContext context; + + public ShellEngine(CommandRegistry registry, ShellContext context) { + this.registry = registry; + this.context = context; + } + + public void execute(String input) { + if (input == null || input.trim().isEmpty()) return; + + String[] parts = input.trim().split("\\s+"); + String cmdName = context.resolveAlias(parts[0]); + String[] args = Arrays.copyOfRange(parts, 1, parts.length); + + Command cmd = registry.get(cmdName); + if (cmd == null) { + System.out.println("❌ Unknown command: " + cmdName); + return; + } + + try { + cmd.execute(args, context); + } catch (IOException e) { + System.out.println("⚠️ Error executing command: " + e.getMessage()); + } + } +} From 6dc457785cd7691ecfd488a6217ac62d704818de Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:16:13 +0530 Subject: [PATCH 08/29] Add ConsoleShell for developer console mode Implement a developer console mode for debugging commands. --- src/main/java/com/mycmd/ConsoleShell.java | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/com/mycmd/ConsoleShell.java diff --git a/src/main/java/com/mycmd/ConsoleShell.java b/src/main/java/com/mycmd/ConsoleShell.java new file mode 100644 index 0000000..a35f824 --- /dev/null +++ b/src/main/java/com/mycmd/ConsoleShell.java @@ -0,0 +1,27 @@ +package com.mycmd; + +import java.util.Scanner; + +/** + * Developer console mode for debugging. + */ +public class ConsoleShell { + + public static void main(String[] args) { + CommandRegistry registry = new CommandRegistry(); + ShellContext context = new ShellContext(); + ShellEngine engine = new ShellEngine(registry, context); + + Scanner sc = new Scanner(System.in); + System.out.println("MyCMD Developer Console Mode\n(Type 'exit' to quit)"); + + while (true) { + System.out.print("> "); + String input = sc.nextLine(); + if (input.equalsIgnoreCase("exit")) break; + engine.execute(input); + } + + sc.close(); + } +} From 049788776f765713ac6beef1bb5d6dd6368e1c29 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:18:23 +0530 Subject: [PATCH 09/29] Refactor StringUtils to add utility methods --- src/main/java/com/mycmd/StringUtils.java | 90 +++--------------------- 1 file changed, 11 insertions(+), 79 deletions(-) diff --git a/src/main/java/com/mycmd/StringUtils.java b/src/main/java/com/mycmd/StringUtils.java index 8c2d4cb..f2e8827 100644 --- a/src/main/java/com/mycmd/StringUtils.java +++ b/src/main/java/com/mycmd/StringUtils.java @@ -1,88 +1,20 @@ package com.mycmd; -import java.util.Collection; -import java.util.Objects; - /** - * Small utility for string-based helper methods. Provides a findClosest(...) implementation using - * Levenshtein distance. + * String helper functions for commands. */ -public final class StringUtils { - - private StringUtils() {} - - /** - * Find the closest string in candidates to the input. Returns null when no candidate is close - * enough. - * - * @param input the input string - * @param candidates candidate strings - * @return the closest candidate or null - */ - public static String findClosest(String input, Collection candidates) { - if (input == null || input.isEmpty() || candidates == null || candidates.isEmpty()) { - return null; - } - - String best = null; - int bestDistance = Integer.MAX_VALUE; - - for (String candidate : candidates) { - if (candidate == null || candidate.isEmpty()) continue; - if (candidate.equalsIgnoreCase(input)) { - // exact match ignoring case - return immediately - return candidate; - } - int distance = levenshteinDistance(input.toLowerCase(), candidate.toLowerCase()); - if (distance < bestDistance) { - bestDistance = distance; - best = candidate; - } - } - - // Choose a threshold: allow suggestion only when the distance is reasonably small. - // Here we allow suggestions when distance <= max(1, input.length()/3) - int threshold = Math.max(1, input.length() / 3); - if (bestDistance <= threshold) { - return best; - } - return null; +public class StringUtils { + public static boolean isEmpty(String s) { + return s == null || s.trim().isEmpty(); } - // Classic iterative Levenshtein algorithm (memory O(min(m,n))) - private static int levenshteinDistance(String a, String b) { - if (Objects.equals(a, b)) return 0; - if (a.length() == 0) return b.length(); - if (b.length() == 0) return a.length(); - - // ensure a is the shorter - if (a.length() > b.length()) { - String tmp = a; - a = b; - b = tmp; - } - - int[] previous = new int[a.length() + 1]; - int[] current = new int[a.length() + 1]; - - for (int i = 0; i <= a.length(); i++) previous[i] = i; - - for (int j = 1; j <= b.length(); j++) { - current[0] = j; - char bj = b.charAt(j - 1); - for (int i = 1; i <= a.length(); i++) { - int cost = (a.charAt(i - 1) == bj) ? 0 : 1; - current[i] = min3(current[i - 1] + 1, previous[i] + 1, previous[i - 1] + cost); - } - // swap previous and current - int[] temporary = previous; - previous = current; - current = temporary; + public static String join(String[] arr, int start) { + StringBuilder sb = new StringBuilder(); + for (int i = start; i < arr.length; i++) { + if (i > start) sb.append(' '); + sb.append(arr[i]); } - return previous[a.length()]; - } - - private static int min3(int x, int y, int z) { - return Math.min(x, Math.min(y, z)); + return sb.toString(); } } + From 7856ea2a7b288bad1d831e533a3981a3b1317a44 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:30:35 +0530 Subject: [PATCH 10/29] Create MainApp as JavaFX entry point for MyCMD Implement JavaFX application for MyCMD terminal. --- src/main/java/com/mycmd/gui/MainApp.java | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/main/java/com/mycmd/gui/MainApp.java diff --git a/src/main/java/com/mycmd/gui/MainApp.java b/src/main/java/com/mycmd/gui/MainApp.java new file mode 100644 index 0000000..60f3867 --- /dev/null +++ b/src/main/java/com/mycmd/gui/MainApp.java @@ -0,0 +1,56 @@ +package com.mycmd.gui; + +import com.mycmd.*; +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.image.Image; +import javafx.stage.Stage; + +/** + * JavaFX entry point — futuristic terminal window for MyCMD. + */ +public class MainApp extends Application { + + private static ShellEngine engine; + private static ShellContext context; + private static CommandRegistry registry; + + @Override + public void start(Stage stage) throws Exception { + // initialize core shell + context = new ShellContext(); + registry = new CommandRegistry(); + engine = new ShellEngine(registry, context); + + // register built-in commands (auto load) + registerBuiltIns(); + + FXMLLoader loader = new FXMLLoader( + getClass().getResource("/com/mycmd/gui/terminal.fxml")); + Scene scene = new Scene(loader.load()); + scene.getStylesheets().add( + getClass().getResource("/com/mycmd/gui/style.css").toExternalForm()); + + TerminalController controller = loader.getController(); + controller.init(engine, context); + + stage.setTitle("MyCMD ░▓ Java Terminal ▓░"); + stage.getIcons().add( + new Image(getClass().getResourceAsStream("/com/mycmd/gui/icon.png"))); + stage.setScene(scene); + stage.setResizable(false); + stage.show(); + } + + private void registerBuiltIns() { + registry.register("alias", new com.mycmd.commands.AliasCommand()); + registry.register("dir", new com.mycmd.commands.DirCommand()); + registry.register("echo", new com.mycmd.commands.EchoCommand()); + // add others automatically here as you expand + } + + public static void main(String[] args) { + launch(); + } +} From fac09139032f3745a2fafa7b73587a1a2f1eee30 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:31:41 +0530 Subject: [PATCH 11/29] Add TerminalController for terminal GUI functionality --- .../com/mycmd/gui/TerminalController.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/main/java/com/mycmd/gui/TerminalController.java diff --git a/src/main/java/com/mycmd/gui/TerminalController.java b/src/main/java/com/mycmd/gui/TerminalController.java new file mode 100644 index 0000000..6ab93b3 --- /dev/null +++ b/src/main/java/com/mycmd/gui/TerminalController.java @@ -0,0 +1,44 @@ +package com.mycmd.gui; + +import com.mycmd.ShellContext; +import com.mycmd.ShellEngine; +import javafx.fxml.FXML; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; + +/** + * Controller for the FXML terminal. + */ +public class TerminalController { + + @FXML private TextArea outputArea; + @FXML private TextField inputField; + @FXML private ScrollPane scrollPane; + + private ShellEngine engine; + private ShellContext context; + + public void init(ShellEngine engine, ShellContext context) { + this.engine = engine; + this.context = context; + + output("💻 Welcome to MyCMD - Java made Terminal"); + output("Type 'help' for available commands.\n"); + + inputField.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.ENTER) { + String input = inputField.getText(); + inputField.clear(); + output("> " + input); + engine.execute(input); + scrollPane.setVvalue(1.0); + } + }); + } + + private void output(String text) { + outputArea.appendText(text + "\n"); + } +} From 6a86af3b93204d3771a75b393d3c73efa8a5127e Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Mon, 10 Nov 2025 17:32:28 +0530 Subject: [PATCH 12/29] Add terminal.fxml layout for terminal GUI --- src/main/java/com/mycmd/gui/terminal.fxml | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/com/mycmd/gui/terminal.fxml diff --git a/src/main/java/com/mycmd/gui/terminal.fxml b/src/main/java/com/mycmd/gui/terminal.fxml new file mode 100644 index 0000000..df83243 --- /dev/null +++ b/src/main/java/com/mycmd/gui/terminal.fxml @@ -0,0 +1,25 @@ + + + + + + + +