Mercurial > vim
diff src/eval.c @ 24234:7ffc795288dd v8.2.2658
patch 8.2.2658: :for cannot loop over a string
Commit: https://github.com/vim/vim/commit/74e54fcb447e5db32f9c2df34c0554bbecdccca2
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Mar 26 20:41:29 2021 +0100
patch 8.2.2658: :for cannot loop over a string
Problem: :for cannot loop over a string.
Solution: Accept a string argument and iterate over its characters.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 26 Mar 2021 20:45:02 +0100 |
parents | 9f64c420f280 |
children | 2194227d034a |
line wrap: on
line diff
--- a/src/eval.c +++ b/src/eval.c @@ -41,6 +41,8 @@ typedef struct list_T *fi_list; // list being used int fi_bi; // index of blob blob_T *fi_blob; // blob being used + char_u *fi_string; // copy of string being used + int fi_byte_idx; // byte index in fi_string } forinfo_T; static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op); @@ -1738,6 +1740,14 @@ eval_for_line( } clear_tv(&tv); } + else if (tv.v_type == VAR_STRING) + { + fi->fi_byte_idx = 0; + fi->fi_string = tv.vval.v_string; + tv.vval.v_string = NULL; + if (fi->fi_string == NULL) + fi->fi_string = vim_strsave((char_u *)""); + } else { emsg(_(e_listreq)); @@ -1790,7 +1800,23 @@ next_for_item(void *fi_void, char_u *arg tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi); ++fi->fi_bi; return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon, - fi->fi_varcount, flag, NULL) == OK; + fi->fi_varcount, flag, NULL) == OK; + } + + if (fi->fi_string != NULL) + { + typval_T tv; + int len; + + len = mb_ptr2len(fi->fi_string + fi->fi_byte_idx); + if (len == 0) + return FALSE; + tv.v_type = VAR_STRING; + tv.v_lock = VAR_FIXED; + tv.vval.v_string = vim_strnsave(fi->fi_string + fi->fi_byte_idx, len); + fi->fi_byte_idx += len; + return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon, + fi->fi_varcount, flag, NULL) == OK; } item = fi->fi_lw.lw_item; @@ -1800,7 +1826,7 @@ next_for_item(void *fi_void, char_u *arg { fi->fi_lw.lw_item = item->li_next; result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon, - fi->fi_varcount, flag, NULL) == OK); + fi->fi_varcount, flag, NULL) == OK); } return result; } @@ -1813,13 +1839,17 @@ free_for_info(void *fi_void) { forinfo_T *fi = (forinfo_T *)fi_void; - if (fi != NULL && fi->fi_list != NULL) + if (fi == NULL) + return; + if (fi->fi_list != NULL) { list_rem_watch(fi->fi_list, &fi->fi_lw); list_unref(fi->fi_list); } - if (fi != NULL && fi->fi_blob != NULL) + else if (fi->fi_blob != NULL) blob_unref(fi->fi_blob); + else + vim_free(fi->fi_string); vim_free(fi); }