feat: SQL 代码编辑器中文自动补全
- 新增 sql.ts 中文补全列表(关键字 + 常用函数,SQLite 方言) - enhanceCompletion 接入 SQL,移除原来的早退逻辑 - CodeEditor.vue 补上 lang-sql 语言扩展,与 SyncCodeEditor 一致 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { cpp } from "@codemirror/lang-cpp"
|
||||
import { python } from "@codemirror/lang-python"
|
||||
import { sql, SQLite } from "@codemirror/lang-sql"
|
||||
import { bracketMatching } from "@codemirror/language"
|
||||
import { Codemirror } from "vue-codemirror"
|
||||
import {
|
||||
@@ -34,6 +35,8 @@ const code = defineModel<string>("value")
|
||||
const isDark = useDark()
|
||||
|
||||
const langExtension = computed(() => {
|
||||
if (language === "SQL")
|
||||
return sql({ dialect: SQLite, upperCaseKeywords: true })
|
||||
return ["Python2", "Python3"].includes(language) ? python() : cpp()
|
||||
})
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { EditorView } from "@codemirror/view"
|
||||
import type { LANGUAGE } from "utils/types"
|
||||
import { c } from "./c"
|
||||
import { python } from "./python"
|
||||
import { sql } from "./sql"
|
||||
|
||||
type ChineseCompletion = Pick<
|
||||
Completion,
|
||||
@@ -18,6 +19,7 @@ type ChineseCompletion = Pick<
|
||||
const chineseAnnotations: Record<string, ChineseCompletion[]> = {
|
||||
python,
|
||||
c,
|
||||
sql,
|
||||
}
|
||||
|
||||
export function enhanceCompletion(language: LANGUAGE): CompletionSource {
|
||||
@@ -27,10 +29,12 @@ export function enhanceCompletion(language: LANGUAGE): CompletionSource {
|
||||
const word = context.matchBefore(/\w+/)
|
||||
if (!word && !context.explicit) return null
|
||||
|
||||
// SQL 没有中文注释提示,关键字补全由 @codemirror/lang-sql 提供
|
||||
if (language === "SQL") return null
|
||||
|
||||
const trulyLanguage = language.startsWith("Python") ? "python" : "c"
|
||||
const trulyLanguage =
|
||||
language === "SQL"
|
||||
? "sql"
|
||||
: language.startsWith("Python")
|
||||
? "python"
|
||||
: "c"
|
||||
const completions: Completion[] = (
|
||||
chineseAnnotations[trulyLanguage] || []
|
||||
).map((completion) => {
|
||||
|
||||
404
src/shared/extensions/sql.ts
Normal file
404
src/shared/extensions/sql.ts
Normal file
@@ -0,0 +1,404 @@
|
||||
export const sql = [
|
||||
{
|
||||
label: "SELECT",
|
||||
detail: "查询数据",
|
||||
type: "keyword",
|
||||
info: "从表中查询数据,后面接要查询的列名,用 * 表示所有列。",
|
||||
boost: 100,
|
||||
apply: "SELECT ",
|
||||
},
|
||||
{
|
||||
label: "FROM",
|
||||
detail: "指定表",
|
||||
type: "keyword",
|
||||
info: "指定要查询的表,和 SELECT 搭配使用,如 SELECT * FROM 表名。",
|
||||
boost: 98,
|
||||
apply: "FROM ",
|
||||
},
|
||||
{
|
||||
label: "WHERE",
|
||||
detail: "筛选条件",
|
||||
type: "keyword",
|
||||
info: "按条件筛选行,只保留满足条件的数据,如 WHERE age > 18。",
|
||||
boost: 96,
|
||||
apply: "WHERE ",
|
||||
},
|
||||
{
|
||||
label: "ORDER BY",
|
||||
detail: "排序",
|
||||
type: "keyword",
|
||||
info: "按指定列排序,默认从小到大(ASC),加 DESC 表示从大到小。",
|
||||
boost: 90,
|
||||
apply: "ORDER BY ",
|
||||
},
|
||||
{
|
||||
label: "GROUP BY",
|
||||
detail: "分组",
|
||||
type: "keyword",
|
||||
info: "按指定列分组,常配合 COUNT、SUM 等聚合函数统计每组数据。",
|
||||
boost: 88,
|
||||
apply: "GROUP BY ",
|
||||
},
|
||||
{
|
||||
label: "HAVING",
|
||||
detail: "分组后筛选",
|
||||
type: "keyword",
|
||||
info: "对分组后的结果再筛选,WHERE 筛选行,HAVING 筛选组。",
|
||||
boost: 86,
|
||||
apply: "HAVING ",
|
||||
},
|
||||
{
|
||||
label: "LIMIT",
|
||||
detail: "限制条数",
|
||||
type: "keyword",
|
||||
info: "限制返回的行数,如 LIMIT 5 只取前 5 条,常和 ORDER BY 搭配。",
|
||||
boost: 84,
|
||||
apply: "LIMIT ",
|
||||
},
|
||||
{
|
||||
label: "DISTINCT",
|
||||
detail: "去重",
|
||||
type: "keyword",
|
||||
info: "去掉查询结果中的重复值,如 SELECT DISTINCT city FROM users。",
|
||||
boost: 82,
|
||||
apply: "DISTINCT ",
|
||||
},
|
||||
{
|
||||
label: "AS",
|
||||
detail: "起别名",
|
||||
type: "keyword",
|
||||
info: "给列或表起别名,让结果更易读,如 SELECT name AS 姓名。",
|
||||
boost: 80,
|
||||
apply: "AS ",
|
||||
},
|
||||
{
|
||||
label: "JOIN",
|
||||
detail: "连接表",
|
||||
type: "keyword",
|
||||
info: "把两张表按条件连接起来查询,需要用 ON 指定连接条件。",
|
||||
boost: 78,
|
||||
apply: "JOIN ",
|
||||
},
|
||||
{
|
||||
label: "LEFT JOIN",
|
||||
detail: "左连接",
|
||||
type: "keyword",
|
||||
info: "以左表为主连接右表,左表的行都保留,右表没匹配的补 NULL。",
|
||||
boost: 76,
|
||||
apply: "LEFT JOIN ",
|
||||
},
|
||||
{
|
||||
label: "ON",
|
||||
detail: "连接条件",
|
||||
type: "keyword",
|
||||
info: "指定两张表的连接条件,如 ON a.id = b.user_id,和 JOIN 搭配。",
|
||||
boost: 74,
|
||||
apply: "ON ",
|
||||
},
|
||||
{
|
||||
label: "INSERT INTO",
|
||||
detail: "插入数据",
|
||||
type: "keyword",
|
||||
info: "向表中插入新行,如 INSERT INTO 表名 (列1, 列2) VALUES (值1, 值2)。",
|
||||
boost: 72,
|
||||
apply: "INSERT INTO ",
|
||||
},
|
||||
{
|
||||
label: "VALUES",
|
||||
detail: "插入的值",
|
||||
type: "keyword",
|
||||
info: "和 INSERT INTO 搭配,写具体要插入的值,顺序要和列名对应。",
|
||||
boost: 70,
|
||||
apply: "VALUES ",
|
||||
},
|
||||
{
|
||||
label: "UPDATE",
|
||||
detail: "更新数据",
|
||||
type: "keyword",
|
||||
info: "修改表中已有的数据,配合 SET 设置新值,别忘了加 WHERE 限定范围。",
|
||||
boost: 68,
|
||||
apply: "UPDATE ",
|
||||
},
|
||||
{
|
||||
label: "SET",
|
||||
detail: "设置新值",
|
||||
type: "keyword",
|
||||
info: "和 UPDATE 搭配,指定要修改的列和新值,如 SET score = 90。",
|
||||
boost: 66,
|
||||
apply: "SET ",
|
||||
},
|
||||
{
|
||||
label: "DELETE FROM",
|
||||
detail: "删除数据",
|
||||
type: "keyword",
|
||||
info: "删除表中的行,一定要配合 WHERE 使用,否则会删掉整张表的数据。",
|
||||
boost: 64,
|
||||
apply: "DELETE FROM ",
|
||||
},
|
||||
{
|
||||
label: "CREATE TABLE",
|
||||
detail: "创建表",
|
||||
type: "keyword",
|
||||
info: "新建一张表,需要定义列名和类型,如 CREATE TABLE users (id INTEGER, name TEXT)。",
|
||||
boost: 62,
|
||||
apply: "CREATE TABLE ",
|
||||
},
|
||||
{
|
||||
label: "DROP TABLE",
|
||||
detail: "删除表",
|
||||
type: "keyword",
|
||||
info: "删除整张表(包括结构和数据),操作不可恢复,要谨慎使用。",
|
||||
boost: 60,
|
||||
apply: "DROP TABLE ",
|
||||
},
|
||||
{
|
||||
label: "ALTER TABLE",
|
||||
detail: "修改表结构",
|
||||
type: "keyword",
|
||||
info: "修改已有表的结构,比如添加列:ALTER TABLE 表名 ADD COLUMN 列名 类型。",
|
||||
boost: 58,
|
||||
apply: "ALTER TABLE ",
|
||||
},
|
||||
{
|
||||
label: "AND",
|
||||
detail: "并且",
|
||||
type: "keyword",
|
||||
info: "连接多个条件,全部成立才算满足,如 WHERE age > 18 AND city = '上海'。",
|
||||
boost: 56,
|
||||
apply: "AND ",
|
||||
},
|
||||
{
|
||||
label: "OR",
|
||||
detail: "或者",
|
||||
type: "keyword",
|
||||
info: "连接多个条件,任意一个成立就算满足。",
|
||||
boost: 54,
|
||||
apply: "OR ",
|
||||
},
|
||||
{
|
||||
label: "NOT",
|
||||
detail: "取反",
|
||||
type: "keyword",
|
||||
info: "对条件取反,如 NOT IN、NOT LIKE、IS NOT NULL。",
|
||||
boost: 52,
|
||||
apply: "NOT ",
|
||||
},
|
||||
{
|
||||
label: "IN",
|
||||
detail: "在列表中",
|
||||
type: "keyword",
|
||||
info: "判断值是否在给定列表中,如 WHERE city IN ('北京', '上海')。",
|
||||
boost: 50,
|
||||
apply: "IN ",
|
||||
},
|
||||
{
|
||||
label: "BETWEEN",
|
||||
detail: "在区间内",
|
||||
type: "keyword",
|
||||
info: "判断值是否在某个范围内(包含两端),如 BETWEEN 60 AND 100。",
|
||||
boost: 48,
|
||||
apply: "BETWEEN ",
|
||||
},
|
||||
{
|
||||
label: "LIKE",
|
||||
detail: "模糊匹配",
|
||||
type: "keyword",
|
||||
info: "模糊查询,% 匹配任意多个字符,_ 匹配单个字符,如 LIKE '张%'。",
|
||||
boost: 46,
|
||||
apply: "LIKE ",
|
||||
},
|
||||
{
|
||||
label: "IS NULL",
|
||||
detail: "是否为空",
|
||||
type: "keyword",
|
||||
info: "判断值是否为 NULL(空值),不能写 = NULL,要用 IS NULL。",
|
||||
boost: 44,
|
||||
},
|
||||
{
|
||||
label: "IS NOT NULL",
|
||||
detail: "是否非空",
|
||||
type: "keyword",
|
||||
info: "判断值不为 NULL,常用于过滤掉缺失数据的行。",
|
||||
boost: 42,
|
||||
},
|
||||
{
|
||||
label: "ASC",
|
||||
detail: "升序",
|
||||
type: "keyword",
|
||||
info: "排序时从小到大排列,是 ORDER BY 的默认方式,可以省略。",
|
||||
boost: 40,
|
||||
},
|
||||
{
|
||||
label: "DESC",
|
||||
detail: "降序",
|
||||
type: "keyword",
|
||||
info: "排序时从大到小排列,如 ORDER BY score DESC 按分数从高到低。",
|
||||
boost: 41,
|
||||
},
|
||||
{
|
||||
label: "UNION",
|
||||
detail: "合并结果",
|
||||
type: "keyword",
|
||||
info: "合并两个查询的结果并去重,两个查询的列数和类型要一致。",
|
||||
boost: 38,
|
||||
apply: "UNION ",
|
||||
},
|
||||
{
|
||||
label: "CASE",
|
||||
detail: "条件表达式",
|
||||
type: "keyword",
|
||||
info: "类似 if/else 的条件判断,语法 CASE WHEN 条件 THEN 值 ELSE 值 END。",
|
||||
boost: 36,
|
||||
apply: "CASE ",
|
||||
},
|
||||
{
|
||||
label: "WHEN",
|
||||
detail: "当条件成立",
|
||||
type: "keyword",
|
||||
info: "和 CASE 搭配,写判断条件,成立时返回 THEN 后面的值。",
|
||||
boost: 34,
|
||||
apply: "WHEN ",
|
||||
},
|
||||
{
|
||||
label: "THEN",
|
||||
detail: "返回值",
|
||||
type: "keyword",
|
||||
info: "和 WHEN 搭配,条件成立时返回的结果。",
|
||||
boost: 32,
|
||||
apply: "THEN ",
|
||||
},
|
||||
{
|
||||
label: "ELSE",
|
||||
detail: "否则",
|
||||
type: "keyword",
|
||||
info: "CASE 中所有 WHEN 都不成立时返回的默认值。",
|
||||
boost: 30,
|
||||
apply: "ELSE ",
|
||||
},
|
||||
{
|
||||
label: "END",
|
||||
detail: "结束 CASE",
|
||||
type: "keyword",
|
||||
info: "标记 CASE 表达式的结束,写 CASE 时不要漏掉。",
|
||||
boost: 28,
|
||||
},
|
||||
{
|
||||
label: "NULL",
|
||||
detail: "空值",
|
||||
type: "keyword",
|
||||
info: "表示没有值(缺失),判断时要用 IS NULL / IS NOT NULL。",
|
||||
boost: 26,
|
||||
},
|
||||
{
|
||||
label: "COUNT",
|
||||
detail: "统计行数",
|
||||
type: "function",
|
||||
info: "统计行数,COUNT(*) 统计所有行,COUNT(列名) 不统计 NULL。",
|
||||
boost: 92,
|
||||
apply: "COUNT()",
|
||||
},
|
||||
{
|
||||
label: "SUM",
|
||||
detail: "求和",
|
||||
type: "function",
|
||||
info: "对某一列求和,只能用于数字列,如 SUM(score)。",
|
||||
boost: 87,
|
||||
apply: "SUM()",
|
||||
},
|
||||
{
|
||||
label: "AVG",
|
||||
detail: "平均值",
|
||||
type: "function",
|
||||
info: "计算某一列的平均值,会自动忽略 NULL,如 AVG(score)。",
|
||||
boost: 85,
|
||||
apply: "AVG()",
|
||||
},
|
||||
{
|
||||
label: "MAX",
|
||||
detail: "最大值",
|
||||
type: "function",
|
||||
info: "求某一列的最大值,如 MAX(score) 找最高分。",
|
||||
boost: 83,
|
||||
apply: "MAX()",
|
||||
},
|
||||
{
|
||||
label: "MIN",
|
||||
detail: "最小值",
|
||||
type: "function",
|
||||
info: "求某一列的最小值,如 MIN(score) 找最低分。",
|
||||
boost: 81,
|
||||
apply: "MIN()",
|
||||
},
|
||||
{
|
||||
label: "LENGTH",
|
||||
detail: "字符串长度",
|
||||
type: "function",
|
||||
info: "返回字符串的字符个数,如 LENGTH(name)。",
|
||||
boost: 79,
|
||||
apply: "LENGTH()",
|
||||
},
|
||||
{
|
||||
label: "UPPER",
|
||||
detail: "转大写",
|
||||
type: "function",
|
||||
info: "把字符串中的字母转成大写,如 UPPER('abc') 得到 'ABC'。",
|
||||
boost: 77,
|
||||
apply: "UPPER()",
|
||||
},
|
||||
{
|
||||
label: "LOWER",
|
||||
detail: "转小写",
|
||||
type: "function",
|
||||
info: "把字符串中的字母转成小写,如 LOWER('ABC') 得到 'abc'。",
|
||||
boost: 75,
|
||||
apply: "LOWER()",
|
||||
},
|
||||
{
|
||||
label: "SUBSTR",
|
||||
detail: "截取子串",
|
||||
type: "function",
|
||||
info: "截取字符串的一部分,语法 SUBSTR(字符串, 起始位置, 长度),位置从 1 开始。",
|
||||
boost: 73,
|
||||
apply: "SUBSTR()",
|
||||
},
|
||||
{
|
||||
label: "REPLACE",
|
||||
detail: "替换字符串",
|
||||
type: "function",
|
||||
info: "把字符串中的内容替换成新内容,语法 REPLACE(字符串, 旧内容, 新内容)。",
|
||||
boost: 71,
|
||||
apply: "REPLACE()",
|
||||
},
|
||||
{
|
||||
label: "ROUND",
|
||||
detail: "四舍五入",
|
||||
type: "function",
|
||||
info: "按指定小数位四舍五入,如 ROUND(3.456, 2) 得到 3.46。",
|
||||
boost: 69,
|
||||
apply: "ROUND()",
|
||||
},
|
||||
{
|
||||
label: "ABS",
|
||||
detail: "绝对值",
|
||||
type: "function",
|
||||
info: "返回数字的绝对值,把负数变成正数,如 ABS(-5) 得到 5。",
|
||||
boost: 67,
|
||||
apply: "ABS()",
|
||||
},
|
||||
{
|
||||
label: "IFNULL",
|
||||
detail: "空值替代",
|
||||
type: "function",
|
||||
info: "如果第一个值是 NULL 就返回第二个值,如 IFNULL(score, 0) 把空分数当 0。",
|
||||
boost: 65,
|
||||
apply: "IFNULL()",
|
||||
},
|
||||
{
|
||||
label: "TRIM",
|
||||
detail: "去首尾空格",
|
||||
type: "function",
|
||||
info: "去掉字符串首尾的空格,常用于清理输入数据。",
|
||||
boost: 63,
|
||||
apply: "TRIM()",
|
||||
},
|
||||
]
|
||||
Reference in New Issue
Block a user