]> git.neil.brown.name Git - edlib.git/commitdiff
emacs: put a menu on the selection.
authorNeilBrown <neil@brown.name>
Fri, 8 Sep 2023 05:19:39 +0000 (15:19 +1000)
committerNeilBrown <neil@brown.name>
Fri, 8 Sep 2023 05:22:01 +0000 (15:22 +1000)
The selection can now trigger a menu (right-click)
to which other modules can easily add entries.

Also: don't claim selection until we are clearly starting one.  A single
click doesn't start a menu.

Also: allow menus to be placed at-mouse rather than always at start
of the active region.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
lib-menu.c
mode-emacs.c
render-lines.c
tests.d/00-mouse

index 0e6df9d585b39fee92d426e6007d69bea004ef11..698954d248ad048463c06f4497d50c3d50bfe947 100644 (file)
@@ -9,7 +9,20 @@ the file.
 
 ### Triage
 
+- [ ] find-document - if default doc has <>, displays wrongly.
+- [ ] From start-of-file move to end, then up, then down.
+      Display jumps.  Why?
+- [ ] Add menubar menu with recent documents?
+- [ ] why does clicking on status line go to top-of-file?
+- [ ] should Docs menu go on doc name in status bar?
 - [X] search hangs when seeking "^( *)"
+- [ ] selection-menu item to show git-commit from list of known git
+      trees
+- [ ] selection-menu item for word-count
+- [ ] selection-menu item for QR-code
+- [ ] selection-menu sub-menu for UPPER lower Caps ??
+- [ ] selection-menu item for text-fill
+- [ ] selection-menu item for spell-check ??
 
 ### Small
 
@@ -19,8 +32,8 @@ the file.
 - [X] fill mode to handle all punctuation at start of this line
 - [X] Enable lib-menu to show short-cut keys
 - [X] Add menu-bar to lib-menu.  Pop it up on F10 with simple commands
-- [ ] attach an extensible menu to the selection
-        copy, paste-in, QR, git-view
+- [X] attach an extensible menu to the selection
+        cut, copy, paste-in, QR, git-view
 
 ### Medium
 
index 03efa03b3f9d97f0d12c8d7ff9fe0c1af8b65fff..41c3cb5857875690c497bfaf60c0f61b1743d031 100644 (file)
@@ -132,6 +132,11 @@ DEF_CMD(menu_attach)
         * V  means show value in menu as well as name
         * F  means to use the focus as the doc, and its
         *    parent as the focus.
+        * ->str2 gives command to call on completion, else
+        *    "menu-done" is used.
+        * ->x,y are co-ordinated relative to ->focus where menu
+        *    (Top-Left) appears
+        * ->comm2 returns the created pane.
         */
        struct pane *docp, *p, *p2;
        /* Multi-line temporary popup with x,y location provided. */
index 82476411a84feaa0bebe0bf7c23d23687b71c1e2..119ff35abd78f379187d7bc9bef845cbdf3753cd 100644 (file)
@@ -2330,7 +2330,7 @@ DEF_CMD(emacs_attrs)
 {
        struct call_return cr;
        int active;
-       char *selection = "bg:white-80,vis-nl"; // grey
+       char *selection = "bg:white-80,vis-nl,menu-at-mouse,action-menu:emacs:selection-menu"; // grey
 
        if (!ci->str)
                return Enoarg;
@@ -2372,6 +2372,64 @@ DEF_CMD(emacs_attrs)
        return Efallthrough;
 }
 
+DEF_CMD(emacs_selection_menu)
+{
+       struct pane *p;
+
+       call("Message", ci->focus, 0, NULL, "So .... you want a menu do you?");
+       p = call_ret(pane, "attach-menu", ci->focus, 0, NULL, "V", 0, NULL,
+                    "emacs:selection-menu-action", ci->x, ci->y+1);
+       if (!p)
+               return Efail;
+       call("global-multicall-selection-menu:add-", p);
+       call("menu-add", p, 0, NULL, "de-select", 0, NULL, ":ESC");
+       return 1;
+}
+
+DEF_CMD(emacs_selection_menu_action)
+{
+       struct pane *home = ci->home;
+       char *dash;
+       const char *e;
+       const char *c = ci->str;
+
+       if (!c)
+               return 1;
+       if (*c == ' ') {
+               /* command for focus */
+               call(c+1, ci->focus, 0, ci->mark);
+               return 1;
+       }
+
+       while ((e = strchr(c, ' ')) != NULL) {
+               int ret;
+
+               dash = "";
+               if (*c != ':' || e == c+1)
+                       dash = "-";
+               ret = call("Keystroke", home, 0, NULL,
+                          strconcat(home, dash,
+                                    strnsave(home, c, e - c)));
+               if (ret < 0)
+                       return Efail;
+               c = e+1;
+       }
+       dash = "";
+       if (*c != ':' || c[1] == '\0')
+               dash = "-";
+       call("Keystroke", home, 0, NULL, strconcat(home, dash, c));
+       return 1;
+}
+
+DEF_CMD(emacs_selection_menu_add)
+{
+       struct pane *p = ci->focus;
+       call("menu-add", p, 0, NULL, "Cut", 0, NULL, ":C-W");
+       call("menu-add", p, 0, NULL, "Copy", 0, NULL, ":A-w");
+       call("menu-add", p, 0, NULL, "Paste-in", 0, NULL, ":C-Y");
+       return 1;
+}
+
 DEF_CMD(emacs_goto_line)
 {
        if (ci->num == NO_NUMERIC)
@@ -2448,9 +2506,14 @@ static void update_sel(struct pane *p safe,
                }
        }
 
-       /* Must call 'claim' first as it might be claiming from us */
-       call("selection:claim", p);
-       set_selection(p, pt, mk, 2);
+       /* Don't set selection until range is non-empty, else we
+        * might clear some other selection too early.
+        */
+       if (!mark_same(pt, mk)) {
+               /* Must call 'claim' first as it might be claiming from us */
+               call("selection:claim", p);
+               set_selection(p, pt, mk, 2);
+       }
 }
 
 DEF_CMD(emacs_press)
@@ -3417,6 +3480,8 @@ static void emacs_init(void)
        key_add(m, "K:C-Y", &emacs_yank);
        key_add(m, "K:A-y", &emacs_yank_pop);
        key_add(m, "map-attr", &emacs_attrs);
+       key_add(m, "emacs:selection-menu", &emacs_selection_menu);
+       key_add(m, "emacs:selection-menu-action", &emacs_selection_menu_action);
 
        key_add(m, "K:A-g", &emacs_goto_line);
        key_add(m, "K:A-x", &emacs_command);
@@ -3518,4 +3583,6 @@ void edlib_init(struct pane *ed safe)
        call_comm("global-set-command", ed, &attach_mode_emacs, 0, NULL, "attach-mode-emacs");
        call_comm("global-set-command", ed, &attach_file_entry, 0, NULL, "attach-file-entry");
        call_comm("global-set-command", ed, &emacs_shell, 0, NULL, "attach-shell-prompt");
+       call_comm("global-set-command", ed, &emacs_selection_menu_add,
+                 0, NULL, "selection-menu:add-00-emacs");
 }
index 3b6567d289d3d739b109c192e8a0dc77eaf1f7bc..4283ce28ed2fc48789ea3b4cc45d7f3d5ef965c8 100644 (file)
@@ -1577,7 +1577,8 @@ DEF_CMD(render_lines_set_cursor)
                                 * Only works for menus below
                                 * the line.
                                 */
-                               if (sscanf(xyattr, "%dx%d,", &x, &y) == 2) {
+                               if (!strstr(xyattr, ",menu-at-mouse,") &&
+                                   sscanf(xyattr, "%dx%d,", &x, &y) == 2) {
                                        cih.x = x;
                                        cih.y = m->mdata->y + y +
                                                attr_find_int(m->mdata->attrs,
index be1d50b0a1ad4f271f07f02bd854eb56bda2454e..c95ab82f3bd404d31a91a9ba1fe2df09266e3a2b 100644 (file)
@@ -34,10 +34,10 @@ Display 80,30 EDD4933334AF53A85CD54C73B19D6437 60,11
 Mouse ":Release-1" 60,20
 Display 80,30 116D6953BCA4DDBCC5EA46655EACE0CD 60,20
 Mouse ":Press-1" 17,7
-Display 80,30 31E7D3F3FFEBF4B1C289521A167ACBC4 17,7
+Display 80,30 E43145302EC09BB7FAB2DE0BFA4D2C02 17,7
 Mouse ":Release-1" 17,20
 Display 80,30 23156FABB80FCF0B81AC12E2F65E1AB4 17,20
 Mouse ":Press-1" 8,4
 Display 80,30 19C6B209451B5890F566C3855120E34D 8,4
 Mouse ":Release-1" 8,4
-Close 244
+Close 246