on main help sign in
add sigil search
8458711John Hyde
desk/app/astrolabe.hoon+20−7
@@ -67,13 +67,15 @@
67 =/ =ship `@p`(slav %p &3.path)
67 =/ =ship `@p`(slav %p &3.path)
68 =/ arg ?~(t.t.t.t.path %all i.t.t.t.t.path)
68 =/ arg ?~(t.t.t.t.path %all i.t.t.t.t.path)
69 ``astrolabe-point-set+!>((get-spawned-points:hc ship arg))
69 ``astrolabe-point-set+!>((get-spawned-points:hc ship arg))
70− [%x %search @ ?(~ [%narrow ~])]
70+ [%x %search %patp @ ?(~ [%narrow ~])]
71− =/ =search-text (trip &3.path)
71+ =/ =search-text (trip &4.path)
72 ?~ search-text ~|(%search-predicted-too-broad !!)
72 ?~ search-text ~|(%search-predicted-too-broad !!)
73− ~& "search text"
74− ~& search-text
75 =/ expand-search =(t.t.t.path ~)
73 =/ expand-search =(t.t.t.path ~)
76− ``astrolabe-point-set+!>((search-opoints:hc search-text expand-search))
74+ ``astrolabe-point-set+!>((search-opoints-patp:hc search-text expand-search))
75+ [%x %search %sigil @ ~]
76+ =/ =search-text (trip &4.path)
77+ ?~ search-text ~|(%search-predicted-too-broad !!)
78+ ``astrolabe-point-set+!>((search-opoints-sigil:hc search-text))
77 [%x %peers ~]
79 [%x %peers ~]
78 =/ peers .^((map ship ?(%alien %known)) %ax (scrio:hc %$ /peers))
80 =/ peers .^((map ship ?(%alien %known)) %ax (scrio:hc %$ /peers))
79 ``astrolabe-point-set+!>((turn ~(tap in peers) head))
81 ``astrolabe-point-set+!>((turn ~(tap in peers) head))
@@ -265,14 +267,25 @@
265 |= [agg=@ud [spawn=ship *]]
267 |= [agg=@ud [spawn=ship *]]
266 +(agg)
268 +(agg)
267::
269::
268−++ search-opoints
270+++ search-opoints-patp
269 |= [=search-text expand-search=?]
271 |= [=search-text expand-search=?]
270 ^- (list ship)
272 ^- (list ship)
271 =/ search-fulls
273 =/ search-fulls
272 ?: expand-search
274 ?: expand-search
273 (search-text-to-fulls search-text)
275 (search-text-to-fulls search-text)
274 ~[(search-text-to-full search-text)]
276 ~[(search-text-to-full search-text)]
277+ (search-opoints search-fulls)
278+::
279+++ search-opoints-sigil
280+ |= [=search-text]
281+ ^- (list ship)
282+ =/ search-fulls
275− :: ~& (turn search-fulls |=(=search-full search-syls.search-full))
283+ ~[(sigil-search-text-to-full search-text)]
284+ (search-opoints search-fulls)
285+::
286+++ search-opoints
287+ |= [search-fulls=(list search-full)]
288+ ^- (list ship)
276 =/ mr-searches (maybe-reverse-searches search-fulls 1.000)
289 =/ mr-searches (maybe-reverse-searches search-fulls 1.000)
277 :: ~& (turn mr-searches |=(=mr-search pain.mr-search))
290 :: ~& (turn mr-searches |=(=mr-search pain.mr-search))
278 :: ~& mr-searches
291 :: ~& mr-searches
desk/lib/astrolabe.hoon+9
@@ -54,6 +54,15 @@
54 .= linear-star-release:contracts:azimuth
54 .= linear-star-release:contracts:azimuth
55 address.owner.own.p
55 address.owner.own.p
56::
56::
57+++ split
58+ |* [nedl=(list) hstk=(list)]
59+ |- ^- (list _hstk)
60+ =/ brk (find nedl hstk)
61+ ?~ brk ~[hstk]
62+ =/ next (add u.brk (lent nedl))
63+ :- (scag u.brk hstk)
64+ $(hstk (slag next hstk))
65+::
57++ smel
66++ smel
58 |%
67 |%
59 ++ ship
68 ++ ship
desk/lib/search.hoon+47−5
@@ -12,7 +12,7 @@
12++ prefixes ^~ (trip-syls sis:po)
12++ prefixes ^~ (trip-syls sis:po)
13++ suffixes ^~ (trip-syls dex:po)
13++ suffixes ^~ (trip-syls dex:po)
14++ full-opts ^~ (gulf .~zod .~fes)
14++ full-opts ^~ (gulf .~zod .~fes)
15−++ galaxies ^~ `(list @p)``(list @)`full-opts
15+++ galaxies ^~ `(list @p)`full-opts
16++ sanitize-search-text
16++ sanitize-search-text
17 |= =search-text
17 |= =search-text
18 ^- tape
18 ^- tape
@@ -129,6 +129,25 @@
129 ?: =(~[~ ~ ~ ~] search-opts.full)
129 ?: =(~[~ ~ ~ ~] search-opts.full)
130 ~
130 ~
131 (some full)
131 (some full)
132+::
133+++ sigil-search-text-to-full
134+ |= text=tape
135+ ^- search-full
136+ :- ~
137+ ^- search-opts
138+ %- flop
139+ %+ turn
140+ (split "_" text)
141+ |= ints-tape=tape
142+ ^- search-syl-opts
143+ ?: =(ints-tape "any")
144+ full-opts
145+ %+ turn
146+ (split "." ints-tape)
147+ |= =tape
148+ ~& tape
149+ `@q`(slav %ud (crip tape))
150+::
132++ reverse-list :: that is, put first 2 in back "abcd" -> "cdab"
151++ reverse-list :: that is, put first 2 in back "abcd" -> "cdab"
133 |* lst=(list)
152 |* lst=(list)
134 ^- _lst
153 ^- _lst
@@ -221,7 +240,10 @@
221 |= [=syl cand=@]
240 |= [=syl cand=@]
222 :: todo check cand < 256
241 :: todo check cand < 256
223 (tape-matches tape.syl (trip (tosd cand pfsf.syl)))
242 (tape-matches tape.syl (trip (tosd cand pfsf.syl)))
243+++ syl-opts-match
244+ |= [opts=search-syl-opts cand=@]
245+ !=(~ (find ~[cand] opts))
224−++ matches-search
246+++ matches-search-syls
225 |= [search=search-syls cand-atom=@]
247 |= [search=search-syls cand-atom=@]
226 =/ cand (rip 3 cand-atom)
248 =/ cand (rip 3 cand-atom)
227 |-
249 |-
@@ -240,6 +262,28 @@
240 $(search t.search, cand t.cand)
262 $(search t.search, cand t.cand)
241 ==
263 ==
242::
264::
265+++ matches-search-opts
266+ |= [search=search-opts cand-atom=@]
267+ =/ cand (rip 3 cand-atom)
268+ |-
269+ ^- ?
270+ ?~ search =(cand ~)
271+ ?~ cand
272+ ?& (syl-opts-match i.search 0)
273+ $(search t.search)
274+ ==
275+ :: =/ nncand ^- (lest @)
276+ :: ?~ cand ~[0] cand
277+ ?& (syl-opts-match i.search i.cand)
278+ $(search t.search, cand t.cand)
279+ ==
280+::
281+++ matches-search
282+ |= [search=search-full cand-atom=@]
283+ ?~ search-syls.search
284+ (matches-search-opts search-opts.search cand-atom)
285+ (matches-search-syls search-syls.search cand-atom)
286+::
243++ opts-in-range
287++ opts-in-range
244 |= [lb=@ rb=@ opts=(list @)]
288 |= [lb=@ rb=@ opts=(list @)]
245 ^- search-syl-opts
289 ^- search-syl-opts
@@ -282,8 +326,6 @@
282 |* [agg=mold search=search-full points=opoints =page-info]
326 |* [agg=mold search=search-full points=opoints =page-info]
283 |= [res=[count=@ =agg] f=$-([agg @q] agg)]
327 |= [res=[count=@ =agg] f=$-([agg @q] agg)]
284 ^- [count=@ =agg]
328 ^- [count=@ =agg]
285− =/ s-syls search-syls.search
286− :: ~& s-syls
287 =/ s-opts search-opts.search
329 =/ s-opts search-opts.search
288 =+ [llb=.~zod rrb=`@q`(sub (bex 32) 1)]
330 =+ [llb=.~zod rrb=`@q`(sub (bex 32) 1)]
289 :: =< +
331 :: =< +
@@ -302,7 +344,7 @@
302 =/ right-view (range-contains-search rlb rrb s-opts)
344 =/ right-view (range-contains-search rlb rrb s-opts)
303 =? res contains.left-view
345 =? res contains.left-view
304 $(points l.points, rrb lrb, s-opts opts.left-view)
346 $(points l.points, rrb lrb, s-opts opts.left-view)
305− =? res (matches-search s-syls n)
347+ =? res (matches-search search n)
306 =/ fits (fits-on-page count.res page-info)
348 =/ fits (fits-on-page count.res page-info)
307 =. count.res +(count.res)
349 =. count.res +(count.res)
308 =? agg.res fits (f agg.res n)
350 =? agg.res fits (f agg.res n)
ui/src/components/search/SearchResults.svelte+4−3
@@ -10,7 +10,7 @@
10
10
11 export let regexQuery: RegExp;
11 export let regexQuery: RegExp;
12 export let sigilQuery: SigilQuery;
12 export let sigilQuery: SigilQuery;
13− export let search: string;
13+ export let patpSearch: string;
14 export let searchMode: ('patp' | 'sigil') = 'patp';
14 export let searchMode: ('patp' | 'sigil') = 'patp';
15 // export let patp: string;
15 // export let patp: string;
16 let combinedSearchResults = [];
16 let combinedSearchResults = [];
@@ -40,7 +40,7 @@
40 // clearTimeout(otherTimer);
40 // clearTimeout(otherTimer);
41 // if (searchMode === 'sigil') {
41 // if (searchMode === 'sigil') {
42 // otherTimer = setTimeout(() => {
42 // otherTimer = setTimeout(() => {
43− // searchedContacts.search(regexQuery, searchMode);
43+ // searchedContacts.patpSearch(regexQuery, searchMode);
44 // }, 1000);
44 // }, 1000);
45 // }
45 // }
46 // }
46 // }
@@ -64,7 +64,8 @@
64 }
64 }
65 });
65 });
66 }
66 }
67− $: [search, sigilQuery], doSearch();
67+ $: search = (searchMode === 'sigil') ? sigilQuery.string : patpSearch;
68+ $: [search], doSearch();
68
69
69 $: {
70 $: {
70 const contactSearchResults: Rolodex = JSON.parse(JSON.stringify($searchedContacts));
71 const contactSearchResults: Rolodex = JSON.parse(JSON.stringify($searchedContacts));
ui/src/components/search/sigil/SigilInput.svelte+2−2
@@ -16,7 +16,7 @@ import { sigil } from '@tlon/sigil-js';
16
16
17 // let symbols: SymbolQuery = [];
17 // let symbols: SymbolQuery = [];
18
18
19− $: gridClasses = (sigilQuery.clan === 'galaxy' ? 'max-w-[10rem] grid items-center' : 'grid grid-cols-2 items-center');
19+ $: gridClasses = (sigilQuery.clan === 'galaxy' ? 'max-w-[10rem] grid items-center' : 'max-w-[18rem] grid grid-cols-2 items-center');
20
20
21 function unfocusSymbol() {
21 function unfocusSymbol() {
22 focusedSymbolIndex = undefined;
22 focusedSymbolIndex = undefined;
@@ -42,7 +42,7 @@ import { sigil } from '@tlon/sigil-js';
42 <ClanSelect bind:clan={sigilQuery.clan} />
42 <ClanSelect bind:clan={sigilQuery.clan} />
43 <div class="flex flex-col xs:flex-row">
43 <div class="flex flex-col xs:flex-row">
44 <div class="grow-[2] w-full xs:m-0 xs:max-w-[18rem]" on:click={unfocusSymbol}>
44 <div class="grow-[2] w-full xs:m-0 xs:max-w-[18rem]" on:click={unfocusSymbol}>
45− <div class="max-w-[18rem] min-h-[14rem] mx-auto p-4 {gridClasses} xs:rounded-bl-2xl">
45+ <div class="min-h-[14rem] mx-auto p-4 {gridClasses} xs:rounded-bl-2xl">
46 {#each sigilQuery.activeSymbols as symbol, index}
46 {#each sigilQuery.activeSymbols as symbol, index}
47 <SymbolInput
47 <SymbolInput
48 bind:symbolQuery={symbol}
48 bind:symbolQuery={symbol}
ui/src/components/search/sigil/Symbol.svelte+1−1
@@ -9,7 +9,7 @@
9 export let fgColor: string = 'black';
9 export let fgColor: string = 'black';
10 export let bgColor: string = 'white';
10 export let bgColor: string = 'white';
11 export let altBgColor: string = undefined;
11 export let altBgColor: string = undefined;
12− export let hoverColor: string = 'blue';
12+ export let hoverColor: string = '#8f8';
13 export let opacity: number = 1;
13 export let opacity: number = 1;
14 export let inverted: boolean = false;
14 export let inverted: boolean = false;
15 export let interactive: boolean = false;
15 export let interactive: boolean = false;
ui/src/lib/api.ts+1−1
@@ -27,7 +27,7 @@ export function getPeers(): Promise<any> {
27}
27}
28
28
29export async function searchPoints(search: string, mode: ('patp' | 'sigil')): Promise<Patp[]> {
29export async function searchPoints(search: string, mode: ('patp' | 'sigil')): Promise<Patp[]> {
30− const { points } = await scry<any>(`/search/${search}`);
30+ const { points } = await scry<any>(`/search/${mode}/${search}`);
31 return points.map(normalizeId);
31 return points.map(normalizeId);
32}
32}
33
33
ui/src/lib/sigil.ts+31−8
@@ -33,9 +33,10 @@ export class SigilQuery {
33 this.symbols.forEach((symbol, i) => {
33 this.symbols.forEach((symbol, i) => {
34 if (i % 2 === 0) {
34 if (i % 2 === 0) {
35 symbol.symbolType = 'prefix';
35 symbol.symbolType = 'prefix';
36+ // symbol.components = ['gci', 'lhf'];
36 } else {
37 } else {
37 symbol.symbolType = 'suffix';
38 symbol.symbolType = 'suffix';
38− // symbol.components = ['gsq', 'ablf2']
39+ // symbol.components = ['gsq', 'atrf4'];
39 }
40 }
40 });
41 });
41 this.symbols = this.symbols;
42 this.symbols = this.symbols;
@@ -50,13 +51,17 @@ export class SigilQuery {
50 }
51 }
51
52
52 get isPlausible() {
53 get isPlausible() {
53− return this.activeSymbols.every(symbol => !symbol.isPlausible);
54+ return this.activeSymbols.every(symbol => symbol.isPlausible);
54 }
55 }
55
56
56 get querySyls(): string[][] {
57 get querySyls(): string[][] {
57 return this.activeSymbols.map(symbol => symbol.plausibleSyllables);
58 return this.activeSymbols.map(symbol => symbol.plausibleSyllables);
58 }
59 }
59
60
61+ get queryInts(): number[][] {
62+ return this.activeSymbols.map(symbol => symbol.plausibleInts);
63+ }
64+
60 get isDefinitive() {
65 get isDefinitive() {
61 return this.querySyls.every(syls => syls.length === 1);
66 return this.querySyls.every(syls => syls.length === 1);
62 }
67 }
@@ -65,8 +70,14 @@ export class SigilQuery {
65 return this.activeSymbols.some(symbol => symbol.components.length > 0);
70 return this.activeSymbols.some(symbol => symbol.components.length > 0);
66 }
71 }
67
72
73+ get isWorthSearching() {
74+ if (!this.isNotEmpty) return false; // 🙃
75+ if (!this.isPlausible) return false;
76+ return 100000 > this.querySyls.reduce((acc, syls) => acc * (syls.length || 256), 1);
77+ }
78+
68 get string(): string {
79 get string(): string {
69− return this.symbols.map((symbol) => symbol.components.join(',')).join('|')
80+ return this.queryInts.map((int) => int.length == 256 ? 'any' : int.join('.')).join('_');
70 }
81 }
71
82
72 setSymbol(symbol: SymbolQuery, activeSymbolIndex: number) {
83 setSymbol(symbol: SymbolQuery, activeSymbolIndex: number) {
@@ -92,15 +103,18 @@ function addEquivalentParts(parts: string[]): string[] {
92 return [...parts, ...moreParts];
103 return [...parts, ...moreParts];
93}
104}
94
105
95−export function getPlausibleSyllables(parts: string[], symbolType: SymbolType): string[] {
106+function getSyllablesBySymbolType(symbolType: SymbolType): string[] {
96− let plausibleSyllables: string[];
97 if (symbolType === 'prefix') {
107 if (symbolType === 'prefix') {
98− plausibleSyllables = prefixes;
108+ return prefixes;
99 } else if (symbolType === 'suffix') {
109 } else if (symbolType === 'suffix') {
100− plausibleSyllables = suffixes;
110+ return suffixes;
101 } else {
111 } else {
102− plausibleSyllables = [...prefixes, ...suffixes];
112+ return [...prefixes, ...suffixes];
103 }
113 }
114+}
115+
116+export function getPlausibleSyllables(parts: string[], symbolType: SymbolType): string[] {
117+ let plausibleSyllables = getSyllablesBySymbolType(symbolType);
104 const possibilitiesByPart = parts.map((partId) => {
118 const possibilitiesByPart = parts.map((partId) => {
105 let parents = partParents[partId];
119 let parents = partParents[partId];
106 const otherPart = equivalentParts[partId];
120 const otherPart = equivalentParts[partId];
@@ -113,6 +127,11 @@ export function getPlausibleSyllables(parts: string[], symbolType: SymbolType):
113 return plausibleSyllables;
127 return plausibleSyllables;
114}
128}
115
129
130+function convertSyllableToInt(syl: string, symbolType: SymbolType): number {
131+ let syls = getSyllablesBySymbolType(symbolType);
132+ return syls.findIndex(s => s === syl) % 256;
133+}
134+
116export function getPlausibleNewParts(parts: string[], symbolType: SymbolType): string[] {
135export function getPlausibleNewParts(parts: string[], symbolType: SymbolType): string[] {
117 const syllables: string[] = getPlausibleSyllables(parts, symbolType);
136 const syllables: string[] = getPlausibleSyllables(parts, symbolType);
118 let plausibleParts = uniq(syllables.map((syllable) => symbolDefs[syllable]).flat());
137 let plausibleParts = uniq(syllables.map((syllable) => symbolDefs[syllable]).flat());
@@ -205,6 +224,10 @@ export class SymbolQuery {
205 return getPlausibleSyllables(this.components, this.symbolType);
224 return getPlausibleSyllables(this.components, this.symbolType);
206 }
225 }
207
226
227+ get plausibleInts() {
228+ return this.plausibleSyllables.map(syl => convertSyllableToInt(syl, this.symbolType));
229+ }
230+
208 get isPlausible() {
231 get isPlausible() {
209 return this.plausibleSyllables.length > 0;
232 return this.plausibleSyllables.length > 0;
210 }
233 }
ui/src/routes/Home.svelte+3−3
@@ -146,9 +146,9 @@
146 <StarChart patp={analysis.patpIsValid ? analysis.patp : null} />
146 <StarChart patp={analysis.patpIsValid ? analysis.patp : null} />
147 {:else if analysis.patpIsValid}
147 {:else if analysis.patpIsValid}
148 <ShipView patp={analysis.patp} />
148 <ShipView patp={analysis.patp} />
149− {:else if (searchMode === 'patp' && analysis.queryIsValid) || (searchMode == 'sigil' && sigilQuery.isNotEmpty)}
149+ {:else if (searchMode === 'patp' && analysis.queryIsValid) || (searchMode == 'sigil' && sigilQuery.isWorthSearching)}
150− <SearchResults regexQuery={analysis.query} sigilQuery={sigilQuery} search={analysis.search}
150+ <SearchResults regexQuery={analysis.query} sigilQuery={sigilQuery}
151− {searchMode} />
151+ patpSearch={analysis.search} {searchMode} />
152 {:else if (analysis.search.length > 0)}
152 {:else if (analysis.search.length > 0)}
153 <ValidationProblems problems={analysis.queryProblems} />
153 <ValidationProblems problems={analysis.queryProblems} />
154 {:else}
154 {:else}