Skip to content
Snippets Groups Projects
Commit 3b922bfd authored by dgelessus's avatar dgelessus
Browse files

Add code completion for B keywords and identifiers in :eval

parent f522d444
No related branches found
No related tags found
No related merge requests found
package de.prob2.jupyter.commands; package de.prob2.jupyter.commands;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.prob.animator.command.CompleteIdentifierCommand;
import de.prob.animator.domainobjects.AbstractEvalResult; import de.prob.animator.domainobjects.AbstractEvalResult;
import de.prob.animator.domainobjects.ComputationNotCompletedResult; import de.prob.animator.domainobjects.ComputationNotCompletedResult;
import de.prob.animator.domainobjects.EnumerationWarning; import de.prob.animator.domainobjects.EnumerationWarning;
import de.prob.animator.domainobjects.EvalResult; import de.prob.animator.domainobjects.EvalResult;
import de.prob.animator.domainobjects.EvaluationErrorResult; import de.prob.animator.domainobjects.EvaluationErrorResult;
import de.prob.statespace.Trace;
import de.prob.unicode.UnicodeTranslator; import de.prob.unicode.UnicodeTranslator;
import de.prob2.jupyter.UserErrorException; import de.prob2.jupyter.UserErrorException;
import io.github.spencerpark.jupyter.kernel.ReplacementOptions;
import io.github.spencerpark.jupyter.kernel.display.DisplayData; import io.github.spencerpark.jupyter.kernel.display.DisplayData;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
...@@ -23,7 +31,15 @@ import org.slf4j.Logger; ...@@ -23,7 +31,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public final class CommandUtils { public final class CommandUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(CommandUtils.class); private static final @NotNull Logger LOGGER = LoggerFactory.getLogger(CommandUtils.class);
private static final @NotNull Pattern B_IDENTIFIER_PATTERN = Pattern.compile("[A-Za-z][A-Za-z0-9_]*");
private CommandUtils() {
super();
throw new AssertionError("Utility class");
}
public static @NotNull List<@NotNull String> splitArgs(final @NotNull String args, final int limit) { public static @NotNull List<@NotNull String> splitArgs(final @NotNull String args, final int limit) {
final String[] split = args.split("\\h+", limit); final String[] split = args.split("\\h+", limit);
...@@ -110,4 +126,35 @@ public final class CommandUtils { ...@@ -110,4 +126,35 @@ public final class CommandUtils {
return result; return result;
} }
} }
public static @NotNull ReplacementOptions completeInBExpression(final @NotNull Trace trace, final @NotNull String code, final int at) {
final Matcher identifierMatcher = B_IDENTIFIER_PATTERN.matcher(code);
String identifier = "";
int start = at;
int end = at;
// Try to find the identifier that the cursor is in.
// If the cursor is not on an identifier, default to empty string, i. e. show all possible completions.
while (identifierMatcher.find() && identifierMatcher.start() < at) {
if (identifierMatcher.end() >= at) {
identifier = code.substring(identifierMatcher.start(), at);
start = identifierMatcher.start();
end = identifierMatcher.end();
break;
}
}
final CompleteIdentifierCommand cmdExact = new CompleteIdentifierCommand(identifier);
cmdExact.setIncludeKeywords(true);
trace.getStateSpace().execute(cmdExact);
// Use LinkedHashSet to remove duplicates while maintaining order.
final Set<String> completions = new LinkedHashSet<>(cmdExact.getCompletions());
final CompleteIdentifierCommand cmdIgnoreCase = new CompleteIdentifierCommand(identifier);
cmdIgnoreCase.setIgnoreCase(true);
cmdIgnoreCase.setIncludeKeywords(true);
trace.getStateSpace().execute(cmdIgnoreCase);
completions.addAll(cmdIgnoreCase.getCompletions());
return new ReplacementOptions(new ArrayList<>(completions), start, end);
}
} }
...@@ -7,6 +7,7 @@ import de.prob.statespace.AnimationSelector; ...@@ -7,6 +7,7 @@ import de.prob.statespace.AnimationSelector;
import de.prob2.jupyter.ProBKernel; import de.prob2.jupyter.ProBKernel;
import io.github.spencerpark.jupyter.kernel.ReplacementOptions;
import io.github.spencerpark.jupyter.kernel.display.DisplayData; import io.github.spencerpark.jupyter.kernel.display.DisplayData;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
...@@ -35,4 +36,9 @@ public final class EvalCommand implements Command { ...@@ -35,4 +36,9 @@ public final class EvalCommand implements Command {
public @NotNull DisplayData run(final @NotNull ProBKernel kernel, final @NotNull String argString) { public @NotNull DisplayData run(final @NotNull ProBKernel kernel, final @NotNull String argString) {
return CommandUtils.displayDataForEvalResult(this.animationSelector.getCurrentTrace().evalCurrent(argString, FormulaExpand.EXPAND)); return CommandUtils.displayDataForEvalResult(this.animationSelector.getCurrentTrace().evalCurrent(argString, FormulaExpand.EXPAND));
} }
@Override
public @NotNull ReplacementOptions complete(final @NotNull ProBKernel kernel, final @NotNull String argString, final int at) {
return CommandUtils.completeInBExpression(this.animationSelector.getCurrentTrace(), argString, at);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment