summaryrefslogtreecommitdiff
path: root/src/bookmarks.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-12-17 21:46:24 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-12-17 21:46:24 +0200
commit0081bb4511d8799fa46639877b57a6f2cbf38925 (patch)
treebde59d5b0ac103fc7bf97f2f72d955388322c64d /src/bookmarks.c
parent34e397e76a0903675b223f638989703009ac5646 (diff)
Listing bookmarks by tag and creation time
Diffstat (limited to 'src/bookmarks.c')
-rw-r--r--src/bookmarks.c98
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
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 21SOFTWARE, 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
31void init_Bookmark(iBookmark *d) { 34void 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
230const iString *bookmarkListPage_Bookmarks(const iBookmarks *d) { 233const 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}