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(),