diff options
| -rw-r--r-- | src/nvim/buffer.c | 125 | ||||
| -rw-r--r-- | src/nvim/fileio.c | 18 | ||||
| -rw-r--r-- | src/nvim/fileio.h | 15 | ||||
| -rw-r--r-- | src/nvim/testdir/Makefile | 2 | ||||
| -rw-r--r-- | src/nvim/testdir/test_startup.vim | 2 | ||||
| -rw-r--r-- | src/nvim/testdir/test_startup_utf8.vim | 64 | ||||
| -rw-r--r-- | src/nvim/version.c | 4 | ||||
| -rw-r--r-- | src/nvim/vim.h | 4 | 
8 files changed, 182 insertions, 52 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index b5ca6543c5..90a564bb6a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -91,6 +91,57 @@ static char *e_auabort = N_("E855: Autocommands caused command to abort");  // Number of times free_buffer() was called.  static int buf_free_count = 0; +// Read data from buffer for retrying. +static int +read_buffer( +    int     read_stdin,     // read file from stdin, otherwise fifo +    exarg_T *eap,           // for forced 'ff' and 'fenc' or NULL +    int     flags)          // extra flags for readfile() +{ +  int       retval = OK; +  linenr_T  line_count; + +  // +  // Read from the buffer which the text is already filled in and append at +  // the end.  This makes it possible to retry when 'fileformat' or +  // 'fileencoding' was guessed wrong. +  // +  line_count = curbuf->b_ml.ml_line_count; +  retval = readfile( +      read_stdin ? NULL : curbuf->b_ffname, +      read_stdin ? NULL : curbuf->b_fname, +      (linenr_T)line_count, (linenr_T)0, (linenr_T)MAXLNUM, eap, +      flags | READ_BUFFER); +  if (retval == OK) { +    // Delete the binary lines. +    while (--line_count >= 0) { +      ml_delete((linenr_T)1, false); +    } +  } else { +    // Delete the converted lines. +    while (curbuf->b_ml.ml_line_count > line_count) { +      ml_delete(line_count, false); +    } +  } +  // Put the cursor on the first line. +  curwin->w_cursor.lnum = 1; +  curwin->w_cursor.col = 0; + +  if (read_stdin) { +    // Set or reset 'modified' before executing autocommands, so that +    // it can be changed there. +    if (!readonlymode && !bufempty()) { +      changed(); +    } else if (retval != FAIL) { +      unchanged(curbuf, false); +    } + +    apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, false, +                          curbuf, &retval); +  } +  return retval; +} +  /*   * Open current buffer, that is: open the memfile and read the file into   * memory. @@ -106,6 +157,7 @@ open_buffer (    int retval = OK;    bufref_T       old_curbuf;    long old_tw = curbuf->b_p_tw; +  int read_fifo = false;    /*     * The 'readonly' flag is only set when BF_NEVERLOADED is being reset. @@ -156,13 +208,45 @@ open_buffer (    if (curbuf->b_ffname != NULL) {      int old_msg_silent = msg_silent; +#ifdef UNIX +    int save_bin = curbuf->b_p_bin; +    int perm; + +    perm = os_getperm((const char *)curbuf->b_ffname); +    if (perm >= 0 && (0 +# ifdef S_ISFIFO +                      || S_ISFIFO(perm) +# endif +# ifdef S_ISSOCK +                      || S_ISSOCK(perm) +# endif +# ifdef OPEN_CHR_FILES +                      || (S_ISCHR(perm) +                          && is_dev_fd_file(curbuf->b_ffname)) +# endif +                      ) +        ) { +      read_fifo = true; +    } +    if (read_fifo) { +      curbuf->b_p_bin = true; +    } +#endif      if (shortmess(SHM_FILEINFO)) {        msg_silent = 1;      }      retval = readfile(curbuf->b_ffname, curbuf->b_fname,                        (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, -                      flags | READ_NEW); +                      flags | READ_NEW | (read_fifo ? READ_FIFO : 0)); +#ifdef UNIX +    if (read_fifo) { +      curbuf->b_p_bin = save_bin; +      if (retval == OK) { +        retval = read_buffer(false, eap, flags); +      } +    } +#endif      msg_silent = old_msg_silent;      // Help buffer is filtered. @@ -171,7 +255,6 @@ open_buffer (      }    } else if (read_stdin) {      int save_bin = curbuf->b_p_bin; -    linenr_T line_count;      /*       * First read the text in binary mode into the buffer. @@ -185,41 +268,13 @@ open_buffer (          flags | (READ_NEW + READ_STDIN));      curbuf->b_p_bin = save_bin;      if (retval == OK) { -      line_count = curbuf->b_ml.ml_line_count; -      retval = readfile(NULL, NULL, (linenr_T)line_count, -          (linenr_T)0, (linenr_T)MAXLNUM, eap, -          flags | READ_BUFFER); -      if (retval == OK) { -        /* Delete the binary lines. */ -        while (--line_count >= 0) -          ml_delete((linenr_T)1, FALSE); -      } else { -        /* Delete the converted lines. */ -        while (curbuf->b_ml.ml_line_count > line_count) -          ml_delete(line_count, FALSE); -      } -      /* Put the cursor on the first line. */ -      curwin->w_cursor.lnum = 1; -      curwin->w_cursor.col = 0; - -      // Set or reset 'modified' before executing autocommands, so that -      // it can be changed there. -      if (!readonlymode && !bufempty()) { -        changed(); -      } else if (retval == OK) { -        unchanged(curbuf, false); -      } - -      if (retval == OK) { -        apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, false, -                              curbuf, &retval); -      } +      retval = read_buffer(true, eap, flags);      }    }    /* if first time loading this buffer, init b_chartab[] */    if (curbuf->b_flags & BF_NEVERLOADED) { -    (void)buf_init_chartab(curbuf, FALSE); +    (void)buf_init_chartab(curbuf, false);      parse_cino(curbuf);    } @@ -234,7 +289,7 @@ open_buffer (        || modified_was_set               // ":set modified" used in autocmd        || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) {      changed(); -  } else if (retval == OK && !read_stdin) { +  } else if (retval != FAIL && !read_stdin && !read_fifo) {      unchanged(curbuf, false);    }    save_file_ff(curbuf);                 // keep this fileformat @@ -416,8 +471,8 @@ void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last)        return;      } -    /* When the buffer becomes hidden, but is not unloaded, trigger -     * BufHidden */ +    // When the buffer becomes hidden, but is not unloaded, trigger +    // BufHidden      if (!unload_buf) {        buf->b_locked++;        if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false, diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index be4188c4df..a0536d456d 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -247,6 +247,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)   *		stdin)   * READ_DUMMY	read into a dummy buffer (to check if file contents changed)   * READ_KEEP_UNDO  don't clear undo info or read it from a file + * READ_FIFO	read from fifo/socket instead of a file   *   * return FAIL for failure, NOTDONE for directory (failure), or OK   */ @@ -267,6 +268,7 @@ readfile (    int filtering = (flags & READ_FILTER);    int read_stdin = (flags & READ_STDIN);    int read_buffer = (flags & READ_BUFFER); +  int read_fifo = (flags & READ_FIFO);    int set_options = newfile || read_buffer                      || (eap != NULL && eap->read_edit);    linenr_T read_buf_lnum = 1;           /* next line to read from curbuf */ @@ -426,7 +428,7 @@ readfile (      }    } -  if (!read_buffer && !read_stdin) { +  if (!read_buffer && !read_stdin && !read_fifo) {      perm = os_getperm((const char *)fname);  #ifdef UNIX      // On Unix it is possible to read a directory, so we have to @@ -468,8 +470,8 @@ readfile (    if (check_readonly && !readonlymode)      curbuf->b_p_ro = FALSE; -  if (newfile && !read_stdin && !read_buffer) { -    /* Remember time of file. */ +  if (newfile && !read_stdin && !read_buffer && !read_fifo) { +    // Remember time of file.      FileInfo file_info;      if (os_fileinfo((char *)fname, &file_info)) {        buf_store_file_info(curbuf, &file_info); @@ -895,6 +897,7 @@ retry:       * and we can't do it internally or with iconv().       */      if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL +        && !read_fifo  #  ifdef USE_ICONV          && iconv_fd == (iconv_t)-1  #  endif @@ -935,7 +938,7 @@ retry:    /* Set "can_retry" when it's possible to rewind the file and try with     * another "fenc" value.  It's FALSE when no other "fenc" to try, reading     * stdin or fixed at a specific encoding. */ -  can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc); +  can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo);    if (!skip_read) {      linerest = 0; @@ -947,6 +950,7 @@ retry:                        && curbuf->b_ffname != NULL                        && curbuf->b_p_udf                        && !filtering +                      && !read_fifo                        && !read_stdin                        && !read_buffer);      if (read_undo_file) @@ -1919,7 +1923,7 @@ failed:      u_read_undo(NULL, hash, fname);    } -  if (!read_stdin && !read_buffer) { +  if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) {      int m = msg_scroll;      int n = msg_scrolled; @@ -1937,7 +1941,7 @@ failed:      if (filtering) {        apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,                             false, curbuf, eap); -    } else if (newfile) { +    } else if (newfile || (read_buffer && sfname != NULL)) {        apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,                             false, curbuf, eap);        if (!au_did_filetype && *curbuf->b_p_ft != NUL) { @@ -1970,7 +1974,7 @@ failed:  /// Do not accept "/dev/fd/[012]", opening these may hang Vim.  ///  /// @param fname file name to check -static bool is_dev_fd_file(char_u *fname) +bool is_dev_fd_file(char_u *fname)    FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT  {    return STRNCMP(fname, "/dev/fd/", 8) == 0 diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h index 426dc0fcb3..8db4b89806 100644 --- a/src/nvim/fileio.h +++ b/src/nvim/fileio.h @@ -4,13 +4,14 @@  #include "nvim/buffer_defs.h"  #include "nvim/os/os.h" -/* Values for readfile() flags */ -#define READ_NEW        0x01    /* read a file into a new buffer */ -#define READ_FILTER     0x02    /* read filter output */ -#define READ_STDIN      0x04    /* read from stdin */ -#define READ_BUFFER     0x08    /* read from curbuf (converting stdin) */ -#define READ_DUMMY      0x10    /* reading into a dummy buffer */ -#define READ_KEEP_UNDO  0x20    /* keep undo info*/ +// Values for readfile() flags +#define READ_NEW        0x01    // read a file into a new buffer +#define READ_FILTER     0x02    // read filter output +#define READ_STDIN      0x04    // read from stdin +#define READ_BUFFER     0x08    // read from curbuf (converting stdin) +#define READ_DUMMY      0x10    // reading into a dummy buffer +#define READ_KEEP_UNDO  0x20    // keep undo info +#define READ_FIFO       0x40    // read from fifo or socket  #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 7e55fffa06..510e8820f4 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -62,6 +62,8 @@ NEW_TESTS ?= \  	    test_signs.res \  	    test_smartindent.res \  	    test_stat.res \ +	    test_startup.res \ +	    test_startup_utf8.res \  	    test_substitute.res \  	    test_syntax.res \  	    test_tabpage.res \ diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 5996b2cd4a..64f7f31294 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -75,7 +75,7 @@ func Test_help_arg()      " check if  couple of lines are there      let found = []      for line in lines -      if line =~ '-R.*Readonly mode' +      if line =~ '-R.*Read-only mode'  	call add(found, 'Readonly mode')        endif        " Watch out for a second --version line in the Gnome version. diff --git a/src/nvim/testdir/test_startup_utf8.vim b/src/nvim/testdir/test_startup_utf8.vim new file mode 100644 index 0000000000..d179a4cc79 --- /dev/null +++ b/src/nvim/testdir/test_startup_utf8.vim @@ -0,0 +1,64 @@ +" Tests for startup using utf-8. +if !has('multi_byte') +  finish +endif + +source shared.vim + +func Test_read_stdin_utf8() +  let linesin = ['テスト', '€ÀÈÌÒÙ'] +  call writefile(linesin, 'Xtestin') +  let before = [ +	\ 'set enc=utf-8', +	\ 'set fencs=cp932,utf-8', +	\ ] +  let after = [ +	\ 'write ++enc=utf-8 Xtestout', +	\ 'quit!', +	\ ] +  if has('win32') +    let pipecmd = 'type Xtestin | ' +  else +    let pipecmd = 'cat Xtestin | ' +  endif +  if RunVimPiped(before, after, '-', pipecmd) +    let lines = readfile('Xtestout') +    call assert_equal(linesin, lines) +  else +    call assert_equal('', 'RunVimPiped failed.') +  endif +  call delete('Xtestout') +  call delete('Xtestin') +endfunc + +func Test_read_fifo_utf8() +  if !has('unix') +    return +  endif +  " Using bash/zsh's process substitution. +  if executable('bash') +    set shell=bash +  elseif executable('zsh') +    set shell=zsh +  else +    return +  endif +  let linesin = ['テスト', '€ÀÈÌÒÙ'] +  call writefile(linesin, 'Xtestin') +  let before = [ +	\ 'set enc=utf-8', +	\ 'set fencs=cp932,utf-8', +	\ ] +  let after = [ +	\ 'write ++enc=utf-8 Xtestout', +	\ 'quit!', +	\ ] +  if RunVim(before, after, '<(cat Xtestin)') +    let lines = readfile('Xtestout') +    call assert_equal(linesin, lines) +  else +    call assert_equal('', 'RunVim failed.') +  endif +  call delete('Xtestout') +  call delete('Xtestin') +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index a1a06f0e7c..5f83dd1fd0 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -215,7 +215,7 @@ static const int included_patches[] = {    // 2232 NA    2231,    2230, -  // 2229, +  2229,    2228,    2227,    2226, @@ -255,7 +255,7 @@ static const int included_patches[] = {    // 2192 NA    // 2191 NA    2190, -  // 2189, +  2189,    2188,    2187,    // 2186 NA diff --git a/src/nvim/vim.h b/src/nvim/vim.h index f29ccdd296..5d2c27a2f4 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -319,4 +319,8 @@ enum { FOLD_TEXT_LEN = 51 };  //!< buffer size for get_foldtext()  // Lowest number used for window ID. Cannot have this many windows per tab.  #define LOWEST_WIN_ID 1000 +#if defined(__FreeBSD__) && defined(S_ISCHR) +# define OPEN_CHR_FILES +#endif +  #endif /* NVIM_VIM_H */  | 
