]> granicus.if.org Git - vim/commitdiff
patch 7.4.813 v7.4.813
authorBram Moolenaar <Bram@vim.org>
Tue, 11 Aug 2015 12:26:19 +0000 (14:26 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 11 Aug 2015 12:26:19 +0000 (14:26 +0200)
Problem:    It is not possible to save and restore character search state.
Solution:   Add getcharsearch() and setcharsearch().  (James McCoy)

13 files changed:
runtime/doc/eval.txt
src/eval.c
src/proto/search.pro
src/search.c
src/testdir/Make_amiga.mak
src/testdir/Make_dos.mak
src/testdir/Make_ming.mak
src/testdir/Make_os2.mak
src/testdir/Make_vms.mms
src/testdir/Makefile
src/testdir/test_charsearch.in [new file with mode: 0644]
src/testdir/test_charsearch.ok [new file with mode: 0644]
src/version.c

index d9f49aefc5e215b83ac056a336505a6baee3dde6..85149b581e579c2d5572dc1a0b9df9d6a52598a5 100644 (file)
@@ -1971,6 +1971,7 @@ server2client( {clientid}, {string})
                                Number  send reply string
 serverlist()                   String  get a list of available servers
 setbufvar( {expr}, {varname}, {val})   set {varname} in buffer {expr} to {val}
+setcharsearch( {dict})         Dict    set character search from {dict}
 setcmdpos( {pos})              Number  set cursor position in command-line
 setline( {lnum}, {line})       Number  set line {lnum} to {line}
 setloclist( {nr}, {list}[, {action}])
@@ -3361,6 +3362,26 @@ getcharmod()                                             *getcharmod()*
                character itself are obtained.  Thus Shift-a results in "A"
                without a modifier.
 
+getcharsearch()                                                *getcharsearch()*
+               Return the current character search information as a {dict}
+               with the following entries:
+
+                   char        character previously used for a character
+                               search (|t|, |f|, |T|, or |F|); empty string
+                               if no character search has been performed
+                   forward     direction of character search; 1 for forward,
+                               0 for backward
+                   until       type of character search; 1 for a |t| or |T|
+                               character search, 0 for an |f| or |F|
+                               character search
+
+               This can be useful to always have |;| and |,| search
+               forward/backward regardless of the direction of the previous
+               character search: >
+                       :nnoremap <expr> ; getcharsearch().forward ? ';' : ','
+                       :nnoremap <expr> , getcharsearch().forward ? ',' : ';'
+<              Also see |setcharsearch()|.
+
 getcmdline()                                           *getcmdline()*
                Return the current command-line.  Only works when the command
                line is being edited, thus requires use of |c_CTRL-\_e| or
@@ -5397,6 +5418,26 @@ setbufvar({expr}, {varname}, {val})                      *setbufvar()*
                        :call setbufvar("todo", "myvar", "foobar")
 <              This function is not available in the |sandbox|.
 
+setcharsearch()                                                *setcharsearch()*
+               Set the current character search information to {dict},
+               which contains one or more of the following entries:
+
+                   char        character which will be used for a subsequent
+                               |,| or |;| command; an empty string clears the
+                               character search
+                   forward     direction of character search; 1 for forward,
+                               0 for backward
+                   until       type of character search; 1 for a |t| or |T|
+                               character search, 0 for an |f| or |F|
+                               character search
+
+               This can be useful to save/restore a user's character search
+               from a script: >
+                       :let prevsearch = getcharsearch()
+                       :" Perform a command which clobbers user's search
+                       :call setcharsearch(prevsearch)
+<              Also see |getcharsearch()|.
+
 setcmdpos({pos})                                       *setcmdpos()*
                Set the cursor position in the command line to byte position
                {pos}.  The first position is 1.
index 0537c4e32b8321fb0fd132d882a6505e44b107ff..8238b6ec6391d7f484257ef36a87176616492350 100644 (file)
@@ -555,6 +555,7 @@ static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getcharsearch __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getcmdtype __ARGS((typval_T *argvars, typval_T *rettv));
@@ -688,6 +689,7 @@ static void f_searchpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setcharsearch __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
@@ -8149,6 +8151,7 @@ static struct fst
     {"getbufvar",      2, 3, f_getbufvar},
     {"getchar",                0, 1, f_getchar},
     {"getcharmod",     0, 0, f_getcharmod},
+    {"getcharsearch",  0, 0, f_getcharsearch},
     {"getcmdline",     0, 0, f_getcmdline},
     {"getcmdpos",      0, 0, f_getcmdpos},
     {"getcmdtype",     0, 0, f_getcmdtype},
@@ -8285,6 +8288,7 @@ static struct fst
     {"server2client",  2, 2, f_server2client},
     {"serverlist",     0, 0, f_serverlist},
     {"setbufvar",      3, 3, f_setbufvar},
+    {"setcharsearch",  1, 1, f_setcharsearch},
     {"setcmdpos",      1, 1, f_setcmdpos},
     {"setline",                2, 2, f_setline},
     {"setloclist",     2, 3, f_setloclist},
@@ -11663,6 +11667,24 @@ f_getcharmod(argvars, rettv)
     rettv->vval.v_number = mod_mask;
 }
 
+/*
+ * "getcharsearch()" function
+ */
+    static void
+f_getcharsearch(argvars, rettv)
+    typval_T   *argvars UNUSED;
+    typval_T   *rettv;
+{
+    if (rettv_dict_alloc(rettv) != FAIL)
+    {
+       dict_T *dict = rettv->vval.v_dict;
+
+       dict_add_nr_str(dict, "char", 0L, last_csearch());
+       dict_add_nr_str(dict, "forward", last_csearch_forward(), NULL);
+       dict_add_nr_str(dict, "until", last_csearch_until(), NULL);
+    }
+}
+
 /*
  * "getcmdline()" function
  */
@@ -17004,6 +17026,48 @@ f_setbufvar(argvars, rettv)
     }
 }
 
+    static void
+f_setcharsearch(argvars, rettv)
+    typval_T   *argvars;
+    typval_T   *rettv UNUSED;
+{
+    dict_T     *d;
+    dictitem_T *di;
+    char_u     *csearch;
+
+    if (argvars[0].v_type != VAR_DICT)
+    {
+       EMSG(_(e_dictreq));
+       return;
+    }
+
+    if ((d = argvars[0].vval.v_dict) != NULL)
+    {
+       csearch = get_dict_string(d, (char_u *)"char", FALSE);
+       if (csearch != NULL)
+       {
+           if (enc_utf8)
+           {
+               int pcc[MAX_MCO];
+               int c = utfc_ptr2char(csearch, pcc);
+               set_last_csearch(c, csearch, utfc_ptr2len(csearch));
+           }
+           else
+               set_last_csearch(mb_ptr2char(csearch),
+                                               csearch, mb_ptr2len(csearch));
+       }
+
+       di = dict_find(d, (char_u *)"forward", -1);
+       if (di != NULL)
+           set_csearch_direction(get_tv_number(&di->di_tv)
+                                                       ? FORWARD : BACKWARD);
+
+       di = dict_find(d, (char_u *)"until", -1);
+       if (di != NULL)
+           set_csearch_until(!!get_tv_number(&di->di_tv));
+    }
+}
+
 /*
  * "setcmdpos()" function
  */
index 07f608789ddf3432f2df0cf0d677bc2125e566d4..27d2016aecec945b3a06b20c4bedb60f2bc6775d 100644 (file)
@@ -8,6 +8,12 @@ void restore_search_patterns __ARGS((void));
 void free_search_patterns __ARGS((void));
 int ignorecase __ARGS((char_u *pat));
 int pat_has_uppercase __ARGS((char_u *pat));
+char_u *last_csearch __ARGS((void));
+int last_csearch_forward __ARGS((void));
+int last_csearch_until __ARGS((void));
+void set_last_csearch __ARGS((int c, char_u *s, int len));
+void set_csearch_direction __ARGS((int cdir));
+void set_csearch_until __ARGS((int t_cmd));
 char_u *last_search_pat __ARGS((void));
 void reset_search_dir __ARGS((void));
 void set_last_search_pat __ARGS((char_u *s, int idx, int magic, int setlast));
index 238fc8160884ec5af9da8b26700ca6440d699016..de7bae86fc88bde57a3d9a33adaae97125100e35 100644 (file)
@@ -89,6 +89,14 @@ static struct spat spats[2] =
 
 static int last_idx = 0;       /* index in spats[] for RE_LAST */
 
+static char_u lastc[2] = {NUL, NUL};   /* last character searched for */
+static int lastcdir = FORWARD;         /* last direction of character search */
+static int last_t_cmd = TRUE;          /* last search t_cmd */
+#ifdef FEAT_MBYTE
+static char_u  lastc_bytes[MB_MAXBYTES + 1];
+static int     lastc_bytelen = 1;      /* >1 for multi-byte char */
+#endif
+
 #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)
 /* copy of spats[], for keeping the search patterns while executing autocmds */
 static struct spat  saved_spats[2];
@@ -378,7 +386,7 @@ ignorecase(pat)
 }
 
 /*
- * Return TRUE if patter "pat" has an uppercase character.
+ * Return TRUE if pattern "pat" has an uppercase character.
  */
     int
 pat_has_uppercase(pat)
@@ -418,6 +426,58 @@ pat_has_uppercase(pat)
     return FALSE;
 }
 
+    char_u *
+last_csearch()
+{
+#ifdef FEAT_MBYTE
+    return lastc_bytes;
+#else
+    return lastc;
+#endif
+}
+
+    int
+last_csearch_forward()
+{
+    return lastcdir == FORWARD;
+}
+
+    int
+last_csearch_until()
+{
+    return last_t_cmd == TRUE;
+}
+
+    void
+set_last_csearch(c, s, len)
+    int                c;
+    char_u     *s;
+    int                len;
+{
+    *lastc = c;
+#ifdef FEAT_MBYTE
+    lastc_bytelen = len;
+    if (len)
+       memcpy(lastc_bytes, s, len);
+    else
+       vim_memset(lastc_bytes, 0, sizeof(lastc_bytes));
+#endif
+}
+
+    void
+set_csearch_direction(cdir)
+    int cdir;
+{
+    lastcdir = cdir;
+}
+
+    void
+set_csearch_until(t_cmd)
+    int t_cmd;
+{
+    last_t_cmd = t_cmd;
+}
+
     char_u *
 last_search_pat()
 {
@@ -1559,47 +1619,42 @@ searchc(cap, t_cmd)
     int                        c = cap->nchar; /* char to search for */
     int                        dir = cap->arg; /* TRUE for searching forward */
     long               count = cap->count1;    /* repeat count */
-    static int         lastc = NUL;    /* last character searched for */
-    static int         lastcdir;       /* last direction of character search */
-    static int         last_t_cmd;     /* last search t_cmd */
     int                        col;
     char_u             *p;
     int                        len;
     int                        stop = TRUE;
-#ifdef FEAT_MBYTE
-    static char_u      bytes[MB_MAXBYTES + 1];
-    static int         bytelen = 1;    /* >1 for multi-byte char */
-#endif
 
     if (c != NUL)      /* normal search: remember args for repeat */
     {
        if (!KeyStuffed)    /* don't remember when redoing */
        {
-           lastc = c;
-           lastcdir = dir;
-           last_t_cmd = t_cmd;
+           *lastc = c;
+           set_csearch_direction(dir);
+           set_csearch_until(t_cmd);
 #ifdef FEAT_MBYTE
-           bytelen = (*mb_char2bytes)(c, bytes);
+           lastc_bytelen = (*mb_char2bytes)(c, lastc_bytes);
            if (cap->ncharC1 != 0)
            {
-               bytelen += (*mb_char2bytes)(cap->ncharC1, bytes + bytelen);
+               lastc_bytelen += (*mb_char2bytes)(cap->ncharC1,
+                       lastc_bytes + lastc_bytelen);
                if (cap->ncharC2 != 0)
-                   bytelen += (*mb_char2bytes)(cap->ncharC2, bytes + bytelen);
+                   lastc_bytelen += (*mb_char2bytes)(cap->ncharC2,
+                           lastc_bytes + lastc_bytelen);
            }
 #endif
        }
     }
     else               /* repeat previous search */
     {
-       if (lastc == NUL)
+       if (*lastc == NUL)
            return FAIL;
        if (dir)        /* repeat in opposite direction */
            dir = -lastcdir;
        else
            dir = lastcdir;
        t_cmd = last_t_cmd;
-       c = lastc;
-       /* For multi-byte re-use last bytes[] and bytelen. */
+       c = *lastc;
+       /* For multi-byte re-use last lastc_bytes[] and lastc_bytelen. */
 
        /* Force a move of at least one char, so ";" and "," will move the
         * cursor, even if the cursor is right in front of char we are looking
@@ -1636,14 +1691,14 @@ searchc(cap, t_cmd)
                        return FAIL;
                    col -= (*mb_head_off)(p, p + col - 1) + 1;
                }
-               if (bytelen == 1)
+               if (lastc_bytelen == 1)
                {
                    if (p[col] == c && stop)
                        break;
                }
                else
                {
-                   if (vim_memcmp(p + col, bytes, bytelen) == 0 && stop)
+                   if (vim_memcmp(p + col, lastc_bytes, lastc_bytelen) == 0 && stop)
                        break;
                }
                stop = TRUE;
@@ -1671,8 +1726,8 @@ searchc(cap, t_cmd)
        if (has_mbyte)
        {
            if (dir < 0)
-               /* Landed on the search char which is bytelen long */
-               col += bytelen - 1;
+               /* Landed on the search char which is lastc_bytelen long */
+               col += lastc_bytelen - 1;
            else
                /* To previous char, which may be multi-byte. */
                col -= (*mb_head_off)(p, p + col);
index 5f687b577b2b4980c9bdaf95072e844dad64ff19..183a80986b224e7303d964594cb70d9753da5cc2 100644 (file)
@@ -42,6 +42,7 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
                test_autoformat_join.out \
                test_breakindent.out \
                test_changelist.out \
+               test_charsearch.out \
                test_close_count.out \
                test_command_count.out \
                test_erasebackword.out \
@@ -194,6 +195,7 @@ test_autocmd_option.out: test_autocmd_option.in
 test_autoformat_join.out: test_autoformat_join.in
 test_breakindent.out: test_breakindent.in
 test_changelist.out: test_changelist.in
+test_charsearch.out: test_charsearch.in
 test_close_count.out: test_close_count.in
 test_command_count.out: test_command_count.in
 test_erasebackword.out: test_erasebackword.in
index 55c52208e984a0fa3957a50e32578ec940db7533..0f9514c27e78630ee04f45de4c7610289f7b04ca 100644 (file)
@@ -41,6 +41,7 @@ SCRIPTS =     test3.out test4.out test5.out test6.out test7.out \
                test_autoformat_join.out \
                test_breakindent.out \
                test_changelist.out \
+               test_charsearch.out \
                test_close_count.out \
                test_command_count.out \
                test_erasebackword.out \
index 9faac68a46188c8285fa4a48065347f49dc213fe..9ce78bf0479bce6754867ce5634c33246876e983 100644 (file)
@@ -63,6 +63,7 @@ SCRIPTS =     test3.out test4.out test5.out test6.out test7.out \
                test_autoformat_join.out \
                test_breakindent.out \
                test_changelist.out \
+               test_charsearch.out \
                test_close_count.out \
                test_command_count.out \
                test_erasebackword.out \
index 6ff7a6bc4eb81d6557b337d317197b76c91b1916..cac8f9c8d511aa2c205f4e5ee3f551bdb0db0dc1 100644 (file)
@@ -43,6 +43,7 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
                test_autoformat_join.out \
                test_breakindent.out \
                test_changelist.out \
+               test_charsearch.out \
                test_close_count.out \
                test_command_count.out \
                test_erasebackword.out \
index d8f54ade0a48047ccb08d91a624b4eb19bbbde0d..d90f59ab011ee0a7dfd3adc04553697877e55b60 100644 (file)
@@ -4,7 +4,7 @@
 # Authors:     Zoltan Arpadffy, <arpadffy@polarhome.com>
 #              Sandor Kopanyi,  <sandor.kopanyi@mailbox.hu>
 #
-# Last change:  2015 Jul 17
+# Last change:  2015 Aug 11
 #
 # This has been tested on VMS 6.2 to 8.3 on DEC Alpha, VAX and IA64.
 # Edit the lines in the Configuration section below to select.
@@ -102,6 +102,7 @@ SCRIPT = test1.out  test2.out  test3.out  test4.out  test5.out  \
         test_autoformat_join.out \
         test_breakindent.out \
         test_changelist.out \
+        test_charsearch.out \
         test_close_count.out \
         test_command_count.out \
         test_erasebackword.out \
index 92bbe612549e24b5dae2dfe2b51e2052f361a5d0..7edebbe4eaad73a7fa6db47a2f1b23ca01897d1a 100644 (file)
@@ -39,6 +39,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
                test_autoformat_join.out \
                test_breakindent.out \
                test_changelist.out \
+               test_charsearch.out \
                test_close_count.out \
                test_command_count.out \
                test_erasebackword.out \
diff --git a/src/testdir/test_charsearch.in b/src/testdir/test_charsearch.in
new file mode 100644 (file)
index 0000000..5085cb3
--- /dev/null
@@ -0,0 +1,25 @@
+Test for character searches
+
+STARTTEST
+:so small.vim
+:" check that "fe" and ";" work
+/^X
+ylfep;;p,,p:
+:" check that save/restore works
+/^Y
+ylfep:let csave = getcharsearch()
+fip:call setcharsearch(csave)
+;p;p:
+:" check that setcharsearch() changes the settins.
+/^Z
+ylfep:call setcharsearch({'char': 'k'})
+;p:call setcharsearch({'forward': 0})
+$;p:call setcharseearch({'until'}: 1})
+;;p:
+:/^X/,$w! test.out
+:qa!
+ENDTEST
+
+Xabcdefghijkemnopqretuvwxyz
+Yabcdefghijkemnopqretuvwxyz
+Zabcdefghijkemnokqretkvwxyz
diff --git a/src/testdir/test_charsearch.ok b/src/testdir/test_charsearch.ok
new file mode 100644 (file)
index 0000000..a0c90e2
--- /dev/null
@@ -0,0 +1,3 @@
+XabcdeXfghijkeXmnopqreXtuvwxyz
+YabcdeYfghiYjkeYmnopqreYtuvwxyz
+ZabcdeZfghijkZemnokZqretkZvwxyz
index 7298a79095927f6abcb5d80b8999819c45cb1d2c..862759c15bb29e3427aced1b5f560650f8a28fd0 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    813,
 /**/
     812,
 /**/