mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-04 17:07:00 +01:00
search: a write reads only its folder, and the match is lit
`file_text::catch_up` read every file without a row, which after a write meant walking every file node there is to find the one or two just put in. It now takes the part of the tree to look in: an upload asks about the folder it went into, an import about the folder it was poured into, an SFTP save about the folder it landed in, a decrypt about what was decrypted. Only an import at the root and the pass at start look at everything. The excerpt of a file found by its text marks each matched word between U+0002 and U+0003, which no text file has a use for, and the list draws them lit. A cut through a match leaves an opening without its close, and the rest is lit to the end rather than the marker shown. The screenshots are taken again, so the search one shows it.
This commit is contained in:
1 parent
767dd076dd
commit
c72b65fc38
28 files changed
+100
-30
No files matched your search
@@ -3,7 +3,7 @@
|
||||
import { carry, into, release } from './carry'
|
||||
import Icon from './Icon.svelte'
|
||||
import { workspace } from './store.svelte'
|
||||
import { formatBytes, formatDay, formatTime, formatWeekday, isTouchDevice } from './util'
|
||||
import { formatBytes, formatDay, formatTime, formatWeekday, hitParts, isTouchDevice } from './util'
|
||||
|
||||
let list = $state<HTMLUListElement>()
|
||||
/** Files are being dragged over the list, which takes them into this folder. */
|
||||
@@ -130,7 +130,7 @@
|
||||
<span class="title">
|
||||
{label(node)}{#if isContainer(node)}<span class="slash">/</span>{/if}
|
||||
{#if workspace.query && node.location}<span class="where">{node.location}</span>{/if}
|
||||
{#if workspace.query && node.in_text}<span class="hit" title="found in the file's text">{node.excerpt}</span>{/if}
|
||||
{#if workspace.query && node.in_text}<span class="hit" title="found in the file's text">{#each hitParts(node.excerpt) as part, at (at)}{#if part.lit}<mark>{part.text}</mark>{:else}{part.text}{/if}{/each}</span>{/if}
|
||||
</span>
|
||||
{#if workspace.isMarked(node.id)}<span class="badge" title="marked — p drops what is marked in a folder">m</span>{/if}
|
||||
{#if node.shared}<span class="shared" title="shared"></span>{/if}
|
||||
@@ -270,6 +270,8 @@
|
||||
color: var(--muted);
|
||||
}
|
||||
.row.active .hit { color: var(--ink); }
|
||||
.hit mark { background: none; color: var(--light); }
|
||||
.row.active .hit mark { color: var(--ink); font-weight: 700; }
|
||||
.aside { flex: none; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
||||
.badge { flex: none; font-size: 11px; font-weight: 700; color: var(--light-dim); }
|
||||
.shared {
|
||||
|
||||
@@ -346,3 +346,19 @@ export function hardWrapped(paragraph: string): boolean {
|
||||
const sentences = body.filter((line) => /[.!?:;]$/.test(line)).length
|
||||
return fits && sentences <= Math.floor((body.length - 1) / 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* A search excerpt cut into what to draw plainly and what to light: the
|
||||
* server puts each matched word between U+0002 and U+0003. A cut through the
|
||||
* middle of a match leaves an opening without its close, lit to the end.
|
||||
*/
|
||||
export function hitParts(excerpt: string): { text: string; lit: boolean }[] {
|
||||
const parts: { text: string; lit: boolean }[] = []
|
||||
let lit = false
|
||||
for (const piece of excerpt.split(/([\u0002\u0003])/)) {
|
||||
if (piece === '\u0002') lit = true
|
||||
else if (piece === '\u0003') lit = false
|
||||
else if (piece) parts.push({ text: piece, lit })
|
||||
}
|
||||
return parts
|
||||
}
|
||||
Reference in new issue
Block a user