From d5fe10eb44c0e6ad9213cf8bef0a5aa7c6c90452 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 17 Oct 2026 20:27:29 +0000 Subject: [PATCH 1/5] Show full script paths when hovering the script list Paths in the script list are truncated, so files with a common prefix, such as inventory_sorting_main.js and inventory_sorting_test.js, or files in subdirectories could not be told apart. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9 --- .../gui/container/ContainerScreenTerminalScripting.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java index 82603fa4c..5ff157ae4 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java @@ -363,8 +363,12 @@ protected void renderScriptPaths(GuiGraphics guiGraphics, int mouseX, int mouseY Font.DisplayMode.NORMAL ); - // If hovering, render removal button + // If hovering, show the full path, as it may be truncated, and render removal button if (hovering) { + // Don't draw over an open dialog + if (pendingScriptRemovalDialog == null) { + this.setTooltipForNextRenderPass(Component.literal(path.toString())); + } guiGraphics.pose().pushPose(); float scale = 0.4F; int size = (int) (Images.ERROR.getWidth() * scale); From d88a8f3a2c3a9e7abad598365d6e3b955002aca9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 17 Oct 2026 20:43:15 +0000 Subject: [PATCH 2/5] Allow renaming scripts in the scripting terminal New scripts were always named script0.js, script1.js and so on, and could only be renamed or moved into directories through the file system, which players on a server can't access. Right-click a script to rename it, which also allows moving it into a directory or changing its language through its extension. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9 --- .../gui/component/input/WidgetDialog.java | 41 +++++++- .../ContainerScreenTerminalScripting.java | 99 ++++++++++++++++--- .../container/ContainerTerminalScripting.java | 29 ++++++ .../TerminalScriptingRenameScriptPacket.java | 68 +++++++++++++ .../proxy/CommonProxy.java | 2 + .../integratedscripting/lang/en_us.json | 6 ++ .../info/scripting_info.xml | 1 + .../core/network/ScriptingDataTest.java | 32 ++++++ 8 files changed, 261 insertions(+), 17 deletions(-) create mode 100644 src/main/java/org/cyclops/integratedscripting/network/packet/TerminalScriptingRenameScriptPacket.java diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java b/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java index b7d77701c..b4a33396b 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java @@ -5,6 +5,7 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; @@ -16,6 +17,8 @@ import org.cyclops.cyclopscore.helper.Helpers; import org.cyclops.integratedscripting.Reference; +import javax.annotation.Nullable; + /** * Shows a confirm/cancel dialog * @author rubensworks @@ -32,10 +35,21 @@ public class WidgetDialog extends AbstractWidget implements GuiEventListener { private final Component message; private final ButtonText buttonConfirm; private final ButtonText buttonCancel; + @Nullable + private final EditBox input; public WidgetDialog(Font font, int x, int y, Screen parent, Component title, Component message, Component confirm, Component cancel, Button.OnPress confirmCallback, Button.OnPress cancelCallback) { + this(font, x, y, parent, title, message, confirm, cancel, confirmCallback, cancelCallback, null); + } + + /** + * @param inputValue If not null, a text input is shown with this initial value. + */ + public WidgetDialog(Font font, int x, int y, Screen parent, + Component title, Component message, Component confirm, Component cancel, + Button.OnPress confirmCallback, Button.OnPress cancelCallback, @Nullable String inputValue) { super(x, y, WIDTH, HEIGHT, message); this.font = font; this.parent = parent; @@ -44,6 +58,14 @@ public WidgetDialog(Font font, int x, int y, Screen parent, this.buttonConfirm = new ButtonText(x + 50, y + HEIGHT - 15 - 5, 50, 15, confirm, confirm, confirmCallback, true); this.buttonCancel = new ButtonText(x + WIDTH - 50 - 50, y + HEIGHT - 15 - 5, 50, 15, cancel, cancel, cancelCallback, true); + if (inputValue != null) { + this.input = new EditBox(font, x + 10, y + 31, WIDTH - 20, 12, message); + this.input.setMaxLength(256); + this.input.setValue(inputValue); + this.input.setFocused(true); + } else { + this.input = null; + } } protected void drawBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { @@ -65,16 +87,33 @@ protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, flo guiGraphics.drawCenteredString(font, title, this.getX() + this.width / 2, this.getY() + 4, 16777215); FormattedCharSequence formattedcharsequence = message.getVisualOrderText(); - guiGraphics.drawString(font, message, (this.getX() + this.width / 2 - font.width(formattedcharsequence) / 2), (this.getY() + 25), 4210752, false); + guiGraphics.drawString(font, message, (this.getX() + this.width / 2 - font.width(formattedcharsequence) / 2), (this.getY() + (this.input != null ? 19 : 25)), 4210752, false); + if (this.input != null) { + this.input.render(guiGraphics, mouseX, mouseY, partialTicks); + } } @Override public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { return this.buttonConfirm.mouseClicked(mouseX, mouseY, mouseButton) || this.buttonCancel.mouseClicked(mouseX, mouseY, mouseButton) + || (this.input != null && this.input.mouseClicked(mouseX, mouseY, mouseButton)) || super.mouseClicked(mouseX, mouseY, mouseButton); } + @Nullable + public EditBox getInput() { + return input; + } + + public void confirm() { + this.buttonConfirm.onPress(); + } + + public void cancel() { + this.buttonCancel.onPress(); + } + @Override protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) { narrationElementOutput.add(NarratedElementType.TITLE, message); diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java index 5ff157ae4..8f81d2acc 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java @@ -12,6 +12,7 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceLocation; @@ -46,9 +47,11 @@ import org.cyclops.integratedscripting.inventory.container.ContainerTerminalScripting; import org.cyclops.integratedscripting.network.packet.TerminalScriptingDeleteScriptPacket; import org.cyclops.integratedscripting.network.packet.TerminalScriptingModifiedScriptPacket; +import org.cyclops.integratedscripting.network.packet.TerminalScriptingRenameScriptPacket; import org.lwjgl.glfw.GLFW; import javax.annotation.Nullable; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -87,7 +90,7 @@ public class ContainerScreenTerminalScripting extends ContainerScreenExtended= this.leftPos + PATHS_X + PATHS_WIDTH - (int) (Images.ERROR.getWidth() * 0.4F) - 1) { this.fieldDisk.playDownSound(Minecraft.getInstance().getSoundManager()); // Show confirmation dialog - pendingScriptRemovalDialog = new WidgetDialog(font, leftPos + getBaseXSize() / 2 - WidgetDialog.WIDTH / 2, topPos + 50, this, + pendingDialog = new WidgetDialog(font, leftPos + getBaseXSize() / 2 - WidgetDialog.WIDTH / 2, topPos + 50, this, Component.translatable("gui.integratedscripting.removal_dialog.title"), Component.translatable("gui.integratedscripting.removal_dialog.message", hoveredScriptPath.toString()), Component.translatable("gui.integratedscripting.removal_dialog.delete"), Component.translatable("gui.integratedscripting.removal_dialog.keep"), (b) -> { - removeWidget(pendingScriptRemovalDialog); - pendingScriptRemovalDialog = null; + removeWidget(pendingDialog); + pendingDialog = null; this.removeScript(hoveredScriptPath); }, (b) -> { - removeWidget(pendingScriptRemovalDialog); - pendingScriptRemovalDialog = null; + removeWidget(pendingDialog); + pendingDialog = null; }); - addRenderableWidget(pendingScriptRemovalDialog); + addRenderableWidget(pendingDialog); return true; } else { @@ -631,6 +641,53 @@ private void onSelectionModified() { getMenu().setSelection(selected); } + private void openRenameDialog(Path path) { + pendingDialog = new WidgetDialog(font, leftPos + getBaseXSize() / 2 - WidgetDialog.WIDTH / 2, topPos + 50, this, + Component.translatable("gui.integratedscripting.rename_dialog.title"), + Component.translatable("gui.integratedscripting.rename_dialog.message"), + Component.translatable("gui.integratedscripting.rename_dialog.rename"), + Component.translatable("gui.integratedscripting.rename_dialog.cancel"), + (b) -> { + String name = pendingDialog.getInput().getValue(); + removeWidget(pendingDialog); + pendingDialog = null; + this.renameScript(path, name); + }, + (b) -> { + removeWidget(pendingDialog); + pendingDialog = null; + }, path.toString()); + addRenderableWidget(pendingDialog); + } + + private void renameScript(Path from, String name) { + int disk = getMenu().getActiveDisk(); + Map scripts = getActiveScripts(); + Path to; + try { + to = Path.of(name.trim()); + } catch (InvalidPathException e) { + return; + } + if (scripts == null || to.toString().isEmpty() || scripts.containsKey(to) || !scripts.containsKey(from)) { + return; + } + + // Apply the rename locally, so an open script stays open with its editor state + String script = scripts.get(from); + boolean active = from.equals(getMenu().getActiveScriptPath()); + getMenu().setLastScript(disk, to, script); + getMenu().setLastScript(disk, from, null); + TextHistory history = scriptHistories.remove(Pair.of(disk, from)); + if (history != null) { + scriptHistories.put(Pair.of(disk, to), history); + } + if (active) { + getMenu().setActiveScriptPath(to); + } + IntegratedScripting._instance.getPacketHandler().sendToServer(new TerminalScriptingRenameScriptPacket(disk, from, to)); + } + private void removeScript(Path path) { IntegratedScripting._instance.getPacketHandler() .sendToServer(new TerminalScriptingDeleteScriptPacket(getMenu().getActiveDisk(), path)); @@ -647,7 +704,7 @@ public boolean mouseScrolled(double mouseX, double mouseY, double mouseZ, double @Override public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double offsetX, double offsetY) { // Make active dialog consume all input - if (pendingScriptRemovalDialog != null) { + if (pendingDialog != null) { return false; } @@ -667,7 +724,17 @@ public boolean mouseReleased(double mouseX, double mouseY, int mouseButton) { @Override public boolean keyPressed(int typedChar, int keyCode, int modifiers) { // Make active dialog consume all input - if (typedChar != GLFW.GLFW_KEY_ESCAPE && pendingScriptRemovalDialog != null) { + if (pendingDialog != null && pendingDialog.getInput() != null) { + if (typedChar == GLFW.GLFW_KEY_ESCAPE) { + pendingDialog.cancel(); + } else if (typedChar == GLFW.GLFW_KEY_ENTER || typedChar == GLFW.GLFW_KEY_KP_ENTER) { + pendingDialog.confirm(); + } else { + pendingDialog.getInput().keyPressed(typedChar, keyCode, modifiers); + } + return true; + } + if (typedChar != GLFW.GLFW_KEY_ESCAPE && pendingDialog != null) { return false; } @@ -796,8 +863,8 @@ private void navigate(int direction) { @Override public boolean charTyped(char p_94683_, int p_94684_) { // Make active dialog consume all input - if (pendingScriptRemovalDialog != null) { - return false; + if (pendingDialog != null) { + return pendingDialog.getInput() != null && pendingDialog.getInput().charTyped(p_94683_, p_94684_); } if (this.searchBar != null && this.searchBar.isFocused()) { return this.searchBar.charTyped(p_94683_, p_94684_); diff --git a/src/main/java/org/cyclops/integratedscripting/inventory/container/ContainerTerminalScripting.java b/src/main/java/org/cyclops/integratedscripting/inventory/container/ContainerTerminalScripting.java index 5e216c843..21ce2e97a 100644 --- a/src/main/java/org/cyclops/integratedscripting/inventory/container/ContainerTerminalScripting.java +++ b/src/main/java/org/cyclops/integratedscripting/inventory/container/ContainerTerminalScripting.java @@ -338,6 +338,35 @@ public void setServerScript(int disk, Path path, @Nullable String script) { ScriptingNetworkHelpers.getScriptingData().setScript(disk, path, script, IScriptingData.ChangeLocation.MEMORY); } + /** + * Rename a script on the server. + * The client already applied the rename to its own state, so it is corrected if the rename fails. + */ + public void renameServerScript(int disk, Path from, Path to) { + IScriptingData scriptingData = ScriptingNetworkHelpers.getScriptingData(); + String script = scriptingData.getScripts(disk).get(from); + if (script != null && !scriptingData.getScripts(disk).containsKey(to)) { + scriptingData.setScript(disk, to, script, IScriptingData.ChangeLocation.MEMORY); + // Only remove the original if the new path was accepted + if (script.equals(scriptingData.getScripts(disk).get(to))) { + scriptingData.setScript(disk, from, null, IScriptingData.ChangeLocation.MEMORY); + } + } + + // Send the actual state of both paths, which also corrects the client if the rename failed + for (Path path : new Path[]{from, to}) { + String value = scriptingData.getScripts(disk).get(path); + setLastScript(disk, path, value); + if (value != null) { + IntegratedScripting._instance.getPacketHandler() + .sendToPlayer(new TerminalScriptingModifiedScriptPacket(disk, path, value), (ServerPlayer) player); + } else { + IntegratedScripting._instance.getPacketHandler() + .sendToPlayer(new TerminalScriptingDeleteScriptPacket(disk, path), (ServerPlayer) player); + } + } + } + public void createNewServerScript(int disk) { // Determine unique script name Set existingScripts = ScriptingNetworkHelpers.getScriptingData().getScripts(disk).keySet(); diff --git a/src/main/java/org/cyclops/integratedscripting/network/packet/TerminalScriptingRenameScriptPacket.java b/src/main/java/org/cyclops/integratedscripting/network/packet/TerminalScriptingRenameScriptPacket.java new file mode 100644 index 000000000..4701fd614 --- /dev/null +++ b/src/main/java/org/cyclops/integratedscripting/network/packet/TerminalScriptingRenameScriptPacket.java @@ -0,0 +1,68 @@ +package org.cyclops.integratedscripting.network.packet; + +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.cyclops.cyclopscore.network.CodecField; +import org.cyclops.cyclopscore.network.PacketCodec; +import org.cyclops.integratedscripting.Reference; +import org.cyclops.integratedscripting.inventory.container.ContainerTerminalScripting; + +import java.nio.file.InvalidPathException; +import java.nio.file.Path; + +/** + * Packet for renaming a script from client to server. + * @author rubensworks + * + */ +public class TerminalScriptingRenameScriptPacket extends PacketCodec { + + public static final Type ID = new Type<>(ResourceLocation.fromNamespaceAndPath(Reference.MOD_ID, "terminal_scripting_rename_script")); + public static final StreamCodec CODEC = getCodec(TerminalScriptingRenameScriptPacket::new); + + @CodecField + private int disk; + @CodecField + private String from; + @CodecField + private String to; + + public TerminalScriptingRenameScriptPacket() { + super(ID); + } + + public TerminalScriptingRenameScriptPacket(int disk, Path from, Path to) { + super(ID); + this.disk = disk; + this.from = from.toString(); + this.to = to.toString(); + } + + @Override + public boolean isAsync() { + return false; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void actionClient(Level world, Player player) { + + } + + @Override + public void actionServer(Level world, ServerPlayer player) { + if(player.containerMenu instanceof ContainerTerminalScripting container) { + try { + container.renameServerScript(disk, Path.of(from), Path.of(to)); + } catch (InvalidPathException e) { + // Ignore invalid paths + } + } + } +} diff --git a/src/main/java/org/cyclops/integratedscripting/proxy/CommonProxy.java b/src/main/java/org/cyclops/integratedscripting/proxy/CommonProxy.java index 9f579a612..64eed3f3d 100644 --- a/src/main/java/org/cyclops/integratedscripting/proxy/CommonProxy.java +++ b/src/main/java/org/cyclops/integratedscripting/proxy/CommonProxy.java @@ -7,6 +7,7 @@ import org.cyclops.integratedscripting.network.packet.TerminalScriptingCreateNewScriptPacket; import org.cyclops.integratedscripting.network.packet.TerminalScriptingDeleteScriptPacket; import org.cyclops.integratedscripting.network.packet.TerminalScriptingModifiedScriptPacket; +import org.cyclops.integratedscripting.network.packet.TerminalScriptingRenameScriptPacket; import org.cyclops.integratedscripting.network.packet.TerminalScriptingSyntaxErrorPacket; /** @@ -29,5 +30,6 @@ public void registerPacketHandlers(PacketHandler packetHandler) { packetHandler.register(TerminalScriptingCreateNewScriptPacket.ID, TerminalScriptingCreateNewScriptPacket.CODEC); packetHandler.register(TerminalScriptingDeleteScriptPacket.ID, TerminalScriptingDeleteScriptPacket.CODEC); packetHandler.register(TerminalScriptingSyntaxErrorPacket.ID, TerminalScriptingSyntaxErrorPacket.CODEC); + packetHandler.register(TerminalScriptingRenameScriptPacket.ID, TerminalScriptingRenameScriptPacket.CODEC); } } diff --git a/src/main/resources/assets/integratedscripting/lang/en_us.json b/src/main/resources/assets/integratedscripting/lang/en_us.json index 126856f1f..3e8ba40a8 100644 --- a/src/main/resources/assets/integratedscripting/lang/en_us.json +++ b/src/main/resources/assets/integratedscripting/lang/en_us.json @@ -37,6 +37,11 @@ "gui.integratedscripting.removal_dialog.message": "Do you want to delete \"%s\"?", "gui.integratedscripting.removal_dialog.delete": "Delete", "gui.integratedscripting.removal_dialog.keep": "Keep", + "gui.integratedscripting.rename_dialog.title": "Rename script", + "gui.integratedscripting.rename_dialog.message": "New path, such as dir/name.js:", + "gui.integratedscripting.rename_dialog.rename": "Rename", + "gui.integratedscripting.rename_dialog.cancel": "Cancel", + "gui.integratedscripting.rename_hint": "Right-click to rename", "gui.integratedscripting.error.invalid_member": "Select a valid function name or variable name inside the script editor to bind with.", "gui.integratedscripting.error.invalid_member.current": "Current selection: \"%s\"", "gui.integratedscripting.error.reserved_member": "\"%s\" is a keyword, so it can not be bound. Select a function name or variable name instead.", @@ -142,6 +147,7 @@ "info_book.integratedscripting.terminal_shortcuts.text1": "The script editor of the &lScripting Terminal&r has the keyboard shortcuts shown below. You can change them in the &oControls&r settings, under &oIntegrated Scripting&r. Most of these actions are also available as buttons above the editor.", "info_book.integratedscripting.terminal_shortcuts.text2": "Some keys can not be changed: &oTab&r and &oShift+Tab&r indent and unindent the selected lines, &oPage Up&r and &oPage Down&r move by a page, &oCtrl+Left&r and &oCtrl+Right&r (&oOption&r on Mac) move by word, &oHome&r and &oEnd&r (also &oCmd+Left&r and &oCmd+Right&r on Mac) move to the start or end of the line, &oCtrl+Home&r and &oCtrl+End&r (also &oCmd+Up&r and &oCmd+Down&r on Mac) move to the start or end of the script, and &oCtrl+Shift+Z&r (&oCmd+Shift+Z&r on Mac) also redoes.", "info_book.integratedscripting.terminal_shortcuts.text3": "While finding text or going to a line, &oEnter&r and &oShift+Enter&r go to the next and previous match, and &oEscape&r closes the search bar.", + "info_book.integratedscripting.terminal_shortcuts.text4": "To rename a script, right-click it in the script list.", "info_book.integratedscripting.writing": "Writing Scripts", diff --git a/src/main/resources/data/integratedscripting/info/scripting_info.xml b/src/main/resources/data/integratedscripting/info/scripting_info.xml index 84b7818ef..94d6191ad 100644 --- a/src/main/resources/data/integratedscripting/info/scripting_info.xml +++ b/src/main/resources/data/integratedscripting/info/scripting_info.xml @@ -59,6 +59,7 @@ info_book.integratedscripting.terminal_shortcuts.text1 info_book.integratedscripting.terminal_shortcuts.text2 info_book.integratedscripting.terminal_shortcuts.text3 + info_book.integratedscripting.terminal_shortcuts.text4 key.integratedscripting.undo key.integratedscripting.redo key.integratedscripting.find diff --git a/src/test/java/org/cyclops/integratedscripting/core/network/ScriptingDataTest.java b/src/test/java/org/cyclops/integratedscripting/core/network/ScriptingDataTest.java index 5ab3cf714..4f062a42b 100644 --- a/src/test/java/org/cyclops/integratedscripting/core/network/ScriptingDataTest.java +++ b/src/test/java/org/cyclops/integratedscripting/core/network/ScriptingDataTest.java @@ -227,6 +227,38 @@ public void testFlushKeepsFilePermissions() throws IOException { } } + @Test + public void testDiskReloadKeepsUnflushedChanges() throws IOException { + Path rootPath = Files.createTempDirectory("integratedscripting-test"); + ScriptingData scriptingData = new ScriptingData(rootPath); + try { + Path diskPath = rootPath.resolve("scripting-disks").resolve("654"); + Files.createDirectories(diskPath); + Files.writeString(diskPath.resolve("old.js"), "old"); + Files.writeString(diskPath.resolve("other.js"), "other"); + scriptingData.initialize(); + + // Rename old.js to new.js in memory, without flushing it to disk yet + scriptingData.setScript(654, Path.of("new.js"), "old", IScriptingData.ChangeLocation.MEMORY); + scriptingData.setScript(654, Path.of("old.js"), null, IScriptingData.ChangeLocation.MEMORY); + + // A file watcher reload, for example caused by another file, must not undo these changes + scriptingData.initializeDiskScripts(654); + assertThat(scriptingData.getScripts(654).get(Path.of("new.js")), equalTo("old")); + assertThat(scriptingData.getScripts(654).get(Path.of("old.js")), nullValue()); + assertThat(scriptingData.getScripts(654).get(Path.of("other.js")), equalTo("other")); + + // After flushing, the disk contents are used again + scriptingData.tick(); + scriptingData.initializeDiskScripts(654); + assertThat(scriptingData.getScripts(654).get(Path.of("new.js")), equalTo("old")); + assertFalse(Files.exists(diskPath.resolve("old.js"))); + } finally { + scriptingData.close(); + FileUtils.deleteDirectory(rootPath.toFile()); + } + } + @Test public void testDiskReloadDuringFirstFlushKeepsScript() throws IOException { Path rootPath = Files.createTempDirectory("integratedscripting-test"); From bfc3760ff0dee86b8a4e95453b3ff2d98adcc762 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Oct 2026 15:37:02 +0000 Subject: [PATCH 3/5] Add a focus mode to enlarge the script editor The editor only uses a small part of the screen, showing about a dozen wrapped lines. Add a toolbar button to show only the editor, using most of the screen, with the toolbar moving along above it. Escape or the button returns to the normal terminal. See #44 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9 --- .../ContainerScreenTerminalScripting.java | 84 +++++++++++++++++- .../client/gui/image/ScriptImages.java | 2 + .../integratedscripting/lang/en_us.json | 3 + .../textures/gui/icons.png | Bin 1286 -> 1389 bytes .../info/scripting_info.xml | 1 + 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java index 8f81d2acc..32e457e4b 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java @@ -11,6 +11,7 @@ import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; @@ -78,6 +79,7 @@ public class ContainerScreenTerminalScripting extends ContainerScreenExtended { @@ -171,9 +181,15 @@ public int getTotalRows() { buttonCreateFile = new ButtonText(this.leftPos + 19, this.topPos + 222, 56, 10, Component.translatable("gui.integratedscripting.create_file"), Component.literal("+"), (button) -> getMenu().createNewFile(), true); - addRenderableWidget(buttonCreateFile); + if (!focusMode) { + addRenderableWidget(buttonCreateFile); + } - this.addToolbar(this.leftPos + SCRIPT_X + SCRIPT_WIDTH, this.topPos + 5); + if (focusMode) { + this.addToolbar(this.width - FOCUS_MARGIN, FOCUS_MARGIN - 12); + } else { + this.addToolbar(this.leftPos + SCRIPT_X + SCRIPT_WIDTH, this.topPos + 5); + } // Restore the open script in the new editor if (getMenu().getActiveScriptPath() != null) { @@ -189,6 +205,13 @@ public int getTotalRows() { * @param y The top of the toolbar. */ private void addToolbar(int right, int y) { + Component focusLabel = Component.translatable(focusMode ? "gui.integratedscripting.focus_mode.exit" : "gui.integratedscripting.focus_mode.enter"); + buttonFocus = new ButtonIcon(right - 10, y, 10, 10, focusLabel, (button) -> this.toggleFocusMode(), + focusMode ? ScriptImages.ACTION_FOCUS_EXIT : ScriptImages.ACTION_FOCUS_ENTER); + buttonFocus.setTooltip(Tooltip.create(focusLabel)); + addRenderableWidget(buttonFocus); + right -= 10; + this.toolbarLeft = right - 50; this.toolbarEditButtons.clear(); this.buttonUndo = this.addToolbarButton(right - 50, y, ScriptImages.ACTION_UNDO, Keys.UNDO, () -> this.textArea.undo()); @@ -283,8 +306,44 @@ protected int getErrorY() { return 139; } + private void toggleFocusMode() { + this.focusMode = !this.focusMode; + // Recreates the widgets, which keeps the open script + this.rebuildWidgets(); + } + + @Override + protected void drawCurrentScreen(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { + if (focusMode) { + // Only show the editor, without the container contents + guiGraphics.fill(textArea.getX() - 2, textArea.getY() - 2, textArea.getX() + textArea.getWidth() + 2, textArea.getY() + textArea.getHeight() + 2, Helpers.RGBAToInt(85, 85, 85, 255)); + guiGraphics.fill(textArea.getX() - 1, textArea.getY() - 1, textArea.getX() + textArea.getWidth() + 1, textArea.getY() + textArea.getHeight() + 1, Helpers.RGBAToInt(224, 224, 224, 255)); + Path path = getMenu().getActiveScriptPath(); + if (path != null) { + guiGraphics.drawString(font, path.toString(), FOCUS_MARGIN, FOCUS_MARGIN - 11, 16777215); + } + for (net.minecraft.client.gui.components.Renderable renderable : this.renderables) { + renderable.render(guiGraphics, mouseX, mouseY, partialTicks); + } + } else { + super.drawCurrentScreen(guiGraphics, mouseX, mouseY, partialTicks); + } + } + + @Override + protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) { + // Slots are hidden in focus mode + if (!focusMode) { + super.renderTooltip(guiGraphics, x, y); + } + } + @Override protected void renderBg(GuiGraphics guiGraphics, float partialTicks, int mouseX, int mouseY) { + // Only the editor is shown in focus mode + if (focusMode) { + return; + } super.renderBg(guiGraphics, partialTicks, mouseX, mouseY); RenderHelpers.bindTexture(this.texture); fieldDisk.render(guiGraphics, mouseX, mouseY, partialTicks); @@ -408,7 +467,7 @@ protected Path getHoveredScriptPath(double mouseX, double mouseY) { protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) { // Shorten the title if it would overlap with the toolbar, as translations can be long Component title = this.title; - int maxTitleWidth = this.toolbarLeft - this.leftPos - this.titleLabelX - 2; + int maxTitleWidth = this.toolbarLeft - this.leftPos - this.titleLabelX - 1; if (this.font.width(title) > maxTitleWidth) { title = Component.literal(this.font.plainSubstrByWidth(title.getString(), maxTitleWidth - this.font.width("\u2026")) + "\u2026"); } @@ -464,6 +523,17 @@ public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { return pendingDialog.mouseClicked(mouseX, mouseY, mouseButton); } + // Only the editor widgets are visible in focus mode, so don't let clicks reach the container + if (focusMode) { + for (GuiEventListener child : this.children()) { + if (child.mouseClicked(mouseX, mouseY, mouseButton)) { + this.setFocused(child); + return true; + } + } + return true; + } + // Handle script path clicks Path hoveredScriptPath = getHoveredScriptPath(mouseX, mouseY); if (hoveredScriptPath != null && mouseButton == 1) { @@ -747,6 +817,12 @@ public boolean keyPressed(int typedChar, int keyCode, int modifiers) { return true; } + // Leave focus mode instead of closing the screen + if (focusMode && typedChar == GLFW.GLFW_KEY_ESCAPE && pendingDialog == null) { + this.toggleFocusMode(); + return true; + } + if (textArea.isFocused()) { boolean ret = textArea.keyPressed(typedChar, keyCode, modifiers); if (typedChar != GLFW.GLFW_KEY_ESCAPE) { diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/image/ScriptImages.java b/src/main/java/org/cyclops/integratedscripting/client/gui/image/ScriptImages.java index 9d6678d8a..0796b72ef 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/image/ScriptImages.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/image/ScriptImages.java @@ -21,5 +21,7 @@ public class ScriptImages { public static final Image ACTION_FIND = new Image(ICONS, 16, 16, 8, 8); public static final Image ACTION_GOTO_LINE = new Image(ICONS, 24, 16, 8, 8); public static final Image ACTION_COMMENT = new Image(ICONS, 32, 16, 8, 8); + public static final Image ACTION_FOCUS_ENTER = new Image(ICONS, 48, 16, 8, 8); + public static final Image ACTION_FOCUS_EXIT = new Image(ICONS, 56, 16, 8, 8); } diff --git a/src/main/resources/assets/integratedscripting/lang/en_us.json b/src/main/resources/assets/integratedscripting/lang/en_us.json index 3e8ba40a8..63dd0056e 100644 --- a/src/main/resources/assets/integratedscripting/lang/en_us.json +++ b/src/main/resources/assets/integratedscripting/lang/en_us.json @@ -27,6 +27,8 @@ "gui.integratedscripting.script": "Script", "gui.integratedscripting.create_file": "Create File", "gui.integratedscripting.find": "Find", + "gui.integratedscripting.focus_mode.enter": "Enlarge editor", + "gui.integratedscripting.focus_mode.exit": "Back to normal size (Escape)", "gui.integratedscripting.goto_line": "Go to line", "gui.integratedscripting.find.label": "Find:", "gui.integratedscripting.goto_line.label": "Line:", @@ -148,6 +150,7 @@ "info_book.integratedscripting.terminal_shortcuts.text2": "Some keys can not be changed: &oTab&r and &oShift+Tab&r indent and unindent the selected lines, &oPage Up&r and &oPage Down&r move by a page, &oCtrl+Left&r and &oCtrl+Right&r (&oOption&r on Mac) move by word, &oHome&r and &oEnd&r (also &oCmd+Left&r and &oCmd+Right&r on Mac) move to the start or end of the line, &oCtrl+Home&r and &oCtrl+End&r (also &oCmd+Up&r and &oCmd+Down&r on Mac) move to the start or end of the script, and &oCtrl+Shift+Z&r (&oCmd+Shift+Z&r on Mac) also redoes.", "info_book.integratedscripting.terminal_shortcuts.text3": "While finding text or going to a line, &oEnter&r and &oShift+Enter&r go to the next and previous match, and &oEscape&r closes the search bar.", "info_book.integratedscripting.terminal_shortcuts.text4": "To rename a script, right-click it in the script list.", + "info_book.integratedscripting.terminal_shortcuts.text5": "In focus mode, &oEscape&r returns to the normal terminal.", "info_book.integratedscripting.writing": "Writing Scripts", diff --git a/src/main/resources/assets/integratedscripting/textures/gui/icons.png b/src/main/resources/assets/integratedscripting/textures/gui/icons.png index c896e55b9d6f00d3cd9968ee8d30a137c676f07f..26a3a8cae54a382f803f80dff4e3a8d1b239011f 100644 GIT binary patch delta 688 zcmV;h0#E&h3hfGzBYy=nNklqX>NE_LvglyBstAGwd zE7`dN-r|jjq9<(plL^ju&I|(vaba^mNf+?$bUF>QaU6gCal!F;+`V*r;I`b)H^y;1 zef#$9(TzWU{(QbYj^pW{FCQM={?peVuY7yJ?{qf|*G>MVYkwv`aQp5|e(1XU({BLy zb6y>Q^?ClMuRomo!#i>R^d{H)^!3N!^Z?$EH$4UT=gS9se|SgUd<{SZ;QiPP!2Egt z`g&^r%0EE5C0)O4Z!^3$YVZYyBHRi*^!)d+k^1iLduYK)H_if#_2142S2w*vBp0eC_ zo=np;4bwC|I?npBt$!%8yziQSI5L~2>Ad}=aJ+PE_*>l#!_SHNoJp~q%;Pwoj>qF} z{>bmrIQ#v6cPS7r+569?X&MfP!}%k}^;lc4c{m)N6@NYW8{ID_!QpTihGE#;i*8Mp zYbMa8=k53V-8vL=NQPlJEp9(*9%sHj9*?`_ee<|m&l!ec`2PL-Q!fF3w|Or)j^p{V zKFlA6|0dG>*u4Gn`In9)*5f`l{!5NVUgLB+xwvF6_rvh(q4{F3`^#Q=cG@rMA{_$n~7VFHf=lTZR77X1s$ Wb`>^g)EMai0000@9*!Aw>O*3;pdNU&u)MB@bt#F2YjTPVYqDg=Pnt3;D7qv7=Gxw`Rq3Ue4aN4 z;PgEI?%~O~KYS6lFK=?WyN9R2=>dEl?|KUG^T#)EF5O zTz`JZzw{Vzy%w(lOdkuL{+(MIa)S?F%j*00?=OCx_bq%C7_Qf9{#yW`#TS7fOaLHE z03hsLF3|1w`+wtwg!OuT(LVS4{o!=m`D07ZFL4b6UhjAWFdyQV%(tBebsWcG9LHz( zbNbxUKNOiicF8{+0bcKB7=8`r-wfP*m^YivVYl0@rjPv2?PtASug(SHHLE}HHn;PE z+-|qSFbs!b`14SHX>cz&YB=}0^?JQJ4aF3aVHggx+ke0Zxt*`d<2W9lSXz;%f&D)e z!#Iw^Znv9We+CXGaJZ zecU%~zaccx)9{};60rKiKXmoK1z4?~Z^5;{f4F8>9{}Lv_$n~7(E^47lfVKh7X1f= WJXFfpbSbg`0000info_book.integratedscripting.terminal_shortcuts.text2 info_book.integratedscripting.terminal_shortcuts.text3 info_book.integratedscripting.terminal_shortcuts.text4 + info_book.integratedscripting.terminal_shortcuts.text5 key.integratedscripting.undo key.integratedscripting.redo key.integratedscripting.find From 973ac6efbbd798d75214deab2e4152472f36287d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 17:19:40 +0000 Subject: [PATCH 4/5] Warn that renaming a script breaks its variable cards Variable cards refer to scripts by path, so they stop working when their script is renamed. The rename dialog now says so. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9 --- .../gui/component/input/WidgetDialog.java | 17 +++++++++++++++++ .../ContainerScreenTerminalScripting.java | 1 + .../assets/integratedscripting/lang/en_us.json | 1 + 3 files changed, 19 insertions(+) diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java b/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java index b4a33396b..959ec6b25 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/component/input/WidgetDialog.java @@ -15,6 +15,7 @@ import net.minecraft.util.FormattedCharSequence; import org.cyclops.cyclopscore.client.gui.component.button.ButtonText; import org.cyclops.cyclopscore.helper.Helpers; +import org.cyclops.cyclopscore.helper.RenderHelpers; import org.cyclops.integratedscripting.Reference; import javax.annotation.Nullable; @@ -37,6 +38,8 @@ public class WidgetDialog extends AbstractWidget implements GuiEventListener { private final ButtonText buttonCancel; @Nullable private final EditBox input; + @Nullable + private Component warning; public WidgetDialog(Font font, int x, int y, Screen parent, Component title, Component message, Component confirm, Component cancel, @@ -68,6 +71,13 @@ public WidgetDialog(Font font, int x, int y, Screen parent, } } + /** + * @param warning A short warning to show below the input, or null. + */ + public void setWarning(@Nullable Component warning) { + this.warning = warning; + } + protected void drawBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { // Gray-out background RenderSystem.setShaderColor(0F, 0F, 0F, 0.95F); @@ -91,6 +101,13 @@ protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, flo if (this.input != null) { this.input.render(guiGraphics, mouseX, mouseY, partialTicks); } + if (this.warning != null) { + // Scaled down to fit between the input and the buttons, and further for long translations + String warning = this.warning.getString(); + float scale = Math.min(0.5F, (float) (WIDTH - 20) / font.width(warning)); + RenderHelpers.drawScaledString(guiGraphics, font, warning, this.getX() + this.width / 2 - (int) (font.width(warning) * scale / 2), + this.getY() + 45, scale, Helpers.RGBToInt(140, 30, 30), false, Font.DisplayMode.NORMAL); + } } @Override diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java index 32e457e4b..7bd854501 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java @@ -727,6 +727,7 @@ private void openRenameDialog(Path path) { removeWidget(pendingDialog); pendingDialog = null; }, path.toString()); + pendingDialog.setWarning(Component.translatable("gui.integratedscripting.rename_dialog.warning")); addRenderableWidget(pendingDialog); } diff --git a/src/main/resources/assets/integratedscripting/lang/en_us.json b/src/main/resources/assets/integratedscripting/lang/en_us.json index 63dd0056e..0beb66f31 100644 --- a/src/main/resources/assets/integratedscripting/lang/en_us.json +++ b/src/main/resources/assets/integratedscripting/lang/en_us.json @@ -43,6 +43,7 @@ "gui.integratedscripting.rename_dialog.message": "New path, such as dir/name.js:", "gui.integratedscripting.rename_dialog.rename": "Rename", "gui.integratedscripting.rename_dialog.cancel": "Cancel", + "gui.integratedscripting.rename_dialog.warning": "Variable cards bound to this script will stop working.", "gui.integratedscripting.rename_hint": "Right-click to rename", "gui.integratedscripting.error.invalid_member": "Select a valid function name or variable name inside the script editor to bind with.", "gui.integratedscripting.error.invalid_member.current": "Current selection: \"%s\"", From 48613ed0ba9b44c2823fda30bb07c5ad2286c302 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 17:23:17 +0000 Subject: [PATCH 5/5] Add a rebindable hotkey to enlarge the script editor The enlarged editor could only be toggled with its button. F12 now toggles it too, as F11 is used by Minecraft for fullscreen, and keeps the editor focused so typing can continue. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018MRyTdV3fSV5Q5NPGep4q9 --- .../ContainerScreenTerminalScripting.java | 20 ++++++++++++++++++- .../integratedscripting/client/key/Keys.java | 4 +++- .../integratedscripting/lang/en_us.json | 5 +++-- .../info/scripting_info.xml | 1 + 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java index 7bd854501..ae9b83a3e 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java +++ b/src/main/java/org/cyclops/integratedscripting/client/gui/container/ContainerScreenTerminalScripting.java @@ -15,6 +15,7 @@ import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; @@ -162,6 +163,13 @@ public int getTotalRows() { openNavigate(!find); return true; } + if (Keys.matches(Keys.FOCUS_MODE, key, scanCode, modifiers)) { + this.toggleFocusMode(); + // Keep typing in the recreated editor + this.setFocused(this.textArea); + this.textArea.setFocused(true); + return true; + } return false; }); getMenu().setRemoteScriptChangeListener(this::onRemoteScriptChanged); @@ -208,7 +216,17 @@ private void addToolbar(int right, int y) { Component focusLabel = Component.translatable(focusMode ? "gui.integratedscripting.focus_mode.exit" : "gui.integratedscripting.focus_mode.enter"); buttonFocus = new ButtonIcon(right - 10, y, 10, 10, focusLabel, (button) -> this.toggleFocusMode(), focusMode ? ScriptImages.ACTION_FOCUS_EXIT : ScriptImages.ACTION_FOCUS_ENTER); - buttonFocus.setTooltip(Tooltip.create(focusLabel)); + // Escape also leaves the enlarged editor + MutableComponent focusKeys = focusMode ? Component.translatable("key.keyboard.escape") : null; + if (!Keys.FOCUS_MODE.isUnbound()) { + focusKeys = focusKeys == null ? Keys.FOCUS_MODE.getTranslatedKeyMessage().copy() + : focusKeys.append(", ").append(Keys.FOCUS_MODE.getTranslatedKeyMessage()); + } + MutableComponent focusTooltip = focusLabel.copy(); + if (focusKeys != null) { + focusTooltip.append(Component.literal(" (").append(focusKeys).append(")").withStyle(ChatFormatting.GRAY)); + } + buttonFocus.setTooltip(Tooltip.create(focusTooltip)); addRenderableWidget(buttonFocus); right -= 10; diff --git a/src/main/java/org/cyclops/integratedscripting/client/key/Keys.java b/src/main/java/org/cyclops/integratedscripting/client/key/Keys.java index 980fbeee9..47350f3db 100644 --- a/src/main/java/org/cyclops/integratedscripting/client/key/Keys.java +++ b/src/main/java/org/cyclops/integratedscripting/client/key/Keys.java @@ -28,8 +28,10 @@ public class Keys { public static final KeyMapping COMMENT = create("comment", KeyModifier.CONTROL, GLFW.GLFW_KEY_SLASH); public static final KeyMapping MOVE_LINES_UP = create("move_lines_up", KeyModifier.ALT, GLFW.GLFW_KEY_UP); public static final KeyMapping MOVE_LINES_DOWN = create("move_lines_down", KeyModifier.ALT, GLFW.GLFW_KEY_DOWN); + // F11 is taken by the window fullscreen toggle of Minecraft + public static final KeyMapping FOCUS_MODE = create("focus_mode", KeyModifier.NONE, GLFW.GLFW_KEY_F12); - public static final List ALL = List.of(UNDO, REDO, FIND, GOTO_LINE, COMMENT, MOVE_LINES_UP, MOVE_LINES_DOWN); + public static final List ALL = List.of(UNDO, REDO, FIND, GOTO_LINE, COMMENT, MOVE_LINES_UP, MOVE_LINES_DOWN, FOCUS_MODE); private static KeyMapping create(String name, KeyModifier modifier, int key) { return new KeyMapping("key." + Reference.MOD_ID + "." + name, KeyConflictContext.GUI, modifier, diff --git a/src/main/resources/assets/integratedscripting/lang/en_us.json b/src/main/resources/assets/integratedscripting/lang/en_us.json index 0beb66f31..e714883a9 100644 --- a/src/main/resources/assets/integratedscripting/lang/en_us.json +++ b/src/main/resources/assets/integratedscripting/lang/en_us.json @@ -28,7 +28,7 @@ "gui.integratedscripting.create_file": "Create File", "gui.integratedscripting.find": "Find", "gui.integratedscripting.focus_mode.enter": "Enlarge editor", - "gui.integratedscripting.focus_mode.exit": "Back to normal size (Escape)", + "gui.integratedscripting.focus_mode.exit": "Back to normal size", "gui.integratedscripting.goto_line": "Go to line", "gui.integratedscripting.find.label": "Find:", "gui.integratedscripting.goto_line.label": "Line:", @@ -59,6 +59,7 @@ "key.integratedscripting.comment": "Toggle comment", "key.integratedscripting.move_lines_up": "Move lines up", "key.integratedscripting.move_lines_down": "Move lines down", + "key.integratedscripting.focus_mode": "Enlarge editor", "_comment": "Value Type Translation", "valuetype.integratedscripting.error.translation.unknown_to_graal": "Could not find a translator from %s values to Graal.", @@ -151,7 +152,7 @@ "info_book.integratedscripting.terminal_shortcuts.text2": "Some keys can not be changed: &oTab&r and &oShift+Tab&r indent and unindent the selected lines, &oPage Up&r and &oPage Down&r move by a page, &oCtrl+Left&r and &oCtrl+Right&r (&oOption&r on Mac) move by word, &oHome&r and &oEnd&r (also &oCmd+Left&r and &oCmd+Right&r on Mac) move to the start or end of the line, &oCtrl+Home&r and &oCtrl+End&r (also &oCmd+Up&r and &oCmd+Down&r on Mac) move to the start or end of the script, and &oCtrl+Shift+Z&r (&oCmd+Shift+Z&r on Mac) also redoes.", "info_book.integratedscripting.terminal_shortcuts.text3": "While finding text or going to a line, &oEnter&r and &oShift+Enter&r go to the next and previous match, and &oEscape&r closes the search bar.", "info_book.integratedscripting.terminal_shortcuts.text4": "To rename a script, right-click it in the script list.", - "info_book.integratedscripting.terminal_shortcuts.text5": "In focus mode, &oEscape&r returns to the normal terminal.", + "info_book.integratedscripting.terminal_shortcuts.text5": "When the editor is enlarged, &oEscape&r also returns to the normal terminal.", "info_book.integratedscripting.writing": "Writing Scripts", diff --git a/src/main/resources/data/integratedscripting/info/scripting_info.xml b/src/main/resources/data/integratedscripting/info/scripting_info.xml index 5327e9aa0..417dd5efa 100644 --- a/src/main/resources/data/integratedscripting/info/scripting_info.xml +++ b/src/main/resources/data/integratedscripting/info/scripting_info.xml @@ -68,6 +68,7 @@ key.integratedscripting.comment key.integratedscripting.move_lines_up key.integratedscripting.move_lines_down + key.integratedscripting.focus_mode