2024-08-27 14:48:46 +02:00
package main
import (
"io/fs"
"log"
"os"
2024-08-28 19:49:23 +02:00
"slices"
2024-08-27 14:48:46 +02:00
"strings"
2024-08-28 19:49:23 +02:00
"golang.org/x/text/search"
2024-08-27 14:48:46 +02:00
)
type Database struct {
2024-08-27 15:27:43 +02:00
Keys [ ] string
Entries map [ string ] string
2024-08-28 19:49:23 +02:00
matcher * search . Matcher
}
func ( db * Database ) search ( query string ) [ ] string { // returns keys (entry names)
results := [ ] string { }
// compile patterns
queryPatterns := [ ] * search . Pattern { }
for _ , q := range strings . Split ( query , " " ) { // per word
queryPatterns = append ( queryPatterns , db . matcher . CompileString ( q ) )
}
// search
for _ , k := range db . Keys {
patternsFound := 0
for _ , p := range queryPatterns {
if s , _ := p . IndexString ( db . Entries [ k ] ) ; s != - 1 {
patternsFound ++ // this pattern was found
}
}
if patternsFound == len ( queryPatterns ) && ! slices . Contains ( results , k ) {
// if all patterns were found, add the key (entry name) to the list
results = append ( results , k )
}
}
return results
2024-08-27 14:48:46 +02:00
}
func BuildDB ( directory string ) Database {
logger := log . Default ( )
logger . Println ( "Building database" )
2024-08-27 15:27:43 +02:00
// keys, entries
var keys [ ] string
entries := map [ string ] string { }
2024-08-27 14:48:46 +02:00
// get files in directory and read them
2024-08-28 19:49:23 +02:00
directory = strings . TrimRight ( directory , "/" ) // we don't need that last /, don't use the root directory /
2024-08-27 14:48:46 +02:00
entriesDirFs := os . DirFS ( directory )
2024-08-27 15:27:43 +02:00
keys , err := fs . Glob ( entriesDirFs , "*" )
2024-08-27 14:48:46 +02:00
if err != nil { logger . Panicln ( err ) }
2024-08-27 15:27:43 +02:00
for _ , k := range keys {
contentB , err := os . ReadFile ( directory + "/" + k )
2024-08-27 14:48:46 +02:00
if err != nil { logger . Panicln ( err ) }
2024-08-28 19:49:23 +02:00
content := string ( contentB )
entries [ k ] = content
2024-08-27 14:48:46 +02:00
}
2024-08-28 19:49:23 +02:00
matcher := search . New ( ContentLanguage , search . IgnoreCase , search . IgnoreDiacritics )
return Database { Keys : keys , Entries : entries , matcher : matcher }
2024-08-27 14:48:46 +02:00
}