diff --git a/src/main/java/de/prob2/jupyter/ProBKernel.java b/src/main/java/de/prob2/jupyter/ProBKernel.java
index 96995ee72621595ca7d8b4c9e7de50e157c83dbd..68a845688c5c82a78ecf619cb2ab291760e78819 100644
--- a/src/main/java/de/prob2/jupyter/ProBKernel.java
+++ b/src/main/java/de/prob2/jupyter/ProBKernel.java
@@ -426,8 +426,8 @@ public final class ProBKernel extends BaseKernel {
 		);
 	}
 	
-	private static @Nullable ReplacementOptions completeCommandArguments(final @NotNull Command command, final @NotNull String argString, final int at) {
-		final SplitResult split = CommandUtils.splitArgs(command.getParameters(), new PositionedString(argString, 0), at);
+	private static @Nullable ReplacementOptions completeCommandArguments(final @NotNull Command command, final @NotNull PositionedString argString, final int at) {
+		final SplitResult split = CommandUtils.splitArgs(command.getParameters(), argString, at);
 		if (split.getParameterAtPosition().isPresent()) {
 			final Optional<Completer> completer = command.getParameterCompleters().getCompleterForParameter(split.getParameterAtPosition().get());
 			if (completer.isPresent()) {
@@ -444,15 +444,13 @@ public final class ProBKernel extends BaseKernel {
 		}
 	}
 	
-	@Override
-	public @Nullable ReplacementOptions complete(final @NotNull String code, final int at) {
-		final Matcher commandMatcher = COMMAND_PATTERN.matcher(code);
+	private @Nullable ReplacementOptions completeInternal(final @NotNull PositionedString code, final int at) {
+		final Matcher commandMatcher = COMMAND_PATTERN.matcher(code.getValue());
 		if (commandMatcher.matches()) {
 			// The code is a valid command.
-			final int argOffset = commandMatcher.start(2);
 			if (at <= commandMatcher.end(1)) {
 				// The cursor is somewhere in the command name, provide command completions.
-				final String prefix = code.substring(commandMatcher.start(1), at);
+				final String prefix = code.substring(commandMatcher.start(1), at).getValue();
 				return new ReplacementOptions(
 					this.getCommands().keySet().stream().filter(s -> s.startsWith(prefix)).sorted().collect(Collectors.toList()),
 					commandMatcher.start(1), 
@@ -465,16 +463,20 @@ public final class ProBKernel extends BaseKernel {
 				// The cursor is somewhere in the command arguments, ask the command to provide completions.
 				final String name = commandMatcher.group(1);
 				assert name != null;
-				final String argString = commandMatcher.group(2) == null ? "" : commandMatcher.group(2);
+				final PositionedString argString;
+				if (commandMatcher.group(2) == null) {
+					argString = code.substring(code.getValue().length());
+				} else {
+					argString = code.substring(commandMatcher.start(2), commandMatcher.end(2));
+				}
 				if (this.getCommands().containsKey(name)) {
-					final ReplacementOptions replacements = completeCommandArguments(this.getCommands().get(name), argString, at - argOffset);
-					return replacements == null ? null : offsetReplacementOptions(replacements, argOffset);
+					return completeCommandArguments(this.getCommands().get(name), argString, at);
 				} else {
 					// Invalid command, can't provide any completions.
 					return null;
 				}
 			}
-		} else if (SPACE_PATTERN.matcher(code).matches()) {
+		} else if (SPACE_PATTERN.matcher(code.getValue()).matches()) {
 			// The code contains only whitespace, provide completions from :eval and for command names.
 			final List<String> replacementStrings = new ArrayList<>();
 			final ReplacementOptions evalReplacements = completeCommandArguments(this.getCommands().get(":eval"), code, at);
@@ -489,6 +491,11 @@ public final class ProBKernel extends BaseKernel {
 		}
 	}
 	
+	@Override
+	public @Nullable ReplacementOptions complete(final @NotNull String code, final int at) {
+		return this.completeInternal(new PositionedString(code, 0), at);
+	}
+	
 	@Override
 	public String isComplete(final String code) {
 		final Matcher commandMatcher = COMMAND_PATTERN.matcher(code);