]> granicus.if.org Git - vim/commitdiff
patch 8.0.0420: text garbled when the system encoding differs from 'encoding' v8.0.0420
authorBram Moolenaar <Bram@vim.org>
Sun, 5 Mar 2017 16:43:31 +0000 (17:43 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 5 Mar 2017 16:43:31 +0000 (17:43 +0100)
Problem:    When running :make the output may be in the system encoding,
            different from 'encoding'.
Solution:   Add the 'makeencoding' option. (Ken Takata)

16 files changed:
runtime/doc/options.txt
runtime/doc/quickfix.txt
runtime/doc/quickref.txt
src/Makefile
src/buffer.c
src/if_cscope.c
src/main.c
src/option.c
src/option.h
src/proto/quickfix.pro
src/quickfix.c
src/structs.h
src/testdir/Make_all.mak
src/testdir/test_makeencoding.py [new file with mode: 0644]
src/testdir/test_makeencoding.vim [new file with mode: 0644]
src/version.c

index 91c864d02f64a65bfe04a52147642ff7eb7e296f..4db9781721a6d320fb8ef1bd3660db5af6bddf08 100644 (file)
@@ -4994,6 +4994,25 @@ A jump table for the options with a short description can be found at |Q_op|.
        This option cannot be set from a |modeline| or in the |sandbox|, for
        security reasons.
 
+                                       *'makeencoding'* *'menc'*
+'makeencoding' 'menc'  string  (default "")
+                       global or local to buffer |global-local|
+                       {only available when compiled with the |+multi_byte|
+                       feature}
+                       {not in Vi}
+       Encoding used for reading the output of external commands.  When empty,
+       encoding is not converted.
+       This is used for `:make`, `:lmake`, `:grep`, `:lgrep`, `:grepadd`,
+       `:lgrepadd`, `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`,
+       and `:laddfile`.
+
+       This would be mostly useful when you use MS-Windows and set 'encoding'
+       to "utf-8".  If |+iconv| is enabled and GNU libiconv is used, setting
+       'makeencoding' to "char" has the same effect as setting to the system
+       locale encoding.  Example: >
+               :set encoding=utf-8
+               :set makeencoding=char  " system locale is used
+<
                                                *'makeprg'* *'mp'*
 'makeprg' 'mp'         string  (default "make", VMS: "MMS")
                        global or local to buffer |global-local|
index 2ad1d2a8caa9bf5e294263dec59511edc0533851..2430cff32b8cd6f4e40d376f45a8f540a7c1a441 100644 (file)
@@ -164,6 +164,9 @@ processing a quickfix or location list command, it will be aborted.
                        keep Vim running while compiling.  If you give the
                        name of the errorfile, the 'errorfile' option will
                        be set to [errorfile].  See |:cc| for [!].
+                       If the encoding of the error file differs from the
+                       'encoding' option, you can use the 'makeencoding'
+                       option to specify the encoding.
 
                                                        *:lf* *:lfile*
 :lf[ile][!] [errorfile]        Same as ":cfile", except the location list for the
@@ -175,6 +178,9 @@ processing a quickfix or location list command, it will be aborted.
 :cg[etfile] [errorfile]                                        *:cg* *:cgetfile*
                        Read the error file.  Just like ":cfile" but don't
                        jump to the first error.
+                       If the encoding of the error file differs from the
+                       'encoding' option, you can use the 'makeencoding'
+                       option to specify the encoding.
 
 
 :lg[etfile] [errorfile]                                        *:lg* *:lgetfile*
@@ -185,6 +191,9 @@ processing a quickfix or location list command, it will be aborted.
 :caddf[ile] [errorfile]        Read the error file and add the errors from the
                        errorfile to the current quickfix list. If a quickfix
                        list is not present, then a new list is created.
+                       If the encoding of the error file differs from the
+                       'encoding' option, you can use the 'makeencoding'
+                       option to specify the encoding.
 
                                                        *:laddf* *:laddfile*
 :laddf[ile] [errorfile]        Same as ":caddfile", except the location list for the
@@ -320,6 +329,7 @@ use this code: >
        endfunction
 
        au QuickfixCmdPost make call QfMakeConv()
+Another option is using 'makeencoding'.
 
 
 EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
@@ -586,6 +596,9 @@ lists, use ":cnewer 99" first.
                           like |:cnext| and |:cprevious|, see above.
                        This command does not accept a comment, any "
                        characters are considered part of the arguments.
+                       If the encoding of the program output differs from the
+                       'encoding' option, you can use the 'makeencoding'
+                       option to specify the encoding.
 
                                                        *:lmak* *:lmake*
 :lmak[e][!] [arguments]
@@ -645,6 +658,7 @@ read the error messages: >
        au QuickfixCmdPost make call QfMakeConv()
 
 (Example by Faque Cheng)
+Another option is using 'makeencoding'.
 
 ==============================================================================
 5. Using :vimgrep and :grep                            *grep* *lid*
@@ -759,6 +773,9 @@ id-utils) in a similar way to its compiler integration (see |:make| above).
                        When 'grepprg' is "internal" this works like
                        |:vimgrep|.  Note that the pattern needs to be
                        enclosed in separator characters then.
+                       If the encoding of the program output differs from the
+                       'encoding' option, you can use the 'makeencoding'
+                       option to specify the encoding.
 
                                                            *:lgr* *:lgrep*
 :lgr[ep][!] [arguments]        Same as ":grep", except the location list for the
@@ -783,6 +800,10 @@ id-utils) in a similar way to its compiler integration (see |:make| above).
                                  \ | catch /E480:/
                                  \ | endtry"
 <
+                       If the encoding of the program output differs from the
+                       'encoding' option, you can use the 'makeencoding'
+                       option to specify the encoding.
+
                                                        *:lgrepa* *:lgrepadd*
 :lgrepa[dd][!] [arguments]
                        Same as ":grepadd", except the location list for the
index b55fce1ce96db1cf75d61cab7afcb0570c741953..e64a5f646cd60c805117d22c55b6750ece9ad1b6 100644 (file)
@@ -782,6 +782,7 @@ Short explanation of each option:           *option-list*
 'macatsui'                 Mac GUI: use ATSUI text drawing
 'magic'                            changes special characters in search patterns
 'makeef'         'mef'     name of the errorfile for ":make"
+'makeencoding'   'menc'    encoding of external make/grep commands
 'makeprg'        'mp'      program to use for the ":make" command
 'matchpairs'     'mps'     pairs of characters that "%" can match
 'matchtime'      'mat'     tenths of a second to show matching paren
index 0bdd1d470c8dc5a61d186c856437d144bcce452b..6e7fdde3c77a91cf15cf3eaabfc2d4d467bb2755 100644 (file)
@@ -2157,6 +2157,7 @@ test_arglist \
        test_listlbr \
        test_listlbr_utf8 \
        test_lua \
+       test_makeencoding \
        test_man \
        test_mapping \
        test_marks \
index 6edb48a6f6f199e228744a529b7868348859e0a4..c25cb2f1a3a1334087794736a50c666b33fe540a 100644 (file)
@@ -2255,6 +2255,9 @@ free_buf_options(
     clear_string_option(&buf->b_p_lw);
 #endif
     clear_string_option(&buf->b_p_bkc);
+#ifdef FEAT_MBYTE
+    clear_string_option(&buf->b_p_menc);
+#endif
 }
 
 /*
index 60480a5b7e173a562068189a6d0b567d13f82c2d..5b384982e36ae7802185c6a2d823e5aff99fe4c2 100644 (file)
@@ -1242,7 +1242,7 @@ cs_find_common(
                wp = curwin;
            /* '-' starts a new error list */
            if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m",
-                                                 *qfpos == '-', cmdline) > 0)
+                                         *qfpos == '-', cmdline, NULL) > 0)
            {
 # ifdef FEAT_WINDOWS
                if (postponed_split != 0)
index 0f9f3fff4e1dec5ec1e48704b78fdf5f2c496b4c..2f8d291bfe4e47fde83ef114c1f7e01bc178b424 100644 (file)
@@ -559,11 +559,16 @@ vim_main2(void)
      */
     if (params.edit_type == EDIT_QF)
     {
+       char_u  *enc = NULL;
+
+# ifdef FEAT_MBYTE
+       enc = p_menc;
+# endif
        if (params.use_ef != NULL)
            set_string_option_direct((char_u *)"ef", -1,
                                           params.use_ef, OPT_FREE, SID_CARG);
        vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
-       if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff) < 0)
+       if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff, enc) < 0)
        {
            out_char('\n');
            mch_exit(3);
index 459179e2e1b5f37f3ee7f75b9c5dc53428908f17..d4e760b89330458618d46c1c9bcbf5ea6c0417f1 100644 (file)
 # define PV_LISP       OPT_BUF(BV_LISP)
 # define PV_LW         OPT_BOTH(OPT_BUF(BV_LW))
 #endif
+#ifdef FEAT_MBYTE
+# define PV_MENC       OPT_BOTH(OPT_BUF(BV_MENC))
+#endif
 #define PV_MA          OPT_BUF(BV_MA)
 #define PV_ML          OPT_BUF(BV_ML)
 #define PV_MOD         OPT_BUF(BV_MOD)
@@ -1898,6 +1901,15 @@ static struct vimoption options[] =
 #else
                            (char_u *)NULL, PV_NONE,
                            {(char_u *)NULL, (char_u *)0L}
+#endif
+                           SCRIPTID_INIT},
+    {"makeencoding","menc", P_STRING|P_VI_DEF,
+#ifdef FEAT_MBYTE
+                           (char_u *)&p_menc, PV_MENC,
+                           {(char_u *)"", (char_u *)0L}
+#else
+                           (char_u *)NULL, PV_NONE,
+                           {(char_u *)0L, (char_u *)0L}
 #endif
                            SCRIPTID_INIT},
     {"makeprg",            "mp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
@@ -5686,6 +5698,9 @@ check_buf_options(buf_T *buf)
     check_string_option(&buf->b_p_lw);
 #endif
     check_string_option(&buf->b_p_bkc);
+#ifdef FEAT_MBYTE
+    check_string_option(&buf->b_p_menc);
+#endif
 }
 
 /*
@@ -6289,8 +6304,9 @@ did_set_string_option(
 #endif
 
 #ifdef FEAT_MBYTE
-    /* 'encoding' and 'fileencoding' */
-    else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc)
+    /* 'encoding', 'fileencoding', 'termencoding' and 'makeencoding' */
+    else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc
+                                                          || gvarp == &p_menc)
     {
        if (gvarp == &p_fenc)
        {
@@ -10424,6 +10440,11 @@ unset_global_local_option(char_u *name, void *from)
        case PV_LW:
            clear_string_option(&buf->b_p_lw);
            break;
+#endif
+#ifdef FEAT_MBYTE
+       case PV_MENC:
+           clear_string_option(&buf->b_p_menc);
+           break;
 #endif
     }
 }
@@ -10478,6 +10499,9 @@ get_varp_scope(struct vimoption *p, int opt_flags)
            case PV_LW:   return (char_u *)&(curbuf->b_p_lw);
 #endif
            case PV_BKC:  return (char_u *)&(curbuf->b_p_bkc);
+#ifdef FEAT_MBYTE
+           case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
+#endif
        }
        return NULL; /* "cannot happen" */
     }
@@ -10553,6 +10577,10 @@ get_varp(struct vimoption *p)
        case PV_LW:     return *curbuf->b_p_lw != NUL
                                    ? (char_u *)&(curbuf->b_p_lw) : p->var;
 #endif
+#ifdef FEAT_MBYTE
+       case PV_MENC:   return *curbuf->b_p_menc != NUL
+                                   ? (char_u *)&(curbuf->b_p_menc) : p->var;
+#endif
 
 #ifdef FEAT_ARABIC
        case PV_ARAB:   return (char_u *)&(curwin->w_p_arab);
@@ -11154,6 +11182,9 @@ buf_copy_options(buf_T *buf, int flags)
 #ifdef FEAT_LISP
            buf->b_p_lw = empty_option;
 #endif
+#ifdef FEAT_MBYTE
+           buf->b_p_menc = empty_option;
+#endif
 
            /*
             * Don't copy the options set by ex_help(), use the saved values,
index 62e66cd3dafd6e07611407d8cb5fd38fc1a8b03e..2c6aeef034303b0eb6f6b46990af3e2caf1abf65 100644 (file)
@@ -630,6 +630,9 @@ EXTERN char_u       *p_luadll;      /* 'luadll' */
 EXTERN int     p_macatsui;     /* 'macatsui' */
 #endif
 EXTERN int     p_magic;        /* 'magic' */
+#ifdef FEAT_MBYTE
+EXTERN char_u  *p_menc;        /* 'makeencoding' */
+#endif
 #ifdef FEAT_QUICKFIX
 EXTERN char_u  *p_mef;         /* 'makeef' */
 EXTERN char_u  *p_mp;          /* 'makeprg' */
@@ -1064,6 +1067,9 @@ enum
 #ifdef FEAT_LISP
     , BV_LISP
     , BV_LW
+#endif
+#ifdef FEAT_MBYTE
+    , BV_MENC
 #endif
     , BV_MA
     , BV_ML
index d48eb25326c44f1f61232119293182847e5194fd..995f41f03388a371406070f42a3113d78307d294 100644 (file)
@@ -1,5 +1,5 @@
 /* quickfix.c */
-int qf_init(win_T *wp, char_u *efile, char_u *errorformat, int newlist, char_u *qf_title);
+int qf_init(win_T *wp, char_u *efile, char_u *errorformat, int newlist, char_u *qf_title, char_u *enc);
 void qf_free_all(win_T *wp);
 void copy_loclist(win_T *from, win_T *to);
 void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit);
index df351634f5c23f5efc678f4c3969eb924effcbf3..e4ea401ecec540a1ac301029297714a6da4cf8c1 100644 (file)
@@ -116,7 +116,7 @@ struct efm_S
 
 static efm_T   *fmt_start = NULL; /* cached across qf_parse_line() calls */
 
-static int     qf_init_ext(qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title);
+static int     qf_init_ext(qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc);
 static void    qf_store_title(qf_info_T *qi, char_u *title);
 static void    qf_new_list(qf_info_T *qi, char_u *qf_title);
 static void    ll_free_all(qf_info_T **pqi);
@@ -167,7 +167,8 @@ qf_init(
     char_u         *efile,
     char_u         *errorformat,
     int                    newlist,            /* TRUE: start a new error list */
-    char_u         *qf_title)
+    char_u         *qf_title,
+    char_u         *enc)
 {
     qf_info_T      *qi = &ql_info;
 
@@ -180,7 +181,7 @@ qf_init(
 
     return qf_init_ext(qi, efile, curbuf, NULL, errorformat, newlist,
                                                    (linenr_T)0, (linenr_T)0,
-                                                   qf_title);
+                                                   qf_title, enc);
 }
 
 /*
@@ -498,6 +499,7 @@ typedef struct {
     buf_T      *buf;
     linenr_T   buflnum;
     linenr_T   lnumlast;
+    vimconv_T  vc;
 } qfstate_T;
 
     static char_u *
@@ -713,6 +715,30 @@ qf_get_next_file_line(qfstate_T *state)
     else
        state->linebuf = IObuff;
 
+#ifdef FEAT_MBYTE
+    /* Convert a line if it contains a non-ASCII character. */
+    if (state->vc.vc_type != CONV_NONE && has_non_ascii(state->linebuf)) {
+       char_u  *line;
+
+       line = string_convert(&state->vc, state->linebuf, &state->linelen);
+       if (line != NULL)
+       {
+           if (state->linelen < IOSIZE)
+           {
+               STRCPY(state->linebuf, line);
+               vim_free(line);
+           }
+           else
+           {
+               vim_free(state->growbuf);
+               state->linebuf = state->growbuf = line;
+               state->growbufsiz = state->linelen < LINE_MAXLEN
+                                               ? state->linelen : LINE_MAXLEN;
+           }
+       }
+    }
+#endif
+
     return QF_OK;
 }
 
@@ -1105,11 +1131,11 @@ qf_init_ext(
     int                    newlist,            /* TRUE: start a new error list */
     linenr_T       lnumfirst,          /* first line number to use */
     linenr_T       lnumlast,           /* last line number to use */
-    char_u         *qf_title)
+    char_u         *qf_title,
+    char_u         *enc)
 {
-    qfstate_T      state = {NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
-                            NULL, 0, 0};
-    qffields_T     fields = {NULL, NULL, 0, 0L, 0, FALSE, NULL, 0, 0, 0};
+    qfstate_T      state;
+    qffields_T     fields;
 #ifdef FEAT_WINDOWS
     qfline_T       *old_last = NULL;
     int                    adding = FALSE;
@@ -1120,6 +1146,13 @@ qf_init_ext(
     int                    retval = -1;        /* default: return error flag */
     int                    status;
 
+    vim_memset(&state, 0, sizeof(state));
+    vim_memset(&fields, 0, sizeof(fields));
+#ifdef FEAT_MBYTE
+    state.vc.vc_type = CONV_NONE;
+    if (enc != NULL && *enc != NUL)
+       convert_setup(&state.vc, enc, p_enc);
+#endif
     fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf);
     fields.errmsglen = CMDBUFFSIZE + 1;
     fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg);
@@ -1286,6 +1319,10 @@ qf_init_end:
 #ifdef FEAT_WINDOWS
     qf_update_buffer(qi, old_last);
 #endif
+#ifdef FEAT_MBYTE
+    if (state.vc.vc_type != CONV_NONE)
+       convert_setup(&state.vc, NULL, NULL);
+#endif
 
     return retval;
 }
@@ -3431,6 +3468,7 @@ ex_make(exarg_T *eap)
 {
     char_u     *fname;
     char_u     *cmd;
+    char_u     *enc = NULL;
     unsigned   len;
     win_T      *wp = NULL;
     qf_info_T  *qi = &ql_info;
@@ -3464,6 +3502,9 @@ ex_make(exarg_T *eap)
 # endif
     }
 #endif
+#ifdef FEAT_MBYTE
+    enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
+#endif
 
     if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep
        || eap->cmdidx == CMD_lgrepadd)
@@ -3511,7 +3552,7 @@ ex_make(exarg_T *eap)
                            && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm,
                                           (eap->cmdidx != CMD_grepadd
                                            && eap->cmdidx != CMD_lgrepadd),
-                                          *eap->cmdlinep);
+                                          *eap->cmdlinep, enc);
     if (wp != NULL)
        qi = GET_LOC_LIST(wp);
 #ifdef FEAT_AUTOCMD
@@ -3850,6 +3891,7 @@ ex_cnext(exarg_T *eap)
     void
 ex_cfile(exarg_T *eap)
 {
+    char_u     *enc = NULL;
     win_T      *wp = NULL;
     qf_info_T  *qi = &ql_info;
 #ifdef FEAT_AUTOCMD
@@ -3874,6 +3916,9 @@ ex_cfile(exarg_T *eap)
     if (au_name != NULL)
        apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, FALSE, curbuf);
 #endif
+#ifdef FEAT_MBYTE
+    enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
+#endif
 #ifdef FEAT_BROWSE
     if (cmdmod.browse)
     {
@@ -3901,7 +3946,7 @@ ex_cfile(exarg_T *eap)
      */
     if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
                                  && eap->cmdidx != CMD_laddfile),
-                                                          *eap->cmdlinep) > 0
+                                                      *eap->cmdlinep, enc) > 0
                                  && (eap->cmdidx == CMD_cfile
                                             || eap->cmdidx == CMD_lfile))
     {
@@ -4927,7 +4972,7 @@ ex_cbuffer(exarg_T *eap)
                            (eap->cmdidx != CMD_caddbuffer
                             && eap->cmdidx != CMD_laddbuffer),
                                                   eap->line1, eap->line2,
-                                                  qf_title) > 0)
+                                                  qf_title, NULL) > 0)
            {
 #ifdef FEAT_AUTOCMD
                if (au_name != NULL)
@@ -4995,7 +5040,8 @@ ex_cexpr(exarg_T *eap)
            if (qf_init_ext(qi, NULL, NULL, tv, p_efm,
                            (eap->cmdidx != CMD_caddexpr
                             && eap->cmdidx != CMD_laddexpr),
-                                (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0)
+                                (linenr_T)0, (linenr_T)0, *eap->cmdlinep,
+                                NULL) > 0)
            {
 #ifdef FEAT_AUTOCMD
                if (au_name != NULL)
index 1e1b1da82cf702688bd9e2efe5192bca345f3769..5745df2ae91c119a8b37e66224d6a20bf20c6037 100644 (file)
@@ -2132,6 +2132,9 @@ struct file_buffer
     char_u     *b_p_kp;        /* 'keywordprg' */
 #ifdef FEAT_LISP
     int                b_p_lisp;       /* 'lisp' */
+#endif
+#ifdef FEAT_MBYTE
+    char_u     *b_p_menc;      /* 'makeencoding' */
 #endif
     char_u     *b_p_mps;       /* 'matchpairs' */
     int                b_p_ml;         /* 'modeline' */
index 513fd897176c32d46c0991b44708ea2a61aa838e..e1ce1518fcb026bfdfaeeef3851d361ae3afa2cf 100644 (file)
@@ -170,6 +170,7 @@ NEW_TESTS = test_arabic.res \
            test_listlbr.res \
            test_listlbr_utf8.res \
            test_lua.res \
+           test_makeencoding.res \
            test_man.res \
            test_marks.res \
            test_matchadd_conceal.res \
diff --git a/src/testdir/test_makeencoding.py b/src/testdir/test_makeencoding.py
new file mode 100644 (file)
index 0000000..041edad
--- /dev/null
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Test program for :make, :grep and :cgetfile.
+
+from __future__ import print_function, unicode_literals
+import locale
+import io
+import sys
+
+def set_output_encoding(enc=None):
+    """Set the encoding of stdout and stderr
+
+    arguments:
+      enc -- Encoding name.
+             If omitted, locale.getpreferredencoding() is used.
+    """
+    if enc is None:
+        enc = locale.getpreferredencoding()
+
+    def get_text_writer(fo, **kwargs):
+        kw = dict(kwargs)
+        kw.setdefault('errors', 'backslashreplace') # use \uXXXX style
+        kw.setdefault('closefd', False)
+
+        if sys.version_info[0] < 3:
+            # Work around for Python 2.x
+            # New line conversion isn't needed here. Done in somewhere else.
+            writer = io.open(fo.fileno(), mode='w', newline='', **kw)
+            write = writer.write    # save the original write() function
+            enc = locale.getpreferredencoding()
+            def convwrite(s):
+                if isinstance(s, bytes):
+                    write(s.decode(enc))    # convert to unistr
+                else:
+                    write(s)
+                try:
+                    writer.flush()  # needed on Windows
+                except IOError:
+                    pass
+            writer.write = convwrite
+        else:
+            writer = io.open(fo.fileno(), mode='w', **kw)
+        return writer
+
+    sys.stdout = get_text_writer(sys.stdout, encoding=enc)
+    sys.stderr = get_text_writer(sys.stderr, encoding=enc)
+
+
+def main():
+    enc = 'utf-8'
+    if len(sys.argv) > 1:
+        enc = sys.argv[1]
+    set_output_encoding(enc)
+
+    message_tbl = {
+            'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
+            'latin1': 'ÀÈÌÒÙ',
+            'cp932': 'こんにちは',
+            'cp936': '你好',
+            }
+
+    print('Xfoobar.c(10) : %s (%s)' % (message_tbl[enc], enc))
+
+
+if __name__ == "__main__":
+    main()
diff --git a/src/testdir/test_makeencoding.vim b/src/testdir/test_makeencoding.vim
new file mode 100644 (file)
index 0000000..a3d5538
--- /dev/null
@@ -0,0 +1,106 @@
+" Tests for 'makeencoding'.
+if !has('multi_byte')
+  finish
+endif
+
+source shared.vim
+
+let s:python = PythonProg()
+if s:python == ''
+  " Can't run this test.
+  finish
+endif
+
+let s:script = 'test_makeencoding.py'
+
+let s:message_tbl = {
+      \ 'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
+      \ 'latin1': 'ÀÈÌÒÙ',
+      \ 'cp932': 'こんにちは',
+      \ 'cp936': '你好',
+      \}
+
+
+" Tests for :cgetfile and :lgetfile.
+func Test_getfile()
+  set errorfile=Xerror.txt
+  set errorformat=%f(%l)\ :\ %m
+
+  " :cgetfile
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    cgetfile
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgetfile
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    lgetfile
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+
+  call delete(&errorfile)
+endfunc
+
+
+" Tests for :grep and :lgrep.
+func Test_grep()
+  let &grepprg = s:python
+  set grepformat=%f(%l)\ :\ %m
+
+  " :grep
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent grep! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgrep
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent lgrep! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+endfunc
+
+
+" Tests for :make and :lmake.
+func Test_make()
+  let &makeprg = s:python
+  set errorformat=%f(%l)\ :\ %m
+
+  " :make
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent make! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lmake
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent lmake! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+endfunc
index 834f1442e006de423aac3d736f825e13bc21ddbc..f3a0b6c906c17eecd8e1e9ea07647335e67dc30b 100644 (file)
@@ -764,6 +764,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    420,
 /**/
     419,
 /**/