Adding 'shell' subcommand for 'acx' to enable multiple commands. Needs to run from a pipe as well, limiting shell capabilities a bit (?).
This commit is contained in:
parent
47206f0fd8
commit
25ddc7f66a
|
@ -19,36 +19,17 @@
|
|||
*/
|
||||
package io.github.applecommander.acx;
|
||||
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import io.github.applecommander.acx.command.CompareCommand;
|
||||
import io.github.applecommander.acx.command.ConvertCommand;
|
||||
import io.github.applecommander.acx.command.CopyFileCommand;
|
||||
import io.github.applecommander.acx.command.CreateDiskCommand;
|
||||
import io.github.applecommander.acx.command.DeleteCommand;
|
||||
import io.github.applecommander.acx.command.DiskMapCommand;
|
||||
import io.github.applecommander.acx.command.DumpCommand;
|
||||
import io.github.applecommander.acx.command.ExportCommand;
|
||||
import io.github.applecommander.acx.command.FindDuplicateFilesCommand;
|
||||
import io.github.applecommander.acx.command.ImportCommand;
|
||||
import io.github.applecommander.acx.command.InfoCommand;
|
||||
import io.github.applecommander.acx.command.ListCommand;
|
||||
import io.github.applecommander.acx.command.LockCommand;
|
||||
import io.github.applecommander.acx.command.MkdirCommand;
|
||||
import io.github.applecommander.acx.command.ReadCommand;
|
||||
import io.github.applecommander.acx.command.RenameDiskCommand;
|
||||
import io.github.applecommander.acx.command.RenameFileCommand;
|
||||
import io.github.applecommander.acx.command.RmdirCommand;
|
||||
import io.github.applecommander.acx.command.UnlockCommand;
|
||||
import io.github.applecommander.acx.command.WriteCommand;
|
||||
import io.github.applecommander.acx.command.*;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.HelpCommand;
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Primary entry point into the 'acx' utility.
|
||||
*/
|
||||
|
@ -77,6 +58,7 @@ import picocli.CommandLine.Option;
|
|||
RenameFileCommand.class,
|
||||
RenameDiskCommand.class,
|
||||
RmdirCommand.class,
|
||||
ShellCommand.class,
|
||||
UnlockCommand.class,
|
||||
WriteCommand.class
|
||||
})
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2019-2023 by Robert Greene and others
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package io.github.applecommander.acx.command;
|
||||
|
||||
import io.github.applecommander.acx.PrintExceptionMessageHandler;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Command(name = "shell",
|
||||
descriptionHeading = "%n",
|
||||
commandListHeading = "%nCommands:%n",
|
||||
optionListHeading = "%nOptions:%n",
|
||||
description = "Enter 'acx' shell mode to support multiple commands.",
|
||||
subcommands = {
|
||||
CompareCommand.class,
|
||||
ConvertCommand.class,
|
||||
CopyFileCommand.class,
|
||||
CreateDiskCommand.class,
|
||||
DeleteCommand.class,
|
||||
DiskMapCommand.class,
|
||||
DumpCommand.class,
|
||||
ExportCommand.class,
|
||||
FindDuplicateFilesCommand.class,
|
||||
CommandLine.HelpCommand.class,
|
||||
ImportCommand.class,
|
||||
InfoCommand.class,
|
||||
ListCommand.class,
|
||||
LockCommand.class,
|
||||
MkdirCommand.class,
|
||||
ReadCommand.class,
|
||||
RenameFileCommand.class,
|
||||
RenameDiskCommand.class,
|
||||
RmdirCommand.class,
|
||||
UnlockCommand.class,
|
||||
WriteCommand.class
|
||||
})
|
||||
public class ShellCommand implements Callable<Integer> {
|
||||
private static final String PROMPT = "ACX> ";
|
||||
|
||||
private boolean exit = false;
|
||||
@Command(name = "exit", aliases = { "quit" }, description = "Exit shell environment")
|
||||
public void exitShell() {
|
||||
exit = true;
|
||||
}
|
||||
|
||||
private String defaultDiskName = null;
|
||||
@Command(name = "default", description = "Display or set the default disk")
|
||||
public void defaultDisk(@Parameters(description = "Disk to be set as default", arity = "0..1", defaultValue = "") String diskName) {
|
||||
if (diskName == null || diskName.isEmpty()) {
|
||||
if (defaultDiskName == null) {
|
||||
System.out.println("No default disk has been set.");
|
||||
}
|
||||
else {
|
||||
System.out.printf("The default disk is '%s'.\n", defaultDiskName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we don't know the commands being used, so can't really test for existence...
|
||||
defaultDiskName = diskName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer call() throws IOException {
|
||||
final boolean isTTY = (System.console() != null);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
|
||||
while (!exit) {
|
||||
System.out.print(PROMPT);
|
||||
String line = reader.readLine();
|
||||
if (line == null) break;
|
||||
if (!isTTY) {
|
||||
System.out.println(line);
|
||||
}
|
||||
|
||||
CommandLine cmd = new CommandLine(new ShellCommand());
|
||||
cmd.setExecutionExceptionHandler(new PrintExceptionMessageHandler());
|
||||
cmd.setCaseInsensitiveEnumValuesAllowed(true);
|
||||
|
||||
List<String> args = getArgs(line);
|
||||
if (defaultDiskName != null) {
|
||||
System.setProperty("ACX_DISK_NAME", defaultDiskName);
|
||||
}
|
||||
cmd.execute(args.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static List<String> getArgs(String line) {
|
||||
// See https://stackoverflow.com/questions/7804335/split-string-on-spaces-in-java-except-if-between-quotes-i-e-treat-hello-wor
|
||||
final Pattern splitter = Pattern.compile("([^\"]\\S*|\".+?\")\\s*");
|
||||
|
||||
Matcher m = splitter.matcher(line);
|
||||
List<String> args = new ArrayList<>();
|
||||
while (m.find()) {
|
||||
String s = m.group(1);
|
||||
if (s.startsWith("\"") && s.endsWith("\"")) {
|
||||
s = s.substring(1, s.length()-1);
|
||||
}
|
||||
args.add(s);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue