mirror of
https://github.com/antos-rde/antosdk-apps.git
synced 2024-12-25 11:48:21 +01:00
Antedit v0.2.0
- fix compatible bug with new Monaco version - the editor now can support diff view of two files
This commit is contained in:
parent
21f2e58768
commit
c994d1c738
@ -6,6 +6,7 @@ The editor functionality can be extended by its extension mechanism.
|
||||
Extension can be developed/released/isntalled by the editor itself.
|
||||
|
||||
### Change logs
|
||||
- 0.2.0-b: Support diff mode in editor + fix new Monaco version compatible bug
|
||||
- 0.1.17-b: Fix extension keybinding bug with the new monaco editor
|
||||
- 0.1.16-b: use the new version of monaco editor
|
||||
- 0.1.14-b: improve output log display
|
||||
|
@ -6,6 +6,7 @@ The editor functionality can be extended by its extension mechanism.
|
||||
Extension can be developed/released/isntalled by the editor itself.
|
||||
|
||||
### Change logs
|
||||
- 0.2.0-b: Support diff mode in editor + fix new Monaco version compatible bug
|
||||
- 0.1.17-b: Fix extension keybinding bug with the new monaco editor
|
||||
- 0.1.16-b: use the new version of monaco editor
|
||||
- 0.1.14-b: improve output log display
|
||||
|
File diff suppressed because one or more lines are too long
@ -7,7 +7,7 @@
|
||||
"author": "Xuan Sang LE",
|
||||
"email": "mrsang@iohub.dev"
|
||||
},
|
||||
"version": "0.1.17-b",
|
||||
"version": "0.2.0-b",
|
||||
"category": "Development",
|
||||
"iconclass": "bi bi-journal-code",
|
||||
"mimes": [
|
||||
|
Binary file not shown.
@ -7,7 +7,7 @@
|
||||
"author": "Xuan Sang LE",
|
||||
"email": "mrsang@iohub.dev"
|
||||
},
|
||||
"version": "0.1.17-b",
|
||||
"version": "0.2.0-b",
|
||||
"category": "Development",
|
||||
"iconclass": "bi bi-journal-code",
|
||||
"mimes": [
|
||||
|
@ -1,12 +1,90 @@
|
||||
namespace OS {
|
||||
//declare var $:any;
|
||||
|
||||
export namespace API
|
||||
{
|
||||
export namespace VFS
|
||||
{
|
||||
export class DiffEditorFileHandle extends OS.API.VFS.BaseFileHandle
|
||||
{
|
||||
text: string;
|
||||
textModel:any;
|
||||
selected: boolean;
|
||||
|
||||
constructor(files: OS.API.VFS.BaseFileHandle[]) {
|
||||
super("");
|
||||
this.path = `${files[0].path} -> ${files[1].path}`;
|
||||
this.cache = files;
|
||||
this.basename = `${files[0].basename} -> ${files[1].basename}`;
|
||||
this.info = {
|
||||
type: "file",
|
||||
mime: undefined,
|
||||
size: 0,
|
||||
name: this.basename,
|
||||
path: this.path
|
||||
};
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
meta(): Promise<any> {
|
||||
return new Promise(async (resolve, reject) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Promise.all([this.cache[0].meta(), this.cache[1].meta]);
|
||||
resolve({
|
||||
result: this.info,
|
||||
error: false,
|
||||
});
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
reject(e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
protected _rd(_t: string): Promise<any> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try
|
||||
{
|
||||
this.cache[0].cache = await this.cache[0].read();
|
||||
this.cache[1].cache = await this.cache[1].read();
|
||||
resolve(this.cache);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected _wr(t: string, d: any): Promise<any> {
|
||||
this.cache = d;
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
resolve({
|
||||
result: true,
|
||||
error: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
setPath(s: string)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace application {
|
||||
|
||||
/**
|
||||
* Extends the [[RemoteFileHandle]] interface with some useful
|
||||
* properties used by [[BaseEditorModel]]
|
||||
*/
|
||||
export type EditorFileHandle = API.VFS.RemoteFileHandle & {
|
||||
export type EditorFileHandle = OS.API.VFS.BaseFileHandle & {
|
||||
/**
|
||||
* The text will be displayed on the tab bar when opened
|
||||
*
|
||||
@ -81,7 +159,7 @@ namespace OS {
|
||||
* @type {boolean}
|
||||
* @memberof BaseEditorModel
|
||||
*/
|
||||
private editormux: boolean;
|
||||
//private editormux: boolean;
|
||||
|
||||
|
||||
/**
|
||||
@ -98,7 +176,7 @@ namespace OS {
|
||||
this.tabbar = tabbar;
|
||||
this.editorSetup(editorarea);
|
||||
this.app = app;
|
||||
this.editormux = false;
|
||||
// this.editormux = false;
|
||||
this.onstatuschange = undefined;
|
||||
|
||||
this.on("focus", () => {
|
||||
@ -106,11 +184,14 @@ namespace OS {
|
||||
this.onstatuschange(this.getEditorStatus());
|
||||
});
|
||||
this.on("input", () => {
|
||||
if (this.editormux) {
|
||||
// console.log(this.editormux, this.currfile.dirty);
|
||||
/*if (this.editormux) {
|
||||
this.editormux = false;
|
||||
console.log("set editor mux to false");
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
if (!this.currfile.dirty) {
|
||||
console.log("dirty", this.currfile.path);
|
||||
this.currfile.dirty = true;
|
||||
this.currfile.text += "*";
|
||||
return this.tabbar.update(undefined);
|
||||
@ -232,10 +313,8 @@ namespace OS {
|
||||
this.currfile = file;
|
||||
}
|
||||
|
||||
this.editormux = true;
|
||||
// this.editormux = true;
|
||||
this.setTextModel(file.textModel);
|
||||
if (this.onstatuschange)
|
||||
this.onstatuschange(this.getEditorStatus());
|
||||
this.focus();
|
||||
}
|
||||
|
||||
@ -274,7 +353,6 @@ namespace OS {
|
||||
this.newTab(file);
|
||||
return;
|
||||
}
|
||||
|
||||
file.read()
|
||||
.then((d) => {
|
||||
file.cache = d || "";
|
||||
@ -295,16 +373,16 @@ namespace OS {
|
||||
* @param {EditorFileHandle} file
|
||||
* @memberof BaseEditorModel
|
||||
*/
|
||||
private write(file: EditorFileHandle): void {
|
||||
private write(): void {
|
||||
this.currfile.cache = this.getValue();
|
||||
file.write("text/plain")
|
||||
this.currfile.write("text/plain")
|
||||
.then((d) => {
|
||||
file.dirty = false;
|
||||
file.text = file.basename;
|
||||
this.currfile.dirty = false;
|
||||
this.currfile.text = this.currfile.basename;
|
||||
this.tabbar.update(undefined);
|
||||
})
|
||||
.catch((e) =>
|
||||
this.app.error(__("Unable to save file: {0}", file.path), e)
|
||||
this.app.error(__("Unable to save file: {0}", this.currfile.path), e)
|
||||
);
|
||||
}
|
||||
|
||||
@ -318,7 +396,7 @@ namespace OS {
|
||||
save(): void {
|
||||
this.currfile.cache = this.getValue();
|
||||
if (this.currfile.basename) {
|
||||
return this.write(this.currfile);
|
||||
return this.write();
|
||||
}
|
||||
return this.saveAs();
|
||||
}
|
||||
@ -339,7 +417,7 @@ namespace OS {
|
||||
d = d.parent();
|
||||
}
|
||||
this.currfile.setPath(`${d.path}/${f.name}`);
|
||||
this.write(this.currfile);
|
||||
this.write();
|
||||
});
|
||||
}
|
||||
|
||||
@ -376,6 +454,7 @@ namespace OS {
|
||||
*/
|
||||
closeAll(): void {
|
||||
this.tabbar.items = [];
|
||||
this.openFile("Untitled".asFileHandle() as EditorFileHandle);
|
||||
this.resetEditor();
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,6 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
protected resetEditor(): void {
|
||||
this.setValue("");
|
||||
// TODO create new textmodel
|
||||
}
|
||||
|
||||
|
||||
@ -76,20 +74,32 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
protected newTextModelFrom(file: EditorFileHandle): any {
|
||||
if(file.path.toString() === "Untitled") {
|
||||
if(Array.isArray(file.cache))
|
||||
{
|
||||
return {
|
||||
model: monaco.editor.createModel(file.cache, "textplain")
|
||||
model: {
|
||||
original: this.newTextModelFrom(file.cache[0]).model,
|
||||
modified: this.newTextModelFrom(file.cache[1]).model
|
||||
}
|
||||
}
|
||||
}
|
||||
const uri = monaco.Uri.parse(file.protocol + "://antedit/file/" + file.genealogy.join("/"));
|
||||
const model = monaco.editor.getModel(uri);
|
||||
if(model)
|
||||
else
|
||||
{
|
||||
model.setValue(file.cache);
|
||||
return { model: model };
|
||||
}
|
||||
return {
|
||||
model: monaco.editor.createModel(file.cache, undefined, uri)
|
||||
if(file.path.toString() === "Untitled") {
|
||||
return {
|
||||
model: monaco.editor.createModel(file.cache, "textplain")
|
||||
}
|
||||
}
|
||||
const uri = monaco.Uri.parse(file.protocol + "://antedit/file/" + file.genealogy.join("/"));
|
||||
const model = monaco.editor.getModel(uri);
|
||||
if(model)
|
||||
{
|
||||
model.setValue(file.cache);
|
||||
return { model: model };
|
||||
}
|
||||
return {
|
||||
model: monaco.editor.createModel(file.cache, undefined, uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +113,11 @@ namespace OS {
|
||||
//const list = [];
|
||||
//return list;
|
||||
return monaco.languages.getLanguages().map(e=>{
|
||||
(e as GenericObject<any>).text = e.aliases[0];
|
||||
const item = (e as GenericObject<any>);
|
||||
if(e.aliases)
|
||||
item.text = e.aliases[0];
|
||||
else
|
||||
item.text = e.id;
|
||||
return e;
|
||||
});
|
||||
}
|
||||
@ -134,12 +148,24 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
setMode(m: GenericObject<any>): void {
|
||||
monaco.editor.setModelLanguage(this.editor.getModel(), m.id);
|
||||
if(this.editor == this._code_editor)
|
||||
{
|
||||
monaco.editor.setModelLanguage(this.editor.getModel(), m.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const model of this.editor.getModel())
|
||||
{
|
||||
monaco.editor.setModelLanguage(model, m.id);
|
||||
}
|
||||
}
|
||||
if(this.onstatuschange)
|
||||
this.onstatuschange(this.getEditorStatus());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private code_container: JQuery<HTMLElement>;
|
||||
private diff_container: JQuery<HTMLElement>;
|
||||
|
||||
/**
|
||||
* Reference to the editor instance
|
||||
@ -148,7 +174,30 @@ namespace OS {
|
||||
* @type {GenericObject<any>}
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
private editor: GenericObject<any>;
|
||||
private _code_editor: GenericObject<any>;
|
||||
/**
|
||||
* Reference to the diff editor instance
|
||||
*
|
||||
* @private
|
||||
* @type {GenericObject<any>}
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
private _diff_editor: GenericObject<any>;
|
||||
/**
|
||||
* Getter get current editor instance based on current file
|
||||
*
|
||||
* @private
|
||||
* @type {GenericObject<any>}
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
private get editor(): GenericObject<any>
|
||||
{
|
||||
if(Array.isArray(this.currfile.cache))
|
||||
{
|
||||
return this._diff_editor;
|
||||
}
|
||||
return this._code_editor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -159,10 +208,24 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
protected editorSetup(el: HTMLElement): void {
|
||||
this.editor = monaco.editor.create(el, {
|
||||
// create two editor instancs for code mode and diff mode
|
||||
this.code_container = $("<div />")
|
||||
.css("width", "100%")
|
||||
.css("height", "100%");
|
||||
this.diff_container = $("<div />")
|
||||
.css("width", "100%")
|
||||
.css("height", "100%")
|
||||
.css("display", "none");
|
||||
$(el).append(this.code_container);
|
||||
$(el).append(this.diff_container);
|
||||
this._code_editor = monaco.editor.create(this.code_container[0], {
|
||||
value: "",
|
||||
language: 'textplain'
|
||||
});
|
||||
this._diff_editor = monaco.editor.createDiffEditor(this.diff_container[0],{
|
||||
readOnly: true
|
||||
});
|
||||
|
||||
if(!MonacoEditorModel.modes)
|
||||
{
|
||||
MonacoEditorModel.modes = {};
|
||||
@ -183,13 +246,17 @@ namespace OS {
|
||||
on(evt_str: string, callback: () => void): void {
|
||||
switch (evt_str) {
|
||||
case "input":
|
||||
this.editor.onDidChangeModelContent(callback);
|
||||
this._code_editor.onDidChangeModelContent(callback);
|
||||
break;
|
||||
case "focus":
|
||||
this.editor.onDidFocusEditorText(callback);
|
||||
this._code_editor.onDidFocusEditorText(callback);
|
||||
this._diff_editor.getOriginalEditor().onDidFocusEditorText(callback);
|
||||
this._diff_editor.getModifiedEditor().onDidFocusEditorText(callback);
|
||||
break;
|
||||
case "changeCursor":
|
||||
this.editor.onDidChangeCursorPosition(callback);
|
||||
this._code_editor.onDidChangeCursorPosition(callback);
|
||||
this._diff_editor.getOriginalEditor().onDidChangeCursorPosition(callback);
|
||||
this._diff_editor.getModifiedEditor().onDidChangeCursorPosition(callback);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -214,8 +281,21 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
focus(): void {
|
||||
if(Array.isArray(this.currfile.cache))
|
||||
{
|
||||
this.code_container.hide();
|
||||
this.diff_container.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.code_container.show();
|
||||
this.diff_container.hide();
|
||||
}
|
||||
if(this.editor)
|
||||
{
|
||||
this.editor.layout();
|
||||
this.editor.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -238,14 +318,34 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
getEditorStatus(): GenericObject<any> {
|
||||
const pos = this.editor.getPosition();
|
||||
const mode = MonacoEditorModel.modes[this.editor.getModel().getLanguageId()];
|
||||
|
||||
let ed = undefined;
|
||||
if(this.editor == this._code_editor)
|
||||
{
|
||||
ed = this.editor;
|
||||
}
|
||||
else
|
||||
{
|
||||
ed = this.editor.getOriginalEditor();
|
||||
if(this.editor.getModifiedEditor().hasTextFocus())
|
||||
{
|
||||
ed = this.editor.getModifiedEditor();
|
||||
}
|
||||
}
|
||||
|
||||
const pos = ed.getPosition();
|
||||
let mode = undefined;
|
||||
const model = ed.getModel();
|
||||
if(model)
|
||||
{
|
||||
mode = MonacoEditorModel.modes[model.getLanguageId()];
|
||||
}
|
||||
return {
|
||||
row: pos.lineNumber,
|
||||
column: pos.column,
|
||||
line: this.editor.getModel().getLineCount(),
|
||||
line: model?model.getLineCount(): 0,
|
||||
langmode: {
|
||||
text: mode.aliases[0],
|
||||
text: mode?mode.aliases[0]: "",
|
||||
mode: mode
|
||||
},
|
||||
file: this.currfile.path
|
||||
@ -260,7 +360,9 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
getValue(): string {
|
||||
return this.editor.getValue();
|
||||
if(this.editor == this._code_editor)
|
||||
return this.editor.getValue();
|
||||
return this.currfile.cache;
|
||||
}
|
||||
|
||||
|
||||
@ -271,7 +373,8 @@ namespace OS {
|
||||
* @memberof MonacoEditorModel
|
||||
*/
|
||||
setValue(value: string): void {
|
||||
this.editor.setValue(value);
|
||||
if(this.editor == this._code_editor)
|
||||
this.editor.setValue(value);
|
||||
}
|
||||
|
||||
getEditor(): any {
|
||||
|
@ -234,6 +234,15 @@ namespace OS {
|
||||
* @memberof Antedit
|
||||
*/
|
||||
private split_mode: boolean;
|
||||
|
||||
/**
|
||||
* Buffer for open diff
|
||||
*
|
||||
* @private
|
||||
* @type {EditorFileHandle[]}
|
||||
* @memberof Antedit
|
||||
*/
|
||||
private diff_buffer: EditorFileHandle[];
|
||||
|
||||
/**
|
||||
* Reference to the editor logger
|
||||
@ -270,6 +279,7 @@ namespace OS {
|
||||
constructor(args: AppArgumentsType[]) {
|
||||
super("Antedit", args);
|
||||
this.currdir = undefined;
|
||||
this.diff_buffer = [undefined, undefined];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -374,7 +384,6 @@ namespace OS {
|
||||
break;
|
||||
case "close-all":
|
||||
model.closeAll();
|
||||
model.openFile("Untitled".asFileHandle() as EditorFileHandle)
|
||||
break;
|
||||
case "mv-side":
|
||||
if(!tab)
|
||||
@ -435,13 +444,21 @@ namespace OS {
|
||||
this.on("focus", () => this.eum.active.focus());
|
||||
|
||||
this.fileview.contextmenuHandle = (e, m) => {
|
||||
m.items = [
|
||||
let file: API.VFS.BaseFileHandle | API.FileInfoType = this
|
||||
.fileview.selectedFile;
|
||||
const items = [
|
||||
{ text: "__(New file)", id: "new" },
|
||||
{ text: "__(New folder)", id: "newdir" },
|
||||
{ text: "__(Rename)", id: "rename" },
|
||||
{ text: "__(Delete)", id: "delete" },
|
||||
{ text: "__(Upload)", id: "upload" },
|
||||
];
|
||||
if(file && file.type === "file")
|
||||
{
|
||||
items.push( { text: "__(Select for compare)", id: "diff-org" });
|
||||
items.push( { text: "__(Compare with selected)", id: "diff-mod" });
|
||||
}
|
||||
m.items = items;
|
||||
m.onmenuselect = (e) => {
|
||||
return this.ctxFileMenuHandle(e);
|
||||
};
|
||||
@ -512,6 +529,7 @@ namespace OS {
|
||||
this.eum.addAction(extension, action, async (e) =>
|
||||
{
|
||||
try{
|
||||
|
||||
const data = await this.openDialog("SelectionDialog", {
|
||||
"title": __("Select language"),
|
||||
data: this.eum.active.getModes()
|
||||
@ -519,7 +537,7 @@ namespace OS {
|
||||
this.eum.active.setMode(data);
|
||||
}catch(e)
|
||||
{
|
||||
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
$(this.find("txt_ext_search")).keyup((e) => this.extension_search(e));
|
||||
@ -686,6 +704,12 @@ namespace OS {
|
||||
this.showBottomBar(true);
|
||||
this.bottombar.selectedIndex = 0;
|
||||
}
|
||||
|
||||
openDiff(files: EditorFileHandle[])
|
||||
{
|
||||
const diff_file = new API.VFS.DiffEditorFileHandle(files);
|
||||
this.eum.active.openFile(diff_file as EditorFileHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply [[showBottomBar]] from user setting value
|
||||
@ -953,6 +977,16 @@ namespace OS {
|
||||
})
|
||||
.catch((e) => this.error(__("Unable to upload file: {e}", e.toString()), __e(e)));
|
||||
break;
|
||||
case "diff-org":
|
||||
if(!file) return;
|
||||
this.diff_buffer[0] = file.path.asFileHandle() as EditorFileHandle;
|
||||
break;
|
||||
case "diff-mod":
|
||||
if(!file) return;
|
||||
if(!this.diff_buffer[0]) return;
|
||||
this.diff_buffer[1] = file.path.asFileHandle() as EditorFileHandle;
|
||||
this.openDiff(this.diff_buffer);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Antedit/README.md",
|
||||
"category": "Development",
|
||||
"author": "Xuan Sang LE",
|
||||
"version": "0.1.17-b",
|
||||
"version": "0.2.0-b",
|
||||
"dependencies": ["MonacoCore@0.33.0-r"],
|
||||
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Antedit/build/release/Antedit.zip"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user