in hybrid/src/main/java/jetbrains/jetpad/hybrid/TokenOperations.java [162:230]
Runnable mergeTokens(Cell contextCell, boolean backward) {
abstract class TokenHandler {
abstract void handle(Token token);
}
final int index = tokenViews().indexOf(contextCell);
Token token = tokens().get(index);
final TokenHandler tokenHandler;
Function<Token, Runnable> completer;
final String newTokenText;
final int pos;
if (backward) {
Token prevToken = tokens().get(index - 1);
String prevText = prevToken.text();
if (prevToken.noSpaceToRight() || token.noSpaceToLeft()) {
prevText = prevText.substring(0, prevText.length() - 1);
}
pos = prevText.length();
newTokenText = prevText + token.text();
tokenHandler = new TokenHandler() {
@Override
public void handle(Token item) {
tokens().remove(index);
tokens().set(index - 1, item);
}
};
completer = new Function<Token, Runnable>() {
@Override
public Runnable apply(Token token) {
tokenHandler.handle(token);
return select(index - 1, 0);
}
};
} else {
String currentText = token.text();
pos = currentText.length();
Token nextToken = tokens().get(index + 1);
String nextText = nextToken.text();
if (token.noSpaceToRight() || nextToken.noSpaceToLeft()) {
nextText = nextText.substring(1);
}
newTokenText = currentText + nextText;
tokenHandler = new TokenHandler() {
@Override
public void handle(Token item) {
tokens().remove(index + 1);
tokens().set(index, item);
}
};
completer = new Function<Token, Runnable>() {
@Override
public Runnable apply(Token token) {
tokenHandler.handle(token);
return select(index, 0);
}
};
}
CompletionItems completion = mySync.tokenCompletion().completion(completer);
List<CompletionItem> matches = completion.matches(newTokenText);
if (matches.size() == 1) {
matches.get(0).complete(newTokenText);
} else {
tokenHandler.handle(new ErrorToken(newTokenText));
}
return select(backward ? index - 1 : index, pos);
}