diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-12-17 21:46:24 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-12-17 21:46:24 +0200 |
commit | 0081bb4511d8799fa46639877b57a6f2cbf38925 (patch) | |
tree | bde59d5b0ac103fc7bf97f2f72d955388322c64d /src/bookmarks.c | |
parent | 34e397e76a0903675b223f638989703009ac5646 (diff) |
Listing bookmarks by tag and creation time
Diffstat (limited to 'src/bookmarks.c')
-rw-r--r-- | src/bookmarks.c | 98 |
1 files changed, 79 insertions, 19 deletions
diff --git a/src/bookmarks.c b/src/bookmarks.c index 1a7bf31c..e8cc5b98 100644 --- a/src/bookmarks.c +++ b/src/bookmarks.c | |||
@@ -21,12 +21,15 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
22 | 22 | ||
23 | #include "bookmarks.h" | 23 | #include "bookmarks.h" |
24 | #include "visited.h" | ||
25 | #include "app.h" | ||
24 | 26 | ||
25 | #include <the_Foundation/file.h> | 27 | #include <the_Foundation/file.h> |
26 | #include <the_Foundation/hash.h> | 28 | #include <the_Foundation/hash.h> |
27 | #include <the_Foundation/mutex.h> | 29 | #include <the_Foundation/mutex.h> |
28 | #include <the_Foundation/path.h> | 30 | #include <the_Foundation/path.h> |
29 | #include <the_Foundation/regexp.h> | 31 | #include <the_Foundation/regexp.h> |
32 | #include <the_Foundation/stringset.h> | ||
30 | 33 | ||
31 | void init_Bookmark(iBookmark *d) { | 34 | void init_Bookmark(iBookmark *d) { |
32 | init_String(&d->url); | 35 | init_String(&d->url); |
@@ -227,35 +230,92 @@ const iPtrArray *list_Bookmarks(const iBookmarks *d, iBookmarksCompareFunc cmp, | |||
227 | return list; | 230 | return list; |
228 | } | 231 | } |
229 | 232 | ||
230 | const iString *bookmarkListPage_Bookmarks(const iBookmarks *d) { | 233 | const iString *bookmarkListPage_Bookmarks(const iBookmarks *d, enum iBookmarkListType listType) { |
231 | iString *str = collectNew_String(); | 234 | iString *str = collectNew_String(); |
232 | lock_Mutex(d->mtx); | 235 | lock_Mutex(d->mtx); |
233 | format_String(str, | 236 | format_String(str, |
234 | "You have %d bookmark%s.\n\n" | 237 | "# %s\n\n", |
235 | "Save this page to export them, or you can copy them to " | 238 | listType == listByFolder_BookmarkListType ? "Bookmarks" |
236 | "the clipboard.\n\n", | 239 | : listType == listByTag_BookmarkListType ? "Bookmark tags" |
237 | size_Hash(&d->bookmarks), | 240 | : "Created bookmarks"); |
238 | size_Hash(&d->bookmarks) != 1 ? "s" : ""); | 241 | if (listType == listByFolder_BookmarkListType) { |
239 | iConstForEach(PtrArray, i, list_Bookmarks(d, cmpTitleAscending_Bookmark_, NULL, NULL)) { | 242 | appendFormat_String(str, |
243 | "You have %d bookmark%s.\n\n" | ||
244 | "Save this page to export them, or you can copy them to " | ||
245 | "the clipboard.\n\n", | ||
246 | size_Hash(&d->bookmarks), | ||
247 | size_Hash(&d->bookmarks) != 1 ? "s" : ""); | ||
248 | } | ||
249 | else if (listType == listByTag_BookmarkListType) { | ||
250 | appendFormat_String(str, "In this list each heading represents a bookmark tag. " | ||
251 | "Bookmarks with multiple tags are repeated under each tag.\n\n"); | ||
252 | } | ||
253 | iStringSet *tags = new_StringSet(); | ||
254 | const iPtrArray *bmList = list_Bookmarks(d, | ||
255 | listType == listByCreationTime_BookmarkListType | ||
256 | ? cmpTimeDescending_Bookmark_ | ||
257 | : cmpTitleAscending_Bookmark_, | ||
258 | NULL, | ||
259 | NULL); | ||
260 | iConstForEach(PtrArray, i, bmList) { | ||
240 | const iBookmark *bm = i.ptr; | 261 | const iBookmark *bm = i.ptr; |
241 | appendFormat_String(str, "=> %s %s\n", cstr_String(&bm->url), cstr_String(&bm->title)); | 262 | if (listType == listByFolder_BookmarkListType) { |
263 | appendFormat_String(str, "=> %s %s\n", cstr_String(&bm->url), cstr_String(&bm->title)); | ||
264 | } | ||
265 | else if (listType == listByCreationTime_BookmarkListType) { | ||
266 | appendFormat_String(str, "=> %s %s - %s\n", cstr_String(&bm->url), | ||
267 | cstrCollect_String(format_Time(&bm->when, "%Y-%m-%d")), | ||
268 | cstr_String(&bm->title)); | ||
269 | } | ||
242 | iRangecc tag = iNullRange; | 270 | iRangecc tag = iNullRange; |
243 | while (nextSplit_Rangecc(range_String(&bm->tags), " ", &tag)) { | 271 | while (nextSplit_Rangecc(range_String(&bm->tags), " ", &tag)) { |
244 | if (!isEmpty_Range(&tag)) { | 272 | if (!isEmpty_Range(&tag)) { |
245 | appendCStr_String(str, "* "); | 273 | iString t; |
246 | appendRange_String(str, tag); | 274 | initRange_String(&t, tag); |
247 | appendChar_String(str, '\n'); | 275 | insert_StringSet(tags, &t); |
276 | deinit_String(&t); | ||
248 | } | 277 | } |
249 | } | 278 | } |
250 | } | 279 | } |
280 | if (listType == listByTag_BookmarkListType) { | ||
281 | iConstForEach(StringSet, t, tags) { | ||
282 | const iString *tag = t.value; | ||
283 | appendFormat_String(str, "\n## %s\n", cstr_String(tag)); | ||
284 | iConstForEach(PtrArray, i, bmList) { | ||
285 | const iBookmark *bm = i.ptr; | ||
286 | iRangecc bmTag = iNullRange; | ||
287 | iBool isTagged = iFalse; | ||
288 | while (nextSplit_Rangecc(range_String(&bm->tags), " ", &bmTag)) { | ||
289 | if (equal_Rangecc(bmTag, cstr_String(tag))) { | ||
290 | isTagged = iTrue; | ||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | if (isTagged) { | ||
295 | appendFormat_String( | ||
296 | str, "=> %s %s\n", cstr_String(&bm->url), cstr_String(&bm->title)); | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | iRelease(tags); | ||
251 | unlock_Mutex(d->mtx); | 302 | unlock_Mutex(d->mtx); |
252 | appendCStr_String(str, | 303 | if (listType == listByCreationTime_BookmarkListType) { |
253 | "\nText lines and preformatted text are comments and should be ignored. " | 304 | appendCStr_String(str, "\nThis page is formatted according to the " |
254 | "Each link line represents a bookmark. " | 305 | "\"Subscribing to Gemini pages\" companion specification.\n"); |
255 | "Folder structure is defined by headings. " | 306 | } |
256 | "All links before the first heading are root level bookmarks. " | 307 | else { |
257 | "Bullet lines following a link are used for tags; each tag gets its own " | 308 | appendFormat_String(str, |
258 | "bullet line. Quotes are reserved for additional information about a " | 309 | "\nEach link represents a bookmark. " |
259 | "bookmark.\n"); | 310 | "%s" |
311 | "Bullet lines and quotes are reserved for additional information about " | ||
312 | "the preceding bookmark. Text lines and preformatted text are considered " | ||
313 | "comments and should be ignored.\n", | ||
314 | listType == listByFolder_BookmarkListType | ||
315 | ? "Folder structure is defined by level 2/3 headings. " | ||
316 | : listType == listByTag_BookmarkListType | ||
317 | ? "Tags are defined by level 2 headings. " | ||
318 | : ""); | ||
319 | } | ||
260 | return str; | 320 | return str; |
261 | } | 321 | } |