From dea95a243cf147818b0ee19fd17957e033518eb9 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Fri, 15 Nov 2024 13:31:54 +0100
Subject: [PATCH] feat(input): add 'code unindent on backspace' for code
languages (@notTamion) (#5991)
---
frontend/__tests__/root/config.spec.ts | 3 ++
frontend/src/html/pages/settings.html | 14 ++++++++
frontend/src/ts/commandline/lists.ts | 2 ++
.../lists/code-unindent-on-backspace.ts | 36 +++++++++++++++++++
frontend/src/ts/config.ts | 19 ++++++++++
frontend/src/ts/constants/default-config.ts | 1 +
.../src/ts/controllers/input-controller.ts | 19 ++++++++++
frontend/src/ts/pages/settings.ts | 5 +++
packages/contracts/src/schemas/configs.ts | 1 +
9 files changed, 100 insertions(+)
create mode 100644 frontend/src/ts/commandline/lists/code-unindent-on-backspace.ts
diff --git a/frontend/__tests__/root/config.spec.ts b/frontend/__tests__/root/config.spec.ts
index 251009468645..d878344c6d68 100644
--- a/frontend/__tests__/root/config.spec.ts
+++ b/frontend/__tests__/root/config.spec.ts
@@ -145,6 +145,9 @@ describe("Config", () => {
expect(Config.setSmoothCaret("medium")).toBe(true);
expect(Config.setSmoothCaret("invalid" as any)).toBe(false);
});
+ it("setCodeUnindentOnBackspace", () => {
+ testBoolean(Config.setCodeUnindentOnBackspace);
+ });
it("setQuickRestartMode", () => {
expect(Config.setQuickRestartMode("off")).toBe(true);
expect(Config.setQuickRestartMode("tab")).toBe(true);
diff --git a/frontend/src/html/pages/settings.html b/frontend/src/html/pages/settings.html
index 66919ff18150..b005e6c37f7c 100644
--- a/frontend/src/html/pages/settings.html
+++ b/frontend/src/html/pages/settings.html
@@ -504,6 +504,20 @@
+
+
+
+ code unindent on backspace
+
+
+ Automatically go back to the previous line when deleting line leading
+ tab characters. Only works in code languages.
+
+
+
+
+
+
diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts
index 8344bc3b3428..485e08bec0c7 100644
--- a/frontend/src/ts/commandline/lists.ts
+++ b/frontend/src/ts/commandline/lists.ts
@@ -69,6 +69,7 @@ import ResultScreenCommands from "./lists/result-screen";
import CustomBackgroundSizeCommands from "./lists/background-size";
import CustomBackgroundFilterCommands from "./lists/background-filter";
import AddOrRemoveThemeToFavorite from "./lists/add-or-remove-theme-to-favorites";
+import CodeUnindentOnBackspace from "./lists/code-unindent-on-backspace";
import TagsCommands from "./lists/tags";
import CustomThemesListCommands from "./lists/custom-themes-list";
@@ -264,6 +265,7 @@ export const commands: CommandsSubgroup = {
...HideExtraLettersCommands,
...LazyModeCommands,
...LayoutsCommands,
+ ...CodeUnindentOnBackspace,
//sound
...SoundVolumeCommands,
diff --git a/frontend/src/ts/commandline/lists/code-unindent-on-backspace.ts b/frontend/src/ts/commandline/lists/code-unindent-on-backspace.ts
new file mode 100644
index 000000000000..3bae0058a84b
--- /dev/null
+++ b/frontend/src/ts/commandline/lists/code-unindent-on-backspace.ts
@@ -0,0 +1,36 @@
+import * as UpdateConfig from "../../config";
+import { Command, CommandsSubgroup } from "../types";
+
+const subgroup: CommandsSubgroup = {
+ title: "Code unindent on backspace...",
+ configKey: "codeUnindentOnBackspace",
+ list: [
+ {
+ id: "setCodeUnindentOnBackspaceOff",
+ display: "off",
+ configValue: false,
+ exec: (): void => {
+ UpdateConfig.setCodeUnindentOnBackspace(false);
+ },
+ },
+ {
+ id: "changeCodeUnindentOnBackspaceOn",
+ display: "on",
+ configValue: true,
+ exec: (): void => {
+ UpdateConfig.setCodeUnindentOnBackspace(true);
+ },
+ },
+ ],
+};
+
+const commands: Command[] = [
+ {
+ id: "changeCodeUnindentOnBackspace",
+ display: "Code unindent on backspace...",
+ icon: "fa-code",
+ subgroup,
+ },
+];
+
+export default commands;
diff --git a/frontend/src/ts/config.ts b/frontend/src/ts/config.ts
index 441f7078e6c8..81d1c104215e 100644
--- a/frontend/src/ts/config.ts
+++ b/frontend/src/ts/config.ts
@@ -1180,6 +1180,24 @@ export function setSmoothCaret(
return true;
}
+export function setCodeUnindentOnBackspace(
+ mode: boolean,
+ nosave?: boolean
+): boolean {
+ if (!isConfigValueValidBoolean("code unindent on backspace", mode)) {
+ return false;
+ }
+ config.codeUnindentOnBackspace = mode;
+
+ saveToLocalStorage("codeUnindentOnBackspace", nosave);
+ ConfigEvent.dispatch(
+ "codeUnindentOnBackspace",
+ config.codeUnindentOnBackspace,
+ nosave
+ );
+ return true;
+}
+
export function setStartGraphsAtZero(mode: boolean, nosave?: boolean): boolean {
if (!isConfigValueValidBoolean("start graphs at zero", mode)) {
return false;
@@ -1993,6 +2011,7 @@ export async function apply(
setKeymapSize(configObj.keymapSize, true);
setFontFamily(configObj.fontFamily, true);
setSmoothCaret(configObj.smoothCaret, true);
+ setCodeUnindentOnBackspace(configObj.codeUnindentOnBackspace, true);
setSmoothLineScroll(configObj.smoothLineScroll, true);
setAlwaysShowDecimalPlaces(configObj.alwaysShowDecimalPlaces, true);
setAlwaysShowWordsHistory(configObj.alwaysShowWordsHistory, true);
diff --git a/frontend/src/ts/constants/default-config.ts b/frontend/src/ts/constants/default-config.ts
index 893c1974933a..bbfcf729101a 100644
--- a/frontend/src/ts/constants/default-config.ts
+++ b/frontend/src/ts/constants/default-config.ts
@@ -25,6 +25,7 @@ const obj = {
favThemes: [],
showKeyTips: true,
smoothCaret: "medium",
+ codeUnindentOnBackspace: false,
quickRestart: "off",
punctuation: false,
numbers: false,
diff --git a/frontend/src/ts/controllers/input-controller.ts b/frontend/src/ts/controllers/input-controller.ts
index f71cad6ed82c..951f04817da1 100644
--- a/frontend/src/ts/controllers/input-controller.ts
+++ b/frontend/src/ts/controllers/input-controller.ts
@@ -1046,6 +1046,25 @@ $(document).on("keydown", async (event) => {
event.preventDefault();
return;
}
+
+ // if the user backspaces the indentation in a code language we need to empty
+ // the current word so the user is set back to the end of the last line
+ if (
+ Config.codeUnindentOnBackspace &&
+ TestInput.input.current.length > 0 &&
+ /^\t*$/.test(TestInput.input.current) &&
+ Config.language.startsWith("code") &&
+ isCharCorrect(
+ TestInput.input.current.slice(-1),
+ TestInput.input.current.length - 1
+ ) &&
+ (TestInput.input.history[TestWords.words.currentIndex - 1] !=
+ TestWords.words.get(TestWords.words.currentIndex - 1) ||
+ Config.freedomMode)
+ ) {
+ TestInput.input.current = "";
+ await TestUI.updateActiveWordLetters();
+ }
}
if (event.key === "Backspace" && TestInput.input.current.length === 0) {
diff --git a/frontend/src/ts/pages/settings.ts b/frontend/src/ts/pages/settings.ts
index 3fe334daeb9f..2581cfb730e7 100644
--- a/frontend/src/ts/pages/settings.ts
+++ b/frontend/src/ts/pages/settings.ts
@@ -37,6 +37,11 @@ async function initGroups(): Promise {
UpdateConfig.setSmoothCaret,
"button"
) as SettingsGroup;
+ groups["codeUnindentOnBackspace"] = new SettingsGroup(
+ "codeUnindentOnBackspace",
+ UpdateConfig.setCodeUnindentOnBackspace,
+ "button"
+ ) as SettingsGroup;
groups["difficulty"] = new SettingsGroup(
"difficulty",
UpdateConfig.setDifficulty,
diff --git a/packages/contracts/src/schemas/configs.ts b/packages/contracts/src/schemas/configs.ts
index b562994a1abd..0a31ba41671f 100644
--- a/packages/contracts/src/schemas/configs.ts
+++ b/packages/contracts/src/schemas/configs.ts
@@ -298,6 +298,7 @@ export const ConfigSchema = z
favThemes: FavThemesSchema,
showKeyTips: z.boolean(),
smoothCaret: SmoothCaretSchema,
+ codeUnindentOnBackspace: z.boolean(),
quickRestart: QuickRestartSchema,
punctuation: z.boolean(),
numbers: z.boolean(),