From 42bc787eaedd361f62495ca0d11683cfe0484c2c Mon Sep 17 00:00:00 2001 From: mrsang Date: Sat, 1 May 2021 12:17:00 +0200 Subject: [PATCH] SUpport to change language mode in antedit --- Antedit/README.md | 1 + Antedit/build/debug/README.md | 1 + Antedit/build/debug/main.js | 2 +- Antedit/build/debug/package.json | 2 +- Antedit/build/release/Antedit.zip | Bin 10002 -> 10126 bytes Antedit/package.json | 2 +- Antedit/ts/MonacoEditorModel.ts | 8 +++++++- Antedit/ts/main.ts | 30 ++++++++++++++++++++++-------- 8 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Antedit/README.md b/Antedit/README.md index 4945b39..78dd376 100644 --- a/Antedit/README.md +++ b/Antedit/README.md @@ -6,4 +6,5 @@ The editor functionality can be extended by its extension mechanism. Extension can be developed/released/isntalled by the editor itself. ### Change logs +- 0.1.8-a: Allow to change language mode - 0.1.7-a: Add keyboard shortcut support to extension actions \ No newline at end of file diff --git a/Antedit/build/debug/README.md b/Antedit/build/debug/README.md index 4945b39..78dd376 100644 --- a/Antedit/build/debug/README.md +++ b/Antedit/build/debug/README.md @@ -6,4 +6,5 @@ The editor functionality can be extended by its extension mechanism. Extension can be developed/released/isntalled by the editor itself. ### Change logs +- 0.1.8-a: Allow to change language mode - 0.1.7-a: Add keyboard shortcut support to extension actions \ No newline at end of file diff --git a/Antedit/build/debug/main.js b/Antedit/build/debug/main.js index 1122bba..9174fc1 100644 --- a/Antedit/build/debug/main.js +++ b/Antedit/build/debug/main.js @@ -1 +1 @@ -var OS;!function(t){let e;!function(t){t.BaseEditorModel=class{constructor(t,e,i){this.container=i,this.currfile="Untitled".asFileHandle(),this.tabbar=e,this.editorSetup(i),this.app=t,this.editormux=!1,this.onstatuschange=void 0,this.on("focus",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.on("input",()=>this.editormux?(this.editormux=!1,!1):this.currfile.dirty?void 0:(this.currfile.dirty=!0,this.currfile.text+="*",this.tabbar.update(void 0))),this.on("changeCursor",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.tabbar.ontabselect=t=>this.selecteTab($(t.data.item).index()),this.tabbar.ontabclose=t=>{const e=t.data.item;return!!e&&(e.data.dirty?(this.app.openDialog("YesNoDialog",{title:__("Close tab"),text:__("Close without saving ?")}).then(t=>t?this.closeTab(e):this.focus()),!1):this.closeTab(e))}}findTabByFile(t){const e=this.tabbar.items,i=(()=>{const i=[];for(let a=0;a(t.cache=e||"",this.newTab(t))).catch(e=>this.app.error(__("Unable to open: {0}",t.path),e)):this.newTab(t):this.tabbar.selected=e}write(t){this.currfile.cache=this.getValue(),t.write("text/plain").then(e=>{t.dirty=!1,t.text=t.basename,this.tabbar.update(void 0)}).catch(e=>this.app.error(__("Unable to save file: {0}",t.path),e))}save(){return this.currfile.cache=this.getValue(),this.currfile.basename?this.write(this.currfile):this.saveAs()}saveAs(){this.app.openDialog("FileDialog",{title:__("Save as"),file:this.currfile}).then(t=>{let e=t.file.path.asFileHandle();"file"===t.file.type&&(e=e.parent()),this.currfile.setPath(`${e.path}/${t.name}`),this.write(this.currfile)})}dirties(){const t=[];for(let e of Array.from(this.tabbar.items))e.dirty&&t.push(e);return t}set contextmenuHandle(t){this.container.contextmenuHandle=t}closeAll(){this.tabbar.items=[],this.resetEditor()}isDirty(){return this.dirties().length>0}}}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends t.application.BaseEditorModel{constructor(t,e,i){super(t,e,i)}resetEditor(){this.setValue("")}getTexModel(){return{model:this.editor.getModel(),position:this.editor.getPosition()}}setTextModel(t){this.editor.setModel(t.model),t.position&&(this.editor.setPosition(t.position),this.editor.revealLineInCenter(t.position.lineNumber))}newTextModelFrom(t){if("Untitled"===t.path.toString())return{model:monaco.editor.createModel(t.cache,"textplain")};const e=monaco.Uri.parse(t.path),i=monaco.editor.getModel(e);return i?(i.setValue(t.cache),{model:i}):{model:monaco.editor.createModel(t.cache,void 0,e)}}getModes(){return monaco.languages.getLanguages()}setTheme(t){}setMode(t){}editorSetup(t){this.editor=monaco.editor.create(t,{value:"",language:"textplain"}),i.modes||(i.modes={},monaco.languages.getLanguages().forEach(t=>{i.modes[t.id]=t}))}on(t,e){switch(t){case"input":this.editor.onDidChangeModelContent(e);break;case"focus":this.editor.onDidFocusEditorText(e);break;case"changeCursor":this.editor.onDidChangeCursorPosition(e)}}resize(){this.editor&&this.editor.layout()}focus(){this.editor&&this.editor.focus()}getModeForPath(t){return{}}getEditorStatus(){const t=this.editor.getPosition(),e=i.modes[this.editor.getModel().getModeId()];return{row:t.lineNumber,column:t.column,line:this.editor.getModel().getLineCount(),langmode:{text:e.aliases[0],mode:e},file:this.currfile.path}}getValue(){return this.editor.getValue()}setValue(t){this.editor.setValue(t)}getEditor(){return this.editor}}e.MonacoEditorModel=i}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends e.BaseApplication{constructor(t){super("Antedit",t),this.currdir=void 0}main(){this.extensions={},this.eum=new a,this.fileview=this.find("fileview"),this.sidebar=this.find("sidebar"),this.bottombar=this.find("bottombar"),this.langstat=this.find("langstat"),this.editorstat=this.find("editorstat"),this.filestat=this.find("current-file-lbl"),this.logger=new s(this.find("output-tab")),this.split_mode=!0,this.fileview.fetch=t=>new Promise((async function(e,i){let a;a="string"==typeof t?t.asFileHandle():t;try{const t=await a.read();return t.error?i(t.error):e(t.result)}catch(t){return i(__e(t))}}));let e="Untitled".asFileHandle();this.args&&this.args.length>0&&(this.addRecent(this.args[0].path),"dir"===this.args[0].type?this.currdir=this.args[0].path.asFileHandle():(e=this.args[0].path.asFileHandle(),this.currdir=e.parent())),this.setting.recent||(this.setting.recent=[]);const i=this.find("wrapper");$(i).css("visibility","hidden"),monaco.editor.setTheme("vs-dark"),this.eum.add(new t.application.MonacoEditorModel(this,this.find("left-tabbar"),this.find("left-editorarea"))).add(new t.application.MonacoEditorModel(this,this.find("right-tabbar"),this.find("right-editorarea"))),this.eum.onstatuschange=t=>this.updateStatus(t),$(i).css("visibility","visible"),this.setup(),this.eum.active.openFile(e)}setup(){this.fileview.onfileopen=t=>{if(t.data&&t.data.path&&"dir"!==t.data.type)return this.addRecent(t.data.path),this.eum.active.openFile(t.data.path.asFileHandle())},this.fileview.onfileselect=t=>{t.data&&t.data.path&&"dir"!==t.data.type&&this.eum.active.selectFile(t.data.path)},this.on("resize",()=>this.eum.resize()),this.on("focus",()=>this.eum.active.focus()),this.fileview.contextmenuHandle=(t,e)=>(e.items=[{text:"__(New file)",id:"new"},{text:"__(New folder)",id:"newdir"},{text:"__(Rename)",id:"rename"},{text:"__(Delete)",id:"delete"}],e.onmenuselect=t=>this.ctxFileMenuHandle(t),e.show(t)),this.bindKey("ALT-N",()=>this.menuAction("new")),this.bindKey("ALT-O",()=>this.menuAction("open")),this.bindKey("ALT-F",()=>this.menuAction("opendir")),this.bindKey("CTRL-S",()=>this.menuAction("save")),this.bindKey("ALT-W",()=>this.menuAction("saveas")),this.fileview.ondragndrop=t=>{const e=t.data.from.data.path.asFileHandle(),i=t.data.to.data.path;return e.move(`${i}/${e.basename}`).then((function(a){const s=i,n=e.parent().path;s.lengththis.error(__("Unable to move file/folder"),t))},this.on("filechange",t=>{let{path:e}=t.file;return"file"===t.type&&({path:e}=t.file.parent()),this.fileview.update(e)}),this.find("logger-clear").onbtclick=()=>{this.logger.clear()},void 0===this.setting.showBottomBar&&(this.setting.showBottomBar=!1),this.loadExtensionMetaData(),this.toggleSideBar(),this.toggleSplitMode(),this.applyAllSetting()}updateStatus(t){t||(t=this.eum.active.getEditorStatus()),this.editorstat.text=__("Row {0}, col {1}, lines: {2}",t.row,t.column,t.line),t.langmode&&(this.langstat.text=t.langmode.text),this.filestat.text=t.file;let e=this.scheme;e.apptitle!=t.file&&(e.apptitle=t.file)}toggleSideBar(){this.currdir?($(this.sidebar).show(),this.fileview.path=this.currdir.path):$(this.sidebar).hide(),this.trigger("resize")}showOutput(t=!1){t&&this.showBottomBar(!0),this.bottombar.selectedIndex=0}applySetting(t){"showBottomBar"==t&&this.showBottomBar(this.setting.showBottomBar)}showBottomBar(t){this.setting.showBottomBar=t,t?$(this.bottombar).show():$(this.bottombar).hide(),this.trigger("resize")}toggleBottomBar(){this.showBottomBar(!this.setting.showBottomBar)}toggleSplitMode(){const t=this.find("right-panel"),e=this.eum.editors[1],i=this.eum.editors[0];if(this.split_mode){if(e.isDirty())return void this.notify(__("Unable to disable split view: Please save changes of modified files on the right panel"));e.closeAll(),$(t).hide(),this.split_mode=!1,i.focus()}else $(t).show(),this.split_mode=!0,e.openFile("Untitled".asFileHandle()),e.focus();this.trigger("resize")}fileMenu(){const t=this.setting.recent.map(t=>({text:t}));return{text:__("File"),nodes:[{text:__("New"),dataid:"new",shortcut:"A-N"},{text:__("Open Recent"),dataid:"recent",nodes:t,onchildselect:(t,e)=>{const i=t.data.item.data.text.asFileHandle();i.onready().then(t=>{t&&("dir"==t.type?(this.currdir=i,this.toggleSideBar()):this.eum.active.openFile(i))})}},{text:__("Open"),dataid:"open",shortcut:"A-O"},{text:__("Open Folder"),dataid:"opendir",shortcut:"A-F"},{text:__("Save"),dataid:"save",shortcut:"C-S"},{text:__("Save as"),dataid:"saveas",shortcut:"A-W"}],onchildselect:(t,e)=>this.menuAction(t.data.item.data.dataid,e)}}ctxFileMenuHandle(t){const e=t.data.item;if(!e)return;const i=e.data;if(!i)return;let a=this.fileview.selectedFile,s=this.currdir;switch(a&&"dir"===a.type&&(s=a.path.asFileHandle()),a&&"file"===a.type&&(s=a.path.asFileHandle().parent()),i.id){case"new":if(!s)return;this.openDialog("PromptDialog",{title:"__(New file)",label:"__(File name)"}).then(async t=>{const e=`${s.path}/${t}`.asFileHandle();try{return await e.write("text/plain"),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",t.stack),t)}});break;case"newdir":if(!s)return;this.openDialog("PromptDialog",{title:"__(New folder)",label:"__(Folder name)"}).then(async t=>{try{return await s.mk(t),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",s.path),t)}});break;case"rename":if(!a)return;this.openDialog("PromptDialog",{title:"__(Rename)",label:"__(File name)",value:a.filename}).then(async t=>{if(t!==a.filename){a=a.path.asFileHandle(),s=a.parent();try{return await a.move(`${s.path}/${t}`),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to rename: {0}",a.path),t)}}});break;case"delete":if(!a)return;this.openDialog("YesNoDialog",{title:"__(Delete)",iconclass:"fa fa-question-circle",text:__("Do you really want to delete: {0}?",a.filename)}).then(async t=>{if(t){a=a.path.asFileHandle(),s=a.parent();try{return await a.remove(),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to delete: {0}",a.path),t)}}})}}addRecent(t){this.setting.recent||(this.setting.recent=[]),this.setting.recent.includes(t)||(this.setting.recent.push(t),this.setting.recent.length>10&&(this.setting.recent=this.setting.recent.slice(0,10)))}menuAction(t,e){let i=this;switch(e&&(i=e),t){case"new":return i.eum.active.openFile("Untitled".asFileHandle());case"open":return i.openDialog("FileDialog",{title:__("Open file"),mimes:Array.from(i.meta().mimes).filter(t=>"dir"!==t)}).then(t=>{this.addRecent(t.file.path),i.eum.active.openFile(t.file.path.asFileHandle())});case"opendir":return i.openDialog("FileDialog",{title:__("Open folder"),mimes:["dir"]}).then((function(t){return i.addRecent(t.file.path),i.currdir=t.file.path.asFileHandle(),i.toggleSideBar()}));case"save":return i.eum.active.save();case"saveas":return i.eum.active.saveAs();default:return console.log(t)}}cleanup(t){let e;const i=this.eum.dirties();if(0!==i.length)t.preventDefault(),this.openDialog("YesNoDialog",{title:"__(Quit)",text:__("Ignore all unsaved files: {0} ?",(()=>{const t=[];for(e of Array.from(i))t.push(e.filename);return t})().join(", "))}).then(t=>{if(t){for(e of Array.from(i))e.dirty=!1;return this.quit(!1)}});else for(let t in this.extensions)this.extensions[t]&&this.extensions[t].cleanup&&this.extensions[t].cleanup()}menu(){return[this.fileMenu(),{text:"__(View)",nodes:[{text:"__(Toggle bottom bar)",dataid:"bottombar"},{text:"__(Toggle split view)",dataid:"splitview"}],onchildselect:(t,e)=>{switch(t.data.item.data.dataid){case"bottombar":return this.toggleBottomBar();case"splitview":return this.toggleSplitMode()}}}]}loadExtensionMetaData(){this.loadExtensionMetaFromFile(this.meta().path+"/extensions/extensions.json").catch(t=>this.error(__("Cannot load extension meta data"),t))}loadExtensionMetaFromFile(t){return new Promise((e,i)=>{t.asFileHandle().read("json").then(t=>{for(let e of t)for(let t of e.actions)this.eum.addAction(e,t,(t,i)=>{this.loadAndRunExtensionAction(t,i,e.root)});e()}).catch(t=>{i(__e(t))})})}loadAndRunExtensionAction(t,e,a){if(i.extensions[t])this.runExtensionAction(t,e);else{let i=`${this.meta().path}/extensions/${t}/main.js`;a&&(i=a+"/main.js"),this._api.requires(i,!0).then(()=>this.runExtensionAction(t,e)).catch(e=>this.error(__("unable to load extension: {0}",t),e))}}runExtensionAction(t,e){if(!this.extensions[t]){if(!i.extensions[t])return this.error(__("Unable to find extension: {0}",t));this.extensions[t]=new i.extensions[t](this)}if(!this.extensions[t][e])return this.error(__("Unable to find action: {0}",e));this.extensions[t].preload().then(()=>this.extensions[t][e]()).catch(t=>this.error(__("Unable to preload extension"),t))}}e.Antedit=i;class a{constructor(){this.active_editor=void 0,this.models=[]}get editors(){return this.models}set contextmenuHandle(t){for(let e of this.models)e.contextmenuHandle=t}get active(){return this.active_editor}add(t){return this.models.push(t),this.active_editor||(this.active_editor=t),t.on("focus",()=>{this.active_editor=t}),this}addAction(t,e,i){const a={id:`${t.name}:${e.name}`,label:`${t.text.__()}: ${e.text.__()}`,keybindings:[],precondition:null,keybindingContext:null,contextMenuGroupId:t.name,run:()=>i(t.name,e.name)};if(e.shortcut){const t=e.shortcut.split("-");let i=0;for(const e of t)switch(e){case"CTRL":i|=monaco.KeyMod.CtrlCmd;break;case"ALT":i|=monaco.KeyMod.Alt;break;case"SHIFT":i|=monaco.KeyMod.Shift;break;case"SUPPER":i|=monaco.KeyMod.WinCtrl;break;default:const t="KEY_"+e;monaco.KeyCode[t]?i|=monaco.KeyCode[t]:i=0}0!=i&&a.keybindings.push(i)}for(let t of this.models){const e=t.getEditor();e.getAction(a.id)||e.addAction(a)}}set onstatuschange(t){for(let e of this.models)e.onstatuschange=t}dirties(){let t=[];for(let e of this.models)t=t.concat(e.dirties());return t}resize(){for(let t of this.models)t.resize()}}class s{constructor(t){this.target=t}info(t){this.log("info",t,!0)}warn(t){this.log("warn",t,!0)}error(t){this.log("error",t,!0)}log(t,e,i){let a=$("
").attr("class","code-pad-log-"+t);if(i){let t=new Date,i=t.getDate()+"/"+(t.getMonth()+1)+"/"+t.getFullYear()+" "+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds();a.text(`[${i}]: ${e.__()}`)}else a.text(e.__());$(this.target).append(a),$(this.target).scrollTop($(this.target)[0].scrollHeight)}print(t){this.log("info",t,!1)}clear(){$(this.target).empty()}}i.Logger=s,i.dependencies=["pkg://MonacoCore/path.js","pkg://MonacoCore/bundle/app.bundle.js"]}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){class e{constructor(t,e){this.app=e,this.name=t}preload(){return t.API.require(t.application.Antedit.extensions[this.name].dependencies)}basedir(){return`${this.app.meta().path}/extensions/${this.name}`}notify(t){return this.app.notify(t)}error(t,e){return this.app.error(t,e)}logger(){return this.app.setting.showBottomBar?this.app.showOutput(!1):this.app.showOutput(!0),this.app.logger}metadata(e){return new Promise((i,a)=>{if(!this.app.currdir)return a(t.API.throwe(__("Current folder is not found")));`${this.app.currdir.path}/${e}`.asFileHandle().read("json").then(t=>{!t.root&&this.app.currdir&&(t.root=this.app.currdir.path),i(t)}).catch(s=>{this.app.openDialog("FileDialog",{title:__("Select build directory"),root:this.app.currdir.path,mimes:["dir"]}).then(t=>{`${t.file.path}/${e}`.asFileHandle().read("json").then(e=>{e.root||(e.root=t.file.path),i(e)}).catch(t=>a(t))}).catch(e=>a(t.API.throwe(__("Unable to read meta-data"))))})})}}e.dependencies=[],t.application.Antedit.extensions={},t.application.Antedit.EditorBaseExtension=e,t.application.Antedit.extensions.EditorExtensionMaker=class extends e{constructor(t){super("EditorExtensionMaker",t)}create(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(New CodePad extension at)",file:{basename:__("ExtensionName")},mimes:["dir"]}).then(t=>this.mktpl(t.file.path,t.name))}build(e){this.logger().clear(),this.metadata("extension.json").then(async i=>{try{const a=await t.API.VFS.cat(i.javascripts.map(t=>`${i.root}/${t}`),"");await(i.root+"/build/debug/main.js").asFileHandle().setCache(a).write("text/plain"),await(i.root+"/build/debug/extension.json").asFileHandle().setCache(i.meta).write("object"),await t.API.VFS.copy(i.copies.map(t=>`${i.root}/${t}`),i.root+"/build/debug"),this.logger().info(__("Files generated in {0}",i.root+"/build/debug")),e&&e()}catch(t){return this.logger().error(__("Unable to build extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}run(){this.logger().clear(),this.metadata("extension.json").then(async e=>{if(!e||!e.meta||!e.meta.name)return this.logger().error(__("Invalid extension meta-data"));try{const i=e.root+"/build/debug/main.js";t.API.shared[i]&&delete t.API.shared[i],await t.API.requires(i),this.app.extensions[e.meta.name]&&this.app.extensions[e.meta.name].cleanup&&this.app.extensions[e.meta.name].cleanup(),this.app.extensions[e.meta.name]=new t.application.Antedit.extensions[e.meta.name](this.app);for(let t of e.meta.actions)this.app.eum.addAction(e.meta,t,(t,i)=>{this.app.loadAndRunExtensionAction(t,i,e.root+"/build")});this.app.eum.active.getEditor().trigger(e.meta.name,"editor.action.quickCommand")}catch(t){return this.logger().error(__("Unable to run extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}release(){this.logger().clear(),this.metadata("extension.json").then(async e=>{this.build(async()=>{try{await t.API.VFS.mkar(e.root+"/build/debug",`${e.root}/build/release/${e.meta.name}.zip`),this.logger().info(__("Archive created at {0}",`${e.root}/build/release/${e.meta.name}.zip`))}catch(t){return this.logger().error(__("Unable to create archive: {0}",t.stack))}})}).catch(t=>this.logger().error(__("Unable to read meta-data: {0}",t.stack)))}install(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(Select extension archive)",mimes:[".*/zip"]}).then(async t=>{try{return await this.installZip(t.file.path),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(t){return this.logger().error(__("Unable to install extension: {0}",t.stack))}})}installFromURL(){this.logger().clear(),this.app.openDialog("PromptDialog",{title:__("Enter URI"),label:__("Please enter extension URI:")}).then(async t=>{if(t)try{return await this.installZip(t),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(e){return this.app.error(__("Unable to install extension: {0}",t))}})}mktpl(e,i){const a=`${e}/${i}`,s=[a,a+"/build",a+"/build/release",a+"/build/debug"],n=[["main.tpl",`${a}/${i}.js`],["meta.tpl",a+"/extension.json"]];t.API.VFS.mkdirAll(s,!0).then(async()=>{try{return await t.API.VFS.mktpl(n,this.basedir(),t=>t.format(i,`${e}/${i}`)),this.app.currdir=a.asFileHandle(),this.app.toggleSideBar(),this.app.eum.active.openFile(`${a}/${i}.js`.asFileHandle())}catch(t){return this.logger().error(__("Unable to create extension template: {0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to create extension directories: {0}",t.stack)))}installZip(e){return new Promise(async(i,a)=>{try{await t.API.requires("os://scripts/jszip.min.js");const a=await e.asFileHandle().read("binary"),s=await JSZip.loadAsync(a),n=await s.file("extension.json").async("uint8array"),o=JSON.parse(new TextDecoder("utf-8").decode(n)),r=this.ext_dir(o.name),l=[r],h=[];for(let t in s.files)s.files[t].dir?l.push(r+"/"+t):"extension.json"!=t&&h.push(t);l.length>0?(await t.API.VFS.mkdirAll(l,!0),await this.installFiles(h,s,o)):await this.installFiles(h,s,o),i()}catch(t){a(__e(t))}})}ext_dir(t){return`${this.app.meta().path}/extensions/${t}`}installFiles(t,e,i){return 0===t.length?this.installMeta(i):new Promise(async(a,s)=>{try{const n=t.splice(0,1)[0],o=`${this.ext_dir(i.name)}/${n}`,r=await e.file(n).async("uint8array"),l=await o.asFileHandle().setCache(new Blob([r],{type:"octet/stream"})).write("text/plain");if(l.error)return s(l.error);await this.installFiles(t,e,i),a()}catch(t){s(__e(t))}})}installMeta(t){return new Promise(async(e,i)=>{const a=(this.ext_dir("")+"/extensions.json").asFileHandle();try{const s=await a.read("json"),n=[];for(let t of s)n.push(t.name);const o=n.indexOf(t.name);o>=0&&s.splice(o,1),s.push(t);try{return await a.setCache(s).write("object"),e()}catch(t){return i(__e(t))}}catch(s){try{return await a.setCache([t]).write("object"),e()}catch(t){return i(__e(t))}}})}}}(OS||(OS={}));
\ No newline at end of file
+var OS;!function(t){let e;!function(t){t.BaseEditorModel=class{constructor(t,e,i){this.container=i,this.currfile="Untitled".asFileHandle(),this.tabbar=e,this.editorSetup(i),this.app=t,this.editormux=!1,this.onstatuschange=void 0,this.on("focus",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.on("input",()=>this.editormux?(this.editormux=!1,!1):this.currfile.dirty?void 0:(this.currfile.dirty=!0,this.currfile.text+="*",this.tabbar.update(void 0))),this.on("changeCursor",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.tabbar.ontabselect=t=>this.selecteTab($(t.data.item).index()),this.tabbar.ontabclose=t=>{const e=t.data.item;return!!e&&(e.data.dirty?(this.app.openDialog("YesNoDialog",{title:__("Close tab"),text:__("Close without saving ?")}).then(t=>t?this.closeTab(e):this.focus()),!1):this.closeTab(e))}}findTabByFile(t){const e=this.tabbar.items,i=(()=>{const i=[];for(let a=0;a(t.cache=e||"",this.newTab(t))).catch(e=>this.app.error(__("Unable to open: {0}",t.path),e)):this.newTab(t):this.tabbar.selected=e}write(t){this.currfile.cache=this.getValue(),t.write("text/plain").then(e=>{t.dirty=!1,t.text=t.basename,this.tabbar.update(void 0)}).catch(e=>this.app.error(__("Unable to save file: {0}",t.path),e))}save(){return this.currfile.cache=this.getValue(),this.currfile.basename?this.write(this.currfile):this.saveAs()}saveAs(){this.app.openDialog("FileDialog",{title:__("Save as"),file:this.currfile}).then(t=>{let e=t.file.path.asFileHandle();"file"===t.file.type&&(e=e.parent()),this.currfile.setPath(`${e.path}/${t.name}`),this.write(this.currfile)})}dirties(){const t=[];for(let e of Array.from(this.tabbar.items))e.dirty&&t.push(e);return t}set contextmenuHandle(t){this.container.contextmenuHandle=t}closeAll(){this.tabbar.items=[],this.resetEditor()}isDirty(){return this.dirties().length>0}}}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends t.application.BaseEditorModel{constructor(t,e,i){super(t,e,i)}resetEditor(){this.setValue("")}getTexModel(){return{model:this.editor.getModel(),position:this.editor.getPosition()}}setTextModel(t){this.editor.setModel(t.model),t.position&&(this.editor.setPosition(t.position),this.editor.revealLineInCenter(t.position.lineNumber))}newTextModelFrom(t){if("Untitled"===t.path.toString())return{model:monaco.editor.createModel(t.cache,"textplain")};const e=monaco.Uri.parse(t.path),i=monaco.editor.getModel(e);return i?(i.setValue(t.cache),{model:i}):{model:monaco.editor.createModel(t.cache,void 0,e)}}getModes(){return monaco.languages.getLanguages().map(t=>(t.text=t.aliases[0],t))}setTheme(t){}setMode(t){monaco.editor.setModelLanguage(this.editor.getModel(),t.id),this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}editorSetup(t){this.editor=monaco.editor.create(t,{value:"",language:"textplain"}),i.modes||(i.modes={},monaco.languages.getLanguages().forEach(t=>{i.modes[t.id]=t}))}on(t,e){switch(t){case"input":this.editor.onDidChangeModelContent(e);break;case"focus":this.editor.onDidFocusEditorText(e);break;case"changeCursor":this.editor.onDidChangeCursorPosition(e)}}resize(){this.editor&&this.editor.layout()}focus(){this.editor&&this.editor.focus()}getModeForPath(t){return{}}getEditorStatus(){const t=this.editor.getPosition(),e=i.modes[this.editor.getModel().getModeId()];return{row:t.lineNumber,column:t.column,line:this.editor.getModel().getLineCount(),langmode:{text:e.aliases[0],mode:e},file:this.currfile.path}}getValue(){return this.editor.getValue()}setValue(t){this.editor.setValue(t)}getEditor(){return this.editor}}e.MonacoEditorModel=i}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends e.BaseApplication{constructor(t){super("Antedit",t),this.currdir=void 0}main(){this.extensions={},this.eum=new a,this.fileview=this.find("fileview"),this.sidebar=this.find("sidebar"),this.bottombar=this.find("bottombar"),this.langstat=this.find("langstat"),this.editorstat=this.find("editorstat"),this.filestat=this.find("current-file-lbl"),this.logger=new s(this.find("output-tab")),this.split_mode=!0,this.fileview.fetch=t=>new Promise((async function(e,i){let a;a="string"==typeof t?t.asFileHandle():t;try{const t=await a.read();return t.error?i(t.error):e(t.result)}catch(t){return i(__e(t))}}));let e="Untitled".asFileHandle();this.args&&this.args.length>0&&(this.addRecent(this.args[0].path),"dir"===this.args[0].type?this.currdir=this.args[0].path.asFileHandle():(e=this.args[0].path.asFileHandle(),this.currdir=e.parent())),this.setting.recent||(this.setting.recent=[]);const i=this.find("wrapper");$(i).css("visibility","hidden"),monaco.editor.setTheme("vs-dark"),this.eum.add(new t.application.MonacoEditorModel(this,this.find("left-tabbar"),this.find("left-editorarea"))).add(new t.application.MonacoEditorModel(this,this.find("right-tabbar"),this.find("right-editorarea"))),this.eum.onstatuschange=t=>this.updateStatus(t),$(i).css("visibility","visible"),this.setup(),this.eum.active.openFile(e)}setup(){this.fileview.onfileopen=t=>{if(t.data&&t.data.path&&"dir"!==t.data.type)return this.addRecent(t.data.path),this.eum.active.openFile(t.data.path.asFileHandle())},this.fileview.onfileselect=t=>{t.data&&t.data.path&&"dir"!==t.data.type&&this.eum.active.selectFile(t.data.path)},this.on("resize",()=>this.eum.resize()),this.on("focus",()=>this.eum.active.focus()),this.fileview.contextmenuHandle=(t,e)=>(e.items=[{text:"__(New file)",id:"new"},{text:"__(New folder)",id:"newdir"},{text:"__(Rename)",id:"rename"},{text:"__(Delete)",id:"delete"}],e.onmenuselect=t=>this.ctxFileMenuHandle(t),e.show(t)),this.bindKey("ALT-N",()=>this.menuAction("new")),this.bindKey("ALT-O",()=>this.menuAction("open")),this.bindKey("ALT-F",()=>this.menuAction("opendir")),this.bindKey("CTRL-S",()=>this.menuAction("save")),this.bindKey("ALT-W",()=>this.menuAction("saveas")),this.fileview.ondragndrop=t=>{const e=t.data.from.data.path.asFileHandle(),i=t.data.to.data.path;return e.move(`${i}/${e.basename}`).then((function(a){const s=i,n=e.parent().path;s.lengththis.error(__("Unable to move file/folder"),t))},this.on("filechange",t=>{let{path:e}=t.file;return"file"===t.type&&({path:e}=t.file.parent()),this.fileview.update(e)}),this.find("logger-clear").onbtclick=()=>{this.logger.clear()},void 0===this.setting.showBottomBar&&(this.setting.showBottomBar=!1);const t={name:"Editor",text:__("Editor")},e={name:"langmode",text:__("Change language mode"),shortcut:"CTRL-K"};this.eum.addAction(t,e,async t=>{try{const t=await this.openDialog("SelectionDialog",{title:__("Select language"),data:this.eum.active.getModes()});this.eum.active.setMode(t)}catch(t){}}),this.loadExtensionMetaData(),this.toggleSideBar(),this.toggleSplitMode(),this.applyAllSetting()}updateStatus(t){t||(t=this.eum.active.getEditorStatus()),this.editorstat.text=__("Row {0}, col {1}, lines: {2}",t.row,t.column,t.line),t.langmode&&(this.langstat.text=t.langmode.text),this.filestat.text=t.file;let e=this.scheme;e.apptitle!=t.file&&(e.apptitle=t.file)}toggleSideBar(){this.currdir?($(this.sidebar).show(),this.fileview.path=this.currdir.path):$(this.sidebar).hide(),this.trigger("resize")}showOutput(t=!1){t&&this.showBottomBar(!0),this.bottombar.selectedIndex=0}applySetting(t){"showBottomBar"==t&&this.showBottomBar(this.setting.showBottomBar)}showBottomBar(t){this.setting.showBottomBar=t,t?$(this.bottombar).show():$(this.bottombar).hide(),this.trigger("resize")}toggleBottomBar(){this.showBottomBar(!this.setting.showBottomBar)}toggleSplitMode(){const t=this.find("right-panel"),e=this.eum.editors[1],i=this.eum.editors[0];if(this.split_mode){if(e.isDirty())return void this.notify(__("Unable to disable split view: Please save changes of modified files on the right panel"));e.closeAll(),$(t).hide(),this.split_mode=!1,i.focus()}else $(t).show(),this.split_mode=!0,e.openFile("Untitled".asFileHandle()),e.focus();this.trigger("resize")}fileMenu(){const t=this.setting.recent.map(t=>({text:t}));return{text:__("File"),nodes:[{text:__("New"),dataid:"new",shortcut:"A-N"},{text:__("Open Recent"),dataid:"recent",nodes:t,onchildselect:(t,e)=>{const i=t.data.item.data.text.asFileHandle();i.onready().then(t=>{t&&("dir"==t.type?(this.currdir=i,this.toggleSideBar()):this.eum.active.openFile(i))})}},{text:__("Open"),dataid:"open",shortcut:"A-O"},{text:__("Open Folder"),dataid:"opendir",shortcut:"A-F"},{text:__("Save"),dataid:"save",shortcut:"C-S"},{text:__("Save as"),dataid:"saveas",shortcut:"A-W"}],onchildselect:(t,e)=>this.menuAction(t.data.item.data.dataid,e)}}ctxFileMenuHandle(t){const e=t.data.item;if(!e)return;const i=e.data;if(!i)return;let a=this.fileview.selectedFile,s=this.currdir;switch(a&&"dir"===a.type&&(s=a.path.asFileHandle()),a&&"file"===a.type&&(s=a.path.asFileHandle().parent()),i.id){case"new":if(!s)return;this.openDialog("PromptDialog",{title:"__(New file)",label:"__(File name)"}).then(async t=>{const e=`${s.path}/${t}`.asFileHandle();try{return await e.write("text/plain"),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",t.stack),t)}});break;case"newdir":if(!s)return;this.openDialog("PromptDialog",{title:"__(New folder)",label:"__(Folder name)"}).then(async t=>{try{return await s.mk(t),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",s.path),t)}});break;case"rename":if(!a)return;this.openDialog("PromptDialog",{title:"__(Rename)",label:"__(File name)",value:a.filename}).then(async t=>{if(t!==a.filename){a=a.path.asFileHandle(),s=a.parent();try{return await a.move(`${s.path}/${t}`),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to rename: {0}",a.path),t)}}});break;case"delete":if(!a)return;this.openDialog("YesNoDialog",{title:"__(Delete)",iconclass:"fa fa-question-circle",text:__("Do you really want to delete: {0}?",a.filename)}).then(async t=>{if(t){a=a.path.asFileHandle(),s=a.parent();try{return await a.remove(),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to delete: {0}",a.path),t)}}})}}addRecent(t){this.setting.recent||(this.setting.recent=[]),this.setting.recent.includes(t)||(this.setting.recent.push(t),this.setting.recent.length>10&&(this.setting.recent=this.setting.recent.slice(0,10)))}menuAction(t,e){let i=this;switch(e&&(i=e),t){case"new":return i.eum.active.openFile("Untitled".asFileHandle());case"open":return i.openDialog("FileDialog",{title:__("Open file"),mimes:Array.from(i.meta().mimes).filter(t=>"dir"!==t)}).then(t=>{this.addRecent(t.file.path),i.eum.active.openFile(t.file.path.asFileHandle())});case"opendir":return i.openDialog("FileDialog",{title:__("Open folder"),mimes:["dir"]}).then((function(t){return i.addRecent(t.file.path),i.currdir=t.file.path.asFileHandle(),i.toggleSideBar()}));case"save":return i.eum.active.save();case"saveas":return i.eum.active.saveAs();default:return console.log(t)}}cleanup(t){let e;const i=this.eum.dirties();if(0!==i.length)t.preventDefault(),this.openDialog("YesNoDialog",{title:"__(Quit)",text:__("Ignore all unsaved files: {0} ?",(()=>{const t=[];for(e of Array.from(i))t.push(e.filename);return t})().join(", "))}).then(t=>{if(t){for(e of Array.from(i))e.dirty=!1;return this.quit(!1)}});else for(let t in this.extensions)this.extensions[t]&&this.extensions[t].cleanup&&this.extensions[t].cleanup()}menu(){return[this.fileMenu(),{text:"__(View)",nodes:[{text:"__(Toggle bottom bar)",dataid:"bottombar"},{text:"__(Toggle split view)",dataid:"splitview"}],onchildselect:(t,e)=>{switch(t.data.item.data.dataid){case"bottombar":return this.toggleBottomBar();case"splitview":return this.toggleSplitMode()}}}]}loadExtensionMetaData(){this.loadExtensionMetaFromFile(this.meta().path+"/extensions/extensions.json").catch(t=>this.error(__("Cannot load extension meta data"),t))}loadExtensionMetaFromFile(t){return new Promise((e,i)=>{t.asFileHandle().read("json").then(t=>{for(let e of t)for(let t of e.actions)this.eum.addAction(e,t,(t,i)=>{this.loadAndRunExtensionAction(t,i,e.root)});e()}).catch(t=>{i(__e(t))})})}loadAndRunExtensionAction(t,e,a){if(i.extensions[t])this.runExtensionAction(t,e);else{let i=`${this.meta().path}/extensions/${t}/main.js`;a&&(i=a+"/main.js"),this._api.requires(i,!0).then(()=>this.runExtensionAction(t,e)).catch(e=>this.error(__("unable to load extension: {0}",t),e))}}runExtensionAction(t,e){if(!this.extensions[t]){if(!i.extensions[t])return this.error(__("Unable to find extension: {0}",t));this.extensions[t]=new i.extensions[t](this)}if(!this.extensions[t][e])return this.error(__("Unable to find action: {0}",e));this.extensions[t].preload().then(()=>this.extensions[t][e]()).catch(t=>this.error(__("Unable to preload extension"),t))}}e.Antedit=i;class a{constructor(){this.active_editor=void 0,this.models=[]}get editors(){return this.models}set contextmenuHandle(t){for(let e of this.models)e.contextmenuHandle=t}get active(){return this.active_editor}add(t){return this.models.push(t),this.active_editor||(this.active_editor=t),t.on("focus",()=>{this.active_editor=t}),this}addAction(t,e,i){const a={id:`${t.name}:${e.name}`,label:`${t.text.__()}: ${e.text.__()}`,keybindings:[],precondition:null,keybindingContext:null,contextMenuGroupId:t.name,run:()=>i(t.name,e.name)};if(e.shortcut){const t=e.shortcut.split("-");let i=0;for(const e of t)switch(e){case"CTRL":i|=monaco.KeyMod.CtrlCmd;break;case"ALT":i|=monaco.KeyMod.Alt;break;case"SHIFT":i|=monaco.KeyMod.Shift;break;case"SUPPER":i|=monaco.KeyMod.WinCtrl;break;default:const t="KEY_"+e;monaco.KeyCode[t]?i|=monaco.KeyCode[t]:i=0}0!=i&&a.keybindings.push(i)}for(let t of this.models){const e=t.getEditor();e.getAction(a.id)||e.addAction(a)}}set onstatuschange(t){for(let e of this.models)e.onstatuschange=t}dirties(){let t=[];for(let e of this.models)t=t.concat(e.dirties());return t}resize(){for(let t of this.models)t.resize()}}class s{constructor(t){this.target=t}info(t){this.log("info",t,!0)}warn(t){this.log("warn",t,!0)}error(t){this.log("error",t,!0)}log(t,e,i){let a=$("
").attr("class","code-pad-log-"+t);if(i){let t=new Date,i=t.getDate()+"/"+(t.getMonth()+1)+"/"+t.getFullYear()+" "+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds();a.text(`[${i}]: ${e.__()}`)}else a.text(e.__());$(this.target).append(a),$(this.target).scrollTop($(this.target)[0].scrollHeight)}print(t){this.log("info",t,!1)}clear(){$(this.target).empty()}}i.Logger=s,i.dependencies=["pkg://MonacoCore/path.js","pkg://MonacoCore/bundle/app.bundle.js"]}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){class e{constructor(t,e){this.app=e,this.name=t}preload(){return t.API.require(t.application.Antedit.extensions[this.name].dependencies)}basedir(){return`${this.app.meta().path}/extensions/${this.name}`}notify(t){return this.app.notify(t)}error(t,e){return this.app.error(t,e)}logger(){return this.app.setting.showBottomBar?this.app.showOutput(!1):this.app.showOutput(!0),this.app.logger}metadata(e){return new Promise((i,a)=>{if(!this.app.currdir)return a(t.API.throwe(__("Current folder is not found")));`${this.app.currdir.path}/${e}`.asFileHandle().read("json").then(t=>{!t.root&&this.app.currdir&&(t.root=this.app.currdir.path),i(t)}).catch(s=>{this.app.openDialog("FileDialog",{title:__("Select build directory"),root:this.app.currdir.path,mimes:["dir"]}).then(t=>{`${t.file.path}/${e}`.asFileHandle().read("json").then(e=>{e.root||(e.root=t.file.path),i(e)}).catch(t=>a(t))}).catch(e=>a(t.API.throwe(__("Unable to read meta-data"))))})})}}e.dependencies=[],t.application.Antedit.extensions={},t.application.Antedit.EditorBaseExtension=e,t.application.Antedit.extensions.EditorExtensionMaker=class extends e{constructor(t){super("EditorExtensionMaker",t)}create(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(New CodePad extension at)",file:{basename:__("ExtensionName")},mimes:["dir"]}).then(t=>this.mktpl(t.file.path,t.name))}build(e){this.logger().clear(),this.metadata("extension.json").then(async i=>{try{const a=await t.API.VFS.cat(i.javascripts.map(t=>`${i.root}/${t}`),"");await(i.root+"/build/debug/main.js").asFileHandle().setCache(a).write("text/plain"),await(i.root+"/build/debug/extension.json").asFileHandle().setCache(i.meta).write("object"),await t.API.VFS.copy(i.copies.map(t=>`${i.root}/${t}`),i.root+"/build/debug"),this.logger().info(__("Files generated in {0}",i.root+"/build/debug")),e&&e()}catch(t){return this.logger().error(__("Unable to build extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}run(){this.logger().clear(),this.metadata("extension.json").then(async e=>{if(!e||!e.meta||!e.meta.name)return this.logger().error(__("Invalid extension meta-data"));try{const i=e.root+"/build/debug/main.js";t.API.shared[i]&&delete t.API.shared[i],await t.API.requires(i),this.app.extensions[e.meta.name]&&this.app.extensions[e.meta.name].cleanup&&this.app.extensions[e.meta.name].cleanup(),this.app.extensions[e.meta.name]=new t.application.Antedit.extensions[e.meta.name](this.app);for(let t of e.meta.actions)this.app.eum.addAction(e.meta,t,(t,i)=>{this.app.loadAndRunExtensionAction(t,i,e.root+"/build")});this.app.eum.active.getEditor().trigger(e.meta.name,"editor.action.quickCommand")}catch(t){return this.logger().error(__("Unable to run extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}release(){this.logger().clear(),this.metadata("extension.json").then(async e=>{this.build(async()=>{try{await t.API.VFS.mkar(e.root+"/build/debug",`${e.root}/build/release/${e.meta.name}.zip`),this.logger().info(__("Archive created at {0}",`${e.root}/build/release/${e.meta.name}.zip`))}catch(t){return this.logger().error(__("Unable to create archive: {0}",t.stack))}})}).catch(t=>this.logger().error(__("Unable to read meta-data: {0}",t.stack)))}install(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(Select extension archive)",mimes:[".*/zip"]}).then(async t=>{try{return await this.installZip(t.file.path),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(t){return this.logger().error(__("Unable to install extension: {0}",t.stack))}})}installFromURL(){this.logger().clear(),this.app.openDialog("PromptDialog",{title:__("Enter URI"),label:__("Please enter extension URI:")}).then(async t=>{if(t)try{return await this.installZip(t),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(e){return this.app.error(__("Unable to install extension: {0}",t))}})}mktpl(e,i){const a=`${e}/${i}`,s=[a,a+"/build",a+"/build/release",a+"/build/debug"],n=[["main.tpl",`${a}/${i}.js`],["meta.tpl",a+"/extension.json"]];t.API.VFS.mkdirAll(s,!0).then(async()=>{try{return await t.API.VFS.mktpl(n,this.basedir(),t=>t.format(i,`${e}/${i}`)),this.app.currdir=a.asFileHandle(),this.app.toggleSideBar(),this.app.eum.active.openFile(`${a}/${i}.js`.asFileHandle())}catch(t){return this.logger().error(__("Unable to create extension template: {0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to create extension directories: {0}",t.stack)))}installZip(e){return new Promise(async(i,a)=>{try{await t.API.requires("os://scripts/jszip.min.js");const a=await e.asFileHandle().read("binary"),s=await JSZip.loadAsync(a),n=await s.file("extension.json").async("uint8array"),o=JSON.parse(new TextDecoder("utf-8").decode(n)),r=this.ext_dir(o.name),l=[r],h=[];for(let t in s.files)s.files[t].dir?l.push(r+"/"+t):"extension.json"!=t&&h.push(t);l.length>0?(await t.API.VFS.mkdirAll(l,!0),await this.installFiles(h,s,o)):await this.installFiles(h,s,o),i()}catch(t){a(__e(t))}})}ext_dir(t){return`${this.app.meta().path}/extensions/${t}`}installFiles(t,e,i){return 0===t.length?this.installMeta(i):new Promise(async(a,s)=>{try{const n=t.splice(0,1)[0],o=`${this.ext_dir(i.name)}/${n}`,r=await e.file(n).async("uint8array"),l=await o.asFileHandle().setCache(new Blob([r],{type:"octet/stream"})).write("text/plain");if(l.error)return s(l.error);await this.installFiles(t,e,i),a()}catch(t){s(__e(t))}})}installMeta(t){return new Promise(async(e,i)=>{const a=(this.ext_dir("")+"/extensions.json").asFileHandle();try{const s=await a.read("json"),n=[];for(let t of s)n.push(t.name);const o=n.indexOf(t.name);o>=0&&s.splice(o,1),s.push(t);try{return await a.setCache(s).write("object"),e()}catch(t){return i(__e(t))}}catch(s){try{return await a.setCache([t]).write("object"),e()}catch(t){return i(__e(t))}}})}}}(OS||(OS={}));
\ No newline at end of file
diff --git a/Antedit/build/debug/package.json b/Antedit/build/debug/package.json
index 5d401c0..e01e187 100644
--- a/Antedit/build/debug/package.json
+++ b/Antedit/build/debug/package.json
@@ -7,7 +7,7 @@
         "author": "Xuan Sang LE",
         "email": "mrsang@iohub.dev"
     },
-    "version":"0.1.7-a",
+    "version":"0.1.8-a",
     "category":"Development",
     "iconclass":"bi bi-journal-code",
     "mimes":[
diff --git a/Antedit/build/release/Antedit.zip b/Antedit/build/release/Antedit.zip
index 395d066589c96a62d27ea525f59b81d6b799eca8..77218f9b20688819826b60c2f4af91b461610a32 100644
GIT binary patch
delta 7287
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
F{9i{wiD3W$

diff --git a/Antedit/package.json b/Antedit/package.json
index 5d401c0..e01e187 100644
--- a/Antedit/package.json
+++ b/Antedit/package.json
@@ -7,7 +7,7 @@
         "author": "Xuan Sang LE",
         "email": "mrsang@iohub.dev"
     },
-    "version":"0.1.7-a",
+    "version":"0.1.8-a",
     "category":"Development",
     "iconclass":"bi bi-journal-code",
     "mimes":[
diff --git a/Antedit/ts/MonacoEditorModel.ts b/Antedit/ts/MonacoEditorModel.ts
index cda1d51..2b379c4 100644
--- a/Antedit/ts/MonacoEditorModel.ts
+++ b/Antedit/ts/MonacoEditorModel.ts
@@ -102,7 +102,10 @@ namespace OS {
             getModes(): GenericObject[] {
                 //const list = [];
                 //return list;
-                return monaco.languages.getLanguages();
+                return monaco.languages.getLanguages().map(e=>{
+                    (e as GenericObject).text = e.aliases[0];
+                    return e;
+                });
             }
 
 
@@ -131,6 +134,9 @@ namespace OS {
              * @memberof MonacoEditorModel
              */
             setMode(m: GenericObject): void {
+                monaco.editor.setModelLanguage(this.editor.getModel(), m.id);
+                if(this.onstatuschange)
+                    this.onstatuschange(this.getEditorStatus());
             }
 
 
diff --git a/Antedit/ts/main.ts b/Antedit/ts/main.ts
index a90737a..b7cb4fb 100644
--- a/Antedit/ts/main.ts
+++ b/Antedit/ts/main.ts
@@ -216,14 +216,6 @@ namespace OS {
                 $(wrapper).css('visibility', 'visible');
                 this.setup();
                 this.eum.active.openFile(file);
-                
-                /*this.load(new Promise((resolve, reject) => {
-                    require.config({ paths: { 'vs': "pkg://MonacoCore/vs".asFileHandle().getlink() }});
-                    require(['vs/editor/editor.main'], () => {
-                        
-                        resolve(undefined);
-                    });
-                }))*/
             }
 
             /**
@@ -321,7 +313,29 @@ namespace OS {
                 if (this.setting.showBottomBar === undefined) {
                     this.setting.showBottomBar = false;
                 }
+                //TODO: support change editor model languages
+                const extension = {
+                    name: "Editor",
+                    text: __("Editor")
+                };
+                const action = {
+                    name: "langmode",
+                    text: __("Change language mode"),
+                    shortcut: 'CTRL-K'
+                }
+                this.eum.addAction(extension, action, async (e) =>
+                {
+                    try{
+                        const data = await this.openDialog("SelectionDialog", {
+                            "title": __("Select language"),
+                            data: this.eum.active.getModes()
+                        });
+                        this.eum.active.setMode(data);
+                    }catch(e)
+                    {
 
+                    }
+                });
                 this.loadExtensionMetaData();
                 this.toggleSideBar();
                 this.toggleSplitMode();