mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-21 12:41:39 +00:00
fix(editor): keep semicolon cursor on statement
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveExecutableSql } from "../sqlExecutionTarget";
|
||||
|
||||
describe("resolveExecutableSql", () => {
|
||||
it("uses selected SQL before cursor-mode resolution", () => {
|
||||
const sql = "select 1;\n\nselect 2;";
|
||||
const selectedSql = " select 2; ";
|
||||
const cursorAfterFirstSemicolon = sql.indexOf(";") + 1;
|
||||
|
||||
expect(resolveExecutableSql(sql, selectedSql, { mode: "current", cursorPos: cursorAfterFirstSemicolon })).toBe("select 2;");
|
||||
});
|
||||
});
|
||||
@@ -172,6 +172,13 @@ describe("statementRangeAtCursor", () => {
|
||||
expect(range?.sql.trim()).toBe("SELECT *\nFROM system_dept");
|
||||
});
|
||||
|
||||
it("keeps a semicolon-line-end cursor on the current multi-line statement", () => {
|
||||
const sql = "SELECT *\nFROM system_dept;";
|
||||
const gapPos = sql.indexOf(";") + 1;
|
||||
const range = statementRangeAtCursor(sql, gapPos);
|
||||
expect(range?.sql.trim()).toBe("SELECT *\nFROM system_dept");
|
||||
});
|
||||
|
||||
it("returns the next same-line statement when the cursor is inside it", () => {
|
||||
const sql = "SELECT 1; SELECT 2;";
|
||||
const pos = indexOf(sql, "SELECT 2") + 1;
|
||||
@@ -409,6 +416,13 @@ describe("buildExecutionCandidates", () => {
|
||||
expect(candidateLabels(candidates)).toEqual(["currentStatement", "allStatements"]);
|
||||
});
|
||||
|
||||
it("uses the current statement when the cursor is immediately after its semicolon before a blank line", () => {
|
||||
const sql = "select 1;\n\nselect 2;";
|
||||
const cursorAfterFirstSemicolon = sql.indexOf(";") + 1;
|
||||
const candidates = buildExecutionCandidates(sql, cursorAfterFirstSemicolon);
|
||||
expect(candidateSummaries(candidates)).toEqual(["cursor:select 1", "all:select 1;\n\nselect 2;"]);
|
||||
});
|
||||
|
||||
it("dedupes when the cursor statement equals the full document", () => {
|
||||
const sql = "SELECT 1;";
|
||||
const candidates = buildExecutionCandidates(sql, indexOf(sql, "1"));
|
||||
|
||||
@@ -356,6 +356,13 @@ export function statementRangeAtCursor(sql: string, cursorPos: number, databaseT
|
||||
if (pos >= statement.from && pos <= statement.to) {
|
||||
return rangeForCursorInSoftRanges(sql, softRanges, pos) ?? rangeFor(statement, sql);
|
||||
}
|
||||
const next = statements[index + 1];
|
||||
// A caret after a statement's semicolon still belongs to that statement
|
||||
// until the next statement's text begins.
|
||||
if (pos > statement.to && (!next || pos < next.from) && isCursorInSameLineDelimiterGap(sql, statement.to, pos)) {
|
||||
return rangeForCursorInSoftRanges(sql, softRanges, pos) ?? rangeFor(statement, sql);
|
||||
}
|
||||
|
||||
// Cursor in indentation or inter-statement whitespace immediately before
|
||||
// the statement should still target that statement, while the returned
|
||||
// execution range remains tight around the SQL text itself.
|
||||
@@ -368,7 +375,6 @@ export function statementRangeAtCursor(sql: string, cursorPos: number, databaseT
|
||||
return rangeForCursorInSoftRanges(sql, softRanges, pos) ?? rangeFor(statement, sql);
|
||||
}
|
||||
|
||||
const next = statements[index + 1];
|
||||
if (pos > statement.to && (!next || pos < next.hitFrom) && isCursorOnStatementLine(sql, pos, statement)) {
|
||||
return rangeForCursorInSoftRanges(sql, softRanges, pos) ?? rangeFor(statement, sql);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user