Skip to content

Commit

Permalink
Cmdline interpreter mode improvements.
Browse files Browse the repository at this point in the history
This adds the ability to clear the environment with ~, and also adds the
ability to print out a variable just by running a line with the
variable.
  • Loading branch information
LadyCailin committed Mar 25, 2024
1 parent 3bd0f4f commit f0bd0ba
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,10 @@ public synchronized void stopAllNow() {
*/
@Override
public synchronized void stopAll() {
service.shutdown();
service = null;
if(service != null) {
service.shutdown();
service = null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,11 @@ public void executeAutoIncludes(Environment env, Script s) {
}
}
}

public void clear() {
this.analysisCache.clear();
this.autoIncludes.clear();
this.dynamicAnalysisParentScopeCache.clear();
this.cache.clear();
}
}
86 changes: 43 additions & 43 deletions src/main/java/com/laytonsmith/tools/Interpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
import com.laytonsmith.PureUtilities.Common.FileUtil;
import com.laytonsmith.PureUtilities.Common.FileWriteMode;
import com.laytonsmith.PureUtilities.Common.HTMLUtils;
import com.laytonsmith.PureUtilities.Common.MutableObject;
import com.laytonsmith.PureUtilities.Common.OSUtils;
import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.PureUtilities.Common.StreamUtils;
import com.laytonsmith.PureUtilities.Common.StringUtils;
import com.laytonsmith.PureUtilities.Common.WinRegistry;
import com.laytonsmith.PureUtilities.LimitedQueue;
import com.laytonsmith.PureUtilities.RunnableQueue;
import com.laytonsmith.PureUtilities.SignalHandler;
import com.laytonsmith.PureUtilities.SignalType;
import com.laytonsmith.PureUtilities.Signals;
Expand Down Expand Up @@ -109,14 +106,12 @@
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
import java.util.UUID;
Expand All @@ -132,6 +127,7 @@
import static com.laytonsmith.PureUtilities.TermColors.pl;
import static com.laytonsmith.PureUtilities.TermColors.reset;
import com.laytonsmith.abstraction.entities.MCTransformation;
import com.laytonsmith.core.natives.interfaces.Mixed;
import org.joml.Quaternionf;
import org.joml.Vector3f;

Expand All @@ -147,14 +143,8 @@ public final class Interpreter {
*
* BAD THINGS WILL HAPPEN TO EVERYBODY YOU LOVE IF THIS IS CHANGED!
*/
private static final String UNIX_INTERPRETER_INSTALLATION_LOCATION = "/usr/local/bin/";
private static final String UNIX_INTERPRETER_INSTALLATION_LOC = "/usr/local/bin/";

/**
* Be sure to update this if the powershell.psm1 file changes.
*/
private static final String POWERSHELL_MODULE_VERSION = "1.0.0";

private boolean inTTYMode = false;
private boolean multilineMode = false;
private boolean inShellMode = false;
private String script = "";
Expand All @@ -164,8 +154,6 @@ public final class Interpreter {

private volatile boolean isExecuting = false;

private final Queue<String> commandHistory = new LimitedQueue<>(MAX_COMMAND_HISTORY);

/**
* If they mash ctrlC a bunch, they probably really want to quit, so we'll keep track of this, and reset it only if
* they then run an actual command.
Expand All @@ -177,11 +165,6 @@ public final class Interpreter {
*/
private static final int MAX_CTRL_C_MASHES = 5;

/**
* Max commands that are tracked.
*/
private static final int MAX_COMMAND_HISTORY = 100;

public static void startWithTTY(File file, List<String> args, boolean systemExitOnFailure) throws IOException, DataSourceException, URISyntaxException, Profiles.InvalidProfileException {
startWithTTY(file.getCanonicalPath(), args, systemExitOnFailure);
}
Expand Down Expand Up @@ -219,7 +202,8 @@ private String getHelpMsg() {
+ "If the line starts with $$, then the rest of the line is taken to be a shell command. The command is taken as a string, wrapped\n"
+ "in shell_adv(), (where system out and system err are piped to the corresponding outputs).\n"
+ "If $$ is on a line by itself, it puts the shell in shell_adv mode, and each line is taken as if it started\n"
+ "with $$. Use - on a line by itself to exit this mode as well.\n\n"
+ "with $$. Use - on a line by itself to exit this mode as well. Using ~ on a line by itself clears\n"
+ "the environment (i.e. unsets all variables and procs, etc).\n\n"
+ "For more information about a specific function, type \"help function\"\n"
+ "and for documentation plus examples, type \"examples function\". See the api tool\n"
+ "for more information about this feature.";
Expand All @@ -240,6 +224,7 @@ private String getHelpMsg() {
* @throws IOException
* @throws DataSourceException
* @throws URISyntaxException
* @throws Profiles.InvalidProfileException
*/
public Interpreter(List<String> args, String cwd) throws IOException, DataSourceException, URISyntaxException, Profiles.InvalidProfileException {
this(args, cwd, false);
Expand All @@ -256,17 +241,17 @@ private Interpreter(List<String> args, String cwd, boolean inTTYMode) throws IOE
if(System.console() == null) {
Scanner scanner = new Scanner(System.in);
//We need to read in everything, it's basically in multiline mode
StringBuilder script = new StringBuilder();
StringBuilder s = new StringBuilder();
String line;
try {
while((line = scanner.nextLine()) != null) {
script.append(line).append("\n");
s.append(line).append("\n");
}
} catch (NoSuchElementException e) {
//Done
}
try {
execute(script.toString(), args);
execute(s.toString(), args);
StreamUtils.GetSystemOut().print(TermColors.reset());
System.exit(0);
} catch (ConfigCompileException ex) {
Expand Down Expand Up @@ -508,7 +493,7 @@ private boolean textLine(String line) throws IOException {
* @throws IOException
* @throws DataSourceException
* @throws URISyntaxException
* @throws com.laytonsmith.tools.docgen.DocGenTemplates.Generator.GenerateException
* @throws DocGenTemplates.Generator.GenerateException
*/
public static String formatDocsForCmdline(String function, boolean showExamples) throws ConfigCompileException,
IOException, DataSourceException, URISyntaxException, DocGenTemplates.Generator.GenerateException {
Expand All @@ -518,8 +503,8 @@ public static String formatDocsForCmdline(String function, boolean showExamples)
b.append(TermColors.CYAN).append(d.ret).append(" ");
b.append(TermColors.RESET).append(f.getName()).append("(")
.append(TermColors.MAGENTA).append(d.originalArgs).append(TermColors.RESET).append(")\n");
if(f instanceof Function) {
Class<? extends CREThrowable>[] thrown = ((Function) f).thrown();
if(f instanceof Function function1) {
Class<? extends CREThrowable>[] thrown = function1.thrown();
if(thrown != null && thrown.length > 0) {
b.append("Throws: ");
Set<String> th = new HashSet<>();
Expand All @@ -541,16 +526,15 @@ public static String formatDocsForCmdline(String function, boolean showExamples)
String desc = reverseHTML(d.extendedDesc);
b.append(TermColors.WHITE).append(desc).append("\n");
}
if(f instanceof Function) {
if(f instanceof Function function1) {
if(f.getClass().getAnnotation(seealso.class) != null) {
List<String> seeAlso = new ArrayList<>();
for(Class c : ((Function) f).seeAlso()) {
for(Class c : function1.seeAlso()) {
Object i = ReflectionUtils.newInstance(c);
if(i instanceof Documentation) {
Documentation seeAlsoDocumentation = (Documentation) i;
if(i instanceof Documentation seeAlsoDocumentation) {
String color = TermColors.YELLOW;
if(i instanceof Function) {
if(((Function) f).isRestricted()) {
if(function1.isRestricted()) {
color = TermColors.CYAN;
} else {
color = TermColors.GREEN;
Expand Down Expand Up @@ -609,8 +593,8 @@ public static String reverseHTML(String input) {
String color;
try {
FunctionBase f = FunctionList.getFunction(function, null, Target.UNKNOWN);
if(f instanceof Function) {
if(((Function) f).isRestricted()) {
if(f instanceof Function function1) {
if(function1.isRestricted()) {
color = TermColors.CYAN;
} else {
color = TermColors.GREEN;
Expand Down Expand Up @@ -718,6 +702,7 @@ public static String reverseHTML(String input) {
* @param args
* @throws ConfigCompileException
* @throws IOException
* @throws cConfigCompileGroupException
*/
public void execute(String script, List<String> args) throws ConfigCompileException, IOException, ConfigCompileGroupException {
execute(script, args, null);
Expand All @@ -732,6 +717,7 @@ public void execute(String script, List<String> args) throws ConfigCompileExcept
* @param fromFile
* @throws ConfigCompileException
* @throws IOException
* @throws ConfigCompileGroupException
*/
public void execute(String script, List<String> args, File fromFile) throws ConfigCompileException, IOException, ConfigCompileGroupException {
CmdlineEvents.cmdline_prompt_input.CmdlinePromptInput input = new CmdlineEvents.cmdline_prompt_input.CmdlinePromptInput(script, inShellMode);
Expand All @@ -752,6 +738,17 @@ public void execute(String script, List<String> args, File fromFile) throws Conf
pl(getHelpMsg());
return;
}
if("~".equals(script)) {
pl("Clearing environment.");
env.getEnv(GlobalEnv.class).GetProcs().clear();
env.getEnv(GlobalEnv.class).GetVarList().clear();
for(Thread t : env.getEnv(StaticRuntimeEnv.class).GetDaemonManager().getActiveThreads()) {
t.interrupt();
}
env.getEnv(StaticRuntimeEnv.class).getExecutionQueue().stopAll();
env.getEnv(StaticRuntimeEnv.class).getIncludeCache().clear();
return;
}
if(fromFile == null) {
fromFile = new File("Interpreter");
}
Expand Down Expand Up @@ -833,12 +830,17 @@ public void execute(String script, List<String> args, File fromFile) throws Conf
ProfilePoint p = this.env.getEnv(StaticRuntimeEnv.class)
.GetProfiler().start("Interpreter Script", LogLevel.ERROR);
try {
final MutableObject<Throwable> wasThrown = new MutableObject<>();
scriptThread = new Thread(new Runnable() {

@Override
public void run() {
try {
if(tree.getChildren().size() == 1 && tree.getChildAt(0).getData() instanceof IVariable ivar) {
Mixed i = env.getEnv(GlobalEnv.class).GetVarList()
.get(ivar.getVariableName(), ivar.getTarget(), env).ival();
StreamUtils.GetSystemOut().println(i.val());
return;
}
MethodScriptCompiler.execute(tree, env, new MethodScriptComplete() {
@Override
public void done(String output) {
Expand Down Expand Up @@ -906,6 +908,7 @@ public void done(String output) {
* @param args Arguments to be passed to the script
* @throws ConfigCompileException If there is a compile error in the script
* @throws IOException
* @throws ConfigCompileGroupException
*/
public void execute(File script, List<String> args) throws ConfigCompileException, IOException, ConfigCompileGroupException {
String scriptString = FileUtil.read(script);
Expand All @@ -914,7 +917,7 @@ public void execute(File script, List<String> args) throws ConfigCompileExceptio

public boolean doBuiltin(String script) {
List<String> args = StringUtils.ArgParser(script);
if(args.size() > 0) {
if(!args.isEmpty()) {
String command = args.get(0);
args.remove(0);
command = command.toLowerCase(Locale.ENGLISH);
Expand Down Expand Up @@ -963,7 +966,7 @@ public boolean doBuiltin(String script) {
// is actually useful as is, because this is not supposed to be a scripting environment.. that's
// what the normal shell is for.
boolean colorize = false;
if(args.size() > 0 && "-e".equals(args.get(0))) {
if(!args.isEmpty() && "-e".equals(args.get(0))) {
colorize = true;
args.remove(0);
}
Expand All @@ -984,12 +987,12 @@ public static void install(String commandName) {
case MAC: {
try {
URL jar = Interpreter.class.getProtectionDomain().getCodeSource().getLocation();
File exe = new File(UNIX_INTERPRETER_INSTALLATION_LOCATION + commandName);
File exe = new File(UNIX_INTERPRETER_INSTALLATION_LOC + commandName);
String bashScript = Static.GetStringResource("/interpreter-helpers/bash.sh");
try {
bashScript = bashScript.replaceAll("%%LOCATION%%", jar.toURI().getPath());
} catch (URISyntaxException ex) {
ex.printStackTrace();
ex.printStackTrace(System.err);
}
exe.createNewFile();
if(!exe.canWrite()) {
Expand All @@ -1016,7 +1019,6 @@ public static void install(String commandName) {
break;
}
case WINDOWS: {
Path tmp = null;
try {
// C# installer, not really uninstallable, so temporarily removing this, so the other installer
// can be used with no risk.
Expand Down Expand Up @@ -1085,7 +1087,7 @@ public static void install(String commandName) {
}
}
StreamUtils.GetSystemOut().println("MethodScript has successfully been installed on your system. Note that you may need to rerun the install command"
+ " if you change locations of the jar, or rename it. Be sure to put \"#!" + UNIX_INTERPRETER_INSTALLATION_LOCATION + commandName + "\" at the top of all your scripts,"
+ " if you change locations of the jar, or rename it. Be sure to put \"#!" + UNIX_INTERPRETER_INSTALLATION_LOC + commandName + "\" at the top of all your scripts,"
+ " if you wish them to be executable on unix systems, and set the execution bit with chmod +x <script name> on unix systems. (Or use the '" + commandName + " -- new' cmdline utility.)");
StreamUtils.GetSystemOut().println("Try this script to test out the basic features of the scripting system:\n");
StreamUtils.GetSystemOut().println(Static.GetStringResource("/interpreter-helpers/sample.ms"));
Expand All @@ -1112,7 +1114,7 @@ public static void uninstall(String commandName) {
case LINUX:
case MAC:
try {
File exe = new File(UNIX_INTERPRETER_INSTALLATION_LOCATION + commandName);
File exe = new File(UNIX_INTERPRETER_INSTALLATION_LOC + commandName);
if(!exe.delete()) {
throw new IOException();
}
Expand All @@ -1134,8 +1136,6 @@ public static void uninstall(String commandName) {
@convert(type = Implementation.Type.SHELL)
public static class ShellConvertor extends AbstractConvertor {

RunnableQueue queue = new RunnableQueue("ShellInterpreter-userland");

@Override
public MCLocation GetLocation(MCWorld w, double x, double y, double z, float yaw, float pitch) {
throw new UnsupportedOperationException("This method is not supported from a shell.");
Expand Down

0 comments on commit f0bd0ba

Please sign in to comment.