]> git.neil.brown.name Git - edlib.git/commitdiff
emacs: add CX-< and CX-> to scroll left or right.
authorNeilBrown <neil@brown.name>
Thu, 8 Jun 2023 05:54:34 +0000 (15:54 +1000)
committerNeilBrown <neil@brown.name>
Wed, 28 Jun 2023 05:40:21 +0000 (15:40 +1000)
The first CX-< switch from wrapping to no-wrapping.  Then it shifts 8
units at a time, unless a number is given.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
mode-emacs.c
render-lines.c

index 94ae699fb95e88b41181c8b409499c1a406b1a26..44c1f573384054ac9f590d8a08023bbaa6318859 100644 (file)
@@ -9,7 +9,7 @@ the file.
 
 ### Trivial
 
-= [ ] :Cx-< and :Cx-> to shift view left and right and disable wrap
+- [X] :Cx-< and :Cx-> to shift view left and right and disable wrap
 - [ ] Unify edlib_timing and pane_too_long ??
 - [X] If an email part doesn't end with newline, last character is swallowed.
 - [X] What is rule for doc:content?  Does the mark move and get passed
@@ -251,6 +251,9 @@ Module features
 - [ ] sort the command names for command-completion?
        Currently lines are inserted into buffer.  I need to store in
        an array first, then qsort()
+- [ ] Do I want a 'truncated' marker at start/end of line when not
+      wrapping, and does the '\' go away properly when I start shifting.
+- [ ] change shift left/right to work in characters rather than pixels
 - [ ] filename completion should ignore uninteresting files like ".o"
       Maybe use .gitignore, or have config module understand that.
 - [ ] maybe alt-, does c-x` if that is the recent search?
index dd018f00b38830f81f0ca4d6f7eb8ed78eb50d06..a2462e2b579a56bd6fde0564327b4af54efc38b6 100644 (file)
@@ -39,6 +39,7 @@ enum {
        N2_undo,        /* Last command was 'undo' too */
        N2_close_others,/* Last command was close-other, just a 1 can repeat */
        N2_runmacro,    /* Last command was CX-e, just an 'e' can repeat */
+       N2_shift,       /* Laset command was CX-< or CX-> */
 };
 static inline int N2(const struct cmd_info *ci safe)
 {
@@ -2631,6 +2632,54 @@ DEF_CMD(emacs_readonly)
        return 1;
 }
 
+DEF_CMD(emacs_shift)
+{
+       int rpt = ci->num;
+       int shift;
+
+       shift = pane_attr_get_int(ci->focus, "shift-left", -1);
+       if (strcmp(ci->key, "K:CX->") == 0 || strcmp(ci->key, "K->") == 0)
+               rpt = -rpt;
+       if (rpt == NO_NUMERIC) {
+               if (shift < 0)
+                       shift = 0;
+               else
+                       shift += 8;
+       } else if (rpt == -NO_NUMERIC) {
+               if (shift >= 8)
+                       shift -= 8;
+               else if (shift > 0)
+                       shift = 0;
+               else
+                       shift = -1;
+       } else if (rpt >= 0) {
+               if (shift < 0)
+                       shift = 0;
+               shift += rpt;
+       } else {
+               if (shift > 0 && shift + rpt < 0)
+                       shift = 0;
+               else
+                       shift += rpt;
+       }
+       if (shift < 0)
+               attr_set_str(&ci->focus->attrs, "shift-left", "");
+       else
+               attr_set_int(&ci->focus->attrs, "shift-left", shift);
+       call("view:changed", ci->focus);
+       call("Mode:set-num2", ci->focus, N2_shift);
+       call("Message:modal", ci->focus, 0, NULL, "Type < or > to shift again");
+       return 1;
+}
+
+DEF_CMD(emacs_shift_again)
+{
+       if (N2(ci) != N2_shift)
+               return emacs_insert_func(ci);
+       else
+               return emacs_shift_func(ci);
+}
+
 DEF_CMD(emacs_curs_pos)
 {
        struct mark *c;
@@ -3159,6 +3208,11 @@ static void emacs_init(void)
        key_add(m, "K:CX-=", &emacs_curs_pos);
        key_add(m, "K:A-=", &emacs_word_count);
 
+       key_add(m, "K:CX-<", &emacs_shift);
+       key_add(m, "K:CX->", &emacs_shift);
+       key_add(m, "K-<", &emacs_shift_again);
+       key_add(m, "K->", &emacs_shift_again);
+
        key_add(m, "K:C-S", &emacs_start_search);
        key_add(m, "K:C-R", &emacs_start_search);
        key_add(m, "K:A-%", &emacs_start_search);
index 2c1ecb7efbdf89cc35c8d022309d0ae98170d845..4f581a5ad385b34d969bf291e2ed9e978de1fd43 100644 (file)
@@ -110,7 +110,8 @@ struct rl_data {
        short           i_moved;        /* I moved cursor, so don't clear
                                         * target
                                         */
-       int             do_wrap;
+       short           do_wrap;
+       short           shift_locked;
        short           shift_left;
        short           shift_left_last_refresh;
        struct mark     *header;
@@ -544,7 +545,8 @@ static void find_lines(struct mark *pm safe, struct pane *p safe,
         * call_render_line() will have created 'end' if it didn't exist.
         */
 
-       rl->shift_left = 0;
+       if (!rl->shift_locked)
+               rl->shift_left = 0;
 
        /* ->cy is top of cursor, we want to measure from bottom */
        if (start->mdata) {
@@ -554,7 +556,7 @@ static void find_lines(struct mark *pm safe, struct pane *p safe,
 
                curs_width = pane_attr_get_int(
                        start->mdata, "curs_width", 1);
-               while (!rl->do_wrap && curs_width > 0 &&
+               while (!rl->do_wrap && !rl->shift_locked && curs_width > 0 &&
                       hp->cx + curs_width >= p->w) {
                        int shift = 8 * curs_width;
                        if (shift > hp->cx)
@@ -869,7 +871,7 @@ DEF_CMD(render_lines_get_attr)
 
        if (ci->str && strcmp(ci->str, "shift_left") == 0) {
                char ret[10];
-               if (rl->do_wrap)
+               if (rl->do_wrap && !rl->shift_locked)
                        return comm_call(ci->comm2, "cb", ci->focus,
                                         0, NULL, "-1");
                snprintf(ret, sizeof(ret), "%d", rl->shift_left);
@@ -918,7 +920,7 @@ static int revalidate_start(struct rl_data *rl safe,
        /* This loop is fragile and sometimes spins.  So ensure we
         * never loop more than 1000 times.
         */
-       if (pm && !rl->do_wrap && shifts++ < 1000) {
+       if (pm && !rl->do_wrap && !rl->shift_locked && shifts++ < 1000) {
                int prefix_len;
                int curs_width;
                /* Need to check if side-shift is needed on cursor line */
@@ -1095,6 +1097,7 @@ DEF_CMD(render_lines_revise)
        bool refresh_all = False;
        char *hdr;
        char *a;
+       int shift;
 
        a = pane_attr_get(focus, "render-wrap");
        if (rl->do_wrap != (!a || strcmp(a, "yes") ==0)) {
@@ -1102,6 +1105,25 @@ DEF_CMD(render_lines_revise)
                refresh_all = True;
        }
 
+       shift = pane_attr_get_int(focus, "shift-left", -1);
+       if (shift >= 0) {
+               if (rl->shift_left != shift)
+                       refresh_all = True;
+
+               rl->shift_left = shift;
+               rl->shift_locked = 1;
+       } else {
+               if (rl->shift_locked)
+                       refresh_all = True;
+               rl->shift_locked = 0;
+       }
+       if (refresh_all) {
+               struct mark *v;
+               for (v = vmark_first(focus, rl->typenum, p);
+                    (v && v->mdata) ; v = vmark_next(v))
+                       pane_damaged(v->mdata, DAMAGED_REFRESH);
+       }
+
        rl->margin = pane_attr_get_int(focus, "render-vmargin", 0);
        if (rl->margin >= p->h/2)
                rl->margin = p->h/2;