diff --git a/script.js b/script.js index ebc4000..c06bdc5 100644 --- a/script.js +++ b/script.js @@ -914,9 +914,28 @@ $q.focus(); } + function buildSearchMatchExpression(rawInput) { + const trimmed = String(rawInput || '').trim(); + if (!trimmed) return ''; + + // Preserve power user syntax (field scoping, phrase searches, boolean ops) + if (/["':*()^+-]/.test(trimmed)) { + return trimmed; + } + + const tokens = trimmed + .split(/\s+/) + .map((token) => token.replace(/[^0-9a-z]/gi, '').toLowerCase()) + .filter(Boolean); + + if (!tokens.length) return ''; + + return tokens.map((token) => `${token}*`).join(' '); + } + function runSearchImmediate() { - const term = state.query.trim(); - if (!term) { + const matchExpr = buildSearchMatchExpression(state.query); + if (!matchExpr) { table.clear(); listState.showIdle('Type to search…'); return; @@ -931,10 +950,11 @@ try { console.debug('[Search] Preparing count query', { sql: countSql.trim(), - params: [term], + params: [matchExpr], + chars: Array.from(matchExpr).map((ch) => ch.codePointAt(0)), }); const countStmt = db.prepare(countSql); - countStmt.bind([term]); + countStmt.bind([matchExpr]); if (countStmt.step()) { const row = countStmt.getAsObject(); total = Number(row.count) || 0; @@ -951,10 +971,11 @@ state.page = Math.max(1, Math.ceil(total / state.pageSize)); } - const searchParams = [term, state.pageSize, (state.page - 1) * state.pageSize]; + const searchParams = [matchExpr, state.pageSize, (state.page - 1) * state.pageSize]; console.debug('[Search] Preparing row query', { sql: effectiveSearchSql.trim(), params: searchParams, + chars: Array.from(matchExpr).map((ch) => ch.codePointAt(0)), }); const searchStmt = db.prepare(effectiveSearchSql); searchStmt.bind(searchParams);