1
0
forked from aniani/vim

patch 7.4.2189

Problem:    Cannot detect encoding in a fifo.
Solution:   Extend the stdin way of detecting encoding to fifo.  Add a test
            for detecting encoding on stdin and fifo. (Ken Takata)
This commit is contained in:
Bram Moolenaar
2016-08-09 22:14:05 +02:00
parent c9fb77c692
commit f71d7b9ee5
7 changed files with 168 additions and 47 deletions

View File

@@ -2114,6 +2114,7 @@ test_arglist \
test_signs \ test_signs \
test_sort \ test_sort \
test_startup \ test_startup \
test_startup_utf8 \
test_stat \ test_stat \
test_statusline \ test_statusline \
test_syn_attr \ test_syn_attr \

View File

@@ -70,6 +70,64 @@ static char *e_auabort = N_("E855: Autocommands caused command to abort");
/* Number of times free_buffer() was called. */ /* Number of times free_buffer() was called. */
static int buf_free_count = 0; 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);
#ifdef FEAT_AUTOCMD
# ifdef FEAT_EVAL
apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
curbuf, &retval);
# else
apply_autocmds(EVENT_STDINREADPOST, NULL, NULL, FALSE, curbuf);
# endif
#endif
}
return retval;
}
/* /*
* Open current buffer, that is: open the memfile and read the file into * Open current buffer, that is: open the memfile and read the file into
* memory. * memory.
@@ -88,6 +146,7 @@ open_buffer(
#ifdef FEAT_SYN_HL #ifdef FEAT_SYN_HL
long old_tw = curbuf->b_p_tw; long old_tw = curbuf->b_p_tw;
#endif #endif
int read_fifo = FALSE;
/* /*
* The 'readonly' flag is only set when BF_NEVERLOADED is being reset. * The 'readonly' flag is only set when BF_NEVERLOADED is being reset.
@@ -143,17 +202,42 @@ open_buffer(
) )
{ {
int old_msg_silent = msg_silent; int old_msg_silent = msg_silent;
#ifdef UNIX
int save_bin = curbuf->b_p_bin;
int perm;
#endif
#ifdef FEAT_NETBEANS_INTG #ifdef FEAT_NETBEANS_INTG
int oldFire = netbeansFireChanges; int oldFire = netbeansFireChanges;
netbeansFireChanges = 0; netbeansFireChanges = 0;
#endif
#ifdef UNIX
perm = mch_getperm(curbuf->b_ffname);
if (perm >= 0 && (0
# ifdef S_ISFIFO
|| S_ISFIFO(perm)
# endif
# ifdef S_ISSOCK
|| S_ISSOCK(perm)
# endif
))
read_fifo = TRUE;
if (read_fifo)
curbuf->b_p_bin = TRUE;
#endif #endif
if (shortmess(SHM_FILEINFO)) if (shortmess(SHM_FILEINFO))
msg_silent = 1; msg_silent = 1;
retval = readfile(curbuf->b_ffname, curbuf->b_fname, retval = readfile(curbuf->b_ffname, curbuf->b_fname,
(linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap, (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; msg_silent = old_msg_silent;
#ifdef FEAT_NETBEANS_INTG #ifdef FEAT_NETBEANS_INTG
netbeansFireChanges = oldFire; netbeansFireChanges = oldFire;
@@ -164,8 +248,7 @@ open_buffer(
} }
else if (read_stdin) else if (read_stdin)
{ {
int save_bin = curbuf->b_p_bin; int save_bin = curbuf->b_p_bin;
linenr_T line_count;
/* /*
* First read the text in binary mode into the buffer. * First read the text in binary mode into the buffer.
@@ -179,42 +262,7 @@ open_buffer(
flags | (READ_NEW + READ_STDIN)); flags | (READ_NEW + READ_STDIN));
curbuf->b_p_bin = save_bin; curbuf->b_p_bin = save_bin;
if (retval == OK) if (retval == OK)
{ retval = read_buffer(TRUE, eap, flags);
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 != FAIL)
unchanged(curbuf, FALSE);
#ifdef FEAT_AUTOCMD
# ifdef FEAT_EVAL
apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
curbuf, &retval);
# else
apply_autocmds(EVENT_STDINREADPOST, NULL, NULL, FALSE, curbuf);
# endif
#endif
}
} }
/* if first time loading this buffer, init b_chartab[] */ /* if first time loading this buffer, init b_chartab[] */
@@ -243,7 +291,7 @@ open_buffer(
#endif #endif
) )
changed(); changed();
else if (retval != FAIL && !read_stdin) else if (retval != FAIL && !read_stdin && !read_fifo)
unchanged(curbuf, FALSE); unchanged(curbuf, FALSE);
save_file_ff(curbuf); /* keep this fileformat */ save_file_ff(curbuf); /* keep this fileformat */

View File

@@ -212,6 +212,7 @@ filemess(
* stdin) * stdin)
* READ_DUMMY read into a dummy buffer (to check if file contents changed) * 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_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, OK otherwise * return FAIL for failure, OK otherwise
*/ */
@@ -231,6 +232,7 @@ readfile(
int filtering = (flags & READ_FILTER); int filtering = (flags & READ_FILTER);
int read_stdin = (flags & READ_STDIN); int read_stdin = (flags & READ_STDIN);
int read_buffer = (flags & READ_BUFFER); int read_buffer = (flags & READ_BUFFER);
int read_fifo = (flags & READ_FIFO);
int set_options = newfile || read_buffer int set_options = newfile || read_buffer
|| (eap != NULL && eap->read_edit); || (eap != NULL && eap->read_edit);
linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
@@ -431,7 +433,7 @@ readfile(
} }
} }
if (!read_stdin && !read_buffer) if (!read_stdin && !read_buffer && !read_fifo)
{ {
#ifdef UNIX #ifdef UNIX
/* /*
@@ -489,7 +491,7 @@ readfile(
if (check_readonly && !readonlymode) if (check_readonly && !readonlymode)
curbuf->b_p_ro = FALSE; curbuf->b_p_ro = FALSE;
if (newfile && !read_stdin && !read_buffer) if (newfile && !read_stdin && !read_buffer && !read_fifo)
{ {
/* Remember time of file. */ /* Remember time of file. */
if (mch_stat((char *)fname, &st) >= 0) if (mch_stat((char *)fname, &st) >= 0)
@@ -1101,6 +1103,7 @@ retry:
* and we can't do it internally or with iconv(). * and we can't do it internally or with iconv().
*/ */
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
&& !read_fifo
# ifdef USE_ICONV # ifdef USE_ICONV
&& iconv_fd == (iconv_t)-1 && iconv_fd == (iconv_t)-1
# endif # endif
@@ -1149,7 +1152,7 @@ retry:
/* Set "can_retry" when it's possible to rewind the file and try with /* 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 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
* stdin or fixed at a specific encoding. */ * stdin or fixed at a specific encoding. */
can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc); can_retry = (*fenc != NUL && !read_stdin && !read_fifo && !keep_dest_enc);
#endif #endif
if (!skip_read) if (!skip_read)
@@ -1166,6 +1169,7 @@ retry:
&& curbuf->b_ffname != NULL && curbuf->b_ffname != NULL
&& curbuf->b_p_udf && curbuf->b_p_udf
&& !filtering && !filtering
&& !read_fifo
&& !read_stdin && !read_stdin
&& !read_buffer); && !read_buffer);
if (read_undo_file) if (read_undo_file)
@@ -2666,7 +2670,7 @@ failed:
#endif #endif
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
if (!read_stdin && !read_buffer) if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL))
{ {
int m = msg_scroll; int m = msg_scroll;
int n = msg_scrolled; int n = msg_scrolled;
@@ -2685,7 +2689,7 @@ failed:
if (filtering) if (filtering)
apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname, apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
FALSE, curbuf, eap); FALSE, curbuf, eap);
else if (newfile) else if (newfile || (read_buffer && sfname != NULL))
{ {
apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname, apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
FALSE, curbuf, eap); FALSE, curbuf, eap);

View File

@@ -185,6 +185,7 @@ NEW_TESTS = test_arglist.res \
test_ruby.res \ test_ruby.res \
test_signs.res \ test_signs.res \
test_startup.res \ test_startup.res \
test_startup_utf8.res \
test_stat.res \ test_stat.res \
test_syntax.res \ test_syntax.res \
test_textobjects.res \ test_textobjects.res \

View File

@@ -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

View File

@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2189,
/**/ /**/
2188, 2188,
/**/ /**/

View File

@@ -980,7 +980,8 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
#define READ_STDIN 0x04 /* read from stdin */ #define READ_STDIN 0x04 /* read from stdin */
#define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */ #define READ_BUFFER 0x08 /* read from curbuf (converting stdin) */
#define READ_DUMMY 0x10 /* reading into a dummy buffer */ #define READ_DUMMY 0x10 /* reading into a dummy buffer */
#define READ_KEEP_UNDO 0x20 /* keep undo info*/ #define READ_KEEP_UNDO 0x20 /* keep undo info */
#define READ_FIFO 0x40 /* read from fifo or socket */
/* Values for change_indent() */ /* Values for change_indent() */
#define INDENT_SET 1 /* set indent */ #define INDENT_SET 1 /* set indent */