2024-08-27 14:48:46 +02:00
package main
2024-08-28 20:29:34 +02:00
// Copyright (c) 2024 Julian Müller (ChaoticByte)
2024-08-27 14:48:46 +02:00
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" )
2025-07-11 21:32:16 +02:00
// files, entries
var files [ ] string
2024-08-27 15:27:43 +02:00
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 )
2025-07-11 21:32:16 +02:00
files , err := fs . Glob ( entriesDirFs , "*.txt" )
2024-08-27 14:48:46 +02:00
if err != nil { logger . Panicln ( err ) }
2025-07-11 21:32:16 +02:00
titles := [ ] string { }
for _ , f := range files {
fileData , err := os . ReadFile ( directory + "/" + f )
2024-08-27 14:48:46 +02:00
if err != nil { logger . Panicln ( err ) }
2025-07-11 21:32:16 +02:00
content := string ( fileData )
content = strings . Trim ( content , "\n\r " )
if strings . HasPrefix ( content , "Title:" ) {
len_content := len ( content )
title_start_idx := 6
var title_stop_idx int
if strings . Contains ( content , "\n" ) {
title_stop_idx = strings . Index ( content , "\n" )
} else {
title_stop_idx = len_content
}
title := content [ title_start_idx : title_stop_idx ]
title = strings . Trim ( title , " " )
body := content [ title_stop_idx : len_content ]
body = strings . TrimLeft ( body , "\n\r" )
if len ( body ) < 1 {
body = " "
}
titles = append ( titles , title )
entries [ title ] = body
} else {
title := f [ : len ( f ) - 4 ] // remove ".txt"
titles = append ( titles , title )
entries [ title ] = 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 )
2025-07-11 21:32:16 +02:00
return Database { Keys : titles , Entries : entries , matcher : matcher }
2024-08-27 14:48:46 +02:00
}