commit e7b982f4e861abb8fc0e18b12312d9b42add0da0 from: Omar Polo date: Wed Jul 14 11:12:26 2021 UTC support completions in minibuffer + related interactive fns * cmd.c (cmd_previous_completion): add previous-completion (cmd_next_completion): add next-completion (cmd_insert_current_candidate): add insert-current-candidate * minibuffer.c (enter_minibuffer): support completions in minibuffer commit - 6b80b8fe2cc0cb093599c913eb911d403fa51cd5 commit + e7b982f4e861abb8fc0e18b12312d9b42add0da0 blob - dc7261e95b645d1344ea53c52b40114a74bbcec4 blob + 975edd75c7fe89c41633f24ed3fe632564fb42ba --- ChangeLog +++ ChangeLog @@ -1,3 +1,11 @@ +2021-07-14 Omar Polo + + * cmd.c (cmd_previous_completion): add previous-completion + (cmd_next_completion): add next-completion + (cmd_insert_current_candidate): add insert-current-candidate + + * minibuffer.c (enter_minibuffer): support completions in minibuffer + 2021-07-13 Omar Polo * pages.c: advertise B and F instead of C-M-b/C-M-f. blob - 3c700286dfa06f282179020891c070f993c8960e blob + b6ad63b2028b48b6fb393297b57713bd943c5252 --- cmd.c +++ cmd.c @@ -691,3 +691,54 @@ cmd_mini_next_history_element(struct buffer *buffer) if (ministate.hist_cur != NULL) buffer->current_line->line = ministate.hist_cur->h; } + +void +cmd_previous_completion(struct buffer *buffer) +{ + if (in_minibuffer != MB_COMPREAD) + return; + + buffer = &ministate.compl.buffer; + + if (buffer->current_line != NULL) + buffer->current_line->parent->type = LINE_COMPL; + + forward_line(buffer, -1); + + if (buffer->current_line != NULL) + buffer->current_line->parent->type = LINE_COMPL_CURRENT; +} + +void +cmd_next_completion(struct buffer *buffer) +{ + if (in_minibuffer != MB_COMPREAD) + return; + + buffer = &ministate.compl.buffer; + + if (buffer->current_line != NULL) + buffer->current_line->parent->type = LINE_COMPL; + + forward_line(buffer, +1); + + if (buffer->current_line != NULL) + buffer->current_line->parent->type = LINE_COMPL_CURRENT; +} + +void +cmd_insert_current_candidate(struct buffer *buffer) +{ + struct vline *vl; + + if (in_minibuffer != MB_COMPREAD) + return; + + buffer = &ministate.compl.buffer; + if ((vl = buffer->current_line) == NULL) + return; + + minibuffer_taint_hist(); + strlcpy(ministate.buf, vl->parent->line, sizeof(ministate.buf)); + ministate.buffer.cpoff = utf8_cplen(ministate.buf); +} blob - 3d74f7ac5de86741073d2bd73b382a3eff8ea6c1 blob + aefb7449c00ddc4a6c2a3df0770ae08df7cb1cf8 --- cmd.h +++ cmd.h @@ -64,3 +64,7 @@ CMD(cmd_mini_abort); CMD(cmd_mini_complete_and_exit); CMD(cmd_mini_previous_history_element); CMD(cmd_mini_next_history_element); + +CMD(cmd_previous_completion); +CMD(cmd_next_completion); +CMD(cmd_insert_current_candidate); blob - 0e2930df2dcc09b3a90e40d8b4abb8ebe09390eb blob + c365fe9e8145518418848b82d609e6fb127b4286 --- defaults.c +++ defaults.c @@ -42,6 +42,9 @@ struct lineprefix line_prefixes[] = { [LINE_PRE_START] = { "```", " " }, [LINE_PRE_CONTENT] = { "", "" }, [LINE_PRE_END] = { "```", "```" }, + + [LINE_COMPL] = {"", ""}, + [LINE_COMPL_CURRENT] = {"", ""}, }; struct line_face line_faces[] = { @@ -100,6 +103,18 @@ struct line_face line_faces[] = { .pair = PPEND, .trail_pair = PPEND_TRAIL, }, + + /* minibuffer */ + [LINE_COMPL] = { + .prfx_pair = PCOMPL_PRFX, + .pair = PCOMPL, + .trail_pair = PCOMPL_TRAIL, + }, + [LINE_COMPL_CURRENT] = { + .prfx_pair = PCOMPL_CURR_PRFX, + .pair = PCOMPL_CURR, + .trail_pair = PCOMPL_CURR_TRAIL, + }, }; struct tab_face tab_face = { @@ -148,6 +163,10 @@ struct mapping { {"pre.start", LINE_PRE_START}, {"pre", LINE_PRE_CONTENT}, {"pre.end", LINE_PRE_END}, + + /* minibuffer */ + {"compl", LINE_COMPL}, + {"compl.current", LINE_COMPL_CURRENT} }; static struct mapping * @@ -316,6 +335,10 @@ load_default_keys(void) minibuffer_set_key("M-n", cmd_mini_next_history_element); minibuffer_set_key("", cmd_mini_previous_history_element); minibuffer_set_key("", cmd_mini_next_history_element); + + minibuffer_set_key("C-p", cmd_previous_completion); + minibuffer_set_key("C-n", cmd_next_completion); + minibuffer_set_key("tab", cmd_insert_current_candidate); } void @@ -334,6 +357,10 @@ config_init(void) line_faces[LINE_LINK].fg = COLOR_BLUE; + line_faces[LINE_COMPL_CURRENT].prfx_bg = COLOR_CYAN; + line_faces[LINE_COMPL_CURRENT].bg = COLOR_CYAN; + line_faces[LINE_COMPL_CURRENT].trail_bg = COLOR_CYAN; + load_default_keys(); } blob - 00e7a2d4e24e1f49fbd241b3dacfecb83efeb8f1 blob + b48c7b920e5bc6656de8541757ee2a10396b029a --- minibuffer.c +++ minibuffer.c @@ -52,11 +52,15 @@ void recompute_completions(int add) { struct line *l; + struct vline *vl; + struct buffer *b; if (in_minibuffer != MB_COMPREAD) return; - TAILQ_FOREACH(l, &ministate.compl.buffer.page.head, lines) { + b = &ministate.compl.buffer; + TAILQ_FOREACH(l, &b->page.head, lines) { + l->type = LINE_COMPL; if (add && l->flags & L_HIDDEN) continue; if (strstr(l->line, ministate.buf) != NULL) @@ -64,6 +68,13 @@ recompute_completions(int add) else l->flags |= L_HIDDEN; } + + if (b->current_line == NULL) + b->current_line = TAILQ_FIRST(&b->head); + b->current_line = adjust_line(b->current_line, b); + vl = b->current_line; + if (vl != NULL) + vl->parent->type = LINE_COMPL_CURRENT; } static void @@ -252,23 +263,6 @@ read_select(void) exit_minibuffer(); minibuffer_hist_save_entry(); read_cb(ministate.buf, read_data); -} - -/* - * Just like erase_buffer, but don't call free(l->line); - */ -static inline void -erase_compl_buffer(struct buffer *buffer) -{ - struct line *l, *lt; - - empty_vlist(buffer); - - TAILQ_FOREACH_SAFE(l, &buffer->page.head, lines, lt) { - TAILQ_REMOVE(&buffer->page.head, l, lines); - /* don't free l->line! */ - free(l); - } } /* @@ -289,14 +283,18 @@ populate_compl_buffer(complfn *fn, void *data) if ((l = calloc(1, sizeof(*l))) == NULL) abort(); - l->type = LINE_TEXT; - l->line = s; + l->type = LINE_COMPL; + if ((l->line = strdup(s)) == NULL) + abort(); if (TAILQ_EMPTY(&p->head)) TAILQ_INSERT_HEAD(&p->head, l, lines); else TAILQ_INSERT_TAIL(&p->head, l, lines); } + + if ((l = TAILQ_FIRST(&p->head)) != NULL) + l->type = LINE_COMPL_CURRENT; } void @@ -308,8 +306,6 @@ enter_minibuffer(void (*self_insert_fn)(void), void (* if (in_minibuffer == MB_COMPREAD) { ui_schedule_redraw(); - erase_compl_buffer(&ministate.compl.buffer); - ministate.compl.fn = complfn; ministate.compl.data = compldata; populate_compl_buffer(complfn, compldata); @@ -336,8 +332,10 @@ enter_minibuffer(void (*self_insert_fn)(void), void (* void exit_minibuffer(void) { - if (in_minibuffer == MB_COMPREAD) + if (in_minibuffer == MB_COMPREAD) { + erase_buffer(&ministate.compl.buffer); ui_schedule_redraw(); + } in_minibuffer = 0; base_map = &global_map; blob - 6094d777443a6653c4f61e751dbf4bb4c9409bbd blob + f0fc7fb45a971d6dedbec80dfd427aa1793b9ba6 --- telescope.1 +++ telescope.1 @@ -338,6 +338,12 @@ mini-next-history-element mini-previous-history-element .It mini-next-history-element +.It C-p +previous-completion +.It C-n +next-completion +.It tab +insert-current-candidate .El .Sh INTERACTIVE COMMANDS Follows the documentation for the interactive commands. @@ -357,18 +363,24 @@ Move point to the end of the buffer. Move point one character forward. .It Ic forward-paragraph Move point one paragraph forward. +.It Ic insert-current-candidate +Copy the current selection text as minibuffer input. .It Ic move-beginning-of-line Move point at the beginning of the current (visual) line. .It Ic move-end-of-line Move point at the end of the current (visual) line. .It Ic next-button Move point to the next link. +.It Ic next-completion +Select the next completion. .It Ic next-heading Move point to the next heading. .It Ic next-line Move point to the next (visual) line, in the same column if possible. .It Ic previous-button Move point to the previous link. +.It Ic previous-completion +Select the previous completion. .It Ic previous-heading Move point to the previous heading. .It Ic previous-line blob - 567cad0aab1a5abd4a3fe1246211bc6238ee54b7 blob + 8debbe52919cb97db7f39fdfc2c43aac905d1ade --- telescope.h +++ telescope.h @@ -67,6 +67,7 @@ enum imsg_type { }; enum line_type { + /* text/gemini */ LINE_TEXT, LINE_LINK, LINE_TITLE_1, @@ -77,6 +78,10 @@ enum line_type { LINE_PRE_START, LINE_PRE_CONTENT, LINE_PRE_END, + + /* minibuffer */ + LINE_COMPL, + LINE_COMPL_CURRENT, }; /* for lines: mark as hidden */ @@ -94,7 +99,7 @@ struct line { }; struct vline { - const struct line *parent; + struct line *parent; char *line; int flags; TAILQ_ENTRY(vline) vlines; @@ -332,6 +337,7 @@ int imsg_compose_event(struct imsgev *, uint16_t, ui void erase_buffer(struct buffer *); void empty_linelist(struct buffer*); void empty_vlist(struct buffer*); +int wrap_one(struct buffer *, const char *, struct line *, size_t); int wrap_text(struct buffer*, const char*, struct line*, size_t); int hardwrap_text(struct buffer*, struct line*, size_t); blob - 540de79098f2017095d3d728b08ede7f01a69e79 blob + 52085730d675a0341c4c2f132d477c2585cb95c5 --- ui.c +++ ui.c @@ -415,6 +415,14 @@ wrap_page(struct buffer *buffer, int width) pre_width = width; hardwrap_text(buffer, l, pre_width); break; + case LINE_COMPL: + case LINE_COMPL_CURRENT: + /* + * TODO: should be width, but will break the + * rendering. Fix when unlocking completions + * buffer from olivetti-mode. + */ + wrap_one(buffer, prfx, l, MIN(fill_column, width)); } if (top_orig == l && buffer->top_line == NULL) { @@ -601,7 +609,7 @@ redraw_tabline(void) * until the end of the buffer; if a visible line is not found, search * backward. Return NULL if no viable line was found. */ -static inline struct vline * +struct vline * adjust_line(struct vline *vl, struct buffer *buffer) { struct vline *t; @@ -692,7 +700,8 @@ again: buffer->top_line = TAILQ_NEXT(buffer->top_line, vlines); } - goto again; + if (vl != NULL) + goto again; } buffer->last_line_off = buffer->line_off; blob - 909ba81917a545d6a5e0a29aaad82c3b3ee8f1f8 blob + e93980071fcbb4244679e7aaf91b2010dd57f27d --- ui.h +++ ui.h @@ -72,6 +72,14 @@ enum pairs { PPEND_PRFX, PPEND_TRAIL, + PCOMPL_PRFX, + PCOMPL, + PCOMPL_TRAIL, + + PCOMPL_CURR_PRFX, + PCOMPL_CURR, + PCOMPL_CURR_TRAIL, + PMODELINE, PMINIBUF, @@ -100,6 +108,7 @@ void ir_select(void); void lu_self_insert(void); void lu_select(void); void bp_select(void); +struct vline *adjust_line(struct vline *, struct buffer *); void vmessage(const char *, va_list); void message(const char *, ...) __attribute__((format(printf, 1, 2))); void start_loading_anim(struct tab *); blob - 04dcedda1c3892437218f86acbe39043880f7986 blob + 33405b9289543ae349b444af2c524cc0a12e068d --- wrap.c +++ wrap.c @@ -101,6 +101,32 @@ push_line(struct buffer *buffer, const struct line *l, } /* + * Similar to wrap_text, but emit only o vline. + */ +int +wrap_one(struct buffer *buffer, const char *prfx, struct line *l, size_t width) +{ + struct vline *vl, *t; + + /* + * be lazy: call wrap_text and then discard the continuations. + */ + + if (!wrap_text(buffer, prfx, l, width)) + return 0; + + TAILQ_FOREACH_SAFE(vl, &buffer->head, vlines, t) { + if (vl->flags & L_CONTINUATION) { + TAILQ_REMOVE(&buffer->head, vl, vlines); + free(vl->line); + free(vl); + } + } + + return 1; +} + +/* * Build a list of visual line by wrapping the given line, assuming * that when printed will have a leading prefix prfx. */