var ace: any; namespace OS { export namespace application { /** * Wrapper model for the ACE text editor * * @export * @class ACEModel * @extends {BaseEditorModel} */ export class ACEModel extends BaseEditorModel { /** * Current editor mode * * @private * @type {GenericObject} * @memberof ACEModel */ private mode: GenericObject; /** * Reference to ACE language modes * * @private * @type {GenericObject} * @memberof ACEModel */ private modes: GenericObject; /** * Creates an instance of ACEModel. * @param {ACEModel} app instance * @param {GUI.tag.TabBarTag} tabbar tabbar element * @param {HTMLElement} editorarea main editor container element * @memberof ACEModel */ constructor(app: BaseApplication, tabbar: GUI.tag.TabBarTag, editorarea: HTMLElement) { ace.require("ace/ext/language_tools"); super(app, tabbar, editorarea); this.modes = ace.require("ace/ext/modelist"); } /** * Reset the editor * * @protected * @memberof ACEModel */ protected resetEditor(): void { this.setValue(""); this.editor.getSession().setUndoManager(new ace.UndoManager()); } /** * Get a text model from the current editor session * * @protected * @return {*} * @memberof ACEModel */ protected getTexModel() { const textModel = {} as any; textModel.cursor = this.editor.getCursorPosition(); textModel.cache = this.getValue(); textModel.um = this.editor.session.getUndoManager(); textModel.langmode = this.mode; return textModel; } /** * Set text model to current editor session * * @protected * @param {*} model * @memberof ACEModel */ protected setTextModel(model: any): void { this.editor.getSession().setUndoManager(new ace.UndoManager()); this.setValue(model.cache); this.setMode(model.langmode); if (model.cursor) { this.setCursor(model.cursor); } this.editor.getSession().setUndoManager(model.um); } /** * Create new editor model from file * * @protected * @param {EditorFileHandle} file * @return {*} {*} * @memberof ACEModel */ protected newTextModelFrom(file: EditorFileHandle): any { const textModel = {} as any; textModel.um = new ace.UndoManager(); textModel.cache = file.cache; textModel.cursor = undefined; if (file.path.toString() !== "Untitled") { textModel.langmode = this.getModeForPath(file.path); } else { textModel.langmode = { text: "Text", mode: "ace/mode/text", }; } return textModel; } /** * Get language modes * * @return {*} {GenericObject[]} * @memberof ACEModel */ getModes(): GenericObject[] { const list = []; let v: GenericObject; for (v of Array.from(this.modes.modes)) { list.push({ text: v.caption, mode: v.mode }); } return list; } /** * Set the editor theme * * @param {string} theme theme name * @memberof ACEModel */ setTheme(theme: string): void { this.editor.setTheme(theme); } /** * Set the editor cursor * * @private * @param {GenericObject} c cursor option * @memberof ACEModel */ private setCursor(c: GenericObject): void { this.editor.renderer.scrollCursorIntoView( { row: c.row, column: c.column, }, 0.5 ); this.editor.selection.moveTo( c.row, c.column ); } /** * Set editor language mode * * The mode object should be in the following format: * ```ts * { * text: string, * mode: string * } * ``` * * @param {GenericObject} m language mode object * @memberof ACEModel */ setMode(m: GenericObject): void { this.mode = m; this.editor.getSession().setMode(m.mode); } /** * Reference to the editor instance * * @protected * @type {GenericObject} * @memberof ACEModel */ protected editor: GenericObject; /** * Setup the editor * * @protected * @param {HTMLElement} el editor container DOM * @memberof ACEModel */ protected editorSetup(el: HTMLElement): void { this.editor = ace.edit(el); this.editor.setOptions({ enableBasicAutocompletion: true, enableSnippets: true, enableLiveAutocompletion: true, highlightActiveLine: true, highlightSelectedWord: true, behavioursEnabled: true, wrap: true, fontSize: "10pt", showInvisibles: true, }); this.editor.setTheme("ace/theme/monokai"); this.editor.completers.push({ getCompletions( editor: any, session: any, pos: any, prefix: any, callback: any ) { }, }); this.editor.getSession().setUseWrapMode(true); } /** * Register to editor event * * @param {string} evt_str event name * @param {() => void} callback callback function * @memberof ACEModel */ on(evt_str: string, callback: () => void): void { switch (evt_str) { case "input": case "focus": this.editor.on(evt_str, callback); break; case "changeCursor": this.editor .getSession() .selection.on(evt_str, callback); break; default: break; } } /** * Resize the editor * * @memberof ACEModel */ resize(): void { this.editor.resize(); } /** * Focus on the editor * * @memberof ACEModel */ focus(): void { this.editor.focus(); } /** * Get language mode from path * * @protected * @param {string} path * @return {*} {GenericObject} * @memberof ACEModel */ protected getModeForPath(path: string): GenericObject { const m = this.modes.getModeForPath(path); return { text: m.caption, mode: m.mode } } /** * Get the editor status * * @return {*} {GenericObject} * @memberof ACEModel */ getEditorStatus(): GenericObject { const c = this.editor.session.selection.getCursor(); const l = this.editor.session.getLength(); return { row: c.row, column: c.column, line: l, langmode: this.mode, file: this.currfile.path } } /** * Get editor value * * @return {*} {string} * @memberof ACEModel */ getValue(): string { return this.editor.getValue(); } /** * Set editor value * * @param {string} value * @memberof ACEModel */ setValue(value: string): void { this.editor.setValue(value, -1); } /** * Get ACE themes */ getThemes(): any { const themes = ace.require("ace/ext/themelist"); const data = []; for(let k in themes.themesByName) { const v = themes.themesByName[k]; data.push({ text: v.caption, theme: v.theme }); } return data; } } } }