diff --git a/common/src/main/java/revxrsal/commands/autocomplete/SingleCommandCompleter.java b/common/src/main/java/revxrsal/commands/autocomplete/SingleCommandCompleter.java
index e58dfabc..517658e9 100644
--- a/common/src/main/java/revxrsal/commands/autocomplete/SingleCommandCompleter.java
+++ b/common/src/main/java/revxrsal/commands/autocomplete/SingleCommandCompleter.java
@@ -31,7 +31,7 @@ final class SingleCommandCompleter {
public SingleCommandCompleter(A actor, ExecutableCommand command, MutableStringStream input) {
this.command = command;
this.input = input;
- this.context = ExecutionContext.createMutable(command, actor, input.toImmutableCopy());
+ this.context = ExecutionContext.createMutable(command, actor, input.toImmutableView());
}
private void rememberPosition() {
@@ -84,7 +84,7 @@ private CompletionResult completeParameter(@NotNull ParameterNode par
context.addResolvedArgument(parameter.name(), value);
int positionAfterParsing = input.position();
String consumed = restorePosition();
- Collection parameterSuggestions = parameter.complete(context.actor(), input, context);
+ Collection parameterSuggestions = parameter.complete(context);
input.setPosition(positionAfterParsing); // restore so that we can move forward
if (input.hasFinished()) {
@@ -96,7 +96,7 @@ private CompletionResult completeParameter(@NotNull ParameterNode par
return CompletionResult.CONTINUE;
} catch (Throwable t) {
String consumed = restorePosition();
- filterSuggestions(consumed, parameter.complete(context.actor(), input, context));
+ filterSuggestions(consumed, parameter.complete(context));
return CompletionResult.HALT;
}
}
@@ -123,7 +123,7 @@ private void completeFlags(@NotNull Map> remain
if (input.hasFinished())
return;
if (input.remaining() == 1 && input.peek() == ' ') {
- Collection parameterSuggestions = targetFlag.complete(context.actor(), input, context);
+ Collection parameterSuggestions = targetFlag.complete(context);
suggestions.addAll(parameterSuggestions);
return;
}
@@ -161,7 +161,7 @@ private void completeFlags(@NotNull Map> remain
if (targetFlag.isSwitch())
continue;
if (input.remaining() == 1 && input.peek() == ' ') {
- Collection parameterSuggestions = targetFlag.complete(context.actor(), input, context);
+ Collection parameterSuggestions = targetFlag.complete(context);
suggestions.addAll(parameterSuggestions);
return;
}
diff --git a/common/src/main/java/revxrsal/commands/node/ParameterNode.java b/common/src/main/java/revxrsal/commands/node/ParameterNode.java
index 31514089..3e56679e 100644
--- a/common/src/main/java/revxrsal/commands/node/ParameterNode.java
+++ b/common/src/main/java/revxrsal/commands/node/ParameterNode.java
@@ -140,13 +140,11 @@ default boolean isRequired() {
/**
* Provides suggestions for the given user input.
*
- * @param actor The actor to generate for
- * @param input The command input
* @param context The execution context.
* @return The
*/
@Contract(pure = true)
- @NotNull Collection complete(A actor, @NotNull StringStream input, @NotNull ExecutionContext context);
+ @NotNull Collection complete(@NotNull ExecutionContext context);
/**
* Returns the parameter Java type
diff --git a/common/src/main/java/revxrsal/commands/node/parser/ParameterNodeImpl.java b/common/src/main/java/revxrsal/commands/node/parser/ParameterNodeImpl.java
index d4cee1df..36d878ea 100644
--- a/common/src/main/java/revxrsal/commands/node/parser/ParameterNodeImpl.java
+++ b/common/src/main/java/revxrsal/commands/node/parser/ParameterNodeImpl.java
@@ -182,7 +182,7 @@ public boolean isOptional() {
}
@Override
- public @NotNull Collection complete(@NotNull A actor, @NotNull StringStream input, @NotNull ExecutionContext context) {
+ public @NotNull Collection complete(@NotNull ExecutionContext context) {
return suggestions.getSuggestions(context);
}
diff --git a/common/src/main/java/revxrsal/commands/stream/MutableStringStream.java b/common/src/main/java/revxrsal/commands/stream/MutableStringStream.java
index b82e012e..2fcb9fb5 100644
--- a/common/src/main/java/revxrsal/commands/stream/MutableStringStream.java
+++ b/common/src/main/java/revxrsal/commands/stream/MutableStringStream.java
@@ -204,4 +204,16 @@ public interface MutableStringStream extends StringStream {
@Contract(pure = true, value = "-> new")
MutableStringStream toMutableCopy();
+ /**
+ * Returns an immutable view of this {@link MutableStringStream}. A view is different
+ * from a copy, as it will reflect changes to the original string stream, but cannot
+ * be used to it.
+ *
+ * @return An immutable string stream view
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Unmodifiable
+ StringStream toImmutableView();
+
}
diff --git a/common/src/main/java/revxrsal/commands/stream/MutableStringStreamImpl.java b/common/src/main/java/revxrsal/commands/stream/MutableStringStreamImpl.java
index 4fc8bd46..e4642d35 100644
--- a/common/src/main/java/revxrsal/commands/stream/MutableStringStreamImpl.java
+++ b/common/src/main/java/revxrsal/commands/stream/MutableStringStreamImpl.java
@@ -25,6 +25,7 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Unmodifiable;
import revxrsal.commands.exception.InputParseException;
import revxrsal.commands.exception.InvalidBooleanException;
import revxrsal.commands.exception.InvalidDecimalException;
@@ -34,6 +35,8 @@
public final class MutableStringStreamImpl extends BaseStringStream implements MutableStringStream {
+ private StringStreamView immutableView = null;
+
/**
* Creates a new {@link MutableStringStream} with its position at zero.
*
@@ -217,4 +220,81 @@ public boolean isMutable() {
return true;
}
+ @Override public @NotNull @Unmodifiable StringStream toImmutableView() {
+ if (immutableView == null)
+ immutableView = new StringStreamView();
+ return immutableView;
+ }
+
+ private class StringStreamView implements StringStream {
+
+ @Override public @NotNull String source() {
+ return MutableStringStreamImpl.this.source();
+ }
+
+ @Override public int totalSize() {
+ return MutableStringStreamImpl.this.totalSize();
+ }
+
+ @Override public int remaining() {
+ return MutableStringStreamImpl.this.remaining();
+ }
+
+ @Override public char peek() {
+ return MutableStringStreamImpl.this.peek();
+ }
+
+ @Override public String peek(int characters) {
+ return MutableStringStreamImpl.this.peek(characters);
+ }
+
+ @Override public char peekOffset(int offset) {
+ return MutableStringStreamImpl.this.peekOffset(offset);
+ }
+
+ @Override public boolean hasRemaining() {
+ return MutableStringStreamImpl.this.hasRemaining();
+ }
+
+ @Override public boolean hasFinished() {
+ return MutableStringStreamImpl.this.hasFinished();
+ }
+
+ @Override public boolean canRead(int characters) {
+ return MutableStringStreamImpl.this.canRead(characters);
+ }
+
+ @Override public int position() {
+ return MutableStringStreamImpl.this.position();
+ }
+
+ @Override public @NotNull String peekUnquotedString() {
+ return MutableStringStreamImpl.this.peekUnquotedString();
+ }
+
+ @Override public @NotNull String peekString() {
+ return MutableStringStreamImpl.this.peekString();
+ }
+
+ @Override public @NotNull String peekRemaining() {
+ return MutableStringStreamImpl.this.peekRemaining();
+ }
+
+ @Override public @NotNull @Unmodifiable StringStream toImmutableCopy() {
+ return MutableStringStreamImpl.this.toImmutableCopy();
+ }
+
+ @Override public @NotNull MutableStringStream toMutableCopy() {
+ return MutableStringStreamImpl.this.toMutableCopy();
+ }
+
+ @Override public boolean isMutable() {
+ return false;
+ }
+
+ @Override public boolean isEmpty() {
+ return MutableStringStreamImpl.this.isEmpty();
+ }
+ }
+
}