mg(1) searches case insensitve and puts the replace string verbatime
in place.
The One True Editor considers the case (capitalised or all uppercase)
and adjusts the replacement string accordingly. This only happens
when the replacement string is all lowercase.

The following diff implements this for mg.

EXAMPLE

----------
foo
Foo
FOO
----------

M-%
foo
bar

results in:

----------
bar
Bar
BAR
----------

while without it it does this:

----------
bar
bar
bar
----------


This comes up surprisingly often while I'm coding.

OK?

diff --git line.c line.c
index ae5d4a7e3bb..dc4e5cf32bc 100644
--- line.c
+++ line.c
@@ -18,6 +18,7 @@
  */
 
 #include <sys/queue.h>
+#include <ctype.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdio.h>
@@ -511,7 +512,10 @@ int
 lreplace(RSIZE plen, char *st)
 {
        RSIZE   rlen;   /* replacement length            */
-       int s;
+       struct line *lp;
+       RSIZE n;
+       int s, doto, is_capitalised = 0, is_allcaps = 0, is_alllower = 0;
+       char *repl;
 
        if ((s = checkdirty(curbp)) != TRUE)
                return (s);
@@ -520,16 +524,57 @@ lreplace(RSIZE plen, char *st)
                ewprintf("Buffer is read only");
                return (FALSE);
        }
+
+       if ((repl = strdup(st)) == NULL) {
+               dobeep();
+               ewprintf("out of memory");
+               return (FALSE);
+       }
+
        undo_boundary_enable(FFRAND, 0);
 
        (void)backchar(FFARG | FFRAND, (int)plen);
+
+       lp = curwp->w_dotp;
+       doto = curwp->w_doto;
+       n = plen;
+
+       is_capitalised = isupper((unsigned char)lgetc(lp, doto));
+
+       if (is_capitalised) {
+               for (n = 0, is_allcaps = 1; n < plen && is_allcaps; n++) {
+                       is_allcaps = !isalpha((unsigned char)lgetc(lp, doto)) ||
+                           isupper((unsigned char)lgetc(lp, doto));
+                       doto++;
+                       if (doto == llength(lp)) {
+                               doto = 0;
+                               lp = lforw(lp);
+                               n++; /* \n is implicit in the buffer */
+                       }
+               }
+       }
+
        (void)ldelete(plen, KNONE);
 
-       rlen = strlen(st);
-       region_put_data(st, rlen);
+       rlen = strlen(repl);
+       for (n = 0, is_alllower = 1; n < rlen && is_alllower; n++)
+               is_alllower = !isupper((unsigned char)repl[n]);
+
+       if (is_alllower) {
+               if (is_allcaps) {
+                       for (n = 0; n < rlen; n++)
+                               repl[n] = toupper((unsigned char)repl[n]);
+               } else if (is_capitalised) {
+                       repl[0] = toupper((unsigned char)repl[0]);
+               }
+       }
+
+       region_put_data(repl, rlen);
        lchange(WFFULL);
 
        undo_boundary_enable(FFRAND, 1);
+
+       free(repl);
        return (TRUE);
 }
 


-- 
I'm not entirely sure you are real.

Reply via email to