From: NeilBrown Date: Fri, 2 Jun 2023 03:07:28 +0000 (+1000) Subject: ncurses: don't block in nc_external_viewer X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=85cc4ab3228c2a207f7789664203e695236c2916;p=edlib.git ncurses: don't block in nc_external_viewer Rather than blocking the whole editor while waiting for use to copy/paste for plain-text screen, set a flag to say that the display is suspended, and resume on next key stroke collected in the normal way. Also timeout after 30 seconds. Signed-off-by: NeilBrown --- diff --git a/DOC/Developer/04-events.md b/DOC/Developer/04-events.md index 40471b11..c4a4d016 100644 --- a/DOC/Developer/04-events.md +++ b/DOC/Developer/04-events.md @@ -44,7 +44,7 @@ The messages that the event subsystem listens for are: be a stream that supports "unget". In such a case there may be content to get, but not from the file descriptor. -- event:free - And register event from the focus pane which is supposed +- event:free - Any register event from the focus pane which is supposed to call the given comm2 will be deactivated. If no comm2 command is given, all registered event for the given focus pane are deregistered. Note that when a pane is closed, the event subsystem detects this and diff --git a/DOC/TODO.md b/DOC/TODO.md index af85751a..00388857 100644 --- a/DOC/TODO.md +++ b/DOC/TODO.md @@ -15,7 +15,7 @@ the file. - [X] ->replace_pane, ->replace_popup can be deleted (Abort) but we don't catch it... - [X] notmuch reply should interpolate the first *visible* text part -- [ ] ncurses - don't block in nc_external_viewer - at least abort after +- [X] ncurses - don't block in nc_external_viewer - at least abort after 30 seconds, but preferrably switch to a mode which leaves everything else running. - [ ] lang-python should put each module in a separate module @@ -247,7 +247,7 @@ Module features ### ncurses -- [ ] don't block in nc_external_viewer - at least abort after +- [X] don't block in nc_external_viewer - at least abort after 30 seconds, but preferrably switch to a mode which leaves everything else running. - [ ] add full list of colour names (to lib-colourmap) diff --git a/display-ncurses.c b/display-ncurses.c index 3f89bdf8..67f36fa1 100644 --- a/display-ncurses.c +++ b/display-ncurses.c @@ -69,6 +69,7 @@ struct display_data { long last_event; bool did_close; + bool suspended; struct buf paste_buf; time_t paste_start; @@ -511,6 +512,18 @@ static void wait_for(struct display_data *dd safe) } } +DEF_CB(ns_resume) +{ + struct display_data *dd = ci->home->data; + + if (dd->suspended) { + dd->suspended = False; + set_screen(ci->home); + doupdate(); + } + return 1; +} + DEF_CMD(nc_external_viewer) { struct pane *p = ci->home; @@ -576,6 +589,9 @@ DEF_CMD(nc_external_viewer) n -= read(fileno(dd->scr_file), buf, n <= (int)sizeof(buf) ? n : (int)sizeof(buf)); endwin(); + /* stay in raw mode */ + raw(); + noecho(); /* Endwin doesn't seem to reset properly, at least on xfce-terminal. * So do it manually @@ -590,7 +606,7 @@ DEF_CMD(nc_external_viewer) tputs(dd->clear, 1, nc_putc); fflush(dd->scr_file); - fprintf(dd->scr_file, "# Consider copy-pasting following\n"); + fprintf(dd->scr_file, "# Consider copy-pasting following\r\n"); if (fqdn && path[0] == '/') { /* File will not be local for the user, so help them copy it. */ const char *tmp = fnormalize(p, ci->str2 ?: "XXXXXX"); @@ -603,11 +619,11 @@ DEF_CMD(nc_external_viewer) tmp, fqdn, fname); path = "$f"; } - fprintf(dd->scr_file, "xdg-open %s\n", path); - fprintf(dd->scr_file, "# Press Enter to continue\n"); - n = read(fileno(dd->scr_file), buf, sizeof(buf)); free(fqdn); - doupdate(); + fprintf(dd->scr_file, "xdg-open %s\r\n", path); + fprintf(dd->scr_file, "# Press Enter to continue\r\n"); + dd->suspended = True; + call_comm("event:timer", p, &ns_resume, 30*1000); return 1; } @@ -1209,9 +1225,13 @@ DEF_CMD(nc_refresh_size) DEF_CMD(nc_refresh_post) { struct pane *p = ci->home; + struct display_data *dd = p->data; struct pane *p1; PANEL *pan, *pan2; + if (dd->suspended) + return 1; + set_screen(p); /* Need to ensure stacking order and panel y,x position @@ -1703,6 +1723,13 @@ REDEF_CMD(input_handle) wait_for(dd); set_screen(p); while ((is_keycode = get_wch(&c)) != ERR) { + if (dd->suspended && c != KEY_MOUSE) { + dd->suspended = False; + doupdate(); + call_comm("event:free", p, &ns_resume); + /* swallow the key */ + continue; + } if (paste_recv(p, is_keycode, c)) continue; if (c == KEY_MOUSE) {