# HG changeset patch # User Bram Moolenaar # Date 1610567104 -3600 # Node ID 7b3317e959e35b95a6ba54b4f215e926a73fd4f0 # Parent 3b600f015796aa8e289d6376cbbd42eaca83a29f patch 8.2.2343: Vim9: return type of readfile() is any Commit: https://github.com/vim/vim/commit/c423ad77ed763c11ba67729bbf63c1cf0915231f Author: Bram Moolenaar Date: Wed Jan 13 20:38:03 2021 +0100 patch 8.2.2343: Vim9: return type of readfile() is any Problem: Vim9: return type of readfile() is any. Solution: Add readblob() so that readfile() can be expected to always return a list of strings. (closes #7671) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2021 Jan 10 +*eval.txt* For Vim version 8.2. Last change: 2021 Jan 13 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2775,6 +2775,7 @@ pyxeval({expr}) any evaluate |python_x rand([{expr}]) Number get pseudo-random number range({expr} [, {max} [, {stride}]]) List items from {expr} to {max} +readblob({fname}) Blob read a |Blob| from {fname} readdir({dir} [, {expr} [, {dict}]]) List file names in {dir} selected by {expr} readdirex({dir} [, {expr} [, {dict}]]) @@ -8265,6 +8266,14 @@ rand([{expr}]) *rand()* *random* :echo rand(seed) :echo rand(seed) % 16 " random number 0 - 15 < + +readblob({fname}) *readblob()* + Read file {fname} in binary mode and return a |Blob|. + When the file can't be opened an error message is given and + the result is an empty |Blob|. + Also see |readfile()| and |writefile()|. + + readdir({directory} [, {expr} [, {dict}]]) *readdir()* Return a list with file and directory names in {directory}. You can also use |glob()| if you don't need to do complicated @@ -8379,6 +8388,7 @@ readdirex({directory} [, {expr} [, {dict Can also be used as a |method|: > GetDirName()->readdirex() < + *readfile()* readfile({fname} [, {type} [, {max}]]) Read file {fname} and return a |List|, each line of the file @@ -8390,8 +8400,6 @@ readfile({fname} [, {type} [, {max}]]) - When the last line ends in a NL an extra empty list item is added. - No CR characters are removed. - When {type} contains "B" a |Blob| is returned with the binary - data of the file unmodified. Otherwise: - CR characters that appear before a NL are removed. - Whether the last line ends in a NL or not does not matter. @@ -8409,6 +8417,9 @@ readfile({fname} [, {type} [, {max}]]) Note that without {max} the whole file is read into memory. Also note that there is no recognition of encoding. Read a file into a buffer if you need to. + Deprecated (use |readblob()| instead): When {type} contains + "B" a |Blob| is returned with the binary data of the file + unmodified. When the file can't be opened an error message is given and the result is an empty list. Also see |writefile()|. @@ -11295,9 +11306,11 @@ win_execute({id}, {command} [, {silent}] call win_execute(winid, 'set syntax=python') < Doing the same with `setwinvar()` would not trigger autocommands and not actually show syntax highlighting. + *E994* Not all commands are allowed in popup windows. - When window {id} does not exist then no error is given. + When window {id} does not exist then no error is given and + an empty string is returned. Can also be used as a |method|, the base is passed as the second argument: > diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -820,6 +820,7 @@ System functions and manipulation of fil setenv() set an environment variable hostname() name of the system readfile() read a file into a List of lines + readblob() read a file into a Blob readdir() get a List of file names in a directory readdirex() get a List of file information in a directory writefile() write a List of lines or Blob into a file diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1344,12 +1344,14 @@ static funcentry_T global_functions[] = ret_number, f_rand}, {"range", 1, 3, FEARG_1, NULL, ret_list_number, f_range}, + {"readblob", 1, 1, FEARG_1, NULL, + ret_blob, f_readblob}, {"readdir", 1, 3, FEARG_1, NULL, ret_list_string, f_readdir}, {"readdirex", 1, 3, FEARG_1, NULL, ret_list_dict_any, f_readdirex}, {"readfile", 1, 3, FEARG_1, NULL, - ret_any, f_readfile}, + ret_list_string, f_readfile}, {"reduce", 2, 3, FEARG_1, NULL, ret_any, f_reduce}, {"reg_executing", 0, 0, 0, NULL, diff --git a/src/filepath.c b/src/filepath.c --- a/src/filepath.c +++ b/src/filepath.c @@ -1640,11 +1640,11 @@ f_readdirex(typval_T *argvars, typval_T /* * "readfile()" function */ - void -f_readfile(typval_T *argvars, typval_T *rettv) + static void +read_file_or_blob(typval_T *argvars, typval_T *rettv, int always_blob) { int binary = FALSE; - int blob = FALSE; + int blob = always_blob; int failed = FALSE; char_u *fname; FILE *fd; @@ -1796,7 +1796,8 @@ f_readfile(typval_T *argvars, typval_T * if (dest < buf) { - adjust_prevlen = (int)(buf - dest); // must be 1 or 2 + // must be 1 or 2 + adjust_prevlen = (int)(buf - dest); dest = buf; } if (readlen > p - buf + 1) @@ -1867,6 +1868,24 @@ f_readfile(typval_T *argvars, typval_T * } /* + * "readblob()" function + */ + void +f_readblob(typval_T *argvars, typval_T *rettv) +{ + read_file_or_blob(argvars, rettv, TRUE); +} + +/* + * "readfile()" function + */ + void +f_readfile(typval_T *argvars, typval_T *rettv) +{ + read_file_or_blob(argvars, rettv, FALSE); +} + +/* * "resolve()" function */ void diff --git a/src/proto/filepath.pro b/src/proto/filepath.pro --- a/src/proto/filepath.pro +++ b/src/proto/filepath.pro @@ -1,5 +1,6 @@ /* filepath.c */ int modify_fname(char_u *src, int tilde_file, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen); +void shorten_dir(char_u *str); void f_chdir(typval_T *argvars, typval_T *rettv); void f_delete(typval_T *argvars, typval_T *rettv); void f_executable(typval_T *argvars, typval_T *rettv); @@ -21,10 +22,10 @@ void f_glob2regpat(typval_T *argvars, ty void f_globpath(typval_T *argvars, typval_T *rettv); void f_isdirectory(typval_T *argvars, typval_T *rettv); void f_mkdir(typval_T *argvars, typval_T *rettv); -void shorten_dir(char_u *str); void f_pathshorten(typval_T *argvars, typval_T *rettv); void f_readdir(typval_T *argvars, typval_T *rettv); void f_readdirex(typval_T *argvars, typval_T *rettv); +void f_readblob(typval_T *argvars, typval_T *rettv); void f_readfile(typval_T *argvars, typval_T *rettv); void f_resolve(typval_T *argvars, typval_T *rettv); void f_tempname(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -623,6 +623,32 @@ def Test_readdir() eval expand('sautest')->readdirex((e) => e.name[0] !=# '.') enddef +def Test_readblob() + var blob = 0z12341234 + writefile(blob, 'Xreadblob') + var read: blob = readblob('Xreadblob') + assert_equal(blob, read) + + var lines =<< trim END + var read: list = readblob('Xreadblob') + END + CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list but got blob', 1) + delete('Xreadblob') +enddef + +def Test_readfile() + var text = ['aaa', 'bbb', 'ccc'] + writefile(text, 'Xreadfile') + var read: list = readfile('Xreadfile') + assert_equal(text, read) + + var lines =<< trim END + var read: dict = readfile('Xreadfile') + END + CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected dict but got list', 1) + delete('Xreadfile') +enddef + def Test_remove_return_type() var l = remove({one: [1, 2], two: [3, 4]}, 'one') var res = 0 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2343, +/**/ 2342, /**/ 2341,