Skip to content

Commit

Permalink
Add simplified syntax highlighter
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Dec 11, 2023
1 parent 7dd235f commit f95996f
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import org.cyclops.cyclopscore.proxy.ICommonProxy;
import org.cyclops.integrateddynamics.IntegratedDynamics;
import org.cyclops.integrateddynamics.infobook.OnTheDynamicsOfIntegrationBook;
import org.cyclops.integratedscripting.api.language.ILanguageHandlerRegistry;
import org.cyclops.integratedscripting.block.BlockScriptingDriveConfig;
import org.cyclops.integratedscripting.blockentity.BlockEntityScriptingDriveConfig;
import org.cyclops.integratedscripting.capability.ScriptingNetworkCapabilityConstructors;
import org.cyclops.integratedscripting.capability.network.ScriptingNetworkConfig;
import org.cyclops.integratedscripting.command.CommandTestScript;
import org.cyclops.integratedscripting.core.language.LanguageHandlerRegistry;
import org.cyclops.integratedscripting.core.language.LanguageHandlers;
import org.cyclops.integratedscripting.core.network.ScriptingData;
import org.cyclops.integratedscripting.evaluate.translation.IValueTranslatorRegistry;
import org.cyclops.integratedscripting.evaluate.translation.ValueTranslatorRegistry;
Expand Down Expand Up @@ -56,6 +59,7 @@ public IntegratedScripting() {
super(Reference.MOD_ID, (instance) -> _instance = instance);

getRegistryManager().addRegistry(IValueTranslatorRegistry.class, ValueTranslatorRegistry.getInstance());
getRegistryManager().addRegistry(ILanguageHandlerRegistry.class, LanguageHandlerRegistry.getInstance());

FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onRegistriesCreate);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::afterSetup);
Expand Down Expand Up @@ -83,6 +87,7 @@ protected void setup(FMLCommonSetupEvent event) {
MinecraftForge.EVENT_BUS.register(new ScriptingNetworkCapabilityConstructors());

ValueTranslators.load();
LanguageHandlers.load();
}

@SubscribeEvent
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.cyclops.integratedscripting.api.language;

import net.minecraft.network.chat.Style;
import org.apache.commons.lang3.tuple.Pair;

import java.util.List;

/**
* Logic for handling a specific programming language.
* @author rubensworks
*/
public interface ILanguageHandler {

public String getName();

public List<String> getExtensions();

public List<Pair<Style, String>> markupLine(String line);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.cyclops.integratedscripting.api.language;

import org.cyclops.cyclopscore.init.IRegistry;

import javax.annotation.Nullable;
import java.nio.file.Path;

/**
* Registry for {@link ILanguageHandler}'s.
* @author rubensworks
*/
public interface ILanguageHandlerRegistry extends IRegistry {

public void register(ILanguageHandler provider);

@Nullable
public ILanguageHandler getProvider(Path filePath);

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,22 @@
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.Pair;
import org.cyclops.cyclopscore.client.gui.component.WidgetScrollBar;
import org.cyclops.cyclopscore.client.gui.component.input.IInputListener;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* A widget to edit multi-line text.
Expand Down Expand Up @@ -66,6 +70,8 @@ public class WidgetTextArea extends AbstractWidget implements Widget, GuiEventLi
@Nullable
private IInputListener listener;
@Nullable
private IMarkupProvider markupProvider;
@Nullable
private WidgetTextArea.DisplayCache displayCache = WidgetTextArea.DisplayCache.EMPTY;
private long lastClickTime;
private int lastIndex = -1;
Expand Down Expand Up @@ -115,10 +121,14 @@ public void setFirstRow(int firstRow, boolean propagateToScrollbar) {
this.clearDisplayCache();
}

public void setListener(IInputListener listener) {
public void setListener(@Nullable IInputListener listener) {
this.listener = listener;
}

public void setMarkupProvider(@Nullable IMarkupProvider markupProvider) {
this.markupProvider = markupProvider;
}

public void setValue(String value) {
this.setValuePassive(value);

Expand Down Expand Up @@ -467,15 +477,15 @@ private DisplayCache rebuildDisplayCache() {
MutableInt mutableint = new MutableInt();
MutableBoolean mutableboolean = new MutableBoolean();
StringSplitter stringsplitter = this.font.getSplitter();
stringsplitter.splitLines(s, this.getWidth() /* changed: constant width */, Style.EMPTY, true, (p_98132_, p_98133_, p_98134_) -> {
stringsplitter.splitLines(s, this.getWidth() /* changed: constant width */, Style.EMPTY, true, (style, startPos, endPos) -> {
int k3 = mutableint.getAndIncrement();
String s2 = s.substring(p_98133_, p_98134_);
mutableboolean.setValue(s2.endsWith("\n"));
String s3 = StringUtils.stripEnd(s2, " \n");
String stringPart = s.substring(startPos, endPos);
mutableboolean.setValue(stringPart.endsWith("\n"));
String s3 = StringUtils.stripEnd(stringPart, " \n");
int l3 = (k3 - this.firstRow) * 9; // Offset firstRow!
Pos2i bookeditscreen$pos2i1 = this.convertLocalToScreen(new Pos2i(0, l3));
linePositionsOld.add(p_98133_);
linesAll.add(new LineInfo(p_98132_, s3, bookeditscreen$pos2i1.x, bookeditscreen$pos2i1.y));
linePositionsOld.add(startPos);
linesAll.add(new LineInfo(this.markupLine(style, s3), bookeditscreen$pos2i1.x, bookeditscreen$pos2i1.y));
});

// --- Changed ---
Expand Down Expand Up @@ -539,6 +549,13 @@ private DisplayCache rebuildDisplayCache() {
}
}

private List<Pair<Style, String>> markupLine(Style style, String line) {
if (this.markupProvider != null) {
return this.markupProvider.markupLine(style, line);
}
return Lists.newArrayList(Pair.of(style, line));
}

static int findLineFromPos(int[] p_98150_, int p_98151_) {
int i = Arrays.binarySearch(p_98150_, p_98151_);
return i < 0 ? -(i + 2) : i;
Expand All @@ -564,7 +581,7 @@ private Rect2i createSelection(Pos2i p_98117_, Pos2i p_98118_) {

@OnlyIn(Dist.CLIENT)
static class DisplayCache {
static final DisplayCache EMPTY = new DisplayCache("", new Pos2i(0, 0), true, new int[]{0}, new LineInfo[]{new LineInfo(Style.EMPTY, "", 0, 0)}, new LineInfo[]{new LineInfo(Style.EMPTY, "", 0, 0)}, new Rect2i[0], 0, 0);
static final DisplayCache EMPTY = new DisplayCache("", new Pos2i(0, 0), true, new int[]{0}, new LineInfo[]{new LineInfo(Collections.emptyList(), 0, 0)}, new LineInfo[]{new LineInfo(Collections.emptyList(), 0, 0)}, new Rect2i[0], 0, 0);
private final String fullText;
@Nullable
final Pos2i cursor;
Expand Down Expand Up @@ -596,7 +613,7 @@ public int getIndexAtPosition(Font p_98214_, Pos2i p_98215_) {
return this.fullText.length();
} else {
LineInfo bookeditscreen$lineinfo = this.linesAll[i];
return this.lineStarts[i] + p_98214_.getSplitter().plainIndexAtWidth(bookeditscreen$lineinfo.contents, p_98215_.x, bookeditscreen$lineinfo.style);
return this.lineStarts[i] + p_98214_.getSplitter().plainIndexAtWidth(bookeditscreen$lineinfo.contents, p_98215_.x, Style.EMPTY);
}
}

Expand Down Expand Up @@ -628,18 +645,23 @@ public int findLineEnd(int p_98219_) {

@OnlyIn(Dist.CLIENT)
static class LineInfo {
final Style style;
final List<Pair<Style, String>> contentsStyled;
final String contents;
final Component asComponent;
final int x;
final int y;

public LineInfo(Style p_98232_, String p_98233_, int p_98234_, int p_98235_) {
this.style = p_98232_;
this.contents = p_98233_;
this.x = p_98234_;
this.y = p_98235_;
this.asComponent = Component.literal(p_98233_).setStyle(p_98232_);
public LineInfo(List<Pair<Style, String>> contentsStyled, int x, int y) {
this.contentsStyled = contentsStyled;
this.contents = contentsStyled.stream().map(Pair::getRight).collect(Collectors.joining());
this.x = x;
this.y = y;

MutableComponent component = Component.literal("");
for (Pair<Style, String> value : contentsStyled) {
component = component.append(Component.literal(value.getRight()).setStyle(value.getLeft()));
}
this.asComponent = component;
}
}

Expand All @@ -653,4 +675,8 @@ static class Pos2i {
this.y = p_98250_;
}
}

public static interface IMarkupProvider {
public List<Pair<Style, String>> markupLine(Style style, String line);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cyclops.integratedscripting.client.gui.container;

import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
Expand All @@ -10,6 +11,7 @@
import net.minecraft.util.StringUtil;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import org.apache.commons.lang3.tuple.Pair;
import org.cyclops.cyclopscore.client.gui.component.WidgetScrollBar;
import org.cyclops.cyclopscore.client.gui.component.button.ButtonText;
import org.cyclops.cyclopscore.client.gui.component.input.WidgetArrowedListField;
Expand All @@ -20,8 +22,10 @@
import org.cyclops.cyclopscore.helper.RenderHelpers;
import org.cyclops.integratedscripting.IntegratedScripting;
import org.cyclops.integratedscripting.Reference;
import org.cyclops.integratedscripting.api.language.ILanguageHandler;
import org.cyclops.integratedscripting.client.gui.component.input.WidgetDialog;
import org.cyclops.integratedscripting.client.gui.component.input.WidgetTextArea;
import org.cyclops.integratedscripting.core.language.LanguageHandlers;
import org.cyclops.integratedscripting.inventory.container.ContainerTerminalScripting;
import org.cyclops.integratedscripting.network.packet.TerminalScriptingDeleteScriptPacket;
import org.lwjgl.glfw.GLFW;
Expand Down Expand Up @@ -99,6 +103,10 @@ public int getTotalRows() {

textArea = new WidgetTextArea(Minecraft.getInstance().font, this.leftPos + SCRIPT_X + 1, this.topPos + SCRIPT_Y + 1, SCRIPT_WIDTH, SCRIPT_HEIGHT, Component.translatable("gui.integratedscripting.script"), true);
textArea.setListener(this::onActiveScriptModified);
textArea.setMarkupProvider((style, line) -> {
ILanguageHandler languageHandler = LanguageHandlers.REGISTRY.getProvider(getMenu().getActiveScriptPath());
return languageHandler != null ? languageHandler.markupLine(line) : Lists.newArrayList(Pair.of(style, line));
});
addRenderableWidget(textArea);

buttonCreateFile = new ButtonText(this.leftPos + 19, this.topPos + 222, 56, 10, Component.translatable("gui.integratedscripting.create_file"), Component.literal("+"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.cyclops.integratedscripting.core.language;

import com.google.common.collect.Maps;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.tuple.Pair;
import org.cyclops.cyclopscore.helper.Helpers;
import org.cyclops.integratedscripting.api.language.ILanguageHandler;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
* @author rubensworks
*/
public class LanguageHandlerJavaScript implements ILanguageHandler {

// These colors are inspired by GitHub's color palette
public static final Style ATTRIBUTE = Style.EMPTY.withColor(TextColor.fromRgb(Helpers.RGBToInt(121, 93, 163))); // Purple
public static final Style COMMENT = Style.EMPTY.withColor(TextColor.fromRgb(Helpers.RGBToInt(150, 152, 150))); // Gray
public static final Style SYMBOL = Style.EMPTY.withColor(TextColor.fromRgb(Helpers.RGBToInt(99, 163, 92))); // Green
public static final Style CONSTANT = Style.EMPTY.withColor(TextColor.fromRgb(Helpers.RGBToInt(0, 134, 179))); // Blue
public static final Style KEYWORD = Style.EMPTY.withColor(TextColor.fromRgb(Helpers.RGBToInt(167, 29, 93))); // Red-purple

public final Map<String, Style> tokenStyles;

public LanguageHandlerJavaScript() {
this.tokenStyles = Maps.newHashMap();

this.tokenStyles.put("const", KEYWORD);
this.tokenStyles.put("let", KEYWORD);
this.tokenStyles.put("var", KEYWORD);
this.tokenStyles.put("function", KEYWORD);
this.tokenStyles.put("return", KEYWORD);
this.tokenStyles.put("true", KEYWORD);
this.tokenStyles.put("false", KEYWORD);

this.tokenStyles.put("{", SYMBOL);
this.tokenStyles.put("}", SYMBOL);
this.tokenStyles.put("(", SYMBOL);
this.tokenStyles.put(")", SYMBOL);
this.tokenStyles.put("[", SYMBOL);
this.tokenStyles.put("]", SYMBOL);
this.tokenStyles.put(".", SYMBOL);
this.tokenStyles.put(";", SYMBOL);
this.tokenStyles.put("=", SYMBOL);
}

@Override
public String getName() {
return "JavaScript";
}

@Override
public List<String> getExtensions() {
return Arrays.stream(new String[]{ "js", "cjs", "mjs" }).toList();
}

@Override
public List<Pair<Style, String>> markupLine(String line) {
// TODO: in the future, write/use JS lexer/tokenizer

List<Pair<Style, String>> segments = Lists.newArrayList();
segments.add(Pair.of(Style.EMPTY, line));

// Split up string by tokens
for (Map.Entry<String, Style> entry : this.tokenStyles.entrySet()) {
String token = entry.getKey();
Style tokenStyle = entry.getValue();
List<Pair<Style, String>> segmentsNew = Lists.newArrayList();

for (Pair<Style, String> segment : segments) {
Style styleOriginal = segment.getLeft();
String hayStack = segment.getRight();
int pos;
while ((pos = hayStack.indexOf(token)) >= 0) {
segmentsNew.add(Pair.of(styleOriginal, hayStack.substring(0, pos)));
segmentsNew.add(Pair.of(tokenStyle, hayStack.substring(pos, pos + token.length())));
hayStack = hayStack.substring(pos + token.length());
}

segmentsNew.add(Pair.of(styleOriginal, hayStack));
}

segments = segmentsNew;
}

return segments;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.cyclops.integratedscripting.core.language;

import com.google.common.collect.Maps;
import org.cyclops.integratedscripting.api.language.ILanguageHandler;
import org.cyclops.integratedscripting.api.language.ILanguageHandlerRegistry;

import javax.annotation.Nullable;
import java.nio.file.Path;
import java.util.Map;

/**
* @author rubensworks
*/
public class LanguageHandlerRegistry implements ILanguageHandlerRegistry {

private static LanguageHandlerRegistry INSTANCE = new LanguageHandlerRegistry();

private final Map<String, ILanguageHandler> extensionToHandlerMap = Maps.newHashMap();

private LanguageHandlerRegistry() {
}

/**
* @return The unique instance.
*/
public static LanguageHandlerRegistry getInstance() {
return INSTANCE;
}

@Override
public void register(ILanguageHandler translator) {
for (String extension : translator.getExtensions()) {
extensionToHandlerMap.put(extension, translator);
}
}

@Nullable
@Override
public ILanguageHandler getProvider(Path filePath) {
String filePathString = filePath.toString();
int dotPos = filePathString.lastIndexOf('.');
if (dotPos >= 0 && dotPos + 1 < filePathString.length()) {
String extension = filePathString.substring(dotPos + 1);
return extensionToHandlerMap.get(extension);
}
return null;
}
}
Loading

0 comments on commit f95996f

Please sign in to comment.