From f62fc97557e172f1379503e70d4538c4177447bd Mon Sep 17 00:00:00 2001 From: Lukas Werner Date: Tue, 2 Jun 2026 13:25:49 -0700 Subject: [PATCH] feat: add config support --- README.md | 27 ++++++++++--------- cmd/createEmbeddings.go | 2 +- cmd/delete.go | 4 ++- cmd/dump.go | 8 ++++-- cmd/edit.go | 6 +++-- cmd/open.go | 6 +++-- cmd/root.go | 4 ++- cmd/show.go | 7 ++--- cmd/web-search.go | 20 +++++++++++--- go.mod | 19 ++++++------- go.sum | 14 ++++++++++ http/api.go | 4 ++- justfile | 1 + search/data.go | 8 ++++++ store/config.go | 57 +++++++++++++++++++++++++++++++++++++++ store/database.go | 60 ++++++++++++++++------------------------- store/tasks.txt | 20 ++++++++++++++ store/util.go | 12 +++++++++ web/results.templ | 9 +------ 19 files changed, 205 insertions(+), 83 deletions(-) create mode 100644 store/config.go create mode 100644 store/tasks.txt diff --git a/README.md b/README.md index e411c3d..135bf51 100644 --- a/README.md +++ b/README.md @@ -25,19 +25,20 @@ Google Drive, Syncthing etc) to synchronize only the changes folder. ### Usage ``` Available Commands: - add Add a bookmark - completion Generate the autocompletion script for the specified shell - delete deletes bookmarks based on given search query - dump dumps the database to a sqlite3 file - edit Edit a bookmark - help Help about any command - import Lets you import bookmarks from an existing csv - keys List all allowed api keys for the local http server - open Opens the matching search link in the user's browser - search [EXPERIMENTAL] google search like tui intended for hosting via gotty or ttyd - server Local HTTP server for managing bookmarks (used for chrome extension) - show Shows the entry of a bookmark - sql Lets you run sql queries on your database + add Add a bookmark + completion Generate the autocompletion script for the specified shell + createEmbeddings Generates vector embeddings that are not currently in the embeddings table + delete deletes bookmarks based on given search query + dump dumps the database to a sqlite3 file + edit Edit a bookmark + help Help about any command + import Lets you import bookmarks from an existing csv + keys List all allowed api keys for the local http server + open Opens the matching search link in the user's browser + search [EXPERIMENTAL] google search like interface + server Local HTTP server for managing bookmarks + show Shows the entry of a bookmark + sql Lets you run sql queries on your database ``` diff --git a/cmd/createEmbeddings.go b/cmd/createEmbeddings.go index 7833b5e..4de8f88 100644 --- a/cmd/createEmbeddings.go +++ b/cmd/createEmbeddings.go @@ -34,7 +34,7 @@ var createEmbeddingsCmd = &cobra.Command{ log.Fatalln(err.Error()) } rows, _ := res.RowsAffected() - fmt.Printf("Successfully did %s rows\n", rows) + fmt.Printf("Successfully did %d rows\n", rows) }, } diff --git a/cmd/delete.go b/cmd/delete.go index 405eb02..b17d897 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/charmbracelet/huh" + "github.com/lukasmwerner/mark/search" "github.com/lukasmwerner/mark/store" "github.com/spf13/cobra" ) @@ -30,11 +31,12 @@ var deleteCmd = &cobra.Command{ searchQuery := strings.Join(args, " ") - bookmarks, err := store.SearchBookmarks(db, searchQuery) + results, err := search.FullText5(db, searchQuery) if err != nil { fmt.Println("unable to search bookmarks", err.Error()) return } + bookmarks := search.ToBookmarks(results) for _, bm := range bookmarks { var affirmative bool err := huh.NewConfirm().Title("Delete?"). diff --git a/cmd/dump.go b/cmd/dump.go index 2e746fa..b11c59a 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -13,9 +13,13 @@ import ( // dumpCmd represents the dump command var dumpCmd = &cobra.Command{ - Use: "dump", + Use: "dump filename.db", Short: "dumps the database to a sqlite3 file", - Args: cobra.MinimumNArgs(1), + Long: `Creates a large dump of the bookmarks table into a new sqlite3. Useful for exports and sharing of bookmark data. +Example Use: + +mark dump ~/Downloads/my_bookmarks.db`, + Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { db, err := store.Open(store.Options{ Flags: []store.Flag{store.Embedding}, diff --git a/cmd/edit.go b/cmd/edit.go index 96d21a0..78eba6c 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/charmbracelet/huh" + "github.com/lukasmwerner/mark/search" "github.com/lukasmwerner/mark/store" "github.com/spf13/cobra" ) @@ -40,15 +41,16 @@ var editCmd = &cobra.Command{ } } - bookmarks, err := store.SearchBookmarks(db, searchQuery) + results, err := search.FullText5(db, searchQuery) if err != nil { fmt.Println("unable to search bookmarks", err.Error()) return } - if len(bookmarks) == 0 { + if len(results) == 0 { fmt.Println("found no bookmarks") return } + bookmarks := search.ToBookmarks(results) if len(bookmarks) != 1 { pickedIndex := 0 diff --git a/cmd/open.go b/cmd/open.go index 365a7df..e395809 100644 --- a/cmd/open.go +++ b/cmd/open.go @@ -9,6 +9,7 @@ import ( "github.com/charmbracelet/huh" "github.com/cli/browser" + "github.com/lukasmwerner/mark/search" "github.com/lukasmwerner/mark/store" "github.com/spf13/cobra" ) @@ -31,15 +32,16 @@ var openCmd = &cobra.Command{ searchQuery := strings.Join(args, " ") - bookmarks, err := store.SearchBookmarks(db, searchQuery) + results, err := search.FullText5(db, searchQuery) if err != nil { fmt.Println("unable to search bookmarks", err.Error()) return } - if len(bookmarks) == 0 { + if len(results) == 0 { fmt.Println("found no bookmarks") return } + bookmarks := search.ToBookmarks(results) if len(bookmarks) == 1 { fmt.Printf("Opening %s %s\n", bookmarks[0].Title, bookmarks[0].Url) diff --git a/cmd/root.go b/cmd/root.go index bde2207..7ec0622 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,6 +16,7 @@ import ( "github.com/charmbracelet/lipgloss" "github.com/cli/browser" "github.com/lukasmwerner/mark/helpers" + "github.com/lukasmwerner/mark/search" "github.com/lukasmwerner/mark/store" "github.com/spf13/cobra" ) @@ -79,11 +80,12 @@ func (m rootAppModel) updateTable() rootAppModel { var bookmarks []store.Bookmark var err error if m.input.Value() != "" { - bookmarks, err = store.SearchBookmarks(m.db, m.input.Value()) + results, err := search.FullText5(m.db, m.input.Value()) if err != nil { log.Panicln(err) return m } + bookmarks = search.ToBookmarks(results) } else { bookmarks, err = store.GetBookmarks(m.db) if err != nil { diff --git a/cmd/show.go b/cmd/show.go index 07a33b3..05047a5 100644 --- a/cmd/show.go +++ b/cmd/show.go @@ -12,6 +12,7 @@ import ( "github.com/charmbracelet/huh" "github.com/charmbracelet/lipgloss" + "github.com/lukasmwerner/mark/search" "github.com/lukasmwerner/mark/store" "github.com/spf13/cobra" ) @@ -36,15 +37,16 @@ var showCmd = &cobra.Command{ searchQuery := strings.Join(args, " ") - bookmarks, err := store.SearchBookmarks(db, searchQuery) + results, err := search.FullText5(db, searchQuery) if err != nil { fmt.Println("unable to search bookmarks", err.Error()) return } - if len(bookmarks) == 0 { + if len(results) == 0 { fmt.Println("found no bookmarks") return } + bookmarks := search.ToBookmarks(results) if len(bookmarks) != 1 { pickedIndex := 0 @@ -64,7 +66,6 @@ var showCmd = &cobra.Command{ } outputBookmark(outputMode, bookmarks[0]) - return }, } diff --git a/cmd/web-search.go b/cmd/web-search.go index 4601ccc..740c593 100644 --- a/cmd/web-search.go +++ b/cmd/web-search.go @@ -4,9 +4,11 @@ Copyright © 2025 Lukas Werner package cmd import ( + "errors" "fmt" "log" "net/http" + "os" _ "embed" @@ -22,8 +24,20 @@ var searchCmd = &cobra.Command{ Use: "search", Short: `[EXPERIMENTAL] google search like interface`, Run: func(cmd *cobra.Command, args []string) { + config, err := store.LoadConfig() + if errors.Is(err, os.ErrNotExist) { + config, err = store.SaveDefaultConfig() + if err != nil { + log.Println(err.Error()) + return + } + } else if err != nil { + log.Println(err.Error()) + return + } + db, err := store.Open(store.Options{ - Flags: []store.Flag{store.Embedding}, + Flags: config.Flags, }) if err != nil { log.Println(err.Error()) @@ -45,11 +59,11 @@ var searchCmd = &cobra.Command{ fmt.Fprintln(w, err.Error()) return } - templ.Handler(web.ResultsPage("lukaswerner.com", q, "(FTS + Embeddings) RRF", results)).ServeHTTP(w, r) + templ.Handler(web.ResultsPage(config.Domain, q, results)).ServeHTTP(w, r) }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { n := store.CountBookmarks(db) - templ.Handler(web.LandingPage("lukaswerner.com", n)).ServeHTTP(w, r) + templ.Handler(web.LandingPage(config.Domain, n)).ServeHTTP(w, r) }) err = http.ListenAndServe(":1995", nil) diff --git a/go.mod b/go.mod index d479993..5842035 100644 --- a/go.mod +++ b/go.mod @@ -1,29 +1,30 @@ module github.com/lukasmwerner/mark -go 1.24.1 +go 1.25.0 require ( github.com/PuerkitoBio/goquery v1.9.2 - github.com/a-h/templ v0.3.1001 + github.com/a-h/templ v0.3.1020 + github.com/asg017/sqlite-vec-go-bindings v0.1.6 github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/huh v0.5.2 github.com/cli/browser v1.3.0 github.com/fsnotify/fsnotify v1.9.0 github.com/mattn/go-sqlite3 v1.14.24 + github.com/ollama/ollama v0.23.0 github.com/spf13/cobra v1.8.1 ) require ( - github.com/asg017/sqlite-vec-go-bindings v0.1.6 // indirect + github.com/BurntSushi/toml v1.6.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/charmbracelet/colorprofile v0.3.2 // indirect github.com/charmbracelet/x/cellbuf v0.0.13 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/ollama/ollama v0.23.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - golang.org/x/crypto v0.43.0 // indirect + golang.org/x/crypto v0.48.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -55,8 +56,8 @@ require ( github.com/sahilm/fuzzy v0.1.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/net v0.46.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/net v0.51.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect ) diff --git a/go.sum b/go.sum index cc5be1d..e25280c 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,13 @@ +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE= github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= github.com/a-h/templ v0.3.960 h1:trshEpGa8clF5cdI39iY4ZrZG8Z/QixyzEyUnA7feTM= github.com/a-h/templ v0.3.960/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= github.com/a-h/templ v0.3.1001 h1:yHDTgexACdJttyiyamcTHXr2QkIeVF1MukLy44EAhMY= github.com/a-h/templ v0.3.1001/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= +github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw= +github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/asg017/sqlite-vec-go-bindings v0.1.6 h1:Nx0jAzyS38XpkKznJ9xQjFXz2X9tI7KqjwVxV8RNoww= @@ -132,6 +136,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -145,6 +151,8 @@ golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -155,6 +163,8 @@ golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -175,6 +185,8 @@ golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -192,6 +204,8 @@ golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/http/api.go b/http/api.go index 3d053d3..c54d942 100644 --- a/http/api.go +++ b/http/api.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" + "github.com/lukasmwerner/mark/search" "github.com/lukasmwerner/mark/store" ) @@ -16,11 +17,12 @@ func SearchBookmarksHandler(db *store.DB) http.Handler { http.Error(w, "Missing query parameter", http.StatusBadRequest) return } - bookmarks, err := store.SearchBookmarks(db, query) + results, err := search.FullText5(db, query) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } + bookmarks := search.ToBookmarks(results) w.Header().Set("Content-Type", "application/json") jsonBytes, err := json.Marshal(bookmarks) if err != nil { diff --git a/justfile b/justfile index d47713b..f764336 100644 --- a/justfile +++ b/justfile @@ -5,6 +5,7 @@ home_dir := env_var('HOME') # Install the Go application install: + templ generate go install -tags "fts5" . mac-service-install: install diff --git a/search/data.go b/search/data.go index 109ecb4..471be5f 100644 --- a/search/data.go +++ b/search/data.go @@ -12,3 +12,11 @@ type Bookmark interface { Get() store.Bookmark Score() float64 } + +func ToBookmarks(results []Bookmark) []store.Bookmark { + res := make([]store.Bookmark, len(results)) + for i, b := range results { + res[i] = b.Get() + } + return res +} diff --git a/store/config.go b/store/config.go new file mode 100644 index 0000000..fc0c455 --- /dev/null +++ b/store/config.go @@ -0,0 +1,57 @@ +package store + +import ( + "errors" + "os" + "path" + + "github.com/BurntSushi/toml" +) + +type Service string + +const ( + APIServer = Service("api") + SearchServer = Service("search") +) + +type Config struct { + Domain string + Flags []Flag `toml:"Features"` + Servers []Service +} + +func LoadConfig() (Config, error) { + markStoreLocation, err := GetStoragePath() + if err != nil { + return Config{}, errors.Join(errors.New("unable to get mark store location"), err) + } + config := &Config{} + _, err = toml.DecodeFile(path.Join(markStoreLocation, "config.toml"), config) + if err != nil { + return Config{}, err + } + return *config, err +} + +var defaultConfig = Config{ + Domain: "lukaswerner.com", + Flags: []Flag{Embedding}, + Servers: []Service{APIServer}, +} + +func SaveDefaultConfig() (Config, error) { + markStoreLocation, err := GetStoragePath() + if err != nil { + return defaultConfig, errors.Join(errors.New("unable to get mark store location"), err) + } + config := defaultConfig + + f, err := os.Create(path.Join(markStoreLocation, "config.toml")) + if err != nil { + return defaultConfig, err + } + defer f.Close() + + return defaultConfig, toml.NewEncoder(f).Encode(config) +} diff --git a/store/database.go b/store/database.go index 6b39fea..7e19811 100644 --- a/store/database.go +++ b/store/database.go @@ -21,7 +21,9 @@ const CRSQLITE_VERSION = "v0.16.3" type Flag string -const Embedding = Flag("embedding") +const ( + Embedding = Flag("embedding") +) type Options struct { Flags []Flag @@ -142,13 +144,9 @@ END;`, } func Open(options Options) (*DB, error) { - markStoreLocation := os.Getenv("MARK_STORE_LOCATION") - homedir, err := os.UserHomeDir() + markStoreLocation, err := GetStoragePath() if err != nil { - return nil, errors.Join(errors.New("unable to get homedir"), err) - } - if markStoreLocation == "" { - markStoreLocation = path.Join(homedir, ".config", "mark") + return nil, errors.Join(errors.New("unable to get mark store location"), err) } if err := EnsureDirExists(markStoreLocation); err != nil { @@ -207,7 +205,7 @@ func Open(options Options) (*DB, error) { Hostname: hostname, } - err = EnsureTables(db, Tables...) + err = EnsureTables(db, options.Flags, Tables...) if err != nil { log.Println(err.Error()) } @@ -272,17 +270,31 @@ func (db *DB) FSWatcher() { case event := <-watcher.Events: if event.Has(fsnotify.Write) || event.Has(fsnotify.Rename) { syncronizeFromHostsToDB(db, db.Hostname, db.ChangesStoreLoc) - log.Println("sync-event!") } } } } -func EnsureTables(db *DB, tables ...requirement) error { +var UnmatchedFlag = fmt.Errorf("flags didn't match") + +func EnsureTables(db *DB, flags []Flag, tables ...requirement) error { for _, table := range tables { + ok := true if table.flags != nil { - // TODO: there are flags... need to check if we have them enabled + count := 0 + for tableFlag := range table.flags { + for flag := range flags { + if flag == tableFlag { + count += 1 + } + } + } + ok = count == len(flags) } + if !ok { + return UnmatchedFlag + } + _, err := db.Exec(table.definition) if err != nil { log.Print(table.name, err.Error()) @@ -304,32 +316,6 @@ func InsertBookmark(db *DB, bookmark Bookmark) (BookmarkId, error) { return BookmarkId(id), err } -func SearchBookmarks(db *DB, query string) ([]Bookmark, error) { - bookmarks := []Bookmark{} - - rows, err := db.Query(`SELECT url, title, description, tags - FROM Bookmarks_fts - WHERE Bookmarks_fts MATCH ? - ORDER BY bm25(Bookmarks_fts) DESC;`, query) - if err != nil { - return bookmarks, err - } - defer rows.Close() - - for rows.Next() { - var b Bookmark - var tags string - err := rows.Scan(&b.Url, &b.Title, &b.Description, &tags) - if err != nil { - return bookmarks, err - } - b.Tags = strings.Split(tags, ", ") - bookmarks = append(bookmarks, b) - } - - return bookmarks, nil -} - func GetBookmark(db *DB, query_url string) (Bookmark, error) { var b Bookmark var tags string diff --git a/store/tasks.txt b/store/tasks.txt new file mode 100644 index 0000000..2aa4048 --- /dev/null +++ b/store/tasks.txt @@ -0,0 +1,20 @@ + +func SubmitTask() { + `insert into tasks (id, )` +} + +func RunTasks() { + completedTasks := []string{} + for task := range tasks { + for matcher := range task.Matches { + results := `select from tasks where completed = 0` + if len(results) > 0 { + for result := range results { + task.Action(result) + completedTasks.append(result.id) + } + } + } + } + `delete tasks where id in {completedTasks};` +} diff --git a/store/util.go b/store/util.go index 325416f..b96b2e1 100644 --- a/store/util.go +++ b/store/util.go @@ -99,3 +99,15 @@ func justPath(s string) string { } return u.Path } + +func GetStoragePath() (string, error) { + markStoreLocation := os.Getenv("MARK_STORE_LOCATION") + homedir, err := os.UserHomeDir() + if err != nil { + return "", errors.Join(errors.New("unable to get homedir"), err) + } + if markStoreLocation == "" { + markStoreLocation = path.Join(homedir, ".config", "mark") + } + return markStoreLocation, nil +} diff --git a/web/results.templ b/web/results.templ index ab06e48..bc30cb7 100644 --- a/web/results.templ +++ b/web/results.templ @@ -28,7 +28,7 @@ func translateSource(s search.Source) string { } } -templ ResultsPage(markHostname string, query string, orderBy string, results []search.Result) { +templ ResultsPage(markHostname string, query string, results []search.Result) { @Page() { @Head(query + " - mark: " + markHostname) @Body() { @@ -44,13 +44,6 @@ templ ResultsPage(markHostname string, query string, orderBy string, results []s /> } @StatusBarGroup("") { -
-
Order By: { orderBy }
- -
@StatusBarItem(Humanize(len(results))+" Results", "#A7C080") @StatusBarItem(markHostname, "#4A545C") } -- 2.51.2