多维表格
 
 
 
 
 
 

296 lines
9.4 KiB

/* eslint-disable */
import assign from "nano-assign";
import sqlAutoCompletions from "./sqlAutoCompletions";
export default {
name: "MonacoEditor",
props: {
value: String,
theme: {
type: String,
default: "vs"
},
lang: String,
options: Object,
readOnly: Boolean,
amdRequire: {
type: Function
},
sqlType: String,
actions: Array,
tables: Array,
columnNames: Object,
columnNameCbk: Function
},
model: {
event: "change"
},
data() {
return {completionItemProvider: null}
// return {
// tables: ["abc", "efg", "actor", "country"],
// columnNames: {
// abc: ["id", "name"],
// efg: ["eid", "title"],
// actor: ["aid", "firstName"],
// country: ["id", "code", "name"]
// }
// }
},
watch: {
options: {
deep: true,
handler(options) {
if (this.editor) {
this.editor.updateOptions(options);
}
}
},
value(newValue) {
if (this.editor) {
if (newValue !== this.editor.getValue()) {
this.editor.setValue(newValue);
}
}
},
lang(newVal) {
if (this.editor) {
window.monaco.editor.setModelLanguage(this.editor.getModel(), newVal);
}
},
theme(newVal) {
if (this.editor) {
window.monaco.editor.setTheme(newVal);
}
}
},
mounted() {
if (this.amdRequire) {
this.amdRequire(["vs/editor/editor.main"], () => {
this.initMonaco(window.monaco);
});
} else {
// ESM format so it can't be resolved by commonjs `require` in eslint
// eslint-disable import/no-unresolved
const monaco = require("monaco-editor");
// monaco.editor.defineTheme('monokai', require('./Cobalt.json'))
// monaco.editor.setTheme('monokai')
this.monaco = monaco;
// this.completionItemProvider = monaco.languages.registerCompletionItemProvider("sql", {
// async provideCompletionItems(model, position) {
// // console.log(sqlAutoCompletions(monaco).actions[0])
// console.log(model === vm.editor,model,vm.editor)
// return model === vm.editor.getModel() ? {suggestions: await vm.getLiveSuggestionsList(model, position)} : {};
// }
// });
this.initMonaco(monaco);
}
},
unmounted() {
},
beforeDestroy() {
this.editor && this.editor.dispose();
},
methods: {
initMonaco(monaco) {
const options = assign(
{
value: this.value,
theme: this.theme,
language: this.lang,
// quickSuggestions: { other: true, comments: true, strings: true },
automaticLayout: true,
readOnly: false
},
this.options
);
this.editor = monaco.editor.create(this.$el, options);
this.$emit("editorDidMount", this.editor);
this.editor.onContextMenu(event => this.$emit("contextMenu", event));
this.editor.onDidBlurEditorWidget(() => this.$emit("blur"));
this.editor.onDidBlurEditorText(() => this.$emit("blurText"));
this.editor.onDidChangeConfiguration(event => this.$emit("configuration", event));
this.editor.onDidChangeCursorPosition(event => this.$emit("position", event));
this.editor.onDidChangeCursorSelection(event => this.$emit("selection", event));
this.editor.onDidChangeModel(event => this.$emit("model", event));
this.editor.onDidChangeModelContent(event => {
const value = this.editor.getValue();
if (this.value !== value) {
this.$emit("change", value, event);
}
});
this.editor.onDidChangeModelDecorations(event => this.$emit("modelDecorations", event));
this.editor.onDidChangeModelLanguage(event => this.$emit("modelLanguage", event));
this.editor.onDidChangeModelOptions(event => this.$emit("modelOptions", event));
this.editor.onDidDispose(event => this.$emit("afterDispose", event));
this.editor.onDidFocusEditorWidget(() => this.$emit("focus"));
this.editor.onDidFocusEditorText(() => this.$emit("focusText"));
this.editor.onDidLayoutChange(event => this.$emit("layout", event));
this.editor.onDidScrollChange(event => this.$emit("scroll", event));
this.editor.onKeyDown(event => this.$emit("keydown", event));
this.editor.onKeyUp(event => this.$emit("keyup", event));
this.editor.onMouseDown(event => this.$emit("mouseDown", event));
this.editor.onMouseLeave(event => this.$emit("mouseLeave", event));
this.editor.onMouseMove(event => this.$emit("mouseMove", event));
this.editor.onMouseUp(event => this.$emit("mouseUp", event));
if (this.actions && this.actions.length)
this.actions.forEach(action => this.editor.addAction(action));
},
getMonaco() {
return this.editor;
},
getMonacoModule() {
return this.monaco;
},
focus() {
this.editor.focus();
this.$nextTick(() => {
this.editor.setPosition({lineNumber: this.editor.getModel().getLineCount(), column: 1})
this.editor.revealLineInCenter(this.editor.getModel().getLineCount())
})
},
getCurrentQuery() {
return this.editor.getModel().getValueInRange(this.editor.getSelection()) || this.getCurrentFocusedQuery().trim();
},
getAllContent() {
return this.editor.getModel().getValueInRange(this.editor.getSelection()) || this.editor.getValue();
},
getCurrentFocusedQuery() {
const line = this.editor.getPosition().lineNumber;
if (this.editor.getValue().split('\n')[line - 1].trim() === '') return '';
let c = 1;
return this.editor.getValue()
.split(/\n\n/)
.find((query, i) => {
let lines = query.split('\n');
return c + 2 * i <= line && 2 * i + (c += lines.length - 1) >= line;
}) || '';
},
async getLiveSuggestionsList(model, position) {
const textUntilPosition = model.getValueInRange({
startLineNumber: 1,
startColumn: 1,
endLineNumber: position.lineNumber,
endColumn: position.column
});
var suggestions;
var match;
if (this.tables) {
if (
(match = textUntilPosition.match(/(from|table|update|select|into)\s+$/i))
) {
suggestions = this.tables.map(name => ({
insertText: `\`${name}\`${
match[1].toLowerCase() === "select" ? "." : " "
}`,
label: name
}));
}
}
if (this.columnNames) {
if (
(match = textUntilPosition.match(/select\s+(`?)(\w+)\1\.$/i))
) {
suggestions = (await this.getColumnNames(match[2]) || []).map(name => ({
insertText: `\`${name}\``,
label: name
}));
} else if (
(match = textUntilPosition.match(
/insert\s+into\s+(`?)(\w+)\1\s+\(\s*(\s*`?\w+`?\s*,\s*)*$/i
))
) {
let columns = (await this.getColumnNames(match[2]) || []);
if (!match[3] && columns.length) columns = [...columns,columns.join('`,`')]
suggestions = columns.map(name => ({
insertText: `\`${name}\``,
label: name
}));
} else if (
(match = textUntilPosition.match(
/update\s+(`?)(\w+)\1\s+set\s+(?:\s*`?\w+`?\s*=\s*(?:'(?:[^']|\\')*'|\d+|NULL)\s*,\s*)*$/i
))
) {
suggestions = (await this.getColumnNames(match[2]) || []).map(name => ({
insertText: `\`${name}\` = `,
label: name
}));
} else if (
(match = textUntilPosition.match(
/(?:from|update)\s*(`?)(\w+)\1[\s\S]*?(?:where|and|or)\s*$/i
))
) {
suggestions = (await this.getColumnNames(match[2]) || []).map(name => ({
insertText: `\`${name}\` `,
label: name
}));
}
}
return suggestions || sqlAutoCompletions(monaco);
}, async getColumnNames(tn) {
if (tn in this.columnNames) return this.columnNames[tn];
else {
if (this.columnNameCbk) return await this.columnNameCbk(tn);
}
}
},
render(h) {
return h("div");
},
created() {
const vm = this;
const monaco = require("monaco-editor");
this.completionItemProvider = monaco.languages.registerCompletionItemProvider("sql", {
async provideCompletionItems(model, position) {
return model === vm.editor.getModel() ? {suggestions: await vm.getLiveSuggestionsList(model, position)} : {};
}
});
},
destroyed() {
if (this.completionItemProvider) this.completionItemProvider.dispose();
}
};
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/