From: NeilBrown Date: Fri, 18 Aug 2023 21:03:10 +0000 (+1000) Subject: history: add support for "favourites". X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=39b83b9c8aa2b9c45b1528f27e7ac511bbaed728;p=edlib.git history: add support for "favourites". 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 --- diff --git a/DOC/TODO.md b/DOC/TODO.md index 669bd549..3cb4c71b 100644 --- a/DOC/TODO.md +++ b/DOC/TODO.md @@ -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 diff --git a/core-doc.c b/core-doc.c index 7030511d..ace6c942 100644 --- a/core-doc.c +++ b/core-doc.c @@ -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) { diff --git a/lib-config.c b/lib-config.c index 40a5d405..ecff730f 100644 --- a/lib-config.c +++ b/lib-config.c @@ -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; } diff --git a/lib-history.c b/lib-history.c index 028ddd3a..74bb019e 100644 --- a/lib-history.c +++ b/lib-history.c @@ -25,10 +25,15 @@ * :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 #include +#include #include #include @@ -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);