Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/com/mycmd/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public static void main(String[] args) {
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);
Expand Down Expand Up @@ -55,6 +58,21 @@ public static void main(String[] args) {
}
}

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 void registerCommands(Map<String, Command> commands) {
commands.put("dir", new DirCommand());
commands.put("cd", new CdCommand());
Expand All @@ -81,5 +99,7 @@ private static void registerCommands(Map<String, Command> commands) {
commands.put("pwd", new PwdCommand());
commands.put("uptime", new UptimeCommand());
commands.put("clearhistory", new ClearHistoryCommand());
commands.put("alias", new AliasCommand());
commands.put("unalias", new UnaliasCommand());
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/mycmd/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ default String description() {
default String usage() {
return "";
}
}
}
102 changes: 86 additions & 16 deletions src/main/java/com/mycmd/ShellContext.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package com.mycmd;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.io.*;
import java.util.*;
import java.time.Instant;

public class ShellContext {
private File currentDir;
private List<String> commandHistory;
private final long startTime;
private static final int MAX_HISTORY = 10;
private List<String> history;
private Map<String, String> aliases;
private static final String ALIAS_FILE = ".mycmd_aliases";
private static final int MAX_HISTORY = 100;
private final List<String> commandHistory;
private final Instant startTime;

public ShellContext() {
this.currentDir = new File(System.getProperty("user.dir"));
this.history = new ArrayList<>();
this.aliases = new HashMap<>();
this.commandHistory = new ArrayList<>();
this.startTime = System.currentTimeMillis();
this.startTime = Instant.now();
loadAliases();
}

public File getCurrentDir() {
Expand All @@ -24,25 +30,89 @@ public void setCurrentDir(File dir) {
this.currentDir = dir;
}

public long getStartTime() {
return startTime;
public void addToHistory(String command) {
history.add(command);
commandHistory.add(command); // Add to command history
if (history.size() > MAX_HISTORY) {
history.remove(0);
}
}

public List<String> getHistory() {
return new ArrayList<>(history);
}

public List<String> getCommandHistory() {
return commandHistory;
}

public void addToHistory(String command) {
if (command != null && !command.trim().isEmpty()) {
commandHistory.add(command.trim());
if (commandHistory.size() > MAX_HISTORY) {
commandHistory.remove(0);
public Instant getStartTime() {
return startTime;
}

public void clearHistory() {
history.clear();
}

// Alias management methods
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 Map<String, String> getAliases() {
return new HashMap<>(aliases);
}

public boolean hasAlias(String name) {
return aliases.containsKey(name);
}

private void loadAliases() {
File aliasFile = new File(System.getProperty("user.home"), ALIAS_FILE);
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());
}
}

public void clearHistory() {
commandHistory.clear();
private void saveAliases() {
File aliasFile = new File(System.getProperty("user.home"), ALIAS_FILE);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(aliasFile))) {
writer.write("# MyCMD Aliases Configuration\n");
writer.write("# Format: aliasName=command\n\n");
for (Map.Entry<String, String> entry : aliases.entrySet()) {
writer.write(entry.getKey() + "=" + entry.getValue() + "\n");
}
} catch (IOException e) {
System.err.println("Warning: Could not save aliases: " + e.getMessage());
}
}

/**
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/com/mycmd/commands/AliasCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.mycmd.commands;

import com.mycmd.Command;
import com.mycmd.ShellContext;

import java.io.IOException;
import java.util.Map;

public class AliasCommand implements Command {
@Override
public void execute(String[] args, ShellContext context) throws IOException {
// no args: list aliases
if (args == null || args.length == 0) {
Map<String, String> aliases = context.getAliases();
if (aliases.isEmpty()) {
System.out.println("No aliases defined.");
} else {
aliases.forEach((k, v) -> System.out.println(k + "=" + v));
}
return;
}

// single arg of form name=command
if (args.length == 1 && args[0].contains("=")) {
String[] parts = args[0].split("=", 2);
String name = parts[0].trim();
String cmd = parts[1].trim();
if (name.isEmpty() || cmd.isEmpty()) {
System.out.println("Invalid alias format. Usage: alias name=command");
return;
}
context.addAlias(name, cmd);
System.out.println("Alias added: " + name + "=" + cmd);
return;
}

// multiple args: first is name, rest form command
if (args.length >= 2) {
String name = args[0];
StringBuilder sb = new StringBuilder();
for (int i = 1; i < args.length; i++) {
if (i > 1) sb.append(' ');
sb.append(args[i]);
}
String cmd = sb.toString();
if (name.trim().isEmpty() || cmd.trim().isEmpty()) {
System.out.println("Invalid alias. Usage: alias name command... or alias name=command");
return;
}
context.addAlias(name, cmd);
System.out.println("Alias added: " + name + "=" + cmd);
return;
}

System.out.println("Invalid usage. Usage: alias [name=command] | alias [name command...]");
}

@Override
public String description() {
return "Create or list command aliases.";
}

@Override
public String usage() {
return "alias # list aliases\n" +
"alias name=command # create alias\n" +
"alias name command... # create alias";
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/mycmd/commands/UnaliasCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.mycmd.commands;

import com.mycmd.Command;
import com.mycmd.ShellContext;

import java.io.IOException;

public class UnaliasCommand implements Command {
@Override
public void execute(String[] args, ShellContext context) throws IOException {
if (args == null || args.length == 0) {
System.out.println("Usage: unalias name [name2 ...]");
return;
}

for (String name : args) {
if (name == null || name.trim().isEmpty()) continue;
if (context.hasAlias(name)) {
context.removeAlias(name);
System.out.println("Removed alias: " + name);
} else {
System.out.println("Alias not found: " + name);
}
}
}

@Override
public String description() {
return "Remove one or more aliases.";
}

@Override
public String usage() {
return "unalias name [name2 ...]";
}
}
34 changes: 22 additions & 12 deletions src/main/java/com/mycmd/commands/UptimeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import com.mycmd.Command;
import com.mycmd.ShellContext;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;

/**
* Displays how long the shell has been running since startup.
*
Expand All @@ -13,24 +17,30 @@
* Usage:
* - uptime : Display shell uptime in hours, minutes, and seconds
*
* The output format shows the uptime as "Up since Xh Ym Zs" where:
* - X is hours
* - Y is minutes
* - Z is seconds
* The output format shows the uptime as "Uptime: Xh Ym Zs" or with days if applicable.
*
* This is useful for monitoring how long a shell session has been active.
*/
public class UptimeCommand implements Command {
@Override
public void execute(String[] args, ShellContext context) {
long uptimeMillis = System.currentTimeMillis() - context.getStartTime();
public void execute(String[] args, ShellContext context) throws IOException {
Instant startTime = context.getStartTime();
Instant now = Instant.now();

// Calculate duration between start time and now
Duration uptime = Duration.between(startTime, now);

long totalSeconds = uptimeMillis / 1000;
long hours = totalSeconds / 3600;
long minutes = (totalSeconds % 3600) / 60;
long seconds = totalSeconds % 60;
long seconds = uptime.getSeconds();
long days = seconds / 86400;
long hours = (seconds % 86400) / 3600;
long minutes = (seconds % 3600) / 60;
long secs = seconds % 60;

System.out.printf("Up since %dh %dm %ds%n", hours, minutes, seconds);
System.out.print("Uptime: ");
if (days > 0) {
System.out.print(days + " day" + (days != 1 ? "s" : "") + ", ");
}
System.out.printf("%02d:%02d:%02d%n", hours, minutes, secs);
}

@Override
Expand All @@ -42,4 +52,4 @@ public String description() {
public String usage() {
return "uptime";
}
}
}