From ebb8be2ccf428f1b05606094e9f417a8c7be1ec2 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 9 Jun 2022 14:03:37 -0400 Subject: [PATCH 01/12] testing search bar --- src/suggestions/suggestions-controller.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index a664b5b..814dca6 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -32,6 +32,7 @@ class Menu { static menuCount = 0; static idPrefix = "suggestion-menu-"; htmlElement: HTMLDivElement; + searchBar: HTMLInputElement; private optionsInViewPort; @@ -43,6 +44,9 @@ class Menu { Menu.menuCount++; + this.searchBar = document.createElement("input"); + this.htmlElement.appendChild(this.searchBar); + for (const [key, value] of options) { const option = new MenuOption(key, false, null, this, null, value); option.attachToParentMenu(this); From a4e6755c023d60919984df8b715757bb80426ee5 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 13 Jun 2022 15:21:27 -0400 Subject: [PATCH 02/12] init menu controller instance --- src/suggestions/suggestions-controller.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index 814dca6..7a5cf4f 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -47,6 +47,8 @@ class Menu { this.searchBar = document.createElement("input"); this.htmlElement.appendChild(this.searchBar); + MenuController.getInstance(); + for (const [key, value] of options) { const option = new MenuOption(key, false, null, this, null, value); option.attachToParentMenu(this); @@ -54,6 +56,8 @@ class Menu { this.options.push(option); } + this.searchBar.addEventListener("input", () => {}); + this.htmlElement.addEventListener("mouseover", () => { this.htmlElement.style.visibility = "visible"; }); From 54212a39e80056a11a6d99e4cd7a5928c8cad0af Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 16 Jun 2022 15:41:52 -0400 Subject: [PATCH 03/12] implemented rudimentary spotlight search for ctrl + space --- src/editor/action-executor.ts | 7 +-- src/suggestions/suggestions-controller.ts | 60 ++++++++++++++++++----- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/editor/action-executor.ts b/src/editor/action-executor.ts index f8fb889..6511c63 100644 --- a/src/editor/action-executor.ts +++ b/src/editor/action-executor.ts @@ -1368,7 +1368,8 @@ export class ActionExecutor { this.openAutocompleteMenu( this.module.actionFilter .getProcessedInsertionsList() - .filter((item) => item.insertionResult.insertionType != InsertionType.Invalid) + .filter((item) => item.insertionResult.insertionType != InsertionType.Invalid), + true ); this.styleAutocompleteMenu(context.position); @@ -1802,10 +1803,10 @@ export class ActionExecutor { } } - private openAutocompleteMenu(inserts: EditCodeAction[]) { + private openAutocompleteMenu(inserts: EditCodeAction[], isSpotlightSearch = false) { if (!this.module.menuController.isMenuOpen()) { inserts = inserts.filter((insert) => insert.insertionResult.insertionType !== InsertionType.Invalid); - this.module.menuController.buildSingleLevelMenu(inserts); + this.module.menuController.buildSingleLevelMenu(inserts, { left: 0, top: 0 }, isSpotlightSearch); } else this.module.menuController.removeMenus(); } diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index 7a5cf4f..c6df43d 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -1,6 +1,6 @@ import { Position } from "monaco-editor"; import { EditCodeAction } from "../editor/action-filter"; -import { Actions, InsertActionType } from "../editor/consts"; +import { Actions, EditActionType, InsertActionType } from "../editor/consts"; import { Editor } from "../editor/editor"; import { EDITOR_DOM_ID } from "../editor/toolbox"; import { Validator } from "../editor/validator"; @@ -36,18 +36,24 @@ class Menu { private optionsInViewPort; - constructor(options: Map) { + constructor(options: Map, isSpotlightSearch: boolean = false) { this.htmlElement = document.createElement("div"); this.htmlElement.classList.add(MenuController.menuElementClass); this.htmlElement.id = `${Menu.idPrefix}${Menu.menuCount}`; document.getElementById(EDITOR_DOM_ID).appendChild(this.htmlElement); - Menu.menuCount++; + if (isSpotlightSearch) { + this.searchBar = document.createElement("input"); + this.searchBar.classList.add(MenuController.spotlightElementClass); + this.htmlElement.appendChild(this.searchBar); - this.searchBar = document.createElement("input"); - this.htmlElement.appendChild(this.searchBar); + const menuController = MenuController.getInstance(); + this.searchBar.addEventListener("keyup", (e: KeyboardEvent) => { + menuController.spotlightSearchOnKeyDown(e); + }); + } - MenuController.getInstance(); + Menu.menuCount++; for (const [key, value] of options) { const option = new MenuOption(key, false, null, this, null, value); @@ -56,8 +62,6 @@ class Menu { this.options.push(option); } - this.searchBar.addEventListener("input", () => {}); - this.htmlElement.addEventListener("mouseover", () => { this.htmlElement.style.visibility = "visible"; }); @@ -425,6 +429,7 @@ export class MenuController { static optionElementClass: string = "suggestionOptionParent"; static draftModeOptionElementClass: string = "draftModeOptionElementClass"; static menuElementClass: string = "suggestionMenuParent"; + static spotlightElementClass: string = "spotlight"; static optionTextElementClass: string = "suggestionOptionText"; static selectedOptionElementClass: string = "selectedSuggestionOptionParent"; @@ -462,7 +467,11 @@ export class MenuController { * * @param pos Starting top-left corner of this menu in the editor. */ - buildSingleLevelMenu(suggestions: EditCodeAction[], pos: any = { left: 0, top: 0 }) { + buildSingleLevelMenu( + suggestions: EditCodeAction[], + pos: any = { left: 0, top: 0 }, + isSpotlightSearch: boolean = false + ) { if (this.menus.length > 0) this.removeMenus(); else if (suggestions.length >= 0) { //TODO: Very hacky way of fixing #569 @@ -472,7 +481,7 @@ export class MenuController { suggestions.push(Actions.instance().actionsList[0]); //this does not have to be this specific aciton, just need one to create the option so that the menu is created and then we immediately delete the option } - const menu = this.module.menuController.buildMenu(suggestions, pos); + const menu = this.module.menuController.buildMenu(suggestions, pos, isSpotlightSearch); //TODO: Continuation of very hacky way of fixing #569 if (suggestions.length === 0) { @@ -515,7 +524,11 @@ export class MenuController { * * @returns the constructed menu. Null if no options was empty. */ - private buildMenu(options: EditCodeAction[], pos: any = { left: 0, top: 0 }): Menu { + private buildMenu( + options: EditCodeAction[], + pos: any = { left: 0, top: 0 }, + isSpotlightSearch: boolean = false + ): Menu { if (options.length > 0) { const menuOptions = new Map(); @@ -531,7 +544,7 @@ export class MenuController { }); } - const menu = new Menu(menuOptions); + const menu = new Menu(menuOptions, isSpotlightSearch); //TODO: These are the same values as the ones used for mouse offset by the messages so maybe make them shared in some util file menu.htmlElement.style.left = `${pos.left + document.getElementById(EDITOR_DOM_ID).offsetLeft}px`; @@ -555,6 +568,29 @@ export class MenuController { return null; } + spotlightSearchOnKeyDown(e: KeyboardEvent) { + const context = this.module.focus.getContext(); + const action = this.module.eventRouter.getKeyAction(e, context); + const target = e.target as HTMLInputElement; + + if (action?.data) action.data.source = { type: "keyboard" }; + + this.updateMenuOptions(target.value); + + if ( + action.type == EditActionType.SelectMenuSuggestion || + action.type == EditActionType.SelectMenuSuggestionAbove || + action.type == EditActionType.SelectMenuSuggestionBelow + ) { + const preventDefaultEvent = this.module.executer.execute(action, context, e); + + if (preventDefaultEvent) { + e.preventDefault(); + e.stopPropagation(); + } + } + } + removeMenus() { this.menus.forEach((menu) => { menu.close(); From 242d610758b062f6e1c057c40d82a9e2f5f55c6e Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 21 Jun 2022 11:39:34 -0400 Subject: [PATCH 04/12] centered suggestions when in spotlight mode and added a modal that greys out the background and closes spotlight search on click --- src/css/suggestion-menu.css | 13 ++++++ src/editor/action-executor.ts | 9 ++-- src/suggestions/suggestions-controller.ts | 51 +++++++++++++++++++---- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/css/suggestion-menu.css b/src/css/suggestion-menu.css index 311d20e..e562c97 100644 --- a/src/css/suggestion-menu.css +++ b/src/css/suggestion-menu.css @@ -120,3 +120,16 @@ .categoryOption { padding-left: 10px; } + +.spotlightModal{ + display: block; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.4); +} diff --git a/src/editor/action-executor.ts b/src/editor/action-executor.ts index 6511c63..37cfed0 100644 --- a/src/editor/action-executor.ts +++ b/src/editor/action-executor.ts @@ -1371,7 +1371,7 @@ export class ActionExecutor { .filter((item) => item.insertionResult.insertionType != InsertionType.Invalid), true ); - this.styleAutocompleteMenu(context.position); + this.styleAutocompleteMenu(context.position, true); break; @@ -2137,8 +2137,11 @@ export class ActionExecutor { ); } - private styleAutocompleteMenu(pos: Position) { + private styleAutocompleteMenu(pos: Position, isSpotlightSearch: boolean = false) { this.module.menuController.styleMenuOptions(); - this.module.menuController.updatePosition(this.module.menuController.getNewMenuPositionFromPosition(pos)); + this.module.menuController.updatePosition( + this.module.menuController.getNewMenuPositionFromPosition(pos), + isSpotlightSearch + ); } } diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index c6df43d..74863b6 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -33,24 +33,41 @@ class Menu { static idPrefix = "suggestion-menu-"; htmlElement: HTMLDivElement; searchBar: HTMLInputElement; + modal: HTMLDivElement; private optionsInViewPort; constructor(options: Map, isSpotlightSearch: boolean = false) { - this.htmlElement = document.createElement("div"); - this.htmlElement.classList.add(MenuController.menuElementClass); - this.htmlElement.id = `${Menu.idPrefix}${Menu.menuCount}`; - document.getElementById(EDITOR_DOM_ID).appendChild(this.htmlElement); - if (isSpotlightSearch) { + this.modal = document.createElement("div"); + this.modal.classList.add(MenuController.modalClass); + document.getElementById(EDITOR_DOM_ID).appendChild(this.modal); + + this.htmlElement = document.createElement("div"); + this.htmlElement.classList.add(MenuController.menuElementClass); + this.htmlElement.id = `${Menu.idPrefix}${Menu.menuCount}`; + this.modal.appendChild(this.htmlElement); + this.searchBar = document.createElement("input"); this.searchBar.classList.add(MenuController.spotlightElementClass); this.htmlElement.appendChild(this.searchBar); const menuController = MenuController.getInstance(); + + window.onclick = (e: MouseEvent) => { + if (e.target == this.modal) { + menuController.removeMenus(); + } + }; + this.searchBar.addEventListener("keyup", (e: KeyboardEvent) => { menuController.spotlightSearchOnKeyDown(e); }); + } else { + this.htmlElement = document.createElement("div"); + this.htmlElement.classList.add(MenuController.menuElementClass); + this.htmlElement.id = `${Menu.idPrefix}${Menu.menuCount}`; + document.getElementById(EDITOR_DOM_ID).appendChild(this.htmlElement); } Menu.menuCount++; @@ -237,7 +254,13 @@ class Menu { } removeFromDOM() { - document.getElementById(EDITOR_DOM_ID).removeChild(this.htmlElement); + let node = this.htmlElement; + let parentNode = node.parentNode; + parentNode.removeChild(this.htmlElement); + + if (parentNode == this.modal) { + document.getElementById(EDITOR_DOM_ID).removeChild(this.modal); + } } getOptionByText(optionText: string) { @@ -429,6 +452,7 @@ export class MenuController { static optionElementClass: string = "suggestionOptionParent"; static draftModeOptionElementClass: string = "draftModeOptionElementClass"; static menuElementClass: string = "suggestionMenuParent"; + static modalClass: string = "spotlightModal"; static spotlightElementClass: string = "spotlight"; static optionTextElementClass: string = "suggestionOptionText"; static selectedOptionElementClass: string = "selectedSuggestionOptionParent"; @@ -577,6 +601,7 @@ export class MenuController { this.updateMenuOptions(target.value); + //only enter and arrow keys work in input right now, other autocomplete keys do not work if ( action.type == EditActionType.SelectMenuSuggestion || action.type == EditActionType.SelectMenuSuggestionAbove || @@ -985,12 +1010,20 @@ export class MenuController { } } - updatePosition(pos: { left: number; top: number }) { + updatePosition(pos: { left: number; top: number }, isSpotlightSearch: boolean = false) { const element = this.menus[this.focusedMenuIndex]?.htmlElement; if (element) { - element.style.left = `${pos.left}px`; - element.style.top = `${pos.top}px`; + if (isSpotlightSearch) { + //centers the menu on the page + element.style.left = "50%"; + element.style.top = "50%"; + element.style.marginLeft = -element.offsetWidth / 2 + "px"; + element.style.marginTop = -element.offsetHeight / 2 + "px"; + } else { + element.style.left = `${pos.left}px`; + element.style.top = `${pos.top}px`; + } } } From fdd2517e33ad94d38b41fab0bd0009aee02b997d Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 27 Jun 2022 15:42:18 -0400 Subject: [PATCH 05/12] spotlight search with autocomplete on matched keys --- src/suggestions/suggestions-controller.ts | 48 ++++++++++++----------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index 74863b6..8afe5de 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -1,6 +1,6 @@ import { Position } from "monaco-editor"; import { EditCodeAction } from "../editor/action-filter"; -import { Actions, EditActionType, InsertActionType } from "../editor/consts"; +import { Actions, InsertActionType } from "../editor/consts"; import { Editor } from "../editor/editor"; import { EDITOR_DOM_ID } from "../editor/toolbox"; import { Validator } from "../editor/validator"; @@ -37,7 +37,7 @@ class Menu { private optionsInViewPort; - constructor(options: Map, isSpotlightSearch: boolean = false) { + constructor(options: EditCodeAction[], optionsMap: Map, isSpotlightSearch: boolean = false) { if (isSpotlightSearch) { this.modal = document.createElement("div"); this.modal.classList.add(MenuController.modalClass); @@ -61,7 +61,7 @@ class Menu { }; this.searchBar.addEventListener("keyup", (e: KeyboardEvent) => { - menuController.spotlightSearchOnKeyDown(e); + menuController.spotlightSearchOnKeyUp(e, options); }); } else { this.htmlElement = document.createElement("div"); @@ -72,7 +72,7 @@ class Menu { Menu.menuCount++; - for (const [key, value] of options) { + for (const [key, value] of optionsMap) { const option = new MenuOption(key, false, null, this, null, value); option.attachToParentMenu(this); @@ -568,7 +568,7 @@ export class MenuController { }); } - const menu = new Menu(menuOptions, isSpotlightSearch); + const menu = new Menu(options, menuOptions, isSpotlightSearch); //TODO: These are the same values as the ones used for mouse offset by the messages so maybe make them shared in some util file menu.htmlElement.style.left = `${pos.left + document.getElementById(EDITOR_DOM_ID).offsetLeft}px`; @@ -592,28 +592,30 @@ export class MenuController { return null; } - spotlightSearchOnKeyDown(e: KeyboardEvent) { + spotlightSearchOnKeyUp(e: KeyboardEvent, options: EditCodeAction[]) { const context = this.module.focus.getContext(); - const action = this.module.eventRouter.getKeyAction(e, context); const target = e.target as HTMLInputElement; - - if (action?.data) action.data.source = { type: "keyboard" }; - - this.updateMenuOptions(target.value); - - //only enter and arrow keys work in input right now, other autocomplete keys do not work - if ( - action.type == EditActionType.SelectMenuSuggestion || - action.type == EditActionType.SelectMenuSuggestionAbove || - action.type == EditActionType.SelectMenuSuggestionBelow - ) { - const preventDefaultEvent = this.module.executer.execute(action, context, e); - - if (preventDefaultEvent) { - e.preventDefault(); - e.stopPropagation(); + let prevText = target.value.slice(0, -1); + let curText = target.value; + + //check match + for (const match of options) { + if (match.terminatingChars.indexOf(e.key) >= 0) { + if (match.trimSpacesBeforeTermChar) prevText = prevText.trim(); + + if (prevText == match.matchString || (match.matchRegex != null && match.matchRegex.test(prevText))) + match.performAction(this.module.executer, this.module.eventRouter, context, { + type: "autocomplete-menu", + precision: this.calculateAutocompleteMatchPrecision(prevText, match.matchString), + length: + match.insertActionType === InsertActionType.InsertNewVariableStmt + ? prevText.length + 1 + : match.matchString.length + 1, + }); } } + + this.updateMenuOptions(curText); } removeMenus() { From 41e68ca45557a7e381bebc79f2ada7576f2b05df Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 28 Jun 2022 12:11:14 -0400 Subject: [PATCH 06/12] fixed bug where arrow keys and enter didn't work as intended --- src/suggestions/suggestions-controller.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index 8afe5de..a5a4807 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -1,6 +1,6 @@ import { Position } from "monaco-editor"; import { EditCodeAction } from "../editor/action-filter"; -import { Actions, InsertActionType } from "../editor/consts"; +import { Actions, EditActionType, InsertActionType } from "../editor/consts"; import { Editor } from "../editor/editor"; import { EDITOR_DOM_ID } from "../editor/toolbox"; import { Validator } from "../editor/validator"; @@ -595,9 +595,25 @@ export class MenuController { spotlightSearchOnKeyUp(e: KeyboardEvent, options: EditCodeAction[]) { const context = this.module.focus.getContext(); const target = e.target as HTMLInputElement; + const action = this.module.eventRouter.getKeyAction(e, context); let prevText = target.value.slice(0, -1); let curText = target.value; + if ( + action.type == EditActionType.SelectMenuSuggestion || + action.type == EditActionType.SelectMenuSuggestionAbove || + action.type == EditActionType.SelectMenuSuggestionBelow + ) { + const preventDefaultEvent = this.module.executer.execute(action, context, e); + + if (preventDefaultEvent) { + e.preventDefault(); + e.stopPropagation(); + } + + return; + } + //check match for (const match of options) { if (match.terminatingChars.indexOf(e.key) >= 0) { From 2394d6384a96e4ffb4282bf8b7e247dda47bcbcb Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 28 Jun 2022 12:54:40 -0400 Subject: [PATCH 07/12] styled spotlight search --- src/css/suggestion-menu.css | 24 +++++++++++++++++++++++ src/suggestions/suggestions-controller.ts | 1 + 2 files changed, 25 insertions(+) diff --git a/src/css/suggestion-menu.css b/src/css/suggestion-menu.css index e562c97..40fcf1c 100644 --- a/src/css/suggestion-menu.css +++ b/src/css/suggestion-menu.css @@ -133,3 +133,27 @@ background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4); } + +.spotlight{ + font-family: Consolas, "Courier New", monospace; + padding: 7px; + box-shadow: 0px 0px 6px 1px #ccc inset; + border: 1px solid #ccc; + + transition: box-shadow 0.15s ease-in-out; + -webkit-transition: box-shadow 0.15s ease-in-out; + -moz-transition: box-shadow 0.15s ease-in-out; + -o-transition: box-shadow 0.15s ease-in-out; + -ms-transition: box-shadow 0.15s ease-in-out; +} + +.spotlight:focus{ + box-shadow: 0px 0px 6px 1px #aaa inset; + font-weight: bold; +} + +.spotlight:focus-visible { + border: 1px solid #bbb; + outline: none; + font-weight: bold; +} \ No newline at end of file diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index a5a4807..8e5edf7 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -50,6 +50,7 @@ class Menu { this.searchBar = document.createElement("input"); this.searchBar.classList.add(MenuController.spotlightElementClass); + this.searchBar.placeholder = "Search for Blocks"; this.htmlElement.appendChild(this.searchBar); const menuController = MenuController.getInstance(); From c96cecec5ad596a06521fb311055b41172a0860e Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 1 Jul 2022 17:22:55 -0400 Subject: [PATCH 08/12] spotlight search using keydown and input --- src/suggestions/suggestions-controller.ts | 25 +++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/suggestions/suggestions-controller.ts b/src/suggestions/suggestions-controller.ts index 8e5edf7..cc6b9d7 100644 --- a/src/suggestions/suggestions-controller.ts +++ b/src/suggestions/suggestions-controller.ts @@ -61,8 +61,12 @@ class Menu { } }; - this.searchBar.addEventListener("keyup", (e: KeyboardEvent) => { - menuController.spotlightSearchOnKeyUp(e, options); + this.searchBar.addEventListener("keydown", (e: KeyboardEvent) => { + menuController.spotlightSearchOnKeyDown(e, options); + }); + + this.searchBar.addEventListener("input", (e: Event) => { + menuController.spotlightSearchOnChange(e, options); }); } else { this.htmlElement = document.createElement("div"); @@ -593,12 +597,9 @@ export class MenuController { return null; } - spotlightSearchOnKeyUp(e: KeyboardEvent, options: EditCodeAction[]) { + spotlightSearchOnKeyDown(e: KeyboardEvent, options: EditCodeAction[]) { const context = this.module.focus.getContext(); - const target = e.target as HTMLInputElement; const action = this.module.eventRouter.getKeyAction(e, context); - let prevText = target.value.slice(0, -1); - let curText = target.value; if ( action.type == EditActionType.SelectMenuSuggestion || @@ -611,13 +612,19 @@ export class MenuController { e.preventDefault(); e.stopPropagation(); } - - return; } + } + + spotlightSearchOnChange(e: Event, options: EditCodeAction[]) { + const context = this.module.focus.getContext(); + const target = e.target as HTMLInputElement; + let prevText = target.value.slice(0, -1); + let curText = target.value; + let lastkey = target.value.slice(-1); //check match for (const match of options) { - if (match.terminatingChars.indexOf(e.key) >= 0) { + if (match.terminatingChars.indexOf(lastkey) >= 0) { if (match.trimSpacesBeforeTermChar) prevText = prevText.trim(); if (prevText == match.matchString || (match.matchRegex != null && match.matchRegex.test(prevText))) From 6dfd08886014f64fc357a5d7b65acb7a70e9ab63 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 5 Jul 2022 12:06:58 -0400 Subject: [PATCH 09/12] implemented settings ui and functionality for spotlight search --- src/css/console.css | 6 ++ src/css/index.css | 1 + src/css/settings.css | 111 +++++++++++++++++++++++++++++++++++++ src/editor/event-router.ts | 10 +++- src/index.html | 1 + src/syntax-tree/module.ts | 3 + src/utilities/settings.ts | 110 ++++++++++++++++++++++++++++++++++++ 7 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/css/settings.css create mode 100644 src/utilities/settings.ts diff --git a/src/css/console.css b/src/css/console.css index 674ff42..e459495 100644 --- a/src/css/console.css +++ b/src/css/console.css @@ -59,6 +59,12 @@ border: solid #4f4f4f 0.5px; } +.settings-btn{ + box-shadow: none; + background-color: #69a; + color: #fff !important; +} + .console-button { color: #000; cursor: pointer; diff --git a/src/css/index.css b/src/css/index.css index 5b21493..a82d06a 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -12,6 +12,7 @@ @import url("notification.css"); @import url("tooltip.css"); @import url("accordion.css"); +@import url("settings.css"); @import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,300;0,400;0,600;0,700;1,300;1,400;1,600&display=swap"); diff --git a/src/css/settings.css b/src/css/settings.css new file mode 100644 index 0000000..d4d62ea --- /dev/null +++ b/src/css/settings.css @@ -0,0 +1,111 @@ +.settingsModal { + display: block; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(102, 153, 170); + background-color: rgba(102, 153, 170, 0.4); +} + +.settingsContainer{ + display: flex; + flex-direction: column; + gap: 10px; + position: fixed; + left: 50%; + top: 25%; + transform: translate(-50%, -50%); + width: 300px; + height: 300px; + border: 1px solid black; + background-color: #fff; + padding: 10px; + font-family: Consolas, "Courier New", monospace; + border-radius: 10px; +} + +.settingsHeader{ + text-align: center; + font-size: 1.5rem; + font-weight: 500; + border-bottom: 1px solid black; +} + +.settingsFooter{ + margin-top: auto; + display: flex; + justify-content: center; + align-items: center; +} + +.exitBtn{ + padding: 8px 10px; + color: #fff; + background-color: rgb(225, 100, 116); + border-radius: 4px; + cursor: pointer; + box-shadow: rgb(0 0 0 / 20%) 0px 3px 1px -2px, rgb(0 0 0 / 14%) 0px 2px 2px 0px, rgb(0 0 0 / 12%) 0px 1px 5px 0px; +} + +.setting{ + display: flex; + justify-content: space-between; + align-items: center; +} + +.toggleBtn{ + position:relative; + display: inline-block; + width: 60px; + height: 34px; +} + +.toggleBtn input{ + opacity: 0; + width: 0; + height: 0; +} + +.toggleBtnSlider{ + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + -webkit-transition: .4s; + transition: .4s; + border-radius: 34px; +} + +.toggleBtnSlider:before { + position: absolute; + content: ""; + height: 26px; + width: 26px; + left: 4px; + bottom: 4px; + background-color: white; + -webkit-transition: .4s; + transition: .4s; + border-radius: 50%; +} + +input:checked + .toggleBtnSlider { + background-color: #69a; +} + +input:focus + .toggleBtnSlider { + box-shadow: 0 0 1px #69a; +} + +input:checked + .toggleBtnSlider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); +} \ No newline at end of file diff --git a/src/editor/event-router.ts b/src/editor/event-router.ts index 8ce3da1..788a624 100644 --- a/src/editor/event-router.ts +++ b/src/editor/event-router.ts @@ -1,6 +1,7 @@ import { editor, IKeyboardEvent, IScrollEvent, Position } from "monaco-editor"; import * as ast from "../syntax-tree/ast"; import { Module } from "../syntax-tree/module"; +import { Settings } from "../utilities/settings"; import { AutoCompleteType, DataType, IdentifierRegex, InsertionType } from "./../syntax-tree/consts"; import { EditCodeAction } from "./action-filter"; import { Actions, EditActionType, InsertActionType, KeyPress } from "./consts"; @@ -9,12 +10,14 @@ import { Context } from "./focus"; export class EventRouter { module: Module; + settings: Settings; curPosition: Position; buttonClicksCount = new Map(); constructor(module: Module) { this.module = module; this.curPosition = module.editor.monaco.getPosition(); + this.settings = new Settings(); } getKeyAction(e: KeyboardEvent, providedContext?: Context): EditAction { @@ -263,7 +266,12 @@ export class EventRouter { case KeyPress.Space: { if (inTextEditMode) return new EditAction(EditActionType.InsertChar); - if (!inTextEditMode && e.ctrlKey && e.key.length == 1) { + if ( + !inTextEditMode && + e.ctrlKey && + e.key.length == 1 && + this.settings.getSettingsObject()["Spotlight Search"] + ) { return new EditAction(EditActionType.OpenValidInsertMenu); } diff --git a/src/index.html b/src/index.html index d0c3780..2105d1c 100644 --- a/src/index.html +++ b/src/index.html @@ -32,6 +32,7 @@

Defined Variables

> Run Code
Clear Console
+
Settings
diff --git a/src/syntax-tree/module.ts b/src/syntax-tree/module.ts index 88a13d2..de6e621 100644 --- a/src/syntax-tree/module.ts +++ b/src/syntax-tree/module.ts @@ -15,6 +15,7 @@ import { MessageController } from "../messages/message-controller"; import { ConstructHighlight } from "../messages/messages"; import { NotificationManager } from "../messages/notifications"; import { MenuController } from "../suggestions/suggestions-controller"; +import { Settings } from "../utilities/settings"; import { Util } from "../utilities/util"; import { AutocompleteTkn, @@ -58,6 +59,7 @@ export class Module { typeSystem: TypeChecker; notificationManager: NotificationManager; toolboxController: ToolboxController; + settings: Settings; scope: Scope; draftExpressions: DraftRecord[]; @@ -77,6 +79,7 @@ export class Module { this.actionFilter = new ActionFilter(this); this.notificationManager = new NotificationManager(this); this.toolboxController = new ToolboxController(this); + this.settings = new Settings(); this.globals = { hoveringOverCascadedMenu: false, diff --git a/src/utilities/settings.ts b/src/utilities/settings.ts new file mode 100644 index 0000000..7f206ff --- /dev/null +++ b/src/utilities/settings.ts @@ -0,0 +1,110 @@ +//Singleton controlling settings for the program +export class Settings { + private static instance: Settings; + private settingsObject: any; + + private modal: HTMLDivElement; + private settingsContainer: HTMLDivElement; + private settingsHeader: HTMLDivElement; + private settingsFooter: HTMLDivElement; + private exitBtn: HTMLDivElement; + + constructor() { + if (Settings.instance instanceof Settings) { + return Settings.instance; + } + + this.settingsObject = { + "Coloured Blocks": true, + "Spotlight Search": true, + "Enable Typing": true, + }; + + this.addEventListeners(); + + Settings.instance = this; + } + + public getSettingsObject() { + return this.settingsObject; + } + + private addEventListeners() { + const settingsBtn = document.getElementById("settingsBtn"); + + settingsBtn.addEventListener("click", () => { + this.renderSettings(); + }); + } + + private renderSettings() { + this.modal = document.createElement("div"); + this.modal.classList.add("settingsModal"); + this.modal.id = "settingsModal"; + document.getElementById("editor-container").appendChild(this.modal); + + this.settingsContainer = document.createElement("div"); + this.settingsContainer.classList.add("settingsContainer"); + this.settingsContainer.id = "settingsContainer"; + document.getElementById("settingsModal").appendChild(this.settingsContainer); + + this.settingsHeader = document.createElement("div"); + this.settingsHeader.classList.add("settingsHeader"); + this.settingsHeader.id = "settingsHeader"; + this.settingsHeader.innerHTML = "Settings"; + this.settingsContainer.appendChild(this.settingsHeader); + + Object.keys(this.settingsObject).map((key) => { + const setting = document.createElement("div"); + setting.classList.add("setting"); + this.settingsContainer.appendChild(setting); + + const settingText = document.createElement("div"); + settingText.classList.add("settingText"); + settingText.innerHTML = key; + setting.appendChild(settingText); + + const toggleBtn = document.createElement("label"); + toggleBtn.classList.add("toggleBtn"); + setting.appendChild(toggleBtn); + + const toggleBtnCheckbox = document.createElement("input"); + toggleBtnCheckbox.type = "checkbox"; + toggleBtnCheckbox.checked = this.settingsObject[key]; + toggleBtn.appendChild(toggleBtnCheckbox); + + const toggleBtnSlider = document.createElement("span"); + toggleBtnSlider.classList.add("toggleBtnSlider"); + toggleBtn.appendChild(toggleBtnSlider); + + toggleBtnCheckbox.addEventListener("change", () => { + this.settingsObject[key] = toggleBtnCheckbox.checked; + }); + }); + + this.settingsFooter = document.createElement("div"); + this.settingsFooter.classList.add("settingsFooter"); + this.settingsFooter.id = "settingsFooter"; + this.settingsContainer.appendChild(this.settingsFooter); + + this.exitBtn = document.createElement("div"); + this.exitBtn.classList.add("exitBtn"); + this.exitBtn.id = "exitBtn"; + this.exitBtn.innerHTML = "Close"; + this.settingsFooter.appendChild(this.exitBtn); + + this.exitBtn.addEventListener("click", () => { + this.closeSettings(); + }); + + window.onclick = (e: MouseEvent) => { + if (e.target === this.modal) { + this.closeSettings(); + } + }; + } + + private closeSettings() { + this.modal.remove(); + } +} From 57c7246ba5d4dab08674b780d8ac2737f316d742 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 5 Jul 2022 15:02:13 -0400 Subject: [PATCH 10/12] pull from blocks-to-code --- readme.md | 4 +- src/css/hole.css | 4 +- src/css/index.css | 4 +- src/css/messages.css | 3 +- src/css/toolbox.css | 4 +- src/docs/add-var.json | 5 +- src/docs/add.json | 5 +- src/docs/and.json | 5 +- src/docs/assign-add.json | 5 +- src/docs/assign-div.json | 5 +- src/docs/assign-mult.json | 5 +- src/docs/assign-sub.json | 5 +- src/docs/assign.json | 5 +- src/docs/break.json | 5 +- src/docs/choice.json | 5 +- src/docs/comp-eq.json | 5 +- src/docs/comp-gt.json | 5 +- src/docs/comp-gte.json | 5 +- src/docs/comp-lt.json | 5 +- src/docs/comp-lte.json | 5 +- src/docs/comp-ne.json | 5 +- src/docs/div.json | 5 +- src/docs/elif.json | 5 +- src/docs/else.json | 5 +- src/docs/f-str-item.json | 5 +- src/docs/f-str.json | 5 +- src/docs/false.json | 5 +- src/docs/find.json | 5 +- src/docs/floor-div.json | 5 +- src/docs/for.json | 5 +- src/docs/if.json | 5 +- src/docs/import.json | 5 +- src/docs/in.json | 5 +- src/docs/input.json | 5 +- src/docs/join.json | 5 +- src/docs/len.json | 5 +- src/docs/list-append.json | 5 +- src/docs/list-element-assign.json | 5 +- src/docs/list-index.json | 5 +- src/docs/list-item.json | 5 +- src/docs/list-literal.json | 5 +- src/docs/mod.json | 5 +- src/docs/mult.json | 5 +- src/docs/not-in.json | 5 +- src/docs/not.json | 5 +- src/docs/num.json | 5 +- src/docs/or.json | 5 +- src/docs/print.json | 5 +- src/docs/randint.json | 5 +- src/docs/range.json | 5 +- src/docs/replace.json | 5 +- src/docs/split.json | 5 +- src/docs/str.json | 5 +- src/docs/sub.json | 5 +- src/docs/to-int.json | 5 +- src/docs/to-str.json | 5 +- src/docs/true.json | 5 +- src/docs/while.json | 5 +- src/editor/action-executor.ts | 113 +++++++- src/editor/action-filter.ts | 5 +- src/editor/consts.ts | 419 ++++++++++++++++++++++-------- src/editor/cursor.ts | 4 +- src/editor/editor.ts | 13 +- src/editor/event-router.ts | 12 +- src/editor/hole.ts | 10 +- src/editor/toolbox.ts | 11 +- src/editor/validator.ts | 17 ++ src/messages/messages.ts | 47 ++-- src/syntax-tree/ast.ts | 123 +++++++-- src/syntax-tree/module.ts | 2 +- 70 files changed, 823 insertions(+), 237 deletions(-) diff --git a/readme.md b/readme.md index f204782..cf836bc 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# Nova Editor +# CodeStruct A new text-based environment that helps beginners transition into conventional text-based programming environments. Features: @@ -7,7 +7,7 @@ Features: - provides learning moments on invalid attempts - provides hints and visual descriptions -Authoring code with Nova: +Authoring code with CodeStruct: - Cursor-aware Toolbox - Suggestion Menus and Autocomplete - Draft Mode Editing diff --git a/src/css/hole.css b/src/css/hole.css index d6ef60d..cc370c8 100644 --- a/src/css/hole.css +++ b/src/css/hole.css @@ -8,6 +8,8 @@ transition-duration: 0.2s; border-radius: 5px; + background-color: white; + z-index: -998; } .editableHole { @@ -29,7 +31,7 @@ .text-editable-expr-hole { border-radius: 15px !important; - border-style: dashed !important; + border-style: dashed !important; } .empty-operator-hole { diff --git a/src/css/index.css b/src/css/index.css index a82d06a..5ca898b 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -34,7 +34,7 @@ body { } .button { - color: #0d0c22; + color: white; cursor: pointer; border-radius: 4px; display: flex; @@ -50,7 +50,7 @@ body { width: -webkit-fit-content; width: -moz-fit-content; width: fit-content; - border: solid 2px #fff; + border: none; } .button.button-invalid { diff --git a/src/css/messages.css b/src/css/messages.css index c7e8a3a..8d6888a 100644 --- a/src/css/messages.css +++ b/src/css/messages.css @@ -115,7 +115,8 @@ margin: 7px 7px 0 0; font-size: 13px; box-shadow: 0 0 3px 1px #aaa; - + + color:black; background-color: #ffffff; height: 17px; padding: 3px 8px 3px 8px; diff --git a/src/css/toolbox.css b/src/css/toolbox.css index 41f0395..2115d1a 100644 --- a/src/css/toolbox.css +++ b/src/css/toolbox.css @@ -51,6 +51,7 @@ hole1 { box-shadow: 0px 0px 1px 1px #0000005e inset; margin: 0px 3px; display: inline-block; + background-color:white; } hole2 { @@ -60,6 +61,7 @@ hole2 { border: dashed 1px #c7c7c7; min-width: 12px; height: 16px; + background-color: white; } #user-variables { @@ -628,4 +630,4 @@ hole2 { .cascaded-menu-extra-item .inline-var { color: #aa5bc8; -} +} \ No newline at end of file diff --git a/src/docs/add-var.json b/src/docs/add-var.json index 9e6d8a1..c011748 100644 --- a/src/docs/add-var.json +++ b/src/docs/add-var.json @@ -25,5 +25,8 @@ ] } ], - "search-queries": ["create new variable", "variable", "var"] + "search-queries": ["create new variable", "variable", "var"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/add.json b/src/docs/add.json index 6b00a7b..065d4aa 100644 --- a/src/docs/add.json +++ b/src/docs/add.json @@ -16,5 +16,8 @@ "example": "a = \"hello\"\nb = \"world\"\nprint((a + \" \" + b))" } ], - "search-queries": ["add", "sum"] + "search-queries": ["add", "sum"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/and.json b/src/docs/and.json index 490f1cf..57f05cd 100644 --- a/src/docs/and.json +++ b/src/docs/and.json @@ -16,5 +16,8 @@ "example": "a = 5\nb = 7\nc=2\n\nif ((a > c) and (b > c)):\n\tprint(\"Both expressions are true.\")" } ], - "search-queries": ["and", "both", "and operator"] + "search-queries": ["and", "both", "and operator"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/assign-add.json b/src/docs/assign-add.json index 1ba8cad..2432a33 100644 --- a/src/docs/assign-add.json +++ b/src/docs/assign-add.json @@ -11,5 +11,8 @@ "example": "a = 2\na += 2\nprint(a)" } ], - "search-queries": ["add to variable"] + "search-queries": ["add to variable"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/assign-div.json b/src/docs/assign-div.json index 694d7bc..23837ae 100644 --- a/src/docs/assign-div.json +++ b/src/docs/assign-div.json @@ -11,5 +11,8 @@ "example": "a = 10\na /= 2\nprint(a)" } ], - "search-queries": ["divide variable"] + "search-queries": ["divide variable"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/assign-mult.json b/src/docs/assign-mult.json index 300bd01..a36d1d3 100644 --- a/src/docs/assign-mult.json +++ b/src/docs/assign-mult.json @@ -11,5 +11,8 @@ "example": "a = 5\na *= 2\nprint(a)" } ], - "search-queries": ["multiply variable"] + "search-queries": ["multiply variable"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/assign-sub.json b/src/docs/assign-sub.json index 01082c0..b554215 100644 --- a/src/docs/assign-sub.json +++ b/src/docs/assign-sub.json @@ -11,5 +11,8 @@ "example": "a = 5\na -= 2\nprint(a)" } ], - "search-queries": ["subtract from variable", "deduct from variable"] + "search-queries": ["subtract from variable", "deduct from variable"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/assign.json b/src/docs/assign.json index 2e7265f..7dd2a47 100644 --- a/src/docs/assign.json +++ b/src/docs/assign.json @@ -11,5 +11,8 @@ "example": "a = 123\nprint(a)\na=321\nprint(a)" } ], - "search-queries": ["set", "assign", "assign variable", "set variable", "update value variable"] + "search-queries": ["set", "assign", "assign variable", "set variable", "update value variable"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/break.json b/src/docs/break.json index 20918e7..7c55486 100644 --- a/src/docs/break.json +++ b/src/docs/break.json @@ -40,5 +40,8 @@ ] } ], - "search-queries": ["exit", "loop", "break"] + "search-queries": ["exit", "loop", "break"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/choice.json b/src/docs/choice.json index d08ceb4..aa063ed 100644 --- a/src/docs/choice.json +++ b/src/docs/choice.json @@ -11,5 +11,8 @@ "example": "from random import choice\n\nif choice([1, 2, 3, 4, 5, 6]) == 6:\n\tprint(\"Rolled Six!\")" } ], - "search-queries": ["choice", "random choice", "choose randomly from list", "select randomly from array"] + "search-queries": ["choice", "random choice", "choose randomly from list", "select randomly from array"], + "styles":{ + "backgroundColor": "#a4e6a1" + } } diff --git a/src/docs/comp-eq.json b/src/docs/comp-eq.json index 1bf5b5e..d221cf9 100644 --- a/src/docs/comp-eq.json +++ b/src/docs/comp-eq.json @@ -16,5 +16,8 @@ "example": "a = 5\nb = 5\nwhile a == b:\n\ta += 1\nprint(a)\nprint(a)" } ], - "search-queries": ["compare equal", "check equal", "are equal"] + "search-queries": ["compare equal", "check equal", "are equal"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/comp-gt.json b/src/docs/comp-gt.json index 4ed677e..f33c3fe 100644 --- a/src/docs/comp-gt.json +++ b/src/docs/comp-gt.json @@ -16,5 +16,8 @@ "example": "a = 1\nb = 5\nwhile b > a:\n\ta += 1\nprint(a)\nprint(a)" } ], - "search-queries": ["compare greater than", "compare", "check greater than"] + "search-queries": ["compare greater than", "compare", "check greater than"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/comp-gte.json b/src/docs/comp-gte.json index 32365d5..902e5d5 100644 --- a/src/docs/comp-gte.json +++ b/src/docs/comp-gte.json @@ -16,5 +16,8 @@ "example": "a = 1\nb = 5\nwhile b >= a:\n\ta += 1\nprint(a)\nprint(a)" } ], - "search-queries": ["compare greater than or equal", "compare", "check greater than or equal"] + "search-queries": ["compare greater than or equal", "compare", "check greater than or equal"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/comp-lt.json b/src/docs/comp-lt.json index aa5a4a2..647e71a 100644 --- a/src/docs/comp-lt.json +++ b/src/docs/comp-lt.json @@ -16,5 +16,8 @@ "example": "a = 1\nb = 5\nwhile a < b:\n\ta += 1\nprint(a)\nprint(a)" } ], - "search-queries": ["compare", "compare less than", "check less than"] + "search-queries": ["compare", "compare less than", "check less than"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/comp-lte.json b/src/docs/comp-lte.json index e48781c..974b237 100644 --- a/src/docs/comp-lte.json +++ b/src/docs/comp-lte.json @@ -16,5 +16,8 @@ "example": "a = 1\nb = 5\nwhile a <= b:\n\ta += 1\nprint(a)\nprint(a)" } ], - "search-queries": ["less than or equal", "compare", "compare less than or equal", "check"] + "search-queries": ["less than or equal", "compare", "compare less than or equal", "check"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/comp-ne.json b/src/docs/comp-ne.json index 010d510..d90c1ad 100644 --- a/src/docs/comp-ne.json +++ b/src/docs/comp-ne.json @@ -16,5 +16,8 @@ "example": "a = 1\nb = 5\nwhile a != b:\n\ta += 1\nprint(a)\nprint(a)" } ], - "search-queries": ["not equal", "compare not equal", "not equal to", "are not equal"] + "search-queries": ["not equal", "compare not equal", "not equal to", "are not equal"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/div.json b/src/docs/div.json index e813b39..cafd721 100644 --- a/src/docs/div.json +++ b/src/docs/div.json @@ -11,5 +11,8 @@ "example": "a = 2\nb = 10\nprint((b / a))" } ], - "search-queries": ["divide", "division", "divide numbers"] + "search-queries": ["divide", "division", "divide numbers"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/elif.json b/src/docs/elif.json index 250c7b4..b26c103 100644 --- a/src/docs/elif.json +++ b/src/docs/elif.json @@ -34,5 +34,8 @@ "id": "elif-after-elif" } ], - "search-queries": ["else if", "else", "else condition", "choose", "path", "elif"] + "search-queries": ["else if", "else", "else condition", "choose", "path", "elif"], + "styles":{ + "backgroundColor": "#FFAB19" + } } diff --git a/src/docs/else.json b/src/docs/else.json index 77e7d6b..f5567cd 100644 --- a/src/docs/else.json +++ b/src/docs/else.json @@ -11,5 +11,8 @@ "example": "a = 2\nif a > 3:\n\tprint(3)\nelif a > 4:\n\tprint(4)\nelif a == 5:\n\tprint(5)\nelif a > 6:\n\tprint(6)\nelse:\n\tprint(\"None of the above are true.\")" } ], - "search-queries": ["else", "otherwise", "if"] + "search-queries": ["else", "otherwise", "if"], + "styles":{ + "backgroundColor": "#FFAB19" + } } diff --git a/src/docs/f-str-item.json b/src/docs/f-str-item.json index 74cbc7c..eb2bd65 100644 --- a/src/docs/f-str-item.json +++ b/src/docs/f-str-item.json @@ -11,5 +11,8 @@ "example": "age = 16\nname = \"Alex\"\nprint(f'My name is {name} and I am {age} years old')" } ], - "search-queries": ["formatted string item", "formatted text item"] + "search-queries": ["formatted string item", "formatted text item"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/f-str.json b/src/docs/f-str.json index c11d663..a8c5ff7 100644 --- a/src/docs/f-str.json +++ b/src/docs/f-str.json @@ -11,5 +11,8 @@ "example": "age = 16\nname = \"Alex\"\nprint(f'My name is {name} and I am {age} years old')" } ], - "search-queries": ["formatted string", "formatted text"] + "search-queries": ["formatted string", "formatted text"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/false.json b/src/docs/false.json index 523b0e9..1550d4c 100644 --- a/src/docs/false.json +++ b/src/docs/false.json @@ -11,5 +11,8 @@ "example": "if False :\n\tprint(\"will not print\")\n\nif True :\n\tprint(\"will print\")" } ], - "search-queries": ["false", "boolean"] + "search-queries": ["false", "boolean"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/find.json b/src/docs/find.json index b1df3e7..fcd2bd9 100644 --- a/src/docs/find.json +++ b/src/docs/find.json @@ -11,5 +11,8 @@ "example": "name = \"Zimmer\"\nindexOfE = name.find(\"e\")\nprint(indexOfE)" } ], - "search-queries": ["search text", "find text", "find string"] + "search-queries": ["search text", "find text", "find string"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/floor-div.json b/src/docs/floor-div.json index 0a88a50..500e33d 100644 --- a/src/docs/floor-div.json +++ b/src/docs/floor-div.json @@ -11,5 +11,8 @@ "example": "a = 2\nb = 7\nprint((b / a))" } ], - "search-queries": ["divide numbers", "divide integer", "divide floor"] + "search-queries": ["divide numbers", "divide integer", "divide floor"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/for.json b/src/docs/for.json index cb499e9..eb09cf7 100644 --- a/src/docs/for.json +++ b/src/docs/for.json @@ -58,5 +58,8 @@ "id": "loop-chars-of-str" } ], - "search-queries": ["for", "loop", "repeat", "go through", "iterate", "list"] + "search-queries": ["for", "loop", "repeat", "go through", "iterate", "list"], + "styles":{ + "backgroundColor": "#411b8c" + } } diff --git a/src/docs/if.json b/src/docs/if.json index 73bad14..0d6d494 100644 --- a/src/docs/if.json +++ b/src/docs/if.json @@ -25,5 +25,8 @@ "id": "check-val-variable" } ], - "search-queries": ["if", "condition", "conditional", "choose", "path"] + "search-queries": ["if", "condition", "conditional", "choose", "path"], + "styles":{ + "backgroundColor": "#FFAB19" + } } diff --git a/src/docs/import.json b/src/docs/import.json index 14c5e5a..4bf287a 100644 --- a/src/docs/import.json +++ b/src/docs/import.json @@ -16,5 +16,8 @@ "example": "from random import randint\nprint(randint(1, 6))" } ], - "search-queries": ["import module", "import random"] + "search-queries": ["import module", "import random"], + "styles":{ + "backgroundColor": "#e897aa" + } } diff --git a/src/docs/in.json b/src/docs/in.json index 41412d9..d0c5ed8 100644 --- a/src/docs/in.json +++ b/src/docs/in.json @@ -11,5 +11,8 @@ "example": "from random import randint\na = randint(1, 10)\nb = [1, 2, 3, 4, 5]\nif a in b:\n\tprint(\"a is inside b\")\n\nif a not in b:\n\tprint(\"a is not inside b\")" } ], - "search-queries": ["in list", "inside list", "is inside list", "check inside list", "check list includes"] + "search-queries": ["in list", "inside list", "is inside list", "check inside list", "check list includes"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/input.json b/src/docs/input.json index aa2b664..dcc4cde 100644 --- a/src/docs/input.json +++ b/src/docs/input.json @@ -11,5 +11,8 @@ "example": "name = input(\"Hi! What’s your name?\")\nprint(name)" } ], - "search-queries": ["input", "prompt", "text", "user", "ask input", "ask user"] + "search-queries": ["input", "prompt", "text", "user", "ask input", "ask user"], + "styles":{ + "backgroundColor": "#5CB1D6" + } } diff --git a/src/docs/join.json b/src/docs/join.json index 01b55a3..e26b93e 100644 --- a/src/docs/join.json +++ b/src/docs/join.json @@ -11,5 +11,8 @@ "example": "names = [\"Anna\", \"John\", \"Peter\"]\njoinedNames = \"-\".join(names)\nprint(joinedNames)" } ], - "search-queries": ["join string", "join text"] + "search-queries": ["join string", "join text"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/len.json b/src/docs/len.json index 4fdd027..dada84d 100644 --- a/src/docs/len.json +++ b/src/docs/len.json @@ -16,5 +16,8 @@ "example": "items = [1, 2, 3]\na = len(items)\nprint(a)" } ], - "search-queries": ["length of list", "length of string", "length of text"] + "search-queries": ["length of list", "length of string", "length of text"], + "styles":{ + "backgroundColor": "#5CB1D6" + } } diff --git a/src/docs/list-append.json b/src/docs/list-append.json index adb57ff..9cd6a6a 100644 --- a/src/docs/list-append.json +++ b/src/docs/list-append.json @@ -23,5 +23,8 @@ "add to end list", "append to end list", "insert end list" - ] + ], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/list-element-assign.json b/src/docs/list-element-assign.json index b36a6f9..4ca37e0 100644 --- a/src/docs/list-element-assign.json +++ b/src/docs/list-element-assign.json @@ -21,5 +21,8 @@ "change value list index", "update item at index", "set value list index" - ] + ], + "styles":{ + "backgroundColor": "#7c8ee6" + } } diff --git a/src/docs/list-index.json b/src/docs/list-index.json index d33b82b..32ffa68 100644 --- a/src/docs/list-index.json +++ b/src/docs/list-index.json @@ -16,5 +16,8 @@ "example": "a = [1, 2, 3]\nif a[1] == 2:\n\tprint(\"The second element of the list is equal to 2.\")" } ], - "search-queries": ["access list item", "access list element", "access list element at index"] + "search-queries": ["access list item", "access list element", "access list element at index"], + "styles":{ + "backgroundColor": "#7c8ee6" + } } diff --git a/src/docs/list-item.json b/src/docs/list-item.json index 760e789..edcc393 100644 --- a/src/docs/list-item.json +++ b/src/docs/list-item.json @@ -11,5 +11,8 @@ "example": "a = []\nb = [1, 2]\nc = [1, 2, 3]" } ], - "search-queries": ["comma", "list item"] + "search-queries": ["comma", "list item"], + "styles":{ + "backgroundColor": "#7c8ee6" + } } diff --git a/src/docs/list-literal.json b/src/docs/list-literal.json index 3ed86bb..0faf6ed 100644 --- a/src/docs/list-literal.json +++ b/src/docs/list-literal.json @@ -16,5 +16,8 @@ "example": "a = [\"cat\", \"dog\", \"parrot\"]\nb = [1, \"cat\", true]\nc = [1, [1, \"dog\"], \"cat\", [true]]" } ], - "search-queries": ["empty list", "create empty list", "create list", "array", "create empty array"] + "search-queries": ["empty list", "create empty list", "create list", "array", "create empty array"], + "styles":{ + "backgroundColor": "#7c8ee6" + } } diff --git a/src/docs/mod.json b/src/docs/mod.json index 1401770..5cc8863 100644 --- a/src/docs/mod.json +++ b/src/docs/mod.json @@ -11,5 +11,8 @@ "example": "print((29 % 5)) # prints 4\nprint((28 % 5)) # prints 3\nprint((27 % 5)) # prints 2\nprint((26 % 5)) # prints 1\nprint((25 % 5)) # prints 0" } ], - "search-queries": ["modulo", "remainder"] + "search-queries": ["modulo", "remainder"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/mult.json b/src/docs/mult.json index 77602a0..1d02664 100644 --- a/src/docs/mult.json +++ b/src/docs/mult.json @@ -11,5 +11,8 @@ "example": "a = 2\nb = 5\nprint((b * a))" } ], - "search-queries": ["multiply numbers", "multiply"] + "search-queries": ["multiply numbers", "multiply"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/not-in.json b/src/docs/not-in.json index ddb815f..69df0a7 100644 --- a/src/docs/not-in.json +++ b/src/docs/not-in.json @@ -11,5 +11,8 @@ "example": "from random import randint\na = randint(1, 10)\nb = [1, 2, 3, 4, 5]\nif a in b:\n\tprint(\"a is inside b\")\n\nif a not in b:\n\tprint(\"a is not inside b\")" } ], - "search-queries": ["not in", "not inside list", "not within list", "does not include"] + "search-queries": ["not in", "not inside list", "not within list", "does not include"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/not.json b/src/docs/not.json index bdf6b8d..1aeadd9 100644 --- a/src/docs/not.json +++ b/src/docs/not.json @@ -11,5 +11,8 @@ "example": "a = 2\nb = 2\nif not (a == b):\n\tprint(\"Will not print.\")\n\nif not (b != a):\n\tprint(\"b is equal to a\")" } ], - "search-queries": ["negate", "not", "logical", "boolean", "opposite"] + "search-queries": ["negate", "not", "logical", "boolean", "opposite"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/num.json b/src/docs/num.json index 6289373..d4816be 100644 --- a/src/docs/num.json +++ b/src/docs/num.json @@ -10,5 +10,8 @@ "id": "ex-num", "example": "age = 21\nprint(age)\nprint(21)" } - ] + ], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/or.json b/src/docs/or.json index bd74815..1cb1b7f 100644 --- a/src/docs/or.json +++ b/src/docs/or.json @@ -16,5 +16,8 @@ "example": "a = 5\nb = 7\nc=2\n\nif ((a > c) and (b < c)):\n\tprint(\"Only the first expression is true.\")" } ], - "search-queries": ["conditional", "or", "logical", "boolean", "one of"] + "search-queries": ["conditional", "or", "logical", "boolean", "one of"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/print.json b/src/docs/print.json index 46aa743..ae6410a 100644 --- a/src/docs/print.json +++ b/src/docs/print.json @@ -16,5 +16,8 @@ "example": "a = \"abc\"\nprint(a)" } ], - "search-queries": ["output", "say", "print", "print output", "console", "write", "see output"] + "search-queries": ["output", "say", "print", "print output", "console", "write", "see output"], + "styles":{ + "backgroundColor": "#d0b7ed" + } } diff --git a/src/docs/randint.json b/src/docs/randint.json index 2055944..93c708a 100644 --- a/src/docs/randint.json +++ b/src/docs/randint.json @@ -11,5 +11,8 @@ "example": "a = randint(0, 10)\nprint(a)" } ], - "search-queries": ["random number", "random integer", "randint", "random between"] + "search-queries": ["random number", "random integer", "randint", "random between"], + "styles":{ + "backgroundColor": "#a4e6a1" + } } diff --git a/src/docs/range.json b/src/docs/range.json index 7e28f37..8c39910 100644 --- a/src/docs/range.json +++ b/src/docs/range.json @@ -11,5 +11,8 @@ "example": "for i in range(10):\n\tprint(i)" } ], - "search-queries": ["range", "sequence", "iterate", "for loop"] + "search-queries": ["range", "sequence", "iterate", "for loop"], + "styles":{ + "backgroundColor": "#a4e6a1" + } } diff --git a/src/docs/replace.json b/src/docs/replace.json index de6d013..1336519 100644 --- a/src/docs/replace.json +++ b/src/docs/replace.json @@ -11,5 +11,8 @@ "example": "name = \"John\"\nname = name.replace(\"oh\", \"a\")\nprint(name)" } ], - "search-queries": ["replace", "replace text", "replace string"] + "search-queries": ["replace", "replace text", "replace string"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/split.json b/src/docs/split.json index 59cc25d..2ec8b0a 100644 --- a/src/docs/split.json +++ b/src/docs/split.json @@ -11,5 +11,8 @@ "example": "name = \"Split-this-text-on-hyphen\"\nsplitName = name.split(\"-\")\nprint(splitName)" } ], - "search-queries": ["split", "split text", "split string"] + "search-queries": ["split", "split text", "split string"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/str.json b/src/docs/str.json index f483e50..4fe79ee 100644 --- a/src/docs/str.json +++ b/src/docs/str.json @@ -11,5 +11,8 @@ "example": "fruit = \"apple\"\nprint(fruit)\nprint(\"apple\")" } ], - "search-queries": ["create text", "create string", "empty string", "empty text"] + "search-queries": ["create text", "create string", "empty string", "empty text"], + "styles":{ + "backgroundColor": "#ebba8a" + } } diff --git a/src/docs/sub.json b/src/docs/sub.json index 40170f4..1dbf92c 100644 --- a/src/docs/sub.json +++ b/src/docs/sub.json @@ -11,5 +11,8 @@ "example": "a = 20\nb = 10\nprint((a - b))" } ], - "search-queries": ["subtract numbers", "subtraction", "deduct"] + "search-queries": ["subtract numbers", "subtraction", "deduct"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/to-int.json b/src/docs/to-int.json index 6d0b786..1c5ccf4 100644 --- a/src/docs/to-int.json +++ b/src/docs/to-int.json @@ -11,5 +11,8 @@ "example": "a = \"2\"\nb = \"5\"\ntext_add = a + b\nnumber_add = int(a) + int(b)" } ], - "search-queries": ["integer cast", "number convert", "convert to number", "convert to integer"] + "search-queries": ["integer cast", "number convert", "convert to number", "convert to integer"], + "styles":{ + "backgroundColor": "#edafdf" + } } diff --git a/src/docs/to-str.json b/src/docs/to-str.json index 623fe52..8d0d8df 100644 --- a/src/docs/to-str.json +++ b/src/docs/to-str.json @@ -20,5 +20,8 @@ "example": "a = 2\nc = \"2\"\nprint(str(a) == c)" } ], - "search-queries": ["string cast", "text convert", "convert to string", "convert to text"] + "search-queries": ["string cast", "text convert", "convert to string", "convert to text"], + "styles":{ + "backgroundColor": "#edafdf" + } } diff --git a/src/docs/true.json b/src/docs/true.json index d025075..b55124c 100644 --- a/src/docs/true.json +++ b/src/docs/true.json @@ -11,5 +11,8 @@ "example": "if True :\n\tprint(\"will print\")\n\nif False :\n\tprint(\"will not print\")" } ], - "search-queries": ["true", "boolean"] + "search-queries": ["true", "boolean"], + "styles":{ + "backgroundColor": "#59C059" + } } diff --git a/src/docs/while.json b/src/docs/while.json index a85b0b7..11dbb29 100644 --- a/src/docs/while.json +++ b/src/docs/while.json @@ -46,5 +46,8 @@ "condition", "conditional", "repeat condition" - ] + ], + "styles":{ + "backgroundColor": "#411b8c" + } } diff --git a/src/editor/action-executor.ts b/src/editor/action-executor.ts index 37cfed0..d3c0b34 100644 --- a/src/editor/action-executor.ts +++ b/src/editor/action-executor.ts @@ -1,4 +1,5 @@ import { Position, Range } from "monaco-editor"; + import { ErrorMessage } from "../messages/error-msg-generator"; import { ConstructHighlight, ScopeHighlight } from "../messages/messages"; import { @@ -57,7 +58,7 @@ import { getUserFriendlyType, isImportable } from "../utilities/util"; import { LogEvent, Logger, LogType } from "./../logger/analytics"; import { BinaryOperator, DataType, InsertionType } from "./../syntax-tree/consts"; import { EditCodeAction } from "./action-filter"; -import { Actions, EditActionType, InsertActionType } from "./consts"; +import { Actions, Docs, EditActionType, InsertActionType } from "./consts"; import { EditAction } from "./data-types"; import { Context, UpdatableContext } from "./focus"; @@ -170,7 +171,7 @@ export class ActionExecutor { } case EditActionType.InsertElseStatement: { - const newStatement = new ElseStatement(action.data.hasCondition); + const newStatement = new ElseStatement(Docs.ElseDocs.styles.backgroundColor, action.data.hasCondition); if (action.data.outside) { // when the else is being inserted outside @@ -243,17 +244,21 @@ export class ActionExecutor { if (flashGreen) this.flashGreen(newStatement); - let scopeHighlight = new ScopeHighlight(this.module.editor, newStatement); + let scopeHighlight = new ScopeHighlight(this.module.editor, newStatement, newStatement.color); eventData.code = "else-statement"; break; } case EditActionType.InsertExpression: { + const expression = action.data?.expression as Expression; + this.insertExpression(context, action.data?.expression); if (flashGreen) this.flashGreen(action.data?.expression); + this.setTokenColor(action.data?.expression, expression.color); + eventData.code = action.data?.expression?.getRenderText(); break; @@ -267,7 +272,9 @@ export class ActionExecutor { if (flashGreen) this.flashGreen(action.data?.statement); if (statement.hasBody()) { - let scopeHighlight = new ScopeHighlight(this.module.editor, statement); + let scopeHighlight = new ScopeHighlight(this.module.editor, statement, statement.color); + } else { + this.setTokenColor(action.data?.statement, statement.color); } eventData.code = action.data?.statement?.getRenderText(); @@ -287,6 +294,8 @@ export class ActionExecutor { if (flashGreen) this.flashGreen(action.data?.statement); + this.setTokenColor(action.data?.statement, statement.color); + eventData.code = "var-assignment"; eventData.id = id; @@ -297,7 +306,11 @@ export class ActionExecutor { if (action.data?.replace) { this.insertExpression( context, - new UnaryOperatorExpr(action.data.operator, (context.token as TypedEmptyExpr).type[0]) + new UnaryOperatorExpr( + Docs.NotDocs.styles.backgroundColor, + action.data.operator, + (context.token as TypedEmptyExpr).type[0] + ) ); } else if (action.data?.wrap) { const expr = context.expressionToRight as Expression; @@ -306,6 +319,7 @@ export class ActionExecutor { const root = expr.rootNode as Statement; const newCode = new UnaryOperatorExpr( + Docs.NotDocs.styles.backgroundColor, action.data.operator, expr.returns, expr.returns, @@ -581,7 +595,11 @@ export class ActionExecutor { this.module.editor.executeEdits(rightTokenRange, rightToken); - const fStringToken = new FormattedStringCurlyBracketsExpr(formattedStringExpr, token.indexInRoot + 1); + const fStringToken = new FormattedStringCurlyBracketsExpr( + Docs.NotDocs.styles.backgroundColor, + formattedStringExpr, + token.indexInRoot + 1 + ); formattedStringExpr.tokens.splice(token.indexInRoot + 1, 0, ...[fStringToken]); @@ -883,6 +901,7 @@ export class ActionExecutor { const initialBoundary = this.getBoundaries(context.expressionToLeft); const varAssignStmt = new VarAssignmentStmt( + Docs.AddVarDocs.styles.backgroundColor, "", context.expressionToLeft.identifier, varOpStmt.rootNode, @@ -895,6 +914,8 @@ export class ActionExecutor { this.module.focus.updateContext(varAssignStmt.getInitialFocus()); if (flashGreen) this.flashGreen(varAssignStmt); + + this.setTokenColor(varAssignStmt, varAssignStmt.color); } else { if ( context.expressionToLeft instanceof VariableReferenceExpr && @@ -910,6 +931,8 @@ export class ActionExecutor { this.module.focus.updateContext(action.data.modifier.getInitialFocus()); if (flashGreen) this.flashGreen(action.data.modifier); + + // this.setTokenColor(action.data.modifier, action.data.modifier.color); } } @@ -1002,6 +1025,7 @@ export class ActionExecutor { const holeDataTypes = exprToLeftRoot.typeOfHoles[context.expressionToLeft.indexInRoot]; const valOprExpr = new ValueOperationExpr( + Docs.AddVarDocs.styles.backgroundColor, context.expressionToLeft, [modifier], context.expressionToLeft.rootNode, @@ -1062,6 +1086,9 @@ export class ActionExecutor { } if (flashGreen) this.flashGreen(action.data.modifier); + + this.setTokenColor(action.data.modifier, action.data.modifier.color); + eventData.code = action.data.modifier.getRenderText(); break; @@ -1079,11 +1106,18 @@ export class ActionExecutor { toRight: true, }); } else if (action.data.replace) { - binExpr = new BinaryOperatorExpr(action.data.operator, (context.token as TypedEmptyExpr).type[0]); + binExpr = new BinaryOperatorExpr( + Docs.AddDocs.styles.backgroundColor, + action.data.operator, + (context.token as TypedEmptyExpr).type[0] + ); this.insertExpression(context, binExpr); } if (flashGreen) this.flashGreen(binExpr); + + this.setTokenColor(binExpr, binExpr.color); + eventData.code = action.data.operator; break; @@ -1143,6 +1177,9 @@ export class ActionExecutor { } if (flashGreen) this.flashGreen(newCode); + + this.setTokenColor(newCode, newCode.color); + eventData.code = action.data.expression.getRenderText(); eventData.wrap = true; @@ -1152,6 +1189,7 @@ export class ActionExecutor { case EditActionType.ConvertAutocompleteToString: { const autocompleteToken = action.data.token as AutocompleteTkn; const literalValExpr = new LiteralValExpr( + Docs.StrDocs.styles.backgroundColor, DataType.String, autocompleteToken.text, autocompleteToken.rootNode as Expression | Statement, @@ -1169,10 +1207,13 @@ export class ActionExecutor { } case EditActionType.InsertEmptyList: { - const newLiteral = new ListLiteralExpression(); + const newLiteral = new ListLiteralExpression(Docs.ListLiteralDocs.styles.backgroundColor); this.insertExpression(context, newLiteral); if (flashGreen) this.flashGreen(newLiteral); + + this.setTokenColor(newLiteral, newLiteral.color); + eventData.code = "empty-list"; break; @@ -1219,6 +1260,7 @@ export class ActionExecutor { case EditActionType.ReplaceExpressionWithItem: { const rootNode = context.token.rootNode as Expression; let replacementTkn; + for (let i = 0; i < rootNode.tokens.length; i++) { if ( !(rootNode.tokens[i] instanceof TypedEmptyExpr) && @@ -1228,7 +1270,9 @@ export class ActionExecutor { replacementTkn = rootNode.tokens[i]; } } + this.replaceCode(rootNode, replacementTkn); + break; } @@ -1241,7 +1285,11 @@ export class ActionExecutor { this.module.editor.cursor.setSelection(null); currContext = this.module.focus.getContext(); - const stmt = new ImportStatement(action.data?.moduleName, action.data?.itemName); + const stmt = new ImportStatement( + Docs.ImportDocs.styles.backgroundColor, + action.data?.moduleName, + action.data?.itemName + ); const insertAction = new EditCodeAction( "from --- import --- :", "add-import-btn", @@ -1277,6 +1325,8 @@ export class ActionExecutor { this.flashGreen(action.data.codeToReplace.rootNode as CodeConstruct); + this.setTokenColor(action.data.codeToReplace.rootNode, action.data.codeToReplace.rootNode.color); + if (root instanceof Expression) root.validateTypes(this.module); eventData.code = action.data.codeToReplace.getRenderText(); @@ -1301,6 +1351,8 @@ export class ActionExecutor { this.insertExpression(this.module.focus.getContext(), action.data.codeToReplace as Expression); this.flashGreen(action.data.codeToReplace.rootNode as CodeConstruct); + this.setTokenColor(action.data.codeToReplace.rootNode, action.data.codeToReplace.rootNode.color); + if (root instanceof Expression) root.validateTypes(this.module); eventData.code = action.data.codeToReplace.getRenderText(); @@ -1350,7 +1402,19 @@ export class ActionExecutor { break; case EditActionType.InsertLiteral: { - const newLiteral = new LiteralValExpr(action.data?.literalType, action.data?.initialValue); + let color: string; + if (action.data?.literalType == DataType.String) { + color = Docs.StrDocs.styles.backgroundColor; + } else if (action.data?.literalType == DataType.Number) { + color = Docs.NumDocs.styles.backgroundColor; + } else if (action.data?.literalType == DataType.Number) { + color = Docs.NumDocs.styles.backgroundColor; + } else if (action.data?.literalType == DataType.Boolean && action.data?.initialValue == "True") { + color = Docs.TrueDocs.styles.backgroundColor; + } else if (action.data?.literalType == DataType.Boolean && action.data?.initialValue == "False") { + color = Docs.FalseDocs.styles.backgroundColor; + } + const newLiteral = new LiteralValExpr(color, action.data?.literalType, action.data?.initialValue); this.insertExpression(context, newLiteral); if (flashGreen) this.flashGreen(newLiteral); @@ -1444,6 +1508,9 @@ export class ActionExecutor { } if (flashGreen) this.flashGreen(action.data.operator); + + this.setTokenColor(action.data.operator, action.data.operator.color); + eventData.code = action.data.operator.getRenderText(); break; @@ -1494,7 +1561,7 @@ export class ActionExecutor { if (this.module.validator.onBeginningOfLine(context)) { const varRef = this.createVarReference(buttonId); - const stmt = new VarOperationStmt(varRef); + const stmt = new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, varRef); this.replaceEmptyStatement(context.lineStatement, stmt); const availableActions = this.module.actionFilter @@ -1531,7 +1598,11 @@ export class ActionExecutor { }), this.module.focus.getContext() ); - this.flashGreen(modifier.rootNode as Statement); + + const varOpStmt = modifier.rootNode as Statement; + + this.flashGreen(varOpStmt); + this.setTokenColor(varOpStmt, varOpStmt.color); }); buttons.push(button); @@ -1543,6 +1614,8 @@ export class ActionExecutor { if (autocompleteData) { this.flashGreen(stmt); + + this.setTokenColor(stmt, stmt.color); } eventData.code = varRef.getRenderText(); @@ -1552,6 +1625,8 @@ export class ActionExecutor { if (autocompleteData) { this.flashGreen(expr); + + this.setTokenColor(expr, expr.color); } eventData.code = expr.getRenderText(); @@ -1660,6 +1735,15 @@ export class ActionExecutor { } } + private setTokenColor(code: CodeConstruct, color: string) { + const aRgbHex = color.substring(1).match(/.{1,2}/g); + const aRgb = [parseInt(aRgbHex[0], 16), parseInt(aRgbHex[1], 16), parseInt(aRgbHex[2], 16)]; + + if (code) { + let highlight = new ConstructHighlight(this.module.editor, code, [aRgb[0], aRgb[1], aRgb[2], 1]); + } + } + private insertEmptyListItem(focusedCode: CodeConstruct, index: number, items: Array) { if (focusedCode instanceof Token || focusedCode instanceof Expression) { const root = focusedCode.rootNode; @@ -1841,6 +1925,7 @@ export class ActionExecutor { const index = expr.indexInRoot; const newCode = new BinaryOperatorExpr( + Docs.AddDocs.styles.backgroundColor, op, expr.returns, // is not that important, will be replaced in the constructor based on the operator. root, @@ -2076,6 +2161,10 @@ export class ActionExecutor { root.rebuild(root.getLeftPosition(), 0); + if (replace instanceof Statement && !(replace instanceof LiteralValExpr)) { + this.setTokenColor(replace, replace.color); + } + this.module.editor.executeEdits(replacementRange, replace); if (replace instanceof Token && replace.isEmpty) { diff --git a/src/editor/action-filter.ts b/src/editor/action-filter.ts index bf69cd0..e46ec3f 100644 --- a/src/editor/action-filter.ts +++ b/src/editor/action-filter.ts @@ -43,6 +43,7 @@ export class ActionFilter { action.getCodeFunction, action.insertActionType, action.insertData, + action.documentation, action.validateAction(this.module.validator, context), action.terminatingChars, action.matchString, @@ -80,6 +81,7 @@ export class ActionFilter { }, null, {}, + null, new InsertionResult(varRecord[1], "MESSAGE BASED ON INSERTION TYPE", []), //TODO: Need to actually check what the insertion type is and populate the insertion result accordingly [""], varStmt.getIdentifier(), @@ -323,6 +325,7 @@ export class EditCodeAction extends UserAction { getCodeFunction: () => Statement | Expression, insertActionType: InsertActionType, insertData: any = {}, + documentation: any, insertionResult: InsertionResult, terminatingChars: string[], matchString: string, @@ -335,7 +338,7 @@ export class EditCodeAction extends UserAction { getCodeFunction, insertActionType, insertData, - null, + documentation, terminatingChars, matchString, matchRegex, diff --git a/src/editor/consts.ts b/src/editor/consts.ts index cc24922..2655320 100644 --- a/src/editor/consts.ts +++ b/src/editor/consts.ts @@ -287,6 +287,61 @@ export enum InsertActionType { InsertOperatorTkn, } +export const Docs: any = { + AddVarDocs, + AddDocs, + AndDocs, + AssignAddDocs, + AssignDivDocs, + AssignMultDocs, + AssignSubDocs, + AssignDocs, + BreakDocs, + RandChoiceDocs, + CompEqDocs, + CompGtDocs, + CompGteDocs, + CompLtDocs, + CompLteDocs, + CompNeDocs, + DivDocs, + ElifDocs, + ElseDocs, + FStringItemDocs, + FStringDocs, + FalseDocs, + FindDocs, + FloorDivDocs, + ForDocs, + IfDocs, + ImportDocs, + InDocs, + InputDocs, + JoinDocs, + LenDocs, + ListAppendDocs, + ListIndexDocs, + ListItemDocs, + ListLiteralDocs, + ModDocs, + MultDocs, + NotInDocs, + NotDocs, + NumDocs, + OrDocs, + PrintDocs, + RandintDocs, + RangeDocs, + ReplaceDocs, + SplitDocs, + StrDocs, + SubDocs, + CastToIntDocs, + CastToStrDocs, + TrueDocs, + WhileDocs, +}; + export class Actions { private static inst: Actions; actionsList: Array; @@ -298,7 +353,10 @@ export class Actions { const PrintStmt = new EditCodeAction( "print(---)", "add-print-btn", - () => new FunctionCallStmt("print", [new Argument([DataType.Any], "item", false)]), + () => + new FunctionCallStmt(PrintDocs.styles.backgroundColor, "print", [ + new Argument([DataType.Any], "item", false), + ]), InsertActionType.InsertPrintFunctionStmt, {}, PrintDocs, @@ -312,6 +370,7 @@ export class Actions { "add-randint-btn", () => new FunctionCallExpr( + RandintDocs.styles.backgroundColor, "randint", [new Argument([DataType.Number], "start", false), new Argument([DataType.Number], "end", false)], DataType.Number, @@ -332,6 +391,7 @@ export class Actions { "add-choice-btn", () => new FunctionCallExpr( + RandChoiceDocs.styles.backgroundColor, "choice", [new Argument([DataType.AnyList], "choices", false)], DataType.Any, @@ -350,7 +410,13 @@ export class Actions { const RangeExpr = new EditCodeAction( "range(---)", "add-range-btn", - () => new FunctionCallExpr("range", [new Argument([DataType.Number], "end", false)], DataType.NumberList), + () => + new FunctionCallExpr( + RangeDocs.styles.backgroundColor, + "range", + [new Argument([DataType.Number], "end", false)], + DataType.NumberList + ), InsertActionType.InsertExpression, {}, RangeDocs, @@ -364,6 +430,7 @@ export class Actions { "add-len-btn", () => new FunctionCallExpr( + LenDocs.styles.backgroundColor, "len", [ new Argument( @@ -391,7 +458,13 @@ export class Actions { const InputExpr = new EditCodeAction( "input(---)", "add-input-btn", - () => new FunctionCallExpr("input", [new Argument([DataType.String], "prompt", true)], DataType.String), + () => + new FunctionCallExpr( + InputDocs.styles.backgroundColor, + "input", + [new Argument([DataType.String], "prompt", true)], + DataType.String + ), InsertActionType.InsertInputExpr, {}, InputDocs, @@ -403,7 +476,7 @@ export class Actions { const StringLiteralExpr = new EditCodeAction( '""', "add-str-btn", - () => new LiteralValExpr(DataType.String, ""), + () => new LiteralValExpr(StrDocs.styles.backgroundColor, DataType.String, ""), InsertActionType.InsertLiteral, { literalType: DataType.String, @@ -418,7 +491,7 @@ export class Actions { const FormattedStringLiteralExpr = new EditCodeAction( "f''", "add-f-str-literal-btn", - () => new FormattedStringExpr(""), + () => new FormattedStringExpr(FStringDocs.styles.backgroundColor, ""), InsertActionType.InsertExpression, {}, FStringDocs, @@ -430,7 +503,7 @@ export class Actions { const FormattedStringItem = new EditCodeAction( "{}", "add-f-str-item-btn", - () => new FormattedStringCurlyBracketsExpr(), + () => new FormattedStringCurlyBracketsExpr(FStringDocs.styles.backgroundColor), InsertActionType.InsertFormattedStringItem, {}, FStringItemDocs, @@ -442,7 +515,7 @@ export class Actions { const NumberLiteralExpr = new EditCodeAction( "0", "add-num-btn", - () => new LiteralValExpr(DataType.Number, "0"), + () => new LiteralValExpr(NumDocs.styles.backgroundColor, DataType.Number, "0"), InsertActionType.InsertExpression, { literalType: DataType.Number, @@ -457,7 +530,7 @@ export class Actions { const BooleanTrueLiteralExpr = new EditCodeAction( "True", "add-true-btn", - () => new LiteralValExpr(DataType.Boolean, "True"), + () => new LiteralValExpr(TrueDocs.styles.backgroundColor, DataType.Boolean, "True"), InsertActionType.InsertExpression, { literalType: DataType.Boolean, @@ -473,7 +546,7 @@ export class Actions { const BooleanFalseLiteralExpr = new EditCodeAction( "False", "add-false-btn", - () => new LiteralValExpr(DataType.Boolean, "False"), + () => new LiteralValExpr(FalseDocs.styles.backgroundColor, DataType.Boolean, "False"), InsertActionType.InsertLiteral, { literalType: DataType.Boolean, @@ -489,7 +562,7 @@ export class Actions { const BinAddExpr = new EditCodeAction( "--- + ---", "add-bin-add-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Add, DataType.Number), //NOTE: For + this will be reassigned in the constructor + () => new BinaryOperatorExpr(AddDocs.styles.backgroundColor, BinaryOperator.Add, DataType.Number), //NOTE: For + this will be reassigned in the constructor InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Add, @@ -503,7 +576,7 @@ export class Actions { const BinSubExpr = new EditCodeAction( "--- - ---", "add-bin-sub-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Subtract, DataType.Number), + () => new BinaryOperatorExpr(SubDocs.styles.backgroundColor, BinaryOperator.Subtract, DataType.Number), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Subtract, @@ -517,7 +590,7 @@ export class Actions { const BinMultExpr = new EditCodeAction( "--- * ---", "add-bin-mul-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Multiply, DataType.Number), + () => new BinaryOperatorExpr(MultDocs.styles.backgroundColor, BinaryOperator.Multiply, DataType.Number), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Multiply, @@ -531,7 +604,7 @@ export class Actions { const BinDivExpr = new EditCodeAction( "--- / ---", "add-bin-div-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Divide, DataType.Number), + () => new BinaryOperatorExpr(DivDocs.styles.backgroundColor, BinaryOperator.Divide, DataType.Number), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Divide, @@ -545,7 +618,7 @@ export class Actions { const BinFloorDivExpr = new EditCodeAction( "--- // ---", "add-bin-floor-div-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.FloorDiv, DataType.Number), + () => new BinaryOperatorExpr(FloorDivDocs.styles.backgroundColor, BinaryOperator.FloorDiv, DataType.Number), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.FloorDiv, @@ -559,7 +632,7 @@ export class Actions { const BinModExpr = new EditCodeAction( "--- % ---", "add-bin-mod-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Mod, DataType.Number), + () => new BinaryOperatorExpr(ModDocs.styles.backgroundColor, BinaryOperator.Mod, DataType.Number), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Mod, @@ -573,7 +646,7 @@ export class Actions { const InOperatorTkn = new EditCodeAction( "in", "add-in-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.In), + () => new OperatorTkn(InDocs.styles.backgroundColor, BinaryOperator.In), InsertActionType.InsertOperatorTkn, {}, InDocs, @@ -585,7 +658,7 @@ export class Actions { const NotInOperatorTkn = new EditCodeAction( "not in", "add-not-in-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.NotIn), + () => new OperatorTkn(NotInDocs.styles.backgroundColor, BinaryOperator.NotIn), InsertActionType.InsertOperatorTkn, {}, NotInDocs, @@ -597,7 +670,7 @@ export class Actions { const AddOperatorTkn = new EditCodeAction( "+", "add-add-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Add), + () => new OperatorTkn(AddDocs.styles.backgroundColor, BinaryOperator.Add), InsertActionType.InsertOperatorTkn, {}, AddDocs, @@ -609,7 +682,7 @@ export class Actions { const SubOperatorTkn = new EditCodeAction( "-", "add-sub-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Subtract), + () => new OperatorTkn(SubDocs.styles.backgroundColor, BinaryOperator.Subtract), InsertActionType.InsertOperatorTkn, {}, SubDocs, @@ -621,7 +694,7 @@ export class Actions { const MultOperatorTkn = new EditCodeAction( "*", "add-mult-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Multiply), + () => new OperatorTkn(MultDocs.styles.backgroundColor, BinaryOperator.Multiply), InsertActionType.InsertOperatorTkn, {}, MultDocs, @@ -633,7 +706,7 @@ export class Actions { const DivOperatorTkn = new EditCodeAction( "/", "add-div-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Divide), + () => new OperatorTkn(DivDocs.styles.backgroundColor, BinaryOperator.Divide), InsertActionType.InsertOperatorTkn, {}, DivDocs, @@ -645,10 +718,10 @@ export class Actions { const FloorDivOperatorTkn = new EditCodeAction( "//", "add-floor-div-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.FloorDiv), + () => new OperatorTkn(FloorDivDocs.styles.backgroundColor, BinaryOperator.FloorDiv), InsertActionType.InsertOperatorTkn, {}, - DivDocs, + FloorDivDocs, ["/"], "/", null @@ -657,10 +730,10 @@ export class Actions { const ModOperatorTkn = new EditCodeAction( "%", "add-mod-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Mod), + () => new OperatorTkn(ModDocs.styles.backgroundColor, BinaryOperator.Mod), InsertActionType.InsertOperatorTkn, {}, - DivDocs, + ModDocs, ["%"], "", null @@ -669,7 +742,7 @@ export class Actions { const BinAndExpr = new EditCodeAction( "--- and ---", "add-bin-and-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.And, DataType.Boolean), + () => new BinaryOperatorExpr(AndDocs.styles.backgroundColor, BinaryOperator.And, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.And, @@ -683,7 +756,7 @@ export class Actions { const BinOrExpr = new EditCodeAction( "--- or ---", "add-bin-or-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Or, DataType.Boolean), + () => new BinaryOperatorExpr(OrDocs.styles.backgroundColor, BinaryOperator.Or, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Or, @@ -697,7 +770,7 @@ export class Actions { const AndOperatorTkn = new EditCodeAction( "and", "add-and-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.And), + () => new OperatorTkn(AndDocs.styles.backgroundColor, BinaryOperator.And), InsertActionType.InsertOperatorTkn, {}, AndDocs, @@ -709,7 +782,7 @@ export class Actions { const OrOperatorTkn = new EditCodeAction( "or", "add-or-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Or), + () => new OperatorTkn(OrDocs.styles.backgroundColor, BinaryOperator.Or), InsertActionType.InsertOperatorTkn, {}, OrDocs, @@ -721,7 +794,7 @@ export class Actions { const BinCompEqExpr = new EditCodeAction( "--- == ---", "add-comp-eq-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.Equal, DataType.Boolean), + () => new BinaryOperatorExpr(CompEqDocs.styles.backgroundColor, BinaryOperator.Equal, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.Equal, @@ -735,7 +808,7 @@ export class Actions { const BinCompNeqExpr = new EditCodeAction( "--- != ---", "add-comp-neq-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.NotEqual, DataType.Boolean), + () => new BinaryOperatorExpr(CompNeDocs.styles.backgroundColor, BinaryOperator.NotEqual, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.NotEqual, @@ -749,7 +822,7 @@ export class Actions { const BinCompLtExpr = new EditCodeAction( "--- < ---", "add-comp-lt-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.LessThan, DataType.Boolean), + () => new BinaryOperatorExpr(CompLtDocs.styles.backgroundColor, BinaryOperator.LessThan, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.LessThan, @@ -764,7 +837,12 @@ export class Actions { const BinCompLteExpr = new EditCodeAction( "--- <= ---", "add-comp-lte-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.LessThanEqual, DataType.Boolean), + () => + new BinaryOperatorExpr( + CompLteDocs.styles.backgroundColor, + BinaryOperator.LessThanEqual, + DataType.Boolean + ), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.LessThanEqual, @@ -778,7 +856,8 @@ export class Actions { const BinCompGtExpr = new EditCodeAction( "--- > ---", "add-comp-gt-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.GreaterThan, DataType.Boolean), + () => + new BinaryOperatorExpr(CompGtDocs.styles.backgroundColor, BinaryOperator.GreaterThan, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.GreaterThan, @@ -793,7 +872,12 @@ export class Actions { const BinCompGteExpr = new EditCodeAction( "--- >= ---", "add-comp-gte-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.GreaterThanEqual, DataType.Boolean), + () => + new BinaryOperatorExpr( + CompGteDocs.styles.backgroundColor, + BinaryOperator.GreaterThanEqual, + DataType.Boolean + ), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.GreaterThanEqual, @@ -807,7 +891,7 @@ export class Actions { const EqOperatorTkn = new EditCodeAction( "==", "add-comp-eq-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.Equal), + () => new OperatorTkn(CompEqDocs.styles.backgroundColor, BinaryOperator.Equal), InsertActionType.InsertOperatorTkn, {}, CompEqDocs, @@ -819,7 +903,7 @@ export class Actions { const NeqOperatorTkn = new EditCodeAction( "!=", "add-comp-neq-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.NotEqual), + () => new OperatorTkn(CompNeDocs.styles.backgroundColor, BinaryOperator.NotEqual), InsertActionType.InsertOperatorTkn, {}, CompNeDocs, @@ -831,7 +915,7 @@ export class Actions { const GtOperatorTkn = new EditCodeAction( ">", "add-comp-gt-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.GreaterThan), + () => new OperatorTkn(CompNeDocs.styles.backgroundColor, BinaryOperator.GreaterThan), InsertActionType.InsertOperatorTkn, {}, CompNeDocs, @@ -843,7 +927,7 @@ export class Actions { const LtOperatorTkn = new EditCodeAction( "<", "add-comp-lt-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.LessThan), + () => new OperatorTkn(CompNeDocs.styles.backgroundColor, BinaryOperator.LessThan), InsertActionType.InsertOperatorTkn, {}, CompNeDocs, @@ -855,7 +939,7 @@ export class Actions { const GteOperatorTkn = new EditCodeAction( ">=", "add-comp-gte-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.GreaterThanEqual), + () => new OperatorTkn(CompNeDocs.styles.backgroundColor, BinaryOperator.GreaterThanEqual), InsertActionType.InsertOperatorTkn, {}, CompNeDocs, @@ -867,7 +951,7 @@ export class Actions { const LteOperatorTkn = new EditCodeAction( "<=", "add-comp-lte-op-tkn-btn", - () => new OperatorTkn(BinaryOperator.LessThanEqual), + () => new OperatorTkn(CompNeDocs.styles.backgroundColor, BinaryOperator.LessThanEqual), InsertActionType.InsertOperatorTkn, {}, CompNeDocs, @@ -879,7 +963,7 @@ export class Actions { const BinInExpr = new EditCodeAction( "--- in ---", "add-bin-in-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.In, DataType.Boolean), + () => new BinaryOperatorExpr(InDocs.styles.backgroundColor, BinaryOperator.In, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.In, @@ -893,7 +977,7 @@ export class Actions { const BinNotInExpr = new EditCodeAction( "--- not in ---", "add-bin-not-in-expr-btn", - () => new BinaryOperatorExpr(BinaryOperator.NotIn, DataType.Boolean), + () => new BinaryOperatorExpr(NotInDocs.styles.backgroundColor, BinaryOperator.NotIn, DataType.Boolean), InsertActionType.InsertBinaryExpr, { operator: BinaryOperator.NotIn, @@ -907,7 +991,7 @@ export class Actions { const UnaryNotExpr = new EditCodeAction( "not ---", "add-unary-not-expr-btn", - () => new UnaryOperatorExpr(UnaryOperator.Not, DataType.Boolean), + () => new UnaryOperatorExpr(NotDocs.styles.backgroundColor, UnaryOperator.Not, DataType.Boolean), InsertActionType.InsertUnaryExpr, { operator: UnaryOperator.Not, @@ -924,6 +1008,7 @@ export class Actions { "add-find-method-call-btn", () => new MethodCallModifier( + FindDocs.styles.backgroundColor, "find", [new Argument([DataType.String], "item", false)], DataType.Number, @@ -940,7 +1025,7 @@ export class Actions { const WhileStmt = new EditCodeAction( "while --- :", "add-while-expr-btn", - () => new WhileStatement(), + () => new WhileStatement(WhileDocs.styles.backgroundColor), InsertActionType.InsertStatement, {}, WhileDocs, @@ -953,7 +1038,7 @@ export class Actions { "break", "add-break-stmt-btn", () => - new KeywordStmt("break", null, null, (context: Context) => { + new KeywordStmt(BreakDocs.styles.backgroundColor, "break", null, null, (context: Context) => { let parent = context.lineStatement.rootNode as Statement | Module; while ( @@ -978,7 +1063,7 @@ export class Actions { const IfStmt = new EditCodeAction( "if --- :", "add-if-expr-btn", - () => new IfStatement(), + () => new IfStatement(IfDocs.styles.backgroundColor), InsertActionType.InsertStatement, {}, IfDocs, @@ -990,7 +1075,7 @@ export class Actions { const ElifStmt = new EditCodeAction( "elif --- :", "add-elif-expr-btn", - () => new ElseStatement(true), + () => new ElseStatement(ElifDocs.styles.backgroundColor, true), InsertActionType.InsertElifStmt, {}, ElifDocs, @@ -1002,7 +1087,7 @@ export class Actions { const ElseStmt = new EditCodeAction( "else :", "add-else-expr-btn", - () => new ElseStatement(false), + () => new ElseStatement(ElseDocs.styles.backgroundColor, false), InsertActionType.InsertElseStmt, {}, ElseDocs, @@ -1014,7 +1099,7 @@ export class Actions { const ForStmt = new EditCodeAction( "for -- in --- :", "add-for-expr-btn", - () => new ForStatement(), + () => new ForStatement(ForDocs.styles.backgroundColor), InsertActionType.InsertStatement, {}, ForDocs, @@ -1026,7 +1111,7 @@ export class Actions { const ImportStmt = new EditCodeAction( "from --- import ---", "add-import-btn", - () => new ImportStatement(), + () => new ImportStatement(ImportDocs.styles.backgroundColor), InsertActionType.InsertStatement, {}, ImportDocs, @@ -1038,7 +1123,7 @@ export class Actions { const ImportRandintStmt = new EditCodeAction( "from random import randint", "add-import-randint-btn", - () => new ImportStatement("random", "randint"), + () => new ImportStatement(ImportDocs.styles.backgroundColor, "random", "randint"), InsertActionType.InsertStatement, {}, ImportDocs, @@ -1050,7 +1135,7 @@ export class Actions { const ImportChoiceStmt = new EditCodeAction( "from random import choice", "add-import-choice-btn", - () => new ImportStatement("random", "choice"), + () => new ImportStatement(ImportDocs.styles.backgroundColor, "random", "choice"), InsertActionType.InsertStatement, {}, ImportDocs, @@ -1062,7 +1147,7 @@ export class Actions { const ListLiteralExpr = new EditCodeAction( "[]", "add-list-literal-btn", - () => new ListLiteralExpression(), + () => new ListLiteralExpression(ListLiteralDocs.styles.backgroundColor), InsertActionType.InsertListLiteral, {}, ListLiteralDocs, @@ -1074,7 +1159,7 @@ export class Actions { const ListCommaItem = new EditCodeAction( ", ---", "add-list-item-btn", - () => new ListComma(), + () => new ListComma(ListItemDocs.styles.backgroundColor), InsertActionType.InsertListItem, {}, ListItemDocs, @@ -1086,7 +1171,7 @@ export class Actions { const ListIndexAccessor = new EditCodeAction( "[---]", "add-list-index-btn", - () => new ListAccessModifier(), + () => new ListAccessModifier(ListIndexDocs.styles.backgroundColor), InsertActionType.InsertListIndexAccessor, {}, ListIndexDocs, @@ -1098,7 +1183,7 @@ export class Actions { const AssignmentMod = new EditCodeAction( "= ---", "add-assign-mod-btn", - () => new AssignmentModifier(), + () => new AssignmentModifier(AssignDocs.styles.backgroundColor), InsertActionType.InsertAssignmentModifier, {}, AssignDocs, @@ -1110,7 +1195,8 @@ export class Actions { const AugAddAssignmentMod = new EditCodeAction( "+= ---", "add-aug-assign-add-mod-btn", - () => new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Add), + () => + new AugmentedAssignmentModifier(AssignAddDocs.styles.backgroundColor, AugmentedAssignmentOperator.Add), InsertActionType.InsertAugmentedAssignmentModifier, {}, AssignAddDocs, @@ -1122,7 +1208,11 @@ export class Actions { const AugSubAssignmentMod = new EditCodeAction( "-= ---", "add-aug-assign-sub-mod-btn", - () => new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Subtract), + () => + new AugmentedAssignmentModifier( + AssignSubDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Subtract + ), InsertActionType.InsertAugmentedAssignmentModifier, {}, AssignSubDocs, @@ -1134,7 +1224,11 @@ export class Actions { const AugMulAssignmentMod = new EditCodeAction( "*= ---", "add-aug-assign-mul-mod-btn", - () => new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Multiply), + () => + new AugmentedAssignmentModifier( + AssignMultDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Multiply + ), InsertActionType.InsertAugmentedAssignmentModifier, {}, AssignMultDocs, @@ -1146,7 +1240,11 @@ export class Actions { const AugDivAssignmentMod = new EditCodeAction( "/= ---", "add-aug-assign-div-mod-btn", - () => new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Divide), + () => + new AugmentedAssignmentModifier( + AssignDivDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Divide + ), InsertActionType.InsertAugmentedAssignmentModifier, {}, AssignDivDocs, @@ -1160,6 +1258,7 @@ export class Actions { "add-list-append-stmt-btn", () => new MethodCallModifier( + ListAppendDocs.styles.backgroundColor, "append", [new Argument([DataType.Any], "object", false)], DataType.Void, @@ -1178,6 +1277,7 @@ export class Actions { "add-replace-method-call-btn", () => new MethodCallModifier( + ReplaceDocs.styles.backgroundColor, "replace", [new Argument([DataType.String], "old", false), new Argument([DataType.String], "new", false)], DataType.String, @@ -1196,6 +1296,7 @@ export class Actions { "add-join-method-call-btn", () => new MethodCallModifier( + JoinDocs.styles.backgroundColor, "join", [ new Argument( @@ -1232,6 +1333,7 @@ export class Actions { "add-split-method-call-btn", () => new MethodCallModifier( + SplitDocs.styles.backgroundColor, "split", [new Argument([DataType.String], "sep", false)], DataType.StringList, @@ -1248,7 +1350,13 @@ export class Actions { const CastStrExpr = new EditCodeAction( "str(---)", "add-cast-str-btn", - () => new FunctionCallExpr("str", [new Argument([DataType.Any], "value", false)], DataType.String), + () => + new FunctionCallExpr( + CastToStrDocs.styles.backgroundColor, + "str", + [new Argument([DataType.Any], "value", false)], + DataType.String + ), InsertActionType.InsertCastStrExpr, {}, CastToStrDocs, @@ -1260,7 +1368,13 @@ export class Actions { const CastIntExpr = new EditCodeAction( "int(---)", "add-cast-int-btn", - () => new FunctionCallExpr("int", [new Argument([DataType.String], "value", false)], DataType.Number), + () => + new FunctionCallExpr( + CastToIntDocs.styles.backgroundColor, + "int", + [new Argument([DataType.String], "value", false)], + DataType.Number + ), InsertActionType.InsertCastStrExpr, {}, CastToIntDocs, @@ -1272,7 +1386,7 @@ export class Actions { const VarAssignStmt = new EditCodeAction( "var = ---", "add-var-btn", - () => new VarAssignmentStmt(), + () => new VarAssignmentStmt(AddVarDocs.styles.backgroundColor), InsertActionType.InsertNewVariableStmt, {}, AddVarDocs, @@ -1359,40 +1473,62 @@ export class Actions { this.varActionsMap = new Map>([ [ DataType.Boolean, - [new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Set Value")], + [ + new VarAction( + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Set Value" + ), + ], ], [ DataType.Number, [ - new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Set Value"), + new VarAction( + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Set Value" + ), new VarAction( () => - new VarOperationStmt(null, [ - new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Add), + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new AugmentedAssignmentModifier( + AssignAddDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Add + ), ]), "add value to {VAR_ID}", "Update Value" ), new VarAction( () => - new VarOperationStmt(null, [ - new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Subtract), + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new AugmentedAssignmentModifier( + AssignSubDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Subtract + ), ]), "subtract value from {VAR_ID}", "Update Value" ), new VarAction( () => - new VarOperationStmt(null, [ - new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Multiply), + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new AugmentedAssignmentModifier( + AssignMultDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Multiply + ), ]), "multiply {VAR_ID} by value", "Update Value" ), new VarAction( () => - new VarOperationStmt(null, [ - new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Divide), + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new AugmentedAssignmentModifier( + AssignDivDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Divide + ), ]), "divide {VAR_ID} by value", "Update Value" @@ -1402,20 +1538,32 @@ export class Actions { [ DataType.String, [ - new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Set Value"), + new VarAction( + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Set Value" + ), new VarAction( () => - new VarOperationStmt(null, [ - new AugmentedAssignmentModifier(AugmentedAssignmentOperator.Add), + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new AugmentedAssignmentModifier( + AssignAddDocs.styles.backgroundColor, + AugmentedAssignmentOperator.Add + ), ]), "add text to {VAR_ID}", "Update Value" ), - new VarAction(() => new ForStatement(), "loop through characters of {VAR_ID}", "Loops"), + new VarAction( + () => new ForStatement(ForDocs.styles.backgroundColor), + "loop through characters of {VAR_ID}", + "Loops" + ), new VarAction( () => - new ValueOperationExpr(null, [ + new ValueOperationExpr(SplitDocs.styles.backgroundColor, null, [ new MethodCallModifier( + SplitDocs.styles.backgroundColor, "split", [new Argument([DataType.String], "sep", false)], DataType.StringList, @@ -1427,8 +1575,9 @@ export class Actions { ), new VarAction( () => - new ValueOperationExpr(null, [ + new ValueOperationExpr(JoinDocs.styles.backgroundColor, null, [ new MethodCallModifier( + JoinDocs.styles.backgroundColor, "join", [ new Argument( @@ -1451,8 +1600,9 @@ export class Actions { ), new VarAction( () => - new ValueOperationExpr(null, [ + new ValueOperationExpr(ReplaceDocs.styles.backgroundColor, null, [ new MethodCallModifier( + ReplaceDocs.styles.backgroundColor, "replace", [ new Argument([DataType.String], "old", false), @@ -1467,8 +1617,9 @@ export class Actions { ), new VarAction( () => - new ValueOperationExpr(null, [ + new ValueOperationExpr(FindDocs.styles.backgroundColor, null, [ new MethodCallModifier( + FindDocs.styles.backgroundColor, "find", [new Argument([DataType.String], "item", false)], DataType.Number, @@ -1484,14 +1635,19 @@ export class Actions { DataType.AnyList, [ new VarAction( - () => new VarOperationStmt(null, [new ListAccessModifier(), new AssignmentModifier()]), + () => + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + new AssignmentModifier(AssignDocs.styles.backgroundColor), + ]), "set an index in {VAR_ID} to value", "Update List" ), new VarAction( () => - new VarOperationStmt(null, [ + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ new MethodCallModifier( + ListAppendDocs.styles.backgroundColor, "append", [new Argument([DataType.Any], "object", false)], DataType.Void, @@ -1501,10 +1657,21 @@ export class Actions { "append value to list {VAR_ID}", "Update List" ), - new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Update List"), - new VarAction(() => new ForStatement(), "loop through items of {VAR_ID}", "Loops"), new VarAction( - () => new ValueOperationExpr(null, [new ListAccessModifier()]), + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Update List" + ), + new VarAction( + () => new ForStatement(ForDocs.styles.backgroundColor), + "loop through items of {VAR_ID}", + "Loops" + ), + new VarAction( + () => + new ValueOperationExpr(ListIndexDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + ]), "get item from {VAR_ID} at index", "Get Value" ), @@ -1514,14 +1681,19 @@ export class Actions { DataType.Boolean, [ new VarAction( - () => new VarOperationStmt(null, [new ListAccessModifier(), new AssignmentModifier()]), + () => + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + new AssignmentModifier(AssignDocs.styles.backgroundColor), + ]), "set an index in {VAR_ID} to value", "Update List" ), new VarAction( () => - new VarOperationStmt(null, [ + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ new MethodCallModifier( + ListAppendDocs.styles.backgroundColor, "append", [new Argument([DataType.Any], "object", false)], DataType.Void, @@ -1531,10 +1703,21 @@ export class Actions { "append value to list {VAR_ID}", "Update List" ), - new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Update List"), - new VarAction(() => new ForStatement(), "loop through items of {VAR_ID}", "Loops"), new VarAction( - () => new ValueOperationExpr(null, [new ListAccessModifier()]), + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Update List" + ), + new VarAction( + () => new ForStatement(ForDocs.styles.backgroundColor), + "loop through items of {VAR_ID}", + "Loops" + ), + new VarAction( + () => + new ValueOperationExpr(ListIndexDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + ]), "get item from {VAR_ID} at index", "Get Value" ), @@ -1544,14 +1727,19 @@ export class Actions { DataType.NumberList, [ new VarAction( - () => new VarOperationStmt(null, [new ListAccessModifier(), new AssignmentModifier()]), + () => + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + new AssignmentModifier(AssignDocs.styles.backgroundColor), + ]), "set an index in {VAR_ID} to value", "Update List" ), new VarAction( () => - new VarOperationStmt(null, [ + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ new MethodCallModifier( + ListAppendDocs.styles.backgroundColor, "append", [new Argument([DataType.Any], "object", false)], DataType.Void, @@ -1561,10 +1749,21 @@ export class Actions { "add value to list {VAR_ID}", "Update List" ), - new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Update List"), - new VarAction(() => new ForStatement(), "loop through items of {VAR_ID}", "Loops"), new VarAction( - () => new ValueOperationExpr(null, [new ListAccessModifier()]), + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Update List" + ), + new VarAction( + () => new ForStatement(ForDocs.styles.backgroundColor), + "loop through items of {VAR_ID}", + "Loops" + ), + new VarAction( + () => + new ValueOperationExpr(ListIndexDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + ]), "get item from {VAR_ID} at index", "Get Value" ), @@ -1574,14 +1773,19 @@ export class Actions { DataType.StringList, [ new VarAction( - () => new VarOperationStmt(null, [new ListAccessModifier(), new AssignmentModifier()]), + () => + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + new AssignmentModifier(AssignDocs.styles.backgroundColor), + ]), "set an index in {VAR_ID} to value", "Update List" ), new VarAction( () => - new VarOperationStmt(null, [ + new VarOperationStmt(Docs.AddVarDocs.styles.backgroundColor, null, [ new MethodCallModifier( + ListAppendDocs.styles.backgroundColor, "append", [new Argument([DataType.Any], "object", false)], DataType.Void, @@ -1591,10 +1795,21 @@ export class Actions { "append value to list {VAR_ID}", "Update List" ), - new VarAction(() => new VarAssignmentStmt(), "set {VAR_ID} to new value", "Update List"), - new VarAction(() => new ForStatement(), "loop through items of {VAR_ID}", "Loops"), new VarAction( - () => new ValueOperationExpr(null, [new ListAccessModifier()]), + () => new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor), + "set {VAR_ID} to new value", + "Update List" + ), + new VarAction( + () => new ForStatement(ForDocs.styles.backgroundColor), + "loop through items of {VAR_ID}", + "Loops" + ), + new VarAction( + () => + new ValueOperationExpr(ListIndexDocs.styles.backgroundColor, null, [ + new ListAccessModifier(ListIndexDocs.styles.backgroundColor), + ]), "get item from {VAR_ID} at index", "Get Value" ), diff --git a/src/editor/cursor.ts b/src/editor/cursor.ts index cce1ed0..5613094 100644 --- a/src/editor/cursor.ts +++ b/src/editor/cursor.ts @@ -39,11 +39,11 @@ export class Cursor { const transform = this.editor.computeBoundingBox(selection); - this.element.style.top = `${transform.y + 5}px`; + this.element.style.top = `${transform.y + 5 + 4}px`; this.element.style.left = `${transform.x - leftPadding}px`; this.element.style.width = `${transform.width + rightPadding}px`; - this.element.style.height = `${transform.height - 5 * 2}px`; + this.element.style.height = `${transform.height - 5 * 2 - 10}px`; } setSelection(code: CodeConstruct = null) { diff --git a/src/editor/editor.ts b/src/editor/editor.ts index 3859455..ffc9135 100644 --- a/src/editor/editor.ts +++ b/src/editor/editor.ts @@ -18,7 +18,6 @@ export class Editor { module: Module; cursor: Cursor; monaco: editor.IStandaloneCodeEditor; - holes: Hole[]; mousePosWindow: number[] = [0, 0]; scrollOffsetTop: number = 0; oldCursorLineNumber: number = 1; @@ -310,7 +309,7 @@ export class Editor { }); this.cursor = new Cursor(this); - this.holes = []; + Hole.holes = []; this.module = module; } @@ -322,7 +321,7 @@ export class Editor { } addHoles(code: CodeConstruct) { - for (const hole of this.holes) if (hole.code == code) return; + for (const hole of Hole.holes) if (hole.code == code) return; if ( code instanceof EditableTextTkn || @@ -330,9 +329,9 @@ export class Editor { code instanceof IdentifierTkn || code instanceof EmptyOperatorTkn ) { - this.holes.push(new Hole(this, code)); + Hole.holes.push(new Hole(this, code)); } else if (code instanceof Statement) { - const statement = code; + const statement = code as Statement; statement.tokens.forEach((token) => this.addHoles(token)); } } @@ -463,7 +462,7 @@ export class Editor { reset() { this.monaco.getModel().setValue(""); - this.holes.forEach((hole) => hole.remove()); - this.holes = []; + Hole.holes.forEach((hole) => hole.remove()); + Hole.holes = []; } } diff --git a/src/editor/event-router.ts b/src/editor/event-router.ts index 788a624..39bfd04 100644 --- a/src/editor/event-router.ts +++ b/src/editor/event-router.ts @@ -1,10 +1,11 @@ import { editor, IKeyboardEvent, IScrollEvent, Position } from "monaco-editor"; + import * as ast from "../syntax-tree/ast"; import { Module } from "../syntax-tree/module"; import { Settings } from "../utilities/settings"; import { AutoCompleteType, DataType, IdentifierRegex, InsertionType } from "./../syntax-tree/consts"; import { EditCodeAction } from "./action-filter"; -import { Actions, EditActionType, InsertActionType, KeyPress } from "./consts"; +import { Actions, Docs, EditActionType, InsertActionType, KeyPress } from "./consts"; import { EditAction } from "./data-types"; import { Context } from "./focus"; @@ -138,6 +139,9 @@ export class EventRouter { toRight: true, }); } else if (this.module.validator.isTknEmpty(context)) { + if (this.module.validator.isMethodCallModifierStatement(context)) { + return new EditAction(EditActionType.DeleteSelectedModifier); + } if (this.module.validator.isAugmentedAssignmentModifierStatement(context)) { return new EditAction(EditActionType.DeleteStatement); } @@ -145,6 +149,7 @@ export class EventRouter { if (this.module.validator.canDeleteExpression(context)) { return new EditAction(EditActionType.DeleteRootNode); } + return new EditAction(EditActionType.ReplaceExpressionWithItem); } if (context.token.rootNode instanceof ast.Statement) { @@ -204,6 +209,9 @@ export class EventRouter { toRight: true, }); } else if (this.module.validator.isTknEmpty(context)) { + if (this.module.validator.isMethodCallModifierStatement(context)) { + return new EditAction(EditActionType.DeleteSelectedModifier); + } if (this.module.validator.isAugmentedAssignmentModifierStatement(context)) { return new EditAction(EditActionType.DeleteStatement); } @@ -617,7 +625,7 @@ export class EventRouter { case InsertActionType.InsertListLiteral: { if (this.module.validator.atLeftOfExpression(context)) { return new EditAction(EditActionType.WrapExpressionWithItem, { - expression: new ast.ListLiteralExpression(), + expression: new ast.ListLiteralExpression(Docs.ListLiteralDocs.styles.backgroundColor), source, }); } else if (this.module.validator.atEmptyExpressionHole(context)) { diff --git a/src/editor/hole.ts b/src/editor/hole.ts index 834cbef..5d56062 100644 --- a/src/editor/hole.ts +++ b/src/editor/hole.ts @@ -42,8 +42,6 @@ export class Hole { this.element = element; const hole = this; - Hole.holes.push(hole); - if (code instanceof EmptyOperatorTkn) this.element.classList.add("empty-operator-hole"); else if (code instanceof IdentifierTkn) this.element.classList.add("identifier-hole"); else if (code instanceof EditableTextTkn) { @@ -125,10 +123,10 @@ export class Hole { code.subscribe( CallbackType.fail, new Callback(() => { - hole.element.style.background = `rgba(255, 0, 0, 0.06)`; + hole.element.style.background = `rgba(255, 0, 0, 0.25)`; setTimeout(() => { - hole.element.style.background = `rgba(255, 0, 0, 0)`; + hole.element.style.background = `rgba(255, 255, 255, 1)`; }, 1000); }) ); @@ -155,11 +153,11 @@ export class Hole { } } - this.element.style.top = `${transform.y + 5}px`; + this.element.style.top = `${transform.y + 5 + 4}px`; this.element.style.left = `${transform.x - leftPadding}px`; this.element.style.width = `${transform.width + rightPadding}px`; - this.element.style.height = `${transform.height - 5 * 2}px`; + this.element.style.height = `${transform.height - 5 * 2 - 10}px`; } remove() { diff --git a/src/editor/toolbox.ts b/src/editor/toolbox.ts index 9bfd2b4..9337029 100644 --- a/src/editor/toolbox.ts +++ b/src/editor/toolbox.ts @@ -177,6 +177,7 @@ export class ToolboxController { const staticDummySpace = document.getElementById("static-toolbox-dummy-space"); const toolboxCategories = Actions.instance().toolboxCategories; + const hello = Actions.instance().actionsMap; for (const constructGroup of toolboxCategories) { if (constructGroup) { @@ -222,11 +223,12 @@ export class ToolboxController { export class ToolboxButton { container: HTMLDivElement; - constructor(text: string, domId?: string, code?: CodeConstruct) { + constructor(text: string, domId?: string, btnColor?: string, code?: CodeConstruct) { this.container = document.createElement("div"); this.container.classList.add("var-button-container"); const button = document.createElement("div"); + button.style.backgroundColor = btnColor; button.classList.add("button"); if (!(code instanceof Expression) && !(code instanceof Modifier)) { @@ -256,7 +258,12 @@ export class ToolboxButton { } static createToolboxButtonFromJsonObj(action: EditCodeAction) { - return new ToolboxButton(action.optionName, action.cssId, action.getCode()); + return new ToolboxButton( + action.optionName, + action.cssId, + action.documentation.styles.backgroundColor, + action.getCode() + ); } divButtonVisualMode(insertionType: InsertionType) { diff --git a/src/editor/validator.ts b/src/editor/validator.ts index b4b256f..396756a 100644 --- a/src/editor/validator.ts +++ b/src/editor/validator.ts @@ -1,4 +1,5 @@ import Fuse from "fuse.js"; + import { AssignmentModifier, AugmentedAssignmentModifier, @@ -17,6 +18,7 @@ import { ImportStatement, ListLiteralExpression, LiteralValExpr, + MethodCallModifier, Modifier, NonEditableTkn, OperatorTkn, @@ -409,6 +411,20 @@ export class Validator { return false; } + /** + * logic: checks if rootNode is instanceof MethodCallModifier + */ + isMethodCallModifierStatement(providedContext?: Context): boolean { + const context = providedContext ? providedContext : this.module.focus.getContext(); + const rootNode = context.token.rootNode; + + if (rootNode instanceof MethodCallModifier) { + return true; + } + + return false; + } + /** * logic: checks if Statement body is empty and if all tokens of Statement are empty */ @@ -445,6 +461,7 @@ export class Validator { if ( !(rootNode.tokens[i] instanceof TypedEmptyExpr) && !(rootNode.tokens[i] instanceof NonEditableTkn) && + !(rootNode.tokens[i] instanceof IdentifierTkn) && !(rootNode.tokens[i] instanceof OperatorTkn) ) return false; diff --git a/src/messages/messages.ts b/src/messages/messages.ts index cf40d73..fe63a41 100644 --- a/src/messages/messages.ts +++ b/src/messages/messages.ts @@ -2,7 +2,7 @@ import { Selection } from "monaco-editor"; import { Editor } from "../editor/editor"; import { EDITOR_DOM_ID } from "../editor/toolbox"; import { nova } from "../index"; -import { CodeConstruct, Statement, TypedEmptyExpr } from "../syntax-tree/ast"; +import { CodeConstruct, Expression, Statement, TypedEmptyExpr } from "../syntax-tree/ast"; import { Callback, CallbackType } from "../syntax-tree/callback"; /** @@ -127,6 +127,10 @@ export class ConstructHighlight extends CodeHighlight { constructor(editor: Editor, codeToHighlight: CodeConstruct, rgbColour: [number, number, number, number]) { super(editor, codeToHighlight); this.changeHighlightColour(rgbColour); + + if (codeToHighlight instanceof Expression) { + this.domElement.style.borderRadius = "20px"; + } } protected createDomElement() { @@ -186,21 +190,32 @@ export class ConstructHighlight extends CodeHighlight { const text = this.code.getRenderText(); top = transform.y + 5; - left = (this.code.getSelection().startColumn - 1) * this.editor.computeCharWidthInvisible(lineNumber); + left = (this.code.getSelection().startColumn - 1) * this.editor.computeCharWidthInvisible(lineNumber) - 4; width = text.length * this.editor.computeCharWidthInvisible(lineNumber) > 0 - ? text.length * this.editor.computeCharWidthInvisible(lineNumber) + ? text.length * this.editor.computeCharWidthInvisible(lineNumber) + 10 : HIGHLIGHT_DEFAULT_WIDTH; height = transform.height > 0 ? transform.height - 5 * 2 : HIGHLIGHT_DEFAULT_HEIGHT; } else { const selection = this.code.getSelection(); const transform = this.editor.computeBoundingBox(selection); - top = (selection.startLineNumber - 1) * this.editor.computeCharHeight(); - left = transform.x; - height = Math.floor(this.editor.computeCharHeight() * 0.95); - width = (selection.endColumn - selection.startColumn) * this.editor.computeCharWidthInvisible(lineNumber); + if (this.code instanceof Expression) { + top = (selection.startLineNumber - 1) * this.editor.computeCharHeight() + 5; + left = transform.x - 5; + height = Math.floor(this.editor.computeCharHeight() * 0.95) - 10; + width = + (selection.endColumn - selection.startColumn) * this.editor.computeCharWidthInvisible(lineNumber) + + 10; + } else { + top = (selection.startLineNumber - 1) * this.editor.computeCharHeight(); + left = transform.x; + height = Math.floor(this.editor.computeCharHeight() * 0.95); + width = + (selection.endColumn - selection.startColumn) * this.editor.computeCharWidthInvisible(lineNumber) + + 10; + } } if (firstInsertion) { @@ -636,14 +651,14 @@ export class ScopeHighlight { */ private callbacks: Map; - constructor(editor: Editor, statement: Statement) { + constructor(editor: Editor, statement: Statement, color: string) { this.statement = statement; this.selection = this.statement.getSelection(); this.editor = editor; this.callbacks = new Map(); - this.createDomElement(); + this.createDomElement(color); ScopeHighlight.idCounter++; this.headerElement.id = `scope-header-${ScopeHighlight.idPrefix}-${ScopeHighlight.idCounter}`; this.bodyElement.id = `scope-body-${ScopeHighlight.idPrefix}-${ScopeHighlight.idCounter}`; @@ -690,14 +705,16 @@ export class ScopeHighlight { /** * Construct the DOM element for this visual. */ - protected createDomElement(): void { + protected createDomElement(color: string): void { this.headerElement = document.createElement("div"); this.headerElement.classList.add("scope-header-highlight"); - this.headerElement.style.backgroundColor = "rgba(75, 200, 255, 0.125)"; + this.headerElement.style.backgroundColor = color; + this.headerElement.style.opacity = "0.25"; this.bodyElement = document.createElement("div"); this.bodyElement.classList.add("scope-body-highlight"); - this.bodyElement.style.backgroundColor = "rgba(75, 200, 255, 0.125)"; + this.bodyElement.style.backgroundColor = color; + this.bodyElement.style.opacity = "0.25"; this.updateDimensions(); @@ -731,7 +748,7 @@ export class ScopeHighlight { this.headerElement.style.top = `${headerDim.top}px`; this.headerElement.style.left = `${headerDim.left}px`; - this.headerElement.style.width = `${maxRight - headerDim.left}px`; + this.headerElement.style.width = `${maxRight - headerDim.left + 10}px`; this.headerElement.style.height = `${headerDim.height}px`; let firstLineInBody = this.statement.body[0]; @@ -744,9 +761,9 @@ export class ScopeHighlight { } this.bodyElement.style.top = `${firstLineInBodyDim.top}px`; - this.bodyElement.style.left = `${firstLineInBodyDim.left}px`; + this.bodyElement.style.left = `${firstLineInBodyDim.left - 10}px`; - this.bodyElement.style.width = `${maxRight - firstLineInBodyDim.left}px`; + this.bodyElement.style.width = `${maxRight - firstLineInBodyDim.left + 20}px`; this.bodyElement.style.height = `${headerDim.height * (maxLineNumber - this.statement.lineNumber)}px`; } diff --git a/src/syntax-tree/ast.ts b/src/syntax-tree/ast.ts index 13c5136..ebe3a0f 100644 --- a/src/syntax-tree/ast.ts +++ b/src/syntax-tree/ast.ts @@ -1,6 +1,6 @@ import { Position, Selection } from "monaco-editor"; import { EditCodeAction, InsertionResult } from "../editor/action-filter"; -import { ConstructName, EditActionType } from "../editor/consts"; +import { ConstructName, Docs, EditActionType } from "../editor/consts"; import { EditAction } from "../editor/data-types"; import { DraftRecord } from "../editor/draft"; import { Context, UpdatableContext } from "../editor/focus"; @@ -201,6 +201,7 @@ export abstract class Statement implements CodeConstruct { right: number; rootNode: Statement | Module = null; indexInRoot: number; + color: string; body = new Array(); scope: Scope = null; tokens = new Array(); @@ -221,6 +222,8 @@ export abstract class Statement implements CodeConstruct { constructor() { for (const type in CallbackType) this.callbacks[type] = new Array(); + this.color = "transparent"; + this.subscribe( CallbackType.delete, new Callback(() => { @@ -970,9 +973,11 @@ export class WhileStatement extends Statement { scope: Scope; private conditionIndex: number; - constructor(root?: CodeConstruct | Module, indexInRoot?: number) { + constructor(color: string, root?: CodeConstruct | Module, indexInRoot?: number) { super(); + this.color = color; + this.tokens.push(new NonEditableTkn("while ", this, this.tokens.length)); this.conditionIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([DataType.Boolean], this, this.tokens.length)); @@ -995,9 +1000,11 @@ export class WhileStatement extends Statement { export class IfStatement extends Statement { private conditionIndex: number; - constructor(root?: CodeConstruct | Module, indexInRoot?: number) { + constructor(color: string, root?: CodeConstruct | Module, indexInRoot?: number) { super(); + this.color = color; + this.tokens.push(new NonEditableTkn("if ", this, this.tokens.length)); this.conditionIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([DataType.Boolean], this, this.tokens.length)); @@ -1021,8 +1028,10 @@ export class ElseStatement extends Statement { private conditionIndex: number; hasCondition: boolean = false; - constructor(hasCondition: boolean, root?: IfStatement, indexInRoot?: number) { + constructor(color: string, hasCondition: boolean, root?: IfStatement, indexInRoot?: number) { super(); + + this.color = color; this.hasCondition = hasCondition; if (hasCondition) { @@ -1058,9 +1067,11 @@ export class ElseStatement extends Statement { export class ImportStatement extends Statement { private moduleNameIndex: number = -1; private itemNameIndex: number = -1; - constructor(moduleName: string = "", itemName: string = "") { + constructor(color: string, moduleName: string = "", itemName: string = "") { super(); + this.color = color; + this.tokens.push(new NonEditableTkn("from ", this, this.tokens.length)); this.moduleNameIndex = this.tokens.length; this.tokens.push(new EditableTextTkn(moduleName, new RegExp("^[a-zA-Z]*$"), this, this.tokens.length)); @@ -1123,10 +1134,11 @@ export class ForStatement extends Statement implements VariableContainer { //TODO: Statements should not have a data type? dataType = DataType.Any; - constructor(root?: CodeConstruct | Module, indexInRoot?: number) { + constructor(color: string, root?: CodeConstruct | Module, indexInRoot?: number) { super(); this.buttonId = ""; + this.color = color; this.tokens.push(new NonEditableTkn("for ", this, this.tokens.length)); this.identifierIndex = this.tokens.length; @@ -1155,7 +1167,7 @@ export class ForStatement extends Statement implements VariableContainer { this.hasEmptyToken = true; - this.loopVar = new VarAssignmentStmt(); + this.loopVar = new VarAssignmentStmt(Docs.AddVarDocs.styles.backgroundColor); this.loopVar.rootNode = this; this.subscribe( @@ -1414,9 +1426,10 @@ export class VarAssignmentStmt extends Statement implements VariableContainer { codeConstructName = ConstructName.VarAssignment; private oldIdentifier: string; - constructor(buttonId?: string, id?: string, root?: Statement | Module, indexInRoot?: number) { + constructor(color: string, buttonId?: string, id?: string, root?: Statement | Module, indexInRoot?: number) { super(); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; @@ -1724,9 +1737,11 @@ export class VariableReferenceExpr extends Expression { export class ValueOperationExpr extends Expression { isVarSet = false; - constructor(value: Expression, modifiers?: Array, root?: Statement, indexInRoot?: number) { + constructor(color: string, value: Expression, modifiers?: Array, root?: Statement, indexInRoot?: number) { super(value != null ? value.returns : DataType.Void); + this.color = color; + if (value != null) { value.indexInRoot = this.tokens.length; value.rootNode = this; @@ -1782,9 +1797,17 @@ export class ValueOperationExpr extends Expression { export class VarOperationStmt extends Statement { isVarSet = false; - constructor(ref: VariableReferenceExpr, modifiers?: Array, root?: Statement, indexInRoot?: number) { + constructor( + color: string, + ref: VariableReferenceExpr, + modifiers?: Array, + root?: Statement, + indexInRoot?: number + ) { super(); + this.color = color; + if (ref != null) { ref.indexInRoot = this.tokens.length; ref.rootNode = this; @@ -1852,9 +1875,10 @@ export class ListAccessModifier extends Modifier { leftExprTypes = [DataType.AnyList]; private indexOfIndexTkn: number; - constructor(root?: ValueOperationExpr | VarOperationStmt, indexInRoot?: number) { + constructor(color: string, root?: ValueOperationExpr | VarOperationStmt, indexInRoot?: number) { super(); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; @@ -1969,6 +1993,7 @@ export class MethodCallModifier extends Modifier { returns: DataType; constructor( + color: string, functionName: string, args: Array, returns: DataType, @@ -1978,6 +2003,7 @@ export class MethodCallModifier extends Modifier { ) { super(); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; @@ -2054,9 +2080,10 @@ export class AssignmentModifier extends Modifier { rootNode: VarOperationStmt; simpleInvalidTooltip = Tooltip.InvalidAugmentedAssignment; - constructor(root?: VarOperationStmt, indexInRoot?: number) { + constructor(color: string, root?: VarOperationStmt, indexInRoot?: number) { super(); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; @@ -2086,9 +2113,10 @@ export class AugmentedAssignmentModifier extends Modifier { private operation: AugmentedAssignmentOperator; simpleInvalidTooltip = Tooltip.InvalidAugmentedAssignment; - constructor(operation: AugmentedAssignmentOperator, root?: VarOperationStmt, indexInRoot?: number) { + constructor(color: string, operation: AugmentedAssignmentOperator, root?: VarOperationStmt, indexInRoot?: number) { super(); + this.color = color; this.operation = operation; this.rootNode = root; @@ -2131,6 +2159,7 @@ export class FunctionCallExpr extends Expression implements Importable { requiredModule: string; constructor( + color: string, functionName: string, args: Array, returns: DataType, @@ -2140,6 +2169,7 @@ export class FunctionCallExpr extends Expression implements Importable { ) { super(returns); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; this.functionName = functionName; @@ -2305,6 +2335,7 @@ export class FunctionCallStmt extends Statement implements Importable { requiredModule: string; constructor( + color: string, functionName: string, args: Array, root?: Statement | Module, @@ -2313,6 +2344,7 @@ export class FunctionCallStmt extends Statement implements Importable { ) { super(); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; this.functionName = functionName; @@ -2449,6 +2481,7 @@ export class KeywordStmt extends Statement { validator: (context: Context) => boolean; constructor( + color: string, keyword, root?: Statement | Expression, indexInRoot?: number, @@ -2456,6 +2489,7 @@ export class KeywordStmt extends Statement { ) { super(); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; this.validator = validator; @@ -2547,9 +2581,16 @@ export class BinaryOperatorExpr extends Expression { static originalReturnTypeAdd = DataType.Any; static originalReturnTypeArithmetic = DataType.Number; - constructor(operator: BinaryOperator, returns: DataType, root?: Statement | Expression, indexInRoot?: number) { + constructor( + color: string, + operator: BinaryOperator, + returns: DataType, + root?: Statement | Expression, + indexInRoot?: number + ) { super(returns); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; this.operator = operator; @@ -2569,7 +2610,9 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Number, DataType.String, ...ListTypes]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push( + new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length) + ); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push( @@ -2584,7 +2627,9 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Number, DataType.String, ...ListTypes]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push( + new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length) + ); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([returns], this, this.tokens.length)); @@ -2595,7 +2640,7 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Number]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push(new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length)); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([DataType.Number], this, this.tokens.length)); @@ -2608,7 +2653,7 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Boolean]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push(new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length)); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([DataType.Boolean], this, this.tokens.length)); @@ -2622,7 +2667,9 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Any]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push( + new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length) + ); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([DataType.Any], this, this.tokens.length)); @@ -2632,7 +2679,9 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Any]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push( + new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length) + ); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push( @@ -2660,7 +2709,9 @@ export class BinaryOperatorExpr extends Expression { this.typeOfHoles[this.tokens.length - 1] = [DataType.Number, DataType.String]; this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.keywordIndex = this.tokens.length; - this.tokens.push(new OperatorTkn(operator, this, this.tokens.length)); + this.tokens.push( + new OperatorTkn(Docs.AddDocs.styles.backgroundColor, operator, this, this.tokens.length) + ); this.tokens.push(new NonEditableTkn(" ", this, this.tokens.length)); this.rightOperandIndex = this.tokens.length; this.tokens.push(new TypedEmptyExpr([DataType.Number, DataType.String], this, this.tokens.length)); @@ -3380,6 +3431,7 @@ export class UnaryOperatorExpr extends Expression { private operandIndex: number; constructor( + color: string, operator: UnaryOperator, returns: DataType, operatesOn: DataType = DataType.Any, @@ -3388,6 +3440,7 @@ export class UnaryOperatorExpr extends Expression { ) { super(returns); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; this.operator = operator; @@ -3496,9 +3549,16 @@ export class OperatorTkn extends Modifier { operator: UnaryOperator | BinaryOperator; operatorCategory: OperatorCategory; - constructor(operator: UnaryOperator | BinaryOperator, root?: Statement | Expression, indexInRoot?: number) { + constructor( + color: string, + operator: UnaryOperator | BinaryOperator, + root?: Statement | Expression, + indexInRoot?: number + ) { super(); + this.color = color; + this.tokens.push(new NonEditableTkn(operator, this, this.tokens.length)); this.operator = operator; @@ -3516,9 +3576,11 @@ export class OperatorTkn extends Modifier { export class LiteralValExpr extends Expression { valueTokenIndex: number = 0; - constructor(returns: DataType, value?: string, root?: Statement | Expression, indexInRoot?: number) { + constructor(color: string, returns: DataType, value?: string, root?: Statement | Expression, indexInRoot?: number) { super(returns); + this.color = color; + switch (returns) { case DataType.String: { this.tokens.push(new NonEditableTkn('"', this, this.tokens.length)); @@ -3585,9 +3647,11 @@ export class LiteralValExpr extends Expression { export class FormattedStringExpr extends Expression { valueTokenIndex: number = 0; - constructor(value?: string, root?: Statement | Expression, indexInRoot?: number) { + constructor(color: string, value?: string, root?: Statement | Expression, indexInRoot?: number) { super(DataType.String); + this.color = color; + this.tokens.push(new NonEditableTkn("f", this, this.tokens.length)); this.tokens.push(new NonEditableTkn("'", this, this.tokens.length)); this.tokens.push(new EditableTextTkn(value == undefined ? "" : value, StringRegex, this, this.tokens.length)); @@ -3618,9 +3682,11 @@ export class FormattedStringExpr extends Expression { export class FormattedStringCurlyBracketsExpr extends Expression { valueTokenIndex: number = 0; - constructor(root?: Statement | Expression, indexInRoot?: number) { + constructor(color: string, root?: Statement | Expression, indexInRoot?: number) { super(DataType.String); + this.color = color; + this.tokens.push(new NonEditableTkn("{", this, this.tokens.length)); this.tokens.push(new TypedEmptyExpr([DataType.Any], this, this.tokens.length)); this.tokens.push(new NonEditableTkn("}", this, this.tokens.length)); @@ -3641,9 +3707,10 @@ export class FormattedStringCurlyBracketsExpr extends Expression { } export class ListLiteralExpression extends Expression { - constructor(root?: Statement | Expression, indexInRoot?: number) { + constructor(color: string, root?: Statement | Expression, indexInRoot?: number) { super(DataType.AnyList); + this.color = color; this.rootNode = root; this.indexInRoot = indexInRoot; @@ -3756,9 +3823,11 @@ export class ListLiteralExpression extends Expression { } export class ListComma extends Expression { - constructor() { + constructor(color: string) { super(DataType.Void); + this.color = color; + this.simpleInvalidTooltip = Tooltip.InvalidInsertListComma; } diff --git a/src/syntax-tree/module.ts b/src/syntax-tree/module.ts index de6e621..99ca97b 100644 --- a/src/syntax-tree/module.ts +++ b/src/syntax-tree/module.ts @@ -40,7 +40,7 @@ import { Reference, Scope } from "./scope"; import { TypeChecker } from "./type-checker"; import { VariableController } from "./variable-controller"; -const ERROR_HIGHLIGHT_COLOUR: [number, number, number, number] = [255, 153, 153, 0.5]; +const ERROR_HIGHLIGHT_COLOUR: [number, number, number, number] = [255, 153, 153, 0.8]; /** * The main body of the code which includes an array of statements. From 8ffd3aea0d1ca5b3fd6ddd93df679025e6d8bea3 Mon Sep 17 00:00:00 2001 From: MajeedKazemi Date: Wed, 6 Jul 2022 14:44:17 -0400 Subject: [PATCH 11/12] will be using simple properties inside the Settings object instead of a map --- src/editor/event-router.ts | 13 ++++--------- src/syntax-tree/module.ts | 7 ++++--- src/utilities/settings.ts | 37 +++++++++++++++++++------------------ 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/editor/event-router.ts b/src/editor/event-router.ts index 39bfd04..a7929af 100644 --- a/src/editor/event-router.ts +++ b/src/editor/event-router.ts @@ -2,7 +2,7 @@ import { editor, IKeyboardEvent, IScrollEvent, Position } from "monaco-editor"; import * as ast from "../syntax-tree/ast"; import { Module } from "../syntax-tree/module"; -import { Settings } from "../utilities/settings"; +import { SettingsController } from "../utilities/settings"; import { AutoCompleteType, DataType, IdentifierRegex, InsertionType } from "./../syntax-tree/consts"; import { EditCodeAction } from "./action-filter"; import { Actions, Docs, EditActionType, InsertActionType, KeyPress } from "./consts"; @@ -11,14 +11,14 @@ import { Context } from "./focus"; export class EventRouter { module: Module; - settings: Settings; + settings: SettingsController; curPosition: Position; buttonClicksCount = new Map(); constructor(module: Module) { this.module = module; this.curPosition = module.editor.monaco.getPosition(); - this.settings = new Settings(); + this.settings = new SettingsController(); } getKeyAction(e: KeyboardEvent, providedContext?: Context): EditAction { @@ -274,12 +274,7 @@ export class EventRouter { case KeyPress.Space: { if (inTextEditMode) return new EditAction(EditActionType.InsertChar); - if ( - !inTextEditMode && - e.ctrlKey && - e.key.length == 1 && - this.settings.getSettingsObject()["Spotlight Search"] - ) { + if (!inTextEditMode && e.ctrlKey && e.key.length == 1 && this.settings.config.enabledSpotlightSearch) { return new EditAction(EditActionType.OpenValidInsertMenu); } diff --git a/src/syntax-tree/module.ts b/src/syntax-tree/module.ts index 99ca97b..cc3e8e3 100644 --- a/src/syntax-tree/module.ts +++ b/src/syntax-tree/module.ts @@ -1,4 +1,5 @@ import { Position, Range } from "monaco-editor"; + import { ActionExecutor } from "../editor/action-executor"; import { ActionFilter } from "../editor/action-filter"; import { CodeStatus, EditActionType } from "../editor/consts"; @@ -15,7 +16,7 @@ import { MessageController } from "../messages/message-controller"; import { ConstructHighlight } from "../messages/messages"; import { NotificationManager } from "../messages/notifications"; import { MenuController } from "../suggestions/suggestions-controller"; -import { Settings } from "../utilities/settings"; +import { SettingsController } from "../utilities/settings"; import { Util } from "../utilities/util"; import { AutocompleteTkn, @@ -59,7 +60,7 @@ export class Module { typeSystem: TypeChecker; notificationManager: NotificationManager; toolboxController: ToolboxController; - settings: Settings; + settings: SettingsController; scope: Scope; draftExpressions: DraftRecord[]; @@ -79,7 +80,7 @@ export class Module { this.actionFilter = new ActionFilter(this); this.notificationManager = new NotificationManager(this); this.toolboxController = new ToolboxController(this); - this.settings = new Settings(); + this.settings = new SettingsController(); this.globals = { hoveringOverCascadedMenu: false, diff --git a/src/utilities/settings.ts b/src/utilities/settings.ts index 7f206ff..2cfb935 100644 --- a/src/utilities/settings.ts +++ b/src/utilities/settings.ts @@ -1,7 +1,6 @@ -//Singleton controlling settings for the program -export class Settings { - private static instance: Settings; - private settingsObject: any; +// Singleton controlling settings for the program +export class SettingsController { + private static instance: SettingsController; private modal: HTMLDivElement; private settingsContainer: HTMLDivElement; @@ -9,24 +8,26 @@ export class Settings { private settingsFooter: HTMLDivElement; private exitBtn: HTMLDivElement; + config: { + enabledColoredBlocks: false; + enabledSpotlightSearch: false; + enabledTyping: false; + }; + constructor() { - if (Settings.instance instanceof Settings) { - return Settings.instance; + if (SettingsController.instance instanceof SettingsController) { + return SettingsController.instance; } - this.settingsObject = { - "Coloured Blocks": true, - "Spotlight Search": true, - "Enable Typing": true, + this.config = { + enabledColoredBlocks: false, + enabledSpotlightSearch: false, + enabledTyping: false, }; this.addEventListeners(); - Settings.instance = this; - } - - public getSettingsObject() { - return this.settingsObject; + SettingsController.instance = this; } private addEventListeners() { @@ -54,7 +55,7 @@ export class Settings { this.settingsHeader.innerHTML = "Settings"; this.settingsContainer.appendChild(this.settingsHeader); - Object.keys(this.settingsObject).map((key) => { + Object.keys(SettingsController.instance.config).map((key) => { const setting = document.createElement("div"); setting.classList.add("setting"); this.settingsContainer.appendChild(setting); @@ -70,7 +71,7 @@ export class Settings { const toggleBtnCheckbox = document.createElement("input"); toggleBtnCheckbox.type = "checkbox"; - toggleBtnCheckbox.checked = this.settingsObject[key]; + toggleBtnCheckbox.checked = SettingsController.instance.config[key]; toggleBtn.appendChild(toggleBtnCheckbox); const toggleBtnSlider = document.createElement("span"); @@ -78,7 +79,7 @@ export class Settings { toggleBtn.appendChild(toggleBtnSlider); toggleBtnCheckbox.addEventListener("change", () => { - this.settingsObject[key] = toggleBtnCheckbox.checked; + SettingsController.instance.config[key] = toggleBtnCheckbox.checked; }); }); From ff4468b33581b145409bb51db8a50207d434ba25 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 21 Jul 2022 10:58:00 -0400 Subject: [PATCH 12/12] Settings v1 --- src/css/index.css | 2 +- src/editor/action-executor.ts | 14 +++- src/editor/consts.ts | 6 ++ src/editor/cursor.ts | 28 +++++++- src/editor/event-router.ts | 11 ++-- src/editor/hole.ts | 58 ++++++++++++++--- src/editor/toolbox.ts | 31 ++++++++- src/messages/messages.ts | 116 ++++++++++++++++++++++++++++++++-- src/syntax-tree/module.ts | 6 +- src/utilities/settings.ts | 44 ++++++++----- 10 files changed, 276 insertions(+), 40 deletions(-) diff --git a/src/css/index.css b/src/css/index.css index 5ca898b..7be2eea 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -34,7 +34,7 @@ body { } .button { - color: white; + color: #0d0c22; cursor: pointer; border-radius: 4px; display: flex; diff --git a/src/editor/action-executor.ts b/src/editor/action-executor.ts index d3c0b34..a205856 100644 --- a/src/editor/action-executor.ts +++ b/src/editor/action-executor.ts @@ -54,6 +54,7 @@ import { import { Module } from "../syntax-tree/module"; import { Reference } from "../syntax-tree/scope"; import { TypeChecker } from "../syntax-tree/type-checker"; +import { SettingsController } from "../utilities/settings"; import { getUserFriendlyType, isImportable } from "../utilities/util"; import { LogEvent, Logger, LogType } from "./../logger/analytics"; import { BinaryOperator, DataType, InsertionType } from "./../syntax-tree/consts"; @@ -272,7 +273,15 @@ export class ActionExecutor { if (flashGreen) this.flashGreen(action.data?.statement); if (statement.hasBody()) { - let scopeHighlight = new ScopeHighlight(this.module.editor, statement, statement.color); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + let scopeHighlight = new ScopeHighlight(this.module.editor, statement, statement.color); + } else { + let scopeHighlight = new ScopeHighlight( + this.module.editor, + statement, + "rgba(75, 200, 255, 0.125)" + ); + } } else { this.setTokenColor(action.data?.statement, statement.color); } @@ -1736,6 +1745,9 @@ export class ActionExecutor { } private setTokenColor(code: CodeConstruct, color: string) { + if (!SettingsController.getInstance().config.enabledColoredBlocks) { + return; + } const aRgbHex = color.substring(1).match(/.{1,2}/g); const aRgb = [parseInt(aRgbHex[0], 16), parseInt(aRgbHex[1], 16), parseInt(aRgbHex[2], 16)]; diff --git a/src/editor/consts.ts b/src/editor/consts.ts index 2655320..b5fd349 100644 --- a/src/editor/consts.ts +++ b/src/editor/consts.ts @@ -287,6 +287,12 @@ export enum InsertActionType { InsertOperatorTkn, } +export enum settingsConfigCategories { + enabledColoredBlocks = "enabledColoredBlocks", + enabledSpotlightSearch = "enabledSpotlightSearch", + enabledTyping = "enabledTyping", +} + export const Docs: any = { AddVarDocs, AddDocs, diff --git a/src/editor/cursor.ts b/src/editor/cursor.ts index 5613094..818246e 100644 --- a/src/editor/cursor.ts +++ b/src/editor/cursor.ts @@ -1,4 +1,5 @@ import { CodeConstruct, EmptyLineStmt, TypedEmptyExpr } from "../syntax-tree/ast"; +import { SettingsController } from "../utilities/settings"; import { Editor } from "./editor"; export class Cursor { @@ -17,7 +18,11 @@ export class Cursor { const cursor = this; function loop() { - cursor.setTransform(cursor.code); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + cursor.setTransformColor(cursor.code); + } else { + cursor.setTransform(cursor.code); + } requestAnimationFrame(loop); } @@ -39,6 +44,27 @@ export class Cursor { const transform = this.editor.computeBoundingBox(selection); + this.element.style.top = `${transform.y + 5}px`; + this.element.style.left = `${transform.x - leftPadding}px`; + + this.element.style.width = `${transform.width + rightPadding}px`; + this.element.style.height = `${transform.height - 5 * 2}px`; + } + + setTransformColor(code: CodeConstruct) { + let leftPadding = 0; + let rightPadding = 0; + + const selection = code != null ? code.getSelection() : this.editor.monaco.getSelection(); + + if (code instanceof TypedEmptyExpr) this.element.style.borderRadius = "15px"; + else this.element.style.borderRadius = "0"; + + this.element.style.visibility = "visible"; + if (!code || code instanceof EmptyLineStmt) this.element.style.visibility = "hidden"; + + const transform = this.editor.computeBoundingBox(selection); + this.element.style.top = `${transform.y + 5 + 4}px`; this.element.style.left = `${transform.x - leftPadding}px`; diff --git a/src/editor/event-router.ts b/src/editor/event-router.ts index a7929af..cf147fd 100644 --- a/src/editor/event-router.ts +++ b/src/editor/event-router.ts @@ -11,14 +11,12 @@ import { Context } from "./focus"; export class EventRouter { module: Module; - settings: SettingsController; curPosition: Position; buttonClicksCount = new Map(); constructor(module: Module) { this.module = module; this.curPosition = module.editor.monaco.getPosition(); - this.settings = new SettingsController(); } getKeyAction(e: KeyboardEvent, providedContext?: Context): EditAction { @@ -274,7 +272,12 @@ export class EventRouter { case KeyPress.Space: { if (inTextEditMode) return new EditAction(EditActionType.InsertChar); - if (!inTextEditMode && e.ctrlKey && e.key.length == 1 && this.settings.config.enabledSpotlightSearch) { + if ( + !inTextEditMode && + e.ctrlKey && + e.key.length == 1 && + SettingsController.getInstance().config.enabledSpotlightSearch + ) { return new EditAction(EditActionType.OpenValidInsertMenu); } @@ -282,7 +285,7 @@ export class EventRouter { } default: { - if (e.key.length == 1) { + if (e.key.length == 1 && SettingsController.getInstance().config.enabledTyping) { if (inTextEditMode) { switch (e.key) { case KeyPress.C: diff --git a/src/editor/hole.ts b/src/editor/hole.ts index 5d56062..d4975a2 100644 --- a/src/editor/hole.ts +++ b/src/editor/hole.ts @@ -12,6 +12,7 @@ import { Callback, CallbackType } from "../syntax-tree/callback"; import { InsertionType } from "../syntax-tree/consts"; import { Module } from "../syntax-tree/module"; import { Reference } from "../syntax-tree/scope"; +import { SettingsController } from "../utilities/settings"; import { Editor } from "./editor"; import { Context } from "./focus"; import { Validator } from "./validator"; @@ -107,7 +108,11 @@ export class Hole { code.subscribe( CallbackType.delete, new Callback(() => { - hole.setTransform(null); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + hole.setTransformColor(null); + } else { + hole.setTransform(null); + } hole.remove(); }) ); @@ -115,7 +120,11 @@ export class Hole { code.subscribe( CallbackType.replace, new Callback(() => { - hole.setTransform(null); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + hole.setTransformColor(null); + } else { + hole.setTransform(null); + } hole.remove(); }) ); @@ -123,16 +132,28 @@ export class Hole { code.subscribe( CallbackType.fail, new Callback(() => { - hole.element.style.background = `rgba(255, 0, 0, 0.25)`; - - setTimeout(() => { - hole.element.style.background = `rgba(255, 255, 255, 1)`; - }, 1000); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + hole.element.style.background = `rgba(255, 0, 0, 0.25)`; + + setTimeout(() => { + hole.element.style.background = `rgba(255, 255, 255, 1)`; + }, 1000); + } else { + hole.element.style.background = `rgba(255, 0, 0, 0.06)`; + + setTimeout(() => { + hole.element.style.background = `rgba(255, 255, 255, 0)`; + }, 1000); + } }) ); function loop() { - hole.setTransform(code); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + hole.setTransformColor(code); + } else { + hole.setTransform(code); + } requestAnimationFrame(loop); } @@ -153,6 +174,27 @@ export class Hole { } } + this.element.style.top = `${transform.y + 5}px`; + this.element.style.left = `${transform.x - leftPadding}px`; + + this.element.style.width = `${transform.width + rightPadding}px`; + this.element.style.height = `${transform.height - 5 * 2}px`; + } + + setTransformColor(code: CodeConstruct) { + let leftPadding = 0; + let rightPadding = 0; + let transform = { x: 0, y: 0, width: 0, height: 0 }; + + if (code) { + transform = this.editor.computeBoundingBox(code.getSelection()); + + if (transform.width == 0) { + transform.x -= 7; + transform.width = 14; + } + } + this.element.style.top = `${transform.y + 5 + 4}px`; this.element.style.left = `${transform.x - leftPadding}px`; diff --git a/src/editor/toolbox.ts b/src/editor/toolbox.ts index 9337029..02a3a89 100644 --- a/src/editor/toolbox.ts +++ b/src/editor/toolbox.ts @@ -6,6 +6,7 @@ import { addTextToConsole, clearConsole, CONSOLE_ERR_TXT_CLASS } from "../pyodid import { CodeConstruct, Expression, Modifier, Statement, VariableReferenceExpr } from "../syntax-tree/ast"; import { DataType, InsertionType, Tooltip } from "../syntax-tree/consts"; import { Module } from "../syntax-tree/module"; +import { SettingsController } from "../utilities/settings"; import { getUserFriendlyType } from "../utilities/util"; import { LogEvent, Logger, LogType } from "./../logger/analytics"; import { Accordion, TooltipType } from "./accordion"; @@ -177,7 +178,6 @@ export class ToolboxController { const staticDummySpace = document.getElementById("static-toolbox-dummy-space"); const toolboxCategories = Actions.instance().toolboxCategories; - const hello = Actions.instance().actionsMap; for (const constructGroup of toolboxCategories) { if (constructGroup) { @@ -218,6 +218,26 @@ export class ToolboxController { toolboxDiv.clientHeight - toolboxDiv.children[toolboxDiv.children.length - 2].clientHeight - 20 }px`; } + + toggleToolboxColors() { + const toolboxCategories = Actions.instance().toolboxCategories; + const isColored = SettingsController.getInstance().config.enabledColoredBlocks; + + for (const constructGroup of toolboxCategories) { + if (constructGroup) { + for (const item of constructGroup.items) { + const button = document.getElementById(item.cssId); + if (isColored) { + button.style.backgroundColor = item.documentation.styles.backgroundColor; + button.style.color = "#fff"; + } else { + button.style.backgroundColor = "#fff"; + button.style.color = "#0d0c22"; + } + } + } + } + } } export class ToolboxButton { @@ -228,9 +248,16 @@ export class ToolboxButton { this.container.classList.add("var-button-container"); const button = document.createElement("div"); - button.style.backgroundColor = btnColor; button.classList.add("button"); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + button.style.backgroundColor = btnColor; + button.style.color = "#fff"; + } else { + button.style.backgroundColor = "#fff"; + button.style.color = "#0d0c22"; + } + if (!(code instanceof Expression) && !(code instanceof Modifier)) { button.classList.add("statement-button"); } else if (code instanceof Modifier) { diff --git a/src/messages/messages.ts b/src/messages/messages.ts index fe63a41..c6fc0f9 100644 --- a/src/messages/messages.ts +++ b/src/messages/messages.ts @@ -4,6 +4,7 @@ import { EDITOR_DOM_ID } from "../editor/toolbox"; import { nova } from "../index"; import { CodeConstruct, Expression, Statement, TypedEmptyExpr } from "../syntax-tree/ast"; import { Callback, CallbackType } from "../syntax-tree/callback"; +import { SettingsController } from "../utilities/settings"; /** * Class name of the DOM element to which messages are appended to. @@ -137,7 +138,11 @@ export class ConstructHighlight extends CodeHighlight { super.createDomElement(); this.domElement.classList.add("highlight"); - this.updateDimensions(true); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + this.updateDimensionsColor(true); + } else { + this.updateDimensions(true); + } document.querySelector(editorDomElementClass).appendChild(this.domElement); } @@ -184,6 +189,57 @@ export class ConstructHighlight extends CodeHighlight { let width = 0; let height = 0; + //no idea why these need separate handling... This was the easiest fix. + if (this.code instanceof TypedEmptyExpr) { + const transform = this.editor.computeBoundingBox(this.code.getSelection()); + const text = this.code.getRenderText(); + + top = transform.y + 5; + left = (this.code.getSelection().startColumn - 1) * this.editor.computeCharWidthInvisible(lineNumber); + + width = + text.length * this.editor.computeCharWidthInvisible(lineNumber) > 0 + ? text.length * this.editor.computeCharWidthInvisible(lineNumber) + : HIGHLIGHT_DEFAULT_WIDTH; + height = transform.height > 0 ? transform.height - 5 * 2 : HIGHLIGHT_DEFAULT_HEIGHT; + } else { + const selection = this.code.getSelection(); + const transform = this.editor.computeBoundingBox(selection); + + if (this.code instanceof Expression) { + top = (selection.startLineNumber - 1) * this.editor.computeCharHeight(); + left = transform.x; + height = Math.floor(this.editor.computeCharHeight() * 0.95); + width = + (selection.endColumn - selection.startColumn) * this.editor.computeCharWidthInvisible(lineNumber) + + 10; + } else { + top = (selection.startLineNumber - 1) * this.editor.computeCharHeight(); + left = transform.x; + height = Math.floor(this.editor.computeCharHeight() * 0.95); + width = + (selection.endColumn - selection.startColumn) * this.editor.computeCharWidthInvisible(lineNumber); + } + } + + if (firstInsertion) { + this.domElement.style.top = `${top}px`; + this.domElement.style.left = `${left}px`; + } + + this.domElement.style.width = `${width}px`; + this.domElement.style.height = `${height}px`; + } + + protected updateDimensionsColor(firstInsertion: boolean = false) { + //instanceof Token does not have lineNumber + let lineNumber = this.code.getLineNumber(); + + let top = 0; + let left = 0; + let width = 0; + let height = 0; + //no idea why these need separate handling... This was the easiest fix. if (this.code instanceof TypedEmptyExpr) { const transform = this.editor.computeBoundingBox(this.code.getSelection()); @@ -665,7 +721,11 @@ export class ScopeHighlight { const onChange = new Callback( (() => { - this.updateDimensions(); + if (SettingsController.getInstance().config.enabledColoredBlocks) { + this.updateDimensionsColor(); + } else { + this.updateDimensions(); + } }).bind(this) ); @@ -709,14 +769,19 @@ export class ScopeHighlight { this.headerElement = document.createElement("div"); this.headerElement.classList.add("scope-header-highlight"); this.headerElement.style.backgroundColor = color; - this.headerElement.style.opacity = "0.25"; this.bodyElement = document.createElement("div"); this.bodyElement.classList.add("scope-body-highlight"); this.bodyElement.style.backgroundColor = color; - this.bodyElement.style.opacity = "0.25"; - this.updateDimensions(); + //TODO: change all colors to rgba - temporary fix + if (SettingsController.getInstance().config.enabledColoredBlocks) { + this.headerElement.style.opacity = "0.25"; + this.bodyElement.style.opacity = "0.25"; + this.updateDimensionsColor(); + } else { + this.updateDimensions(); + } document.querySelector(editorDomElementClass).appendChild(this.headerElement); document.querySelector(editorDomElementClass).appendChild(this.bodyElement); @@ -748,6 +813,47 @@ export class ScopeHighlight { this.headerElement.style.top = `${headerDim.top}px`; this.headerElement.style.left = `${headerDim.left}px`; + this.headerElement.style.width = `${maxRight - headerDim.left}px`; + this.headerElement.style.height = `${headerDim.height}px`; + + let firstLineInBody = this.statement.body[0]; + let firstLineInBodyDim: LineDimension; + + if (firstLineInBody) { + firstLineInBodyDim = LineDimension.compute(firstLineInBody, this.editor); + } else { + firstLineInBodyDim = LineDimension.compute(this.statement, this.editor); + } + + this.bodyElement.style.top = `${firstLineInBodyDim.top}px`; + this.bodyElement.style.left = `${firstLineInBodyDim.left}px`; + + this.bodyElement.style.width = `${maxRight - firstLineInBodyDim.left}px`; + this.bodyElement.style.height = `${headerDim.height * (maxLineNumber - this.statement.lineNumber)}px`; + } + + protected updateDimensionsColor(): void { + const headerDim = LineDimension.compute(this.statement, this.editor); + + let maxRight = headerDim.right; + let maxLineNumber = 0; + + const stack = Array(); + stack.unshift(...this.statement.body); + + while (stack.length > 0) { + const line = stack.pop(); + + const lineDim = LineDimension.compute(line, this.editor); + if (lineDim.right > maxRight) maxRight = lineDim.right; + if (line.lineNumber > maxLineNumber) maxLineNumber = line.lineNumber; + + if (line.hasBody()) stack.unshift(...line.body); + } + + this.headerElement.style.top = `${headerDim.top}px`; + this.headerElement.style.left = `${headerDim.left}px`; + this.headerElement.style.width = `${maxRight - headerDim.left + 10}px`; this.headerElement.style.height = `${headerDim.height}px`; diff --git a/src/syntax-tree/module.ts b/src/syntax-tree/module.ts index cc3e8e3..1d0c30a 100644 --- a/src/syntax-tree/module.ts +++ b/src/syntax-tree/module.ts @@ -60,7 +60,7 @@ export class Module { typeSystem: TypeChecker; notificationManager: NotificationManager; toolboxController: ToolboxController; - settings: SettingsController; + settingsController: SettingsController; scope: Scope; draftExpressions: DraftRecord[]; @@ -80,7 +80,6 @@ export class Module { this.actionFilter = new ActionFilter(this); this.notificationManager = new NotificationManager(this); this.toolboxController = new ToolboxController(this); - this.settings = new SettingsController(); this.globals = { hoveringOverCascadedMenu: false, @@ -150,6 +149,9 @@ export class Module { this.menuController = MenuController.getInstance(); this.menuController.setInstance(this, this.editor); + this.settingsController = SettingsController.getInstance(); + this.settingsController.setInstance(this); + Util.getInstance(this); } diff --git a/src/utilities/settings.ts b/src/utilities/settings.ts index 2cfb935..d90ebc5 100644 --- a/src/utilities/settings.ts +++ b/src/utilities/settings.ts @@ -1,3 +1,6 @@ +import { settingsConfigCategories } from "../editor/consts"; +import { Module } from "../syntax-tree/module"; + // Singleton controlling settings for the program export class SettingsController { private static instance: SettingsController; @@ -8,26 +11,28 @@ export class SettingsController { private settingsFooter: HTMLDivElement; private exitBtn: HTMLDivElement; - config: { - enabledColoredBlocks: false; - enabledSpotlightSearch: false; - enabledTyping: false; - }; + public config: any; - constructor() { - if (SettingsController.instance instanceof SettingsController) { - return SettingsController.instance; - } + module: Module; + constructor() { this.config = { - enabledColoredBlocks: false, - enabledSpotlightSearch: false, - enabledTyping: false, + [settingsConfigCategories.enabledColoredBlocks]: false, + [settingsConfigCategories.enabledSpotlightSearch]: false, + [settingsConfigCategories.enabledTyping]: false, }; this.addEventListeners(); + } - SettingsController.instance = this; + static getInstance() { + if (!SettingsController.instance) SettingsController.instance = new SettingsController(); + + return SettingsController.instance; + } + + setInstance(module: Module) { + this.module = module; } private addEventListeners() { @@ -55,7 +60,7 @@ export class SettingsController { this.settingsHeader.innerHTML = "Settings"; this.settingsContainer.appendChild(this.settingsHeader); - Object.keys(SettingsController.instance.config).map((key) => { + Object.keys(this.config).map((key) => { const setting = document.createElement("div"); setting.classList.add("setting"); this.settingsContainer.appendChild(setting); @@ -71,7 +76,8 @@ export class SettingsController { const toggleBtnCheckbox = document.createElement("input"); toggleBtnCheckbox.type = "checkbox"; - toggleBtnCheckbox.checked = SettingsController.instance.config[key]; + toggleBtnCheckbox.checked = this.config[key]; + toggleBtnCheckbox.id = key; toggleBtn.appendChild(toggleBtnCheckbox); const toggleBtnSlider = document.createElement("span"); @@ -79,7 +85,13 @@ export class SettingsController { toggleBtn.appendChild(toggleBtnSlider); toggleBtnCheckbox.addEventListener("change", () => { - SettingsController.instance.config[key] = toggleBtnCheckbox.checked; + this.config[key] = toggleBtnCheckbox.checked; + + //TODO: update the blocks to be colorless + //re-render the toolbox + if (toggleBtnCheckbox.id == settingsConfigCategories.enabledColoredBlocks) { + this.module.toolboxController.toggleToolboxColors(); + } }); });