<template>
<div class="RightContent">
<div id="code-editor"></div>
<el-button type="primary" size="mini" @click="getValue">获取内容</el-button>
</div>
</template>
<script>
import * as monaco from "monaco-editor";
import { language } from "monaco-editor/esm/vs/basic-languages/sql/sql";
// 从 monaco-editor 的 sql 里面拿到关键字
const { keywords } = language;
import sqlFormatter from 'sql-formatter' // 格式化sql 安装4以下的版本
export default {
name: "App",
data() {
return {
// 编辑器实例
monacoEditor: null,
// 原本已经写入的数据
value: "SELECT * FROM users;\n\nSELECT * FROM roles;",
// 补全的数据,建议在编辑器初始化之间就请求回来放好
tables: {
users: ["name", "id","email","phone","password"],
roles: ["id","name","order","created_at","updated_at","deleted_at"],
alonezc: ["name", "id","email","phone","zcop"],
},
// 编辑器主题
theme: "hc-black", // 默认是 "vs" // vs | hc-black | vs-dark
};
},
methods: {
/**
* @description: 获取编辑器中填写的值
*/
getValue() {
console.log(this.monacoEditor.getValue())
console.log('formaterSql', sqlFormatter)
// return
this.monacoEditor.setValue(sqlFormatter.format(this.monacoEditor.getValue()))
return this.monacoEditor.getValue();
},
/**
* @description: 初始化自动补全
*/
initAutoCompletion() {
// console.log(...keywords)
monaco.languages.registerCompletionItemProvider("sql", {
ignoreCase: true,
// 触发提示的字符
triggerCharacters: [".", " ", ...keywords],
provideCompletionItems: (model, position) => {
let suggestions = [];
// 行号,列号
const { lineNumber, column } = position;
// 光标之前的所有字符,即从这一行的 0 到当前的字符
const textBeforePointer = model.getValueInRange({
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: column,
});
// trim() 取消两边空格,保证拆分出来前后都不是空值
// \s是指空白,包括空格、换行、tab缩进等所有的空白
const words = textBeforePointer.trim().split(/\s+/);
// 最后的一个有效词
const lastWord = words[words.length - 1];
console.log(lastWord,'lastWord')
if (lastWord.endsWith(".")) { // 如果这个词以 . 结尾,那么认为是希望补全表的字段
// 拿到真实的表名,把 . 去掉
const tableName = lastWord.slice(0, lastWord.length - 1);
if (Object.keys(this.tables).includes(tableName)) {
suggestions = [...this.getFieldsSuggest(tableName)];
}
} else if (lastWord === ".") {
// 如果这个词本身就是一个 . 即点前面是空的,那么什么都不用补全了
// 按理说这应该是个语法错误
suggestions = [];
} else {
// 其他时候都补全表名,以及关键字
suggestions = [...this.getTableSuggest(), ...this.getKeywordsSuggest()];
}
return {
suggestions,
};
},
});
},
/**
* @description: 获取关键字的补全列表
* @tips: CompletionItemKind 的所有枚举可以在monaco.d.ts 文件中找到,有二十多个,取需即可
*/
getKeywordsSuggest() {
return keywords.map((key) => ({
label: key,// 显示的名称
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: key,// 真实补全的值
}));
},
/**
* @description: 获取表名的补全列表
*/
getTableSuggest() {
return Object.keys(this.tables).map((key) => ({
label: key, // 显示的名称
kind: monaco.languages.CompletionItemKind.Variable,
insertText: key, // 真实补全的值
}));
},
/**
* @description: 根据表名获取字段补全列表
* @param {*} tableName
*/
getFieldsSuggest(tableName) {
const fields = this.tables[tableName];
if (!fields) {
return [];
}
return fields.map((name) => ({
label: name,
kind: monaco.languages.CompletionItemKind.Field,
insertText: name,
}));
},
},
mounted() {
// 建议在这里把表名和字段名先拿出来
// ....
// this.tables = res.data?.data
// 首先初始化
this.initAutoCompletion();
// 初始化编辑器
this.monacoEditor = monaco.editor.create(document.getElementById("code-editor"), {
value: this.value, // 初始文字
language: "sql", // 语言
readOnly: false, // 是否只读
automaticLayout: true, // 自动布局
theme: this.theme, // vs | hc-black | vs-dark
minimap: {
enabled: false,// 关闭小地图
},
tabSize: 2, // tab缩进长度
fontSize: 16, // 文字大小
acceptSuggestionOnCommitCharacter: true, // 接受关于提交字符的建议
acceptSuggestionOnEnter: 'on', // 接受输入建议 "on" | "off" | "smart" //-如果设置off 编辑器上的代码补全显示了,但却不补上
accessibilityPageSize: 10, // 辅助功能页面大小 Number 说明:控制编辑器中可由屏幕阅读器读出的行数。警告:这对大于默认值的数字具有性能含义。
accessibilitySupport: 'off', // 辅助功能支持 控制编辑器是否应在为屏幕阅读器优化的模式下运行。
autoClosingBrackets: 'always', // 是否自动添加结束括号(包括中括号) "always" | "languageDefined" | "beforeWhitespace" | "never"
autoClosingDelete: 'always', // 是否自动删除结束括号(包括中括号) "always" | "never" | "auto"
autoClosingOvertype: 'always', // 是否关闭改写 即使用insert模式时是覆盖后面的文字还是不覆盖后面的文字 "always" | "never" | "auto"
autoClosingQuotes: 'always', // 是否自动添加结束的单引号 双引号 "always" | "languageDefined" | "beforeWhitespace" | "never"
autoIndent: 'None', // 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进
automaticLayout: true, // 自动布局
foldingStrategy: 'indentation', // 折叠方式 auto | indentation
codeLens: false, // 是否显示codeLens 通过 CodeLens,你可以在专注于工作的同时了解代码所发生的情况 – 而无需离开编辑器。 可以查找代码引用、代码更改、关联的 Bug、工作项、代码评审和单元测试。
codeLensFontFamily: '', // codeLens的字体样式
codeLensFontSize: 14, // codeLens的字体大小
colorDecorators: false, // 呈现内联色彩装饰器和颜色选择器
comments: {
ignoreEmptyLines: true, // 插入行注释时忽略空行。默认为真。
insertSpace: true // 在行注释标记之后和块注释标记内插入一个空格。默认为真。
}, // 注释配置
contextmenu: true, // 启用上下文菜单
columnSelection: false, // 启用列编辑 按下shift键位然后按↑↓键位可以实现列选择 然后实现列编辑
autoSurround: 'never', // 是否应自动环绕选择
copyWithSyntaxHighlighting: true, // 是否应将语法突出显示复制到剪贴板中 即 当你复制到word中是否保持文字高亮颜色
cursorBlinking: 'Solid', // 光标动画样式
cursorSmoothCaretAnimation: true, // 是否启用光标平滑插入动画 当你在快速输入文字的时候 光标是直接平滑的移动还是直接"闪现"到当前文字所处位置
cursorStyle: 'UnderlineThin', // "Block"|"BlockOutline"|"Line"|"LineThin"|"Underline"|"UnderlineThin" 光标样式
cursorSurroundingLines: 0, // 光标环绕行数 当文字输入超过屏幕时 可以看见右侧滚动条中光标所处位置是在滚动条中间还是顶部还是底部 即光标环绕行数 环绕行数越大 光标在滚动条中位置越居中
cursorSurroundingLinesStyle: 'all', // "default" | "all" 光标环绕样式
cursorWidth: 2, // <=25 光标宽度
minimap: {
enabled: true // 是否启用预览图
}, // 预览图设置
folding: true, // 是否启用代码折叠
links: true, // 是否点击链接
overviewRulerBorder: false, // 是否应围绕概览标尺绘制边框
renderLineHighlight: 'gutter', // 当前行突出显示方式
roundedSelection: false, // 选区是否有圆角
scrollBeyondLastLine: false // 设置编辑器是否可以滚动到最后一行之后
});
this.monacoEditor.onDidChangeModelContent(() => {
console.log('value', this.monacoEditor.getValue())
})
},
beforeDestroy() {
// 销毁之前把monaco的实例也销毁了,不然会多次注册
if (this.monacoEditor) {
this.monacoEditor.dispose();
}
},
};
</script>
<style>
#code-editor {
height: 600px;
}
</style>
vue+monaco +sql提示
最新推荐文章于 2024-04-29 10:42:46 发布