Skip to content
This repository has been archived by the owner on Aug 6, 2024. It is now read-only.

Commit

Permalink
feat: use Monaco for code editing
Browse files Browse the repository at this point in the history
  • Loading branch information
sverben committed Mar 24, 2024
1 parent 98cf655 commit 78f2177
Show file tree
Hide file tree
Showing 26 changed files with 182 additions and 206 deletions.
14 changes: 1 addition & 13 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,7 @@
],
"scripts": [
"./node_modules/jquery/dist/jquery.min.js",
"./node_modules/bootstrap/dist/js/bootstrap.min.js",
"./node_modules/prismjs/prism.js",
"./node_modules/prismjs/components/prism-clike.js",
"./node_modules/prismjs/components/prism-c.js",
"./node_modules/prismjs/components/prism-cpp.js",
"./node_modules/prismjs/components/prism-arduino.js",
"./node_modules/ace-builds/src-min/ace.js",
"./node_modules/ace-builds/src-min/mode-c_cpp.js",
"./node_modules/ace-builds/src-min/mode-python.js",
"./node_modules/ace-builds/src-min/theme-solarized_light.js",
"./node_modules/ace-builds/src-min/ext-beautify.js",
"./node_modules/ace-builds/src-min/ext-searchbox.js",
"./node_modules/ace-builds/src-min/ext-language_tools.js"
"./node_modules/bootstrap/dist/js/bootstrap.min.js"
]
},
"configurations": {
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"@ngx-translate/http-loader": "^7.0.0",
"@serialport/parser-readline": "^10.3.0",
"@types/w3c-web-serial": "^1.0.3",
"ace-builds": "^1.5.1",
"base64-js": "^1.5.1",
"blockly": "^10.1.3",
"bootstrap": "^5.1.3",
Expand All @@ -51,11 +50,11 @@
"jquery": "^3.5.1",
"jszip": "^3.10.1",
"moment": "^2.30.1",
"monaco-editor": "^0.47.0",
"ng-terminal": "~6.1.0",
"ng2-charts": "3.0.11",
"ngx-matomo": "2.0.0",
"papaparse": "^5.4.1",
"prismjs": "^1.28.0",
"rxjs": "~7.5.5",
"showdown": "^2.1.0",
"tslib": "^2.4.0",
Expand Down
44 changes: 0 additions & 44 deletions src/app/effects/code-editor.effects.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import {Injectable} from "@angular/core";
import {filter, withLatestFrom} from "rxjs/operators";
import * as ace from "ace-builds";
import {CodeEditorState} from "../state/code-editor.state";
import {AppState} from "../state/app.state";
import {CodeEditorType} from "../domain/code-editor.type";
import {WorkspaceService} from "../services/workspace.service";
import {genericRobotType} from "../domain/robots";


Expand All @@ -18,48 +15,7 @@ export class CodeEditorEffects {
constructor(
private codeEditorState: CodeEditorState,
private appState: AppState,
private workspaceService: WorkspaceService
) {

this.codeEditorState.aceElement$
.pipe(
filter(element => !!element))
.subscribe(element => {
ace.config.set("fontSize", "14px");
//ace.config.set('basePath', 'https://unpkg.com/ace-builds@1.4.12/src-noconflict');
const aceEditor = ace.edit(element.nativeElement);
aceEditor.setTheme('ace/theme/solarized_light');
if (this.appState.getCurrentEditor() == CodeEditorType.Python) {
aceEditor.session.setMode('ace/mode/python');
} else if (this.appState.getCurrentEditor() == CodeEditorType.CPP) {
aceEditor.session.setMode('ace/mode/c_cpp');
}
aceEditor.setOptions({
enableBasicAutocompletion: true,
enableLiveAutocompletion: true
});
this.codeEditorState.setAceEditor(aceEditor);
});


// When the Ace Editor is set, set it with the code, and update the blockly code with changes
this.codeEditorState.aceEditor$
.pipe(filter(aceEditor => !!aceEditor))
.pipe(withLatestFrom(this.codeEditorState.code$))
.subscribe(([aceEditor]) => {

const startingCode = this.codeEditorState.getCode();
aceEditor.session.setValue(startingCode);
this.codeEditorState.setOriginalCode(startingCode);
this.codeEditorState.setCode(startingCode);
this.workspaceService.restoreWorkspaceTemp().then(() => {});

aceEditor.on("change", () => {
const changedCode = aceEditor.getValue();
this.codeEditorState.setCode(changedCode)
});
});

this.appState.codeEditor$
.subscribe(codeEditor => {
if (codeEditor == CodeEditorType.Python) {
Expand Down
11 changes: 0 additions & 11 deletions src/app/effects/dialog.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,6 @@ export class DialogEffects {
});
});


// When the info dialog visibility is set to true, open the dialog
this.dialogState.isEditorTypeChangeConfirmationDialogVisible$
.pipe(filter(isVisible => !!isVisible))
.subscribe(() => {
this.dialog.open(ConfirmEditorDialog, {
width: "450px",
disableClose: true,
});
});

const language = localStorage.getItem('currentLanguage');
if (!language) {
const languageDialogRef = this.dialog.open(LanguageSelectDialog, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<pre id="code-view" >
<code [innerHTML]="codeEditor.tokenizedCode$ | async" class="language-arduino"></code>
</pre>
<monaco-editor
class="code-view"
[code]="codeEditor.code$ | async"
readonly="true"
/>
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
#code-view {
.code-view {
width: 100%;
height: 100%;
margin: 0;
overflow-x: scroll;
}

.language-arduino {
height: 100%;
}
6 changes: 5 additions & 1 deletion src/app/modules/code-editor-cpp/code-editor-cpp.page.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<div id="container">
<div class="app-ace-editor" #editor></div>
<monaco-editor
class="monaco-editor"
[code]="codeEditorState.code$ | async"
(codeChange)="codeEditorState.setCode($event)"
/>
<app-button-bar></app-button-bar>
</div>
12 changes: 5 additions & 7 deletions src/app/modules/code-editor-cpp/code-editor-cpp.page.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
.app-ace-editor {
border: 2px solid #f8f9fa;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
width: 100%;
height: 100%
.monaco-editor {
width: 100%;
height: 100%;
}

#container {
Expand All @@ -28,5 +26,5 @@ app-button-bar {
position: absolute;
right: 0;
top: 0;
z-index: 2;
}
z-index: 5;
}
9 changes: 2 additions & 7 deletions src/app/modules/code-editor-cpp/code-editor-cpp.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,14 @@ import {WorkspaceService} from "../../services/workspace.service";
]
})
export class CodeEditorCppPage implements AfterViewInit {

@ViewChild("editor") private editor: ElementRef<HTMLElement>;

constructor(
private codeEditorState: CodeEditorState,
public codeEditorState: CodeEditorState,
private workspaceService: WorkspaceService
) {}

ngAfterViewInit(): void {
this.codeEditorState.setAceElement(this.editor);

window.addEventListener("beforeunload", async () => {
this.workspaceService.saveWorkspaceTemp(this.codeEditorState.getCode());
await this.workspaceService.saveWorkspaceTemp(this.codeEditorState.getCode());
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<div id="container">
<div class="app-ace-editor" #editor></div>
<monaco-editor
class="monaco-editor"
[code]="codeEditorState.code$ | async"
(codeChange)="codeEditorState.setCode($event)"
language="python"
/>
<app-button-bar></app-button-bar>
<app-terminal class="terminal" #terminal></app-terminal>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
.app-ace-editor {
border: 2px solid #f8f9fa;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
.monaco-editor {
width: 100%;
height: 80%
}
Expand Down Expand Up @@ -28,7 +26,7 @@ app-button-bar {
position: absolute;
right: 0;
top: 0;
z-index: 2;
z-index: 5;
}

.terminal {
Expand Down
13 changes: 4 additions & 9 deletions src/app/modules/code-editor-python/code-editor-python.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,14 @@ import {WorkspaceService} from "../../services/workspace.service";
]
})
export class CodeEditorPythonPage implements AfterViewInit {

@ViewChild("editor") private editor: ElementRef<HTMLElement>;

constructor(
private codeEditorState: CodeEditorState,
public codeEditorState: CodeEditorState,
private workspaceService: WorkspaceService
) {}

ngAfterViewInit(): void {
this.codeEditorState.setAceElement(this.editor);

window.addEventListener("beforeunload", async (event) => {
this.workspaceService.saveWorkspaceTemp(this.codeEditorState.getCode());
});
window.addEventListener("beforeunload", async () => {
await this.workspaceService.saveWorkspaceTemp(this.codeEditorState.getCode());
})
}
}
4 changes: 2 additions & 2 deletions src/app/modules/components/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ export class HeaderComponent {
}
}

public onCodeEditorClicked() {
this.appState.switchCodeEditor();
public async onCodeEditorClicked() {
await this.workspaceService.switchCodeEditor();
}

public onSaveWorkspaceAsClicked() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<h1 mat-dialog-title>
{{ "CONFIRMEDITORCHANGE_TITLE" | translate}}
{{ "CONFIRMEDITORCHANGE_TITLE" | translate }}
</h1>
<div mat-dialog-content>
<p>{{"EDITORCHANGEINSTRUCTIONS"|translate}}</p>
<p>{{ "EDITORCHANGEINSTRUCTIONS"|translate }}</p>
</div>
<div mat-dialog-actions align="center">
<button mat-flat-button (click)="onEditorChangeConfirmed()">
{{"EDITORCHANGE_CONFIRM"|translate}}
</button>
<button mat-flat-button (click)="onEditorChangeCancelled()">
{{"EDITORCHANGE_CANCEL"|translate}}
</button>
<div mat-dialog-actions class="actions" align="center">
<button mat-flat-button (click)="close(false)">
{{ "EDITORCHANGE_CANCEL"|translate }}
</button>
<button mat-flat-button (click)="close(true)">
{{ "EDITORCHANGE_CONFIRM"|translate }}
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.actions {
display: flex;
justify-content: space-between;
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { AppState } from 'src/app/state/app.state';
import {Component, Inject} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {AppState} from 'src/app/state/app.state';

@Component({
selector: 'app-confirm-editor',
templateUrl: './confirm-editor.dialog.html',
styleUrls: ['../dialog-styles.scss', './confirm-editor.dialog.scss']
selector: 'app-confirm-editor',
templateUrl: './confirm-editor.dialog.html',
styleUrls: ['../dialog-styles.scss', './confirm-editor.dialog.scss']
})

export class ConfirmEditorDialog {
constructor(
public dialogRef: MatDialogRef<ConfirmEditorDialog>,
public appState: AppState
) { }
constructor(
public dialogRef: MatDialogRef<ConfirmEditorDialog>,
public appState: AppState,
) { }

public onEditorChangeConfirmed() {
this.appState.setIsCodeEditorToggleConfirmed(true);
this.dialogRef.close();
}
public onEditorChangeCancelled() {
this.dialogRef.close();
}
public close(confirm: boolean) {
this.dialogRef.close(confirm)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="editor" #element></div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.editor {
width: 100%;
height: 100%;
}
54 changes: 54 additions & 0 deletions src/app/modules/shared/components/monaco/monaco.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
Output,
SimpleChanges,
ViewChild
} from "@angular/core";
import * as monaco from 'monaco-editor'

@Component({
selector: "monaco-editor",
styleUrls: ["./monaco.component.scss"],
templateUrl: "./monaco.component.html",
})
export class MonacoComponent implements AfterViewInit, OnChanges {
@Input() language = 'cpp'

@Input() code = ''
@Output() codeChange = new EventEmitter<string>()

@Input() readonly = false

@ViewChild('element') element: ElementRef<HTMLDivElement>
private editor?: monaco.editor.IStandaloneCodeEditor

ngAfterViewInit() {
this.editor = monaco.editor.create(this.element.nativeElement, {
value: this.code,
language: this.language,
automaticLayout: true,
readOnly: this.readonly,
})

this.editor.getModel().onDidChangeContent(() => {
this.setCode(this.editor.getValue())
})
}

ngOnChanges(changes: SimpleChanges) {
if (!this.editor) return
if (this.editor.getValue() !== changes.code.currentValue) {
this.editor.setValue(changes.code.currentValue)
}
}

public setCode(code: string) {
this.code = code
this.codeChange.emit(code)
}
}
Loading

0 comments on commit 78f2177

Please sign in to comment.