]> git.neil.brown.name Git - edlib.git/commitdiff
history: add support for "favourites".
authorNeilBrown <neil@brown.name>
Fri, 18 Aug 2023 21:03:10 +0000 (07:03 +1000)
committerNeilBrown <neil@brown.name>
Sun, 20 Aug 2023 22:45:30 +0000 (08:45 +1000)
favourites can be configured for different history files.
A-n moves to favourites if not in history.

config file can now have "doc:FOO" sections for docs that don't have
file names.

A bug in doc:EOL is fixed

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
core-doc.c
lib-config.c
lib-history.c

index 669bd549765fbd07113d9cf204beaf84f5c23e15..3cb4c71bbec827fdfafa37787adbe9625b4a449e 100644 (file)
@@ -15,7 +15,7 @@ the file.
       decides. YES.
 - [X] in xcb, find-file draws result a pixel high, then moves done
       when cursor moves
-- [ ] favourites...  I want some favourite documents that are easy to
+- [X] favourites...  I want some favourite documents that are easy to
       find, favourite directories, favourite make or shell commands.
       Maybe that are found by moving "down" in history?  Maybe alt-*
       flags them?
@@ -44,6 +44,8 @@ the file.
       "nm" already gets me to the email project quickly.  Getting back
       is not so easy.
       Maybe some docs could be marked "project" and so be easy to find?
+      Maybe docs could be associated with a session, and are preferred
+      for select-new-document operations.
 - [ ] path completion in shell command.  If cannot find look for '/'
       following punctuation (=) and try there.
 - [ ] resolve shift-left vs shift_left distinction - add a "fixed" suffix?
@@ -60,6 +62,9 @@ the file.
       I want.  Maybe have a menu of choices to remind me
 - [ ] Teach render-lines to pad spaces to left/right align text
 - [ ] revise *Welcome* page
+- [ ] history doesn't restore initial default (or empty) string when
+      returning after excursion into history or favourites.
+- [ ] how can we save history-favourites back to a config file?
 
 ### Small
 
index 7030511df1b4142286a3e11bef1ef8eb1dd9c6a3..ace6c9423045f7c314f32ed4fae72b9d80ccf4da 100644 (file)
@@ -350,19 +350,29 @@ DEF_CMD(doc_eol)
                while ((ch = doc_next(f, m)) != WEOF &&
                       !is_eol(ch))
                        ;
-               rpt -= 1;
+               if (ch != WEOF)
+                       rpt -= 1;
        }
        while (rpt < 0 && ch != WEOF) {
                while ((ch = doc_prev(f, m)) != WEOF &&
                       !is_eol(ch))
                        ;
-               rpt += 1;
+               if (ch != WEOF)
+                       rpt += 1;
        }
-       if (!one_more && is_eol(ch)) {
-               if (RPT_NUM(ci) > 0)
-                       doc_prev(f, m);
-               else if (RPT_NUM(ci) < 0)
-                       doc_next(f, m);
+       if (!one_more) {
+               if (is_eol(ch)) {
+                       if (RPT_NUM(ci) > 0)
+                               doc_prev(f, m);
+                       else if (RPT_NUM(ci) < 0)
+                               doc_next(f, m);
+               }
+               if (ch == WEOF) {
+                       if (RPT_NUM(ci) > 0)
+                               rpt -= 1;
+                       else if (RPT_NUM(ci) < 0)
+                               rpt += 1;
+               }
        }
        return rpt == 0 ? 1 : Efalse;
 }
@@ -522,7 +532,7 @@ DEF_CMD(doc_append)
        if (!val || !val[0])
                return Enoarg;
        /* Append the string to the attr.  It attr doesn't
-        * exists, string first char of val and use that.
+        * exists, strip first char of val and use that.
         */
        old = attr_find(p->attrs, attr);
        if (!old) {
index 40a5d405e90d47d25ee22a96d119718c4fd1625f..ecff730fb525d9a51d2cf95989c37ffad53c3dd6 100644 (file)
@@ -76,12 +76,17 @@ struct config_data {
        struct pane *root safe;
        struct trigger {
                char *path safe;
+               enum {
+                       TRIGGER_FILE,
+                       TRIGGER_DOC,
+               } type;
                struct attrset *attrs;
                struct trigger *next;
        } *triggers, *last_trigger;
 };
 
-static void add_trigger(struct config_data *cd safe, char *path safe,
+static void add_trigger(struct config_data *cd safe, unsigned int type,
+                       char *path safe,
                        char *name safe, char *val safe, int append)
 {
        struct trigger *t = cd->last_trigger;
@@ -96,10 +101,11 @@ static void add_trigger(struct config_data *cd safe, char *path safe,
                        return;
                name += 10;
        }
-       if (!t || strcmp(t->path, path) != 0) {
+       if (!t || strcmp(t->path, path) != 0 || t->type != type) {
                alloc(t, pane);
                t->path = strdup(path);
                t->next = NULL;
+               t->type = type;
                if (cd->last_trigger)
                        cd->last_trigger->next = t;
                else
@@ -118,13 +124,14 @@ static void add_trigger(struct config_data *cd safe, char *path safe,
                attr_set_str(&t->attrs, name, val);
 }
 
-static void config_file(char *path safe, struct pane *doc safe,
+static void config_file(char *path safe, unsigned int type,
+                       struct pane *doc safe,
                        struct config_data *cd safe)
 {
        struct trigger *t;
 
        for (t = cd->triggers; t; t = t->next)
-               if (glob_match(t->path, path)) {
+               if (t->type == type && glob_match(t->path, path)) {
                        const char *val;
                        const char *k = "";
                        while ((k = attr_get_next_key(t->attrs, k, -1, &val)) != NULL) {
@@ -209,7 +216,11 @@ static void handle(void *data, char *section safe, char *name safe, char *value
        }
 
        if (strstarts(section, "file:")) {
-               add_trigger(cd, section+5, name, value, append);
+               add_trigger(cd, TRIGGER_FILE, section+5, name, value, append);
+               return;
+       }
+       if (strstarts(section, "doc:")) {
+               add_trigger(cd, TRIGGER_DOC, section+4, name, value, append);
                return;
        }
 }
@@ -251,9 +262,15 @@ DEF_CMD(config_appeared)
 {
        struct config_data *cd = container_of(ci->comm, struct config_data, appeared);
        char *path = pane_attr_get(ci->focus, "filename");
-       if (!path)
+       if (path) {
+               config_file(path, TRIGGER_FILE, ci->focus, cd);
                return Efallthrough;
-       config_file(path, ci->focus, cd);
+       }
+       path = pane_attr_get(ci->focus, "doc-name");
+       if (path) {
+               config_file(path, TRIGGER_DOC, ci->focus, cd);
+               return Efallthrough;
+       }
        return Efallthrough;
 }
 
index 028ddd3a1e9702596d8cd56d8da84da03d869ab2..74bb019e2aa59043d0c15da587440ff616d00eb3 100644 (file)
  *   :A-s - sets next line as search start and repeats.
  *   :Enter - drops out of search mode
  * Anything else drops out of search mode and repeats the command as normal
+ *
+ * For each history document a number of "favourites" can be registered.
+ * These are accessed by moving "down" from the start point rather than "up"
+ * for previous history items.
  */
 
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
@@ -41,6 +46,7 @@ struct history_info {
        char            *prompt;
        struct buf      search;
        int             search_back;
+       int             favourite;
        struct si {
                int i;
                struct si *prev;
@@ -188,18 +194,65 @@ DEF_CMD(history_move)
 {
        struct history_info *hi = ci->home->data;
        const char *suffix = ksuffix(ci, "K:A-");
+       char attr[sizeof("doc:favourite-") + 12];
 
        if (!hi->history)
                return Enoarg;
-       if (*suffix == 'p')
-               call("doc:EOL", hi->history, -2);
-       else
-               call("doc:EOL", hi->history, 1, NULL, NULL, 1);
-
+       if (*suffix == 'p') {
+               if (hi->favourite > 0)
+                       hi->favourite -= 1;
+               else
+                       call("doc:EOL", hi->history, -2);
+       } else {
+               if (hi->favourite > 0)
+                       hi->favourite += 1;
+               else if (call("doc:EOL", hi->history, 1, NULL, NULL, 1) < 0)
+                       hi->favourite = 1;
+       }
+       while (hi->favourite > 0) {
+               char *f;
+               struct mark *m;
+               snprintf(attr, sizeof(attr)-1, "doc:favourite-%d",
+                        hi->favourite);
+               f = pane_attr_get(hi->history, attr);
+               if (!f) {
+                       hi->favourite -= 1;
+                       continue;
+               }
+               call("doc:EOL", ci->focus, -1);
+               m = mark_at_point(ci->focus, NULL, MARK_UNGROUPED);
+               call("doc:EOL", ci->focus, 1, m);
+               call("Replace", ci->focus, 1, m, f);
+               mark_free(m);
+               return 1;
+       }
        recall_line(ci->home, ci->focus, *suffix == 'n');
        return 1;
 }
 
+DEF_CMD(history_add_favourite)
+{
+       struct history_info *hi = ci->home->data;
+       char attr[sizeof("doc:favourite-") + 10];
+       int f;
+       char *l;
+
+       if (!hi->history)
+               return 1;
+       l = call_ret(strsave, "doc:get-str", ci->focus);
+       if (!l || !*l)
+               return 1;
+       for (f = 1; f < 100; f++) {
+               snprintf(attr, sizeof(attr)-1, "doc:favourite-%d", f);
+               if (pane_attr_get(hi->history, attr))
+                       continue;
+               call("doc:set:", hi->history, 0, NULL, l, 0, NULL, attr);
+               call("Message:modal", ci->focus, 0, NULL, "Added as favourite");
+               break;
+       }
+       return 1;
+}
+
 DEF_CMD(history_attach)
 {
        struct history_info *hi;
@@ -498,6 +551,7 @@ void edlib_init(struct pane *ed safe)
        key_add(history_map, "K:A-n", &history_move);
        key_add(history_map, "K:A-r", &history_search);
        key_add(history_map, "K:A-s", &history_search);
+       key_add(history_map, "K:A-*", &history_add_favourite);
        key_add_prefix(history_map, "K:History-search-", &history_search_again);
        key_add_prefix(history_map, "K:History-search:",
                       &history_search_retry);