diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b95ad1..0c37d98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Plaintext documents are escaped properly (regression from v1.8.0) - Help page scrollbar color matches what's in the theme config - Regression where lists would not appear if `bullets = false` (#234, #235) +- Support multiple bookmarks with the same name ## [1.8.0] - 2021-02-17 diff --git a/bookmarks/bookmarks.go b/bookmarks/bookmarks.go index 7ac9e0e..a38c548 100644 --- a/bookmarks/bookmarks.go +++ b/bookmarks/bookmarks.go @@ -159,27 +159,35 @@ func Remove(url string) { } } -// All returns all the bookmarks in a map of URLs to names. -// It also returns a slice of map keys, sorted so that the map *values* -// are in alphabetical order, with case ignored. -func All() (map[string]string, []string) { - bkmksMap := make(map[string]string) - - inverted := make(map[string]string) // Holds inverted map, name->URL - names := make([]string, len(data.Bookmarks)) // Holds bookmark names, for sorting - keys := make([]string, len(data.Bookmarks)) // Final sorted keys (URLs), for returning at the end - - for i, bkmk := range data.Bookmarks { - bkmksMap[bkmk.URL] = bkmk.Name - inverted[bkmk.Name] = bkmk.URL - names[i] = bkmk.Name - } - - // Sort, then turn back into URL keys - sort.Strings(names) - for i, name := range names { - keys[i] = inverted[name] - } - - return bkmksMap, keys +// bkmkNameSlice is used for sorting bookmarks alphabetically. +// It implements sort.Interface. +type bkmkNameSlice struct { + names []string + urls []string +} + +func (b *bkmkNameSlice) Len() int { + return len(b.names) +} +func (b *bkmkNameSlice) Less(i, j int) bool { + return b.names[i] < b.names[j] +} +func (b *bkmkNameSlice) Swap(i, j int) { + b.names[i], b.names[j] = b.names[j], b.names[i] + b.urls[i], b.urls[j] = b.urls[j], b.urls[i] +} + +// All returns all the bookmarks, as two arrays, one for names and one for URLs. +// They are sorted alphabetically. +func All() ([]string, []string) { + b := bkmkNameSlice{ + make([]string, len(data.Bookmarks)), + make([]string, len(data.Bookmarks)), + } + for i, bkmk := range data.Bookmarks { + b.names[i] = bkmk.Name + b.urls[i] = bkmk.URL + } + sort.Sort(&b) + return b.names, b.urls } diff --git a/bookmarks/xbel.go b/bookmarks/xbel.go index 38406f8..43ba076 100644 --- a/bookmarks/xbel.go +++ b/bookmarks/xbel.go @@ -2,6 +2,7 @@ package bookmarks // Structs and code for the XBEL XML bookmark format. // https://github.com/makeworld-the-better-one/amfora/issues/68 +// http://xbel.sourceforge.net/ import ( "encoding/xml" @@ -38,7 +39,7 @@ type xbel struct { XMLName xml.Name `xml:"xbel"` Version string `xml:"version,attr"` Bookmarks []*xbelBookmark `xml:"bookmark"` - // Later: Folders []*xbelFolder + // Folders []*xbelFolder // Use later for #56 } // Instance of xbel - loaded from bookmarks file diff --git a/display/bookmarks.go b/display/bookmarks.go index e20c223..62f7803 100644 --- a/display/bookmarks.go +++ b/display/bookmarks.go @@ -127,9 +127,9 @@ func Bookmarks(t *tab) { bkmkPageRaw := "# Bookmarks\r\n\r\n" // Gather bookmarks - m, keys := bookmarks.All() - for i := range keys { - bkmkPageRaw += fmt.Sprintf("=> %s %s\r\n", keys[i], m[keys[i]]) + names, urls := bookmarks.All() + for i := range names { + bkmkPageRaw += fmt.Sprintf("=> %s %s\r\n", urls[i], names[i]) } // Render and display content, links := renderer.RenderGemini(bkmkPageRaw, textWidth(), false)