Skip to content

Commit b1d5f81

Browse files
committed
feat: cte completion, hover tooltip for keywords and tables
1 parent a4c730f commit b1d5f81

16 files changed

+3319
-35
lines changed

README.md

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ A CodeMirror extension for SQL linting and visual gutter indicators.
44

55
## Features
66

7-
### SQL Linting
8-
9-
- **Syntax Validation**: Real-time syntax validation with detailed error messages
10-
- **Statement Recognition**: Supports SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, USE, and other SQL statements
7+
-**Real-time validation** - SQL syntax checking as you type with detailed error messages
8+
- 🎨 **Visual gutter** - Color-coded statement indicators and error highlighting
9+
- 💡 **Hover tooltips** - Schema info, keywords, and column details on hover
10+
- 🔮 **CTE autocomplete** - Auto-complete support for CTEs
1111

1212
## Installation
1313

@@ -19,22 +19,48 @@ pnpm add @marimo-team/codemirror-sql
1919

2020
## Usage
2121

22-
### Basic SQL Extension
22+
### Basic Setup
2323

2424
```ts
25-
import { sqlExtension } from '@marimo-team/codemirror-sql';
26-
import { EditorView } from '@codemirror/view';
25+
import { sql, StandardSQL } from '@codemirror/lang-sql';
26+
import { basicSetup, EditorView } from 'codemirror';
27+
import { sqlExtension, cteCompletionSource } from '@marimo-team/codemirror-sql';
28+
29+
const schema = {
30+
users: ["id", "name", "email", "active"],
31+
posts: ["id", "title", "content", "user_id"]
32+
};
2733

28-
const view = new EditorView({
34+
const editor = new EditorView({
35+
doc: "SELECT * FROM users WHERE active = true",
2936
extensions: [
30-
sqlExtension({
31-
delay: 250, // Delay before running validation
32-
enableStructureAnalysis: true, // Enable gutter markers for SQL expressions
33-
enableGutterMarkers: true, // Show vertical bars in gutter
34-
backgroundColor: "#3b82f6", // Blue for current statement
35-
errorBackgroundColor: "#ef4444", // Red for invalid statements
36-
hideWhenNotFocused: true, // Hide gutter when editor loses focus
37+
basicSetup,
38+
sql({
39+
dialect: StandardSQL,
40+
schema: schema,
41+
upperCaseKeywords: true
3742
}),
43+
StandardSQL.language.data.of({
44+
autocomplete: cteCompletionSource,
45+
}),
46+
sqlExtension({
47+
linterConfig: {
48+
delay: 250 // Validation delay in ms
49+
},
50+
gutterConfig: {
51+
backgroundColor: "#3b82f6", // Current statement color
52+
errorBackgroundColor: "#ef4444", // Error highlight color
53+
hideWhenNotFocused: true
54+
},
55+
enableHover: true,
56+
hoverConfig: {
57+
schema: schema,
58+
hoverTime: 300,
59+
enableKeywords: true,
60+
enableTables: true,
61+
enableColumns: true
62+
}
63+
})
3864
],
3965
parent: document.querySelector('#editor')
4066
});

demo/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ <h1 class="text-4xl font-bold mb-4">
2222
A CodeMirror extension for SQL with real-time syntax validation and error diagnostics using
2323
<a href="https://www.npmjs.com/package/node-sql-parser" class="text-blue-600 hover:text-blue-800">node-sql-parser</a>.
2424
</p>
25-
25+
2626
<div class="grid gap-8">
2727
<section>
2828
<h2 class="text-2xl font-bold mb-4">SQL Editor with Diagnostics</h2>
2929
<p class="mb-4 text-gray-600">
3030
Try typing invalid SQL syntax to see real-time error highlighting and messages.
31+
Valid tables are: <span class="font-bold">users, posts, orders, customers, categories</span>
3132
</p>
3233
<div class="border rounded-lg bg-white shadow-sm">
3334
<div id="sql-editor" class="min-h-[400px] overflow-y-auto"></div>

demo/index.ts

Lines changed: 117 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import { sql } from "@codemirror/lang-sql";
1+
import { SQLDialect, StandardSQL, sql } from "@codemirror/lang-sql";
22
import { basicSetup, EditorView } from "codemirror";
3+
import { cteCompletionSource } from "../src/sql/cte-completion-source.js";
34
import { sqlExtension } from "../src/sql/extension.js";
5+
import type { SqlKeywordInfo } from "../src/sql/hover.js";
46

57
// Default SQL content for the demo
68
const defaultSqlDoc = `-- Welcome to the SQL Editor Demo!
79
-- Try editing the queries below to see real-time validation
810
11+
WITH cte_name AS (
12+
SELECT * FROM users
13+
)
14+
915
-- Valid queries (no errors):
1016
SELECT id, name, email
1117
FROM users
@@ -46,23 +52,91 @@ WHERE order_date >= '2024-01-01'
4652
ORDER BY total_amount DESC;
4753
`;
4854

55+
const schema = {
56+
// Users table
57+
users: ["id", "name", "email", "active", "status", "created_at", "updated_at", "profile_id"],
58+
// Posts table
59+
posts: [
60+
"id",
61+
"title",
62+
"content",
63+
"user_id",
64+
"published",
65+
"created_at",
66+
"updated_at",
67+
"category_id",
68+
],
69+
// Orders table
70+
orders: [
71+
"id",
72+
"customer_id",
73+
"order_date",
74+
"total_amount",
75+
"status",
76+
"shipping_address",
77+
"created_at",
78+
],
79+
// Customers table (additional example)
80+
customers: ["id", "first_name", "last_name", "email", "phone", "address", "city", "country"],
81+
// Categories table
82+
categories: ["id", "name", "description", "parent_id"],
83+
};
84+
4985
let editor: EditorView;
5086

87+
const completionKindStyles = {
88+
borderRadius: "4px",
89+
padding: "2px 4px",
90+
marginRight: "4px",
91+
display: "inline-flex",
92+
alignItems: "center",
93+
justifyContent: "center",
94+
width: "12px",
95+
height: "12px",
96+
};
97+
98+
const dialect = StandardSQL;
99+
51100
// Initialize the SQL editor
52101
function initializeEditor() {
53102
const extensions = [
54103
basicSetup,
55104
EditorView.lineWrapping,
56-
sql(), // SQL language support
105+
sql({
106+
dialect: dialect,
107+
// Example schema for autocomplete
108+
schema: schema,
109+
// Enable uppercase keywords for more traditional SQL style
110+
upperCaseKeywords: true,
111+
}),
57112
sqlExtension({
58-
// Our custom SQL extension with diagnostics and structure analysis
59-
delay: 250, // Delay before running validation
60-
enableStructureAnalysis: true, // Enable gutter markers for SQL expressions
61-
enableGutterMarkers: true, // Show vertical bars in gutter
62-
backgroundColor: "#3b82f6", // Blue for current statement
63-
errorBackgroundColor: "#ef4444", // Red for invalid statements
64-
hideWhenNotFocused: true, // Hide gutter when editor loses focus
65-
// unfocusedOpacity: 0.1, // Alternative: set low opacity instead of hiding
113+
// Linter extension configuration
114+
linterConfig: {
115+
delay: 250, // Delay before running validation
116+
},
117+
118+
// Gutter extension configuration
119+
gutterConfig: {
120+
backgroundColor: "#3b82f6", // Blue for current statement
121+
errorBackgroundColor: "#ef4444", // Red for invalid statements
122+
hideWhenNotFocused: true, // Hide gutter when editor loses focus
123+
},
124+
// Hover extension configuration
125+
enableHover: true, // Enable hover tooltips
126+
hoverConfig: {
127+
schema: schema, // Use the same schema as autocomplete
128+
hoverTime: 300, // 300ms hover delay
129+
enableKeywords: true, // Show keyword information
130+
enableTables: true, // Show table information
131+
enableColumns: true, // Show column information
132+
keywords: async () => {
133+
const keywords = await import("../src/data/common-keywords.json");
134+
return keywords.default.keywords;
135+
},
136+
},
137+
}),
138+
dialect.language.data.of({
139+
autocomplete: cteCompletionSource,
66140
}),
67141
// Custom theme for better SQL editing
68142
EditorView.theme({
@@ -94,6 +168,39 @@ function initializeEditor() {
94168
color: "#dc2626",
95169
fontSize: "13px",
96170
},
171+
// Completion kind backgrounds
172+
".cm-completionIcon-keyword": {
173+
backgroundColor: "#e0e7ff", // indigo-100
174+
...completionKindStyles,
175+
},
176+
".cm-completionIcon-variable": {
177+
backgroundColor: "#fef9c3", // yellow-100
178+
...completionKindStyles,
179+
},
180+
".cm-completionIcon-property": {
181+
backgroundColor: "#bbf7d0", // green-100
182+
...completionKindStyles,
183+
},
184+
".cm-completionIcon-function": {
185+
backgroundColor: "#bae6fd", // sky-100
186+
...completionKindStyles,
187+
},
188+
".cm-completionIcon-class": {
189+
backgroundColor: "#fbcfe8", // pink-100
190+
...completionKindStyles,
191+
},
192+
".cm-completionIcon-constant": {
193+
backgroundColor: "#fde68a", // amber-200
194+
...completionKindStyles,
195+
},
196+
".cm-completionIcon-type": {
197+
backgroundColor: "#ddd6fe", // violet-200
198+
...completionKindStyles,
199+
},
200+
".cm-completionIcon-text": {
201+
backgroundColor: "#f3f4f6", // gray-100
202+
...completionKindStyles,
203+
},
97204
}),
98205
];
99206

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json.schemastore.org/package.json",
33
"name": "@marimo-team/codemirror-sql",
4-
"version": "0.2.2",
4+
"version": "0.1.0",
55
"publishConfig": {
66
"access": "public"
77
},
@@ -46,7 +46,8 @@
4646
"vitest": "^3.0.5"
4747
},
4848
"files": [
49-
"dist"
49+
"dist",
50+
"src/data"
5051
],
5152
"exports": {
5253
"./package.json": "./package.json",
@@ -55,7 +56,8 @@
5556
"types": "./dist/index.d.ts",
5657
"default": "./dist/index.js"
5758
}
58-
}
59+
},
60+
"./data/common-keywords.json": "./src/data/common-keywords.json"
5961
},
6062
"types": "./dist/index.d.ts",
6163
"type": "module",
@@ -72,6 +74,7 @@
7274
},
7375
"dependencies": {
7476
"@codemirror/lint": "^6.0.0",
77+
"@codemirror/autocomplete": "^6.0.0",
7578
"node-sql-parser": "^5.3.10"
7679
}
7780
}

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__tests__/index.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ describe("index.ts exports", () => {
88
[
99
"SqlParser",
1010
"SqlStructureAnalyzer",
11+
"cteCompletionSource",
1112
"sqlExtension",
13+
"sqlHover",
14+
"sqlHoverTheme",
1215
"sqlLinter",
1316
"sqlStructureGutter",
1417
]

0 commit comments

Comments
 (0)