@deaquinodev/querky 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +52 -36
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1189,7 +1189,7 @@ function useVimInput(onSubmit, isActive, vimEnabled = true, onTab, history = [],
1189
1189
  }
1190
1190
  if (key.leftArrow) return { ...s, cursor: Math.max(0, s.cursor - 1) };
1191
1191
  if (key.rightArrow) return { ...s, cursor: Math.min(s.value.length, s.cursor + 1) };
1192
- if (key.tab) {
1192
+ if (key.tab && !key.shift) {
1193
1193
  const sugs = getSuggestions?.(s.value, s.cursor) ?? [];
1194
1194
  if (sugs.length > 0) {
1195
1195
  const next = s.suggestionIndex < sugs.length - 1 ? s.suggestionIndex + 1 : 0;
@@ -1199,6 +1199,14 @@ function useVimInput(onSubmit, isActive, vimEnabled = true, onTab, history = [],
1199
1199
  if (completed != null) return { ...s, value: completed, cursor: completed.length };
1200
1200
  return s;
1201
1201
  }
1202
+ if (key.tab && key.shift) {
1203
+ const sugs = getSuggestions?.(s.value, s.cursor) ?? [];
1204
+ if (sugs.length > 0) {
1205
+ const next = s.suggestionIndex <= 0 ? sugs.length - 1 : s.suggestionIndex - 1;
1206
+ return { ...s, suggestionIndex: next };
1207
+ }
1208
+ return s;
1209
+ }
1202
1210
  if (key.ctrl && input === "e") {
1203
1211
  return { ...s, pendingEditor: s.value };
1204
1212
  }
@@ -1496,9 +1504,10 @@ function FuzzyHighlight({ text, token, selected }) {
1496
1504
  (seg, i) => seg.hit ? /* @__PURE__ */ jsx(Text, { color: ACCENT, bold: true, children: seg.chars }, i) : /* @__PURE__ */ jsx(Text, { dimColor: !selected, children: seg.chars }, i)
1497
1505
  ) });
1498
1506
  }
1499
- var BG = "#1e1b4b";
1507
+ var BG = "#1e1e1e";
1500
1508
  var ACCENT = "#818cf8";
1501
- var PLACEHOLDER = "#6366f1";
1509
+ var PROMPT_MUTED = "#6b7280";
1510
+ var PLACEHOLDER = "#4b5563";
1502
1511
  var KW_COLOR = "#a5b4fc";
1503
1512
  var STR_COLOR = "#fb923c";
1504
1513
  var NUM_COLOR = "#86efac";
@@ -1510,9 +1519,9 @@ function sqlTokenColor(type) {
1510
1519
  if (type === "comment") return CMT_COLOR;
1511
1520
  return void 0;
1512
1521
  }
1513
- function SqlLine({ text }) {
1522
+ function SqlLine({ text, bg }) {
1514
1523
  const tokens = tokenizeSql(text);
1515
- return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((tok, i) => /* @__PURE__ */ jsx(Text, { color: sqlTokenColor(tok.type), children: tok.text }, i)) });
1524
+ return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((tok, i) => /* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: sqlTokenColor(tok.type), children: tok.text }, i)) });
1516
1525
  }
1517
1526
  function SqlHighlightedInput({ text, cursorAt, mode, pad: pad2 }) {
1518
1527
  const tokens = tokenizeSql(text);
@@ -1530,7 +1539,7 @@ function SqlHighlightedInput({ text, cursorAt, mode, pad: pad2 }) {
1530
1539
  const after = tok.text.slice(rel + 1);
1531
1540
  if (before) parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, color, children: before }, `${i}b`));
1532
1541
  if (mode === "INSERT") {
1533
- parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: ACCENT, bold: true, children: "\u258C" }, `${i}c`));
1542
+ parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: PROMPT_MUTED, bold: true, children: "\u258C" }, `${i}c`));
1534
1543
  } else {
1535
1544
  parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: ch || " " }, `${i}c`));
1536
1545
  }
@@ -1543,7 +1552,7 @@ function SqlHighlightedInput({ text, cursorAt, mode, pad: pad2 }) {
1543
1552
  }
1544
1553
  if (!cursorDone) {
1545
1554
  if (mode === "INSERT") {
1546
- parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: ACCENT, bold: true, children: "\u258C" }, "c"));
1555
+ parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: PROMPT_MUTED, bold: true, children: "\u258C" }, "c"));
1547
1556
  } else {
1548
1557
  parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: " " }, "c"));
1549
1558
  }
@@ -1635,16 +1644,19 @@ function QueryInput({ onSubmit, isLoading, onModeChange, onShellModeChange, vimE
1635
1644
  const isMultiLine = !isEmpty && !isShellMode && !isCommand && value.includes("\n");
1636
1645
  const dOff = isShellMode ? 2 : 0;
1637
1646
  const placeholder = "Type a SQL query\u2026";
1647
+ const previewResult = !isMultiLine && suggestionIndex >= 0 && suggestions.length > 0 ? handleSuggestionAccept(value, cursorPos, suggestions[suggestionIndex]) : null;
1648
+ const renderValue = previewResult?.value ?? value;
1649
+ const renderCursor = previewResult?.cursor ?? cursorPos;
1638
1650
  const lineWidth = innerWidth - 4;
1639
- const displayValue = value.slice(dOff);
1640
- const displayCursor = Math.max(0, cursorPos - dOff);
1651
+ const displayValue = renderValue.slice(dOff);
1652
+ const displayCursor = Math.max(0, renderCursor - dOff);
1641
1653
  const scrollStart = displayCursor > lineWidth - 1 ? displayCursor - lineWidth + 1 : 0;
1642
1654
  const visibleBefore = displayValue.slice(scrollStart, displayCursor);
1643
- const cursorChar = cursorPos < dOff ? " " : displayValue[displayCursor] ?? " ";
1655
+ const cursorChar = renderCursor < dOff ? " " : displayValue[displayCursor] ?? " ";
1644
1656
  const visibleAfter = displayValue.slice(displayCursor + 1, scrollStart + lineWidth);
1645
1657
  const textPad = " ".repeat(Math.max(0, lineWidth - visibleBefore.length - 1 - visibleAfter.length));
1646
- const visibleSql = value.slice(scrollStart, scrollStart + lineWidth);
1647
- const relativeSqlCursor = cursorPos - scrollStart;
1658
+ const visibleSql = renderValue.slice(scrollStart, scrollStart + lineWidth);
1659
+ const relativeSqlCursor = renderCursor - scrollStart;
1648
1660
  const sqlCursorAtEnd = relativeSqlCursor >= visibleSql.length;
1649
1661
  const sqlPad = " ".repeat(Math.max(0, lineWidth - visibleSql.length - (sqlCursorAtEnd ? 1 : 0)));
1650
1662
  const emptyPad = " ".repeat(Math.max(0, lineWidth - placeholder.length - 1));
@@ -1656,31 +1668,37 @@ function QueryInput({ onSubmit, isLoading, onModeChange, onShellModeChange, vimE
1656
1668
  );
1657
1669
  const hintsInline = totalHintsWidth <= termWidth;
1658
1670
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
1659
- isMultiLine ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
1660
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: ACCENT, paddingX: 1, children: value.split("\n").map((line, i, arr) => {
1671
+ isMultiLine ? /* @__PURE__ */ jsxs(Fragment, { children: [
1672
+ /* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: emptyLine }),
1673
+ value.split("\n").map((line, i, arr) => {
1661
1674
  const numW = String(arr.length).length;
1675
+ const prefixWidth = 2 + numW + 3;
1676
+ const contentWidth = innerWidth - prefixWidth;
1662
1677
  const isLast = i === arr.length - 1;
1678
+ const linePad = " ".repeat(Math.max(0, contentWidth - line.length - (isLast ? 1 : 0)));
1663
1679
  return /* @__PURE__ */ jsxs(Box, { children: [
1664
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1680
+ /* @__PURE__ */ jsxs(Text, { backgroundColor: BG, dimColor: true, children: [
1681
+ " ",
1665
1682
  String(i + 1).padStart(numW),
1666
1683
  " \u2502 "
1667
1684
  ] }),
1668
- /* @__PURE__ */ jsx(SqlLine, { text: line }),
1669
- isLast && (mode === "INSERT" ? /* @__PURE__ */ jsx(Text, { color: ACCENT, bold: true, children: "\u258C" }) : /* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: " " }))
1685
+ /* @__PURE__ */ jsx(SqlLine, { text: line, bg: BG }),
1686
+ isLast && (mode === "INSERT" ? /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: PROMPT_MUTED, bold: true, children: "\u258C" }) : /* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: " " })),
1687
+ /* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: linePad })
1670
1688
  ] }, i);
1671
- }) }),
1672
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Enter: run \xB7 Ctrl+E / e: re-edit" }) })
1689
+ }),
1690
+ /* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: emptyLine })
1673
1691
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1674
1692
  /* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: emptyLine }),
1675
1693
  /* @__PURE__ */ jsxs(Box, { children: [
1676
- /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: isShellMode ? theme.shellMode : ACCENT, bold: true, children: isShellMode ? " $ " : " > " }),
1694
+ /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: isShellMode ? theme.shellMode : PROMPT_MUTED, bold: true, children: isShellMode ? " $ " : " > " }),
1677
1695
  isEmpty ? /* @__PURE__ */ jsxs(Fragment, { children: [
1678
1696
  /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: PLACEHOLDER, children: placeholder }),
1679
- /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: ACCENT, bold: true, children: "\u258C" }),
1697
+ /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: PROMPT_MUTED, bold: true, children: "\u258C" }),
1680
1698
  /* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: emptyPad })
1681
1699
  ] }) : isShellMode || isCommand ? /* @__PURE__ */ jsxs(Fragment, { children: [
1682
1700
  /* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: visibleBefore }),
1683
- mode === "INSERT" ? /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: ACCENT, bold: true, children: "\u258C" }) : /* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: cursorChar }),
1701
+ mode === "INSERT" ? /* @__PURE__ */ jsx(Text, { backgroundColor: BG, color: PROMPT_MUTED, bold: true, children: "\u258C" }) : /* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: cursorChar }),
1684
1702
  /* @__PURE__ */ jsxs(Text, { backgroundColor: BG, children: [
1685
1703
  visibleAfter,
1686
1704
  textPad
@@ -1802,21 +1820,13 @@ function Table({ columns, rows, expanded = false }) {
1802
1820
 
1803
1821
  // src/ui/components/QueryResult.tsx
1804
1822
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1805
- var ERROR_BG = "#3b0f0f";
1806
1823
  var ERROR_FG = "#ff4444";
1807
1824
  function ErrorBox({ message }) {
1808
- const cols = Math.max(0, (process.stdout.columns ?? 80) - 2);
1809
- const blank = " ".repeat(cols);
1810
1825
  const lines = message.split("\n");
1811
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
1812
- /* @__PURE__ */ jsx3(Text3, { backgroundColor: ERROR_BG, children: blank }),
1813
- lines.map((line, i) => {
1814
- const content = (i === 0 ? " \u2717 " : " ") + line;
1815
- const padded = content.length < cols ? content + " ".repeat(cols - content.length) : content;
1816
- return /* @__PURE__ */ jsx3(Text3, { backgroundColor: ERROR_BG, color: ERROR_FG, bold: true, children: padded }, i);
1817
- }),
1818
- /* @__PURE__ */ jsx3(Text3, { backgroundColor: ERROR_BG, children: blank })
1819
- ] });
1826
+ return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", marginTop: 1, children: lines.map((line, i) => /* @__PURE__ */ jsxs3(Text3, { color: ERROR_FG, bold: true, children: [
1827
+ i === 0 ? "\u2717 " : " ",
1828
+ line
1829
+ ] }, i)) });
1820
1830
  }
1821
1831
  function formatDuration(ms) {
1822
1832
  if (ms < 1e3) return `${ms}ms`;
@@ -2138,6 +2148,12 @@ function limitLines(s, n) {
2138
2148
  return lines.slice(0, n).join("\n") + `
2139
2149
  \u2026 +${lines.length - n} more lines (scroll up after next submit)`;
2140
2150
  }
2151
+ function displayQuery(query) {
2152
+ const cols = process.stdout.columns ?? 80;
2153
+ const max = Math.max(20, cols - 16);
2154
+ const flat = query.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
2155
+ return flat.length > max ? flat.slice(0, max) + "\u2026" : flat;
2156
+ }
2141
2157
  function EntryView({ entry }) {
2142
2158
  const showAi = entry.aiResponse !== "" || entry.aiError !== null;
2143
2159
  const showErd = entry.erdData !== null;
@@ -2150,7 +2166,7 @@ function EntryView({ entry }) {
2150
2166
  label,
2151
2167
  " "
2152
2168
  ] }),
2153
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: entry.query })
2169
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: displayQuery(entry.query) })
2154
2170
  ] }),
2155
2171
  /* @__PURE__ */ jsx7(Box7, { marginTop: 1, flexDirection: "column", children: isShell ? entry.shellOutput !== null && /* @__PURE__ */ jsx7(Text7, { children: entry.shellOutput || "(no output)" }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
2156
2172
  entry.commandMessage && (entry.commandMessage.helpData ? /* @__PURE__ */ jsx7(HelpView, { data: entry.commandMessage.helpData }) : entry.commandMessage.ok ? /* @__PURE__ */ jsxs7(Text7, { color: theme.accent, children: [
@@ -2433,7 +2449,7 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
2433
2449
  activeLabel,
2434
2450
  " "
2435
2451
  ] }),
2436
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: lastQuery })
2452
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: displayQuery(lastQuery) })
2437
2453
  ] }),
2438
2454
  /* @__PURE__ */ jsx7(Box7, { marginTop: 1, flexDirection: "column", children: isShellEntry ? isShellRunning ? /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "running\u2026" }) : /* @__PURE__ */ jsx7(Text7, { children: limitLines(shellOutput ?? "", activePageSize()) }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
2439
2455
  commandMessage && (commandMessage.helpData ? /* @__PURE__ */ jsx7(HelpView, { data: commandMessage.helpData }) : commandMessage.ok ? /* @__PURE__ */ jsxs7(Text7, { color: theme.accent, children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deaquinodev/querky",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "A quirky terminal SQL client with vim mode, AI features, and schema-aware autocomplete",
5
5
  "main": "dist/index.js",
6
6
  "files": [