Hi,
2016/9/9 Fri 0:30:00 UTC+9 Ken Takata wrote:
> Hi,
>
> 2016/9/7 Wed 3:08:50 UTC+9 Bram Moolenaar wrote:
> > Ken Takata wrote:
> >
> > > 2016/8/23 Tue 20:00:50 UTC+9 Ken Takata wrote:
> > > > Hi Bram,
> > > >
> > > > 2016/8/22 Mon 2:29:28 UTC+9 Bram Moolenaar wrote:
> > > > > Ken Takata wrote:
> > > > >
> > > > > > > > > > I wrote a patch for the following todo item:
> > > > > > > > > >
> > > > > > > > > > > Win32: When running ":make" and 'encoding' differs from
> > > > > > > > > > > the system locale, the
> > > > > > > > > > > output should be converted. Esp. when 'encoding' is
> > > > > > > > > > > "utf-8". (Yongwei Wu)
> > > > > > > > > > > Should we use 'termencoding' for this?
> > > > > > > > > >
> > > > > > > > > > I think using 'termencoding' for this is not so good.
> > > > > > > > > > Normally
> > > > > > > > > > the encoding of a command output is the same as the
> > > > > > > > > > encoding of
> > > > > > > > > > the terminal, but not always the same. I hear that some
> > > > > > > > > > commands
> > > > > > > > > > on Windows use utf-8 instead of the current codepage. So I
> > > > > > > > > > added
> > > > > > > > > > a new option 'cmdencoding' ('cenc').
> > > > > > > > > > What do you think of this?
> > > > > > > > >
> > > > > > > > > Seems reasonable. It's not nice that it's yet another
> > > > > > > > > option. But in
> > > > > > > > > case you know the compiler output is in a certain encoding
> > > > > > > > > it's the only
> > > > > > > > > way to make it work.
> > > > > > > > >
> > > > > > > > > Why they "char" value? It's using the system locale,
> > > > > > > > > wouldn't "system"
> > > > > > > > > be better? Hmm, I don't see where "char" is recognized.
> > > > > > > >
> > > > > > > > At least, GNU libiconv supports "char".
> > > > > > > >
> > > > > > > > See: https://www.gnu.org/software/libiconv/
> > > > > > > > | Locale dependent, in terms of `char' or `wchar_t' (with
> > > > > > > > machine dependent
> > > > > > > > | endianness and alignment, and with OS and locale dependent
> > > > > > > > semantics)
> > > > > > > > | char, wchar_t
> > > > > > > > | The empty encoding name "" is equivalent to "char": it
> > > > > > > > denotes the locale
> > > > > > > > | dependent character encoding.
> > > > > > > >
> > > > > > > > I don't know about other iconv implementations.
> > > > > > >
> > > > > > > I found a few, but they all say that the name supported are system
> > > > > > > dependent. Perhaps someone can dig deeper?
> > > > > >
> > > > > > I hear that the "char" encoding would be a GNU extension. So the
> > > > > > description
> > > > > > in options.txt would be:
> > > > > >
> > > > > > This would be mostly useful when you use MS-Windows and set
> > > > > > 'encoding'
> > > > > > to "utf-8". If GNU libiconv is available, setting
> > > > > > 'cmdencoding' to
> > > > > > "char" has the same effect as setting to the system locale
> > > > > > encoding.
> > > > > > Example: >
> > > > > > :set encoding=utf-8
> > > > > > :set cmdencoding=char " system locale is used
> > > > > >
> > > > > > On Japanese Windows, `set cenc=char` has the same effect as `set
> > > > > > cenc=cp932`.
> > > > > > (I suppose the Vim 8.0 win32 installer will contain GNU libiconv.)
> > > > >
> > > > > Looking at this patch, I think it also applies the conversion to
> > > > > ":cbuffer". That should not happen. Also ":cexpr".
> > > >
> > > > No, the conversion will not be applied to `:cbuffer` and `:cexpr`.
> > > > As I wrote in the help, it will be applied to:
> > > > `:make`, `:lmake`, `:grep`, `:lgrep`, `:grepadd`, `:lgrepadd`,
> > > > `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`, and
> > > > `:laddfile`.
> > > > (Oh, I didn't mention 'cenc' in each of them, only in `:make` and
> > > > `:lmake`.)
> > > >
> > > > My patch only adds the conversion to the function
> > > > qf_get_next_file_line()
> > > > which is used only when reading from a file. (Note that `:make` and
> > > > `:grep`
> > > > also use a file.)
> > > > Hm, is it confusing that 'cmdencoding' also applies to `:[cl].*file`?
> > > >
> > > > `:cbuffer` calls qf_get_next_buf_line(), I think.
> > > >
> > > >
> > > > > In general, whether the conversion is needed depends on the command
> > > > > used. E.g. for :grep and :make it might be different. Not sure how
> > > > > to
> > > > > deal with that.
> > > >
> > > > Do you mean `:grep` and `:make` should have different encoding options?
> > > > Maybe a user can create wrapper commands which set 'cenc' before
> > > > executing
> > > > `:grep` or `:make`.
> > > > Of course, it would be nice if Vim supports it natively, but I have no
> > > > idea
> > > > how to implement it.
> > >
> > > I'm thinking this issue again.
> > > Maybe we can do this by adding an parameter for encoding to qf_init() in
> > > quickfix.c. I think we can use three options instead of 'cenc':
> > >
> > > 1. 'makeencoding', 'menc':
> > > Option for `:make` and `:lmake`.
> > > 2. 'grepencoding', 'genc':
> > > Option for `:grep`, `:grepadd`, `:lgrep` and `:lgrepadd`.
> > > 3. 'errfileencoding', 'eenc':
> > > Option for `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`,
> > > and `:laddfile`.
> > >
> > > And I think these options should be global-local options.
> > > What do you think?
> >
> > That's a lot of new options, but it's probably needed. An alternative
> > is to make a comma separated list, but that's hard to use by plugins.
> > e.g. if a plugin uses ":cfile" it probably wants to save, set and
> > restore an option.
> >
> > I would use 'menc' encoding for all commands when 'genc' and 'eenc' are
> > empty. On MS-Windows you probably want to set it to the system
> > codepage.
>
> I wrote a patch to implement this. Please check the attached patch.
> I haven't add a test for this yet. It's not so easy.
I have updated the patch. Now, it includes tests.
I think that the patch is ready to be included.
Regards,
Ken Takata
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
# HG changeset patch
# Parent 533dca4c48ee68ae2094e098cb069f21802aef57
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2785,6 +2785,19 @@ A jump table for the options with a shor
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
+ *'errfileencoding'* *'eenc'*
+'errfileencoding' 'eenc'
+ 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 error file. When empty, the value of
+ 'makeencoding' is used.
+ This is used for `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`,
+ `:lgetfile` and `:laddfile`.
+ See also: 'makeencoding', 'grepencoding'
+
*'errorbells'* *'eb'* *'noerrorbells'* *'noeb'*
'errorbells' 'eb' boolean (default off)
global
@@ -3468,6 +3481,17 @@ A jump table for the options with a shor
NOTE: This option is reset when 'compatible' is set.
+ *'grepencoding'* *'genc'*
+'grepencoding' 'genc' 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 grep commands. When
+ empty, the value of 'makeencoding' is used.
+ This is used for `:grep`, `:lgrep`, `:grepadd` and `:lgrepadd`.
+ See also: 'makeencoding', 'errfileencoding'
+
*'grepformat'* *'gfm'*
'grepformat' 'gfm' string (default "%f:%l:%m,%f:%l%m,%f %l%m")
global
@@ -4971,6 +4995,26 @@ A jump table for the options with a shor
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` and `:lmake`.
+
+ This is also used as a default value for 'errfileencoding' and
+ 'grepencoding' if they are empty.
+
+ 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|
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -164,6 +164,9 @@ processing a quickfix or location list c
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 'errfileencoding'
+ 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 c
: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 'errfileencoding'
+ option to specify the encoding.
:lg[etfile] [errorfile] *:lg* *:lgetfile*
@@ -185,6 +191,9 @@ processing a quickfix or location list c
: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 'errfileencoding'
+ 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 @@ 4. Using :make *:make_makeprg*
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 compil
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 'grepencoding'
+ 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 compil
\ | catch /E480:/
\ | endtry"
<
+ If the encoding of the program output differs from the
+ 'encoding' option, you can use the 'grepencoding'
+ option to specify the encoding.
+
*:lgrepa* *:lgrepadd*
:lgrepa[dd][!] [arguments]
Same as ":grepadd", except the location list for the
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -684,6 +684,7 @@ Short explanation of each option: *opti
'endofline' 'eol' write <EOL> for last line in file
'equalalways' 'ea' windows are automatically made the same size
'equalprg' 'ep' external program to use for "=" command
+'errfileencoding' 'eenc' encoding of the error file
'errorbells' 'eb' ring the bell for error messages
'errorfile' 'ef' name of the errorfile for the QuickFix mode
'errorformat' 'efm' description of the lines in the error file
@@ -719,6 +720,7 @@ Short explanation of each option: *opti
'formatprg' 'fp' name of external program used with "gq" command
'fsync' 'fs' whether to invoke fsync() after file write
'gdefault' 'gd' the ":substitute" flag 'g' is default on
+'grepencoding' 'genc' encoding of external grep commands
'grepformat' 'gfm' format of 'grepprg' output
'grepprg' 'gp' program to use for ":grep"
'guicursor' 'gcr' GUI: settings for cursor shape and blinking
@@ -782,6 +784,7 @@ Short explanation of each option: *opti
'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 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
diff --git a/src/Makefile b/src/Makefile
--- a/src/Makefile
+++ b/src/Makefile
@@ -2127,6 +2127,7 @@ test_arglist \
test_langmap \
test_largefile \
test_lispwords \
+ test_makeencoding \
test_man \
test_mapping \
test_marks \
diff --git a/src/buffer.c b/src/buffer.c
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2225,6 +2225,11 @@ 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_eenc);
+ clear_string_option(&buf->b_p_genc);
+ clear_string_option(&buf->b_p_menc);
+#endif
}
/*
diff --git a/src/if_cscope.c b/src/if_cscope.c
--- a/src/if_cscope.c
+++ b/src/if_cscope.c
@@ -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)
diff --git a/src/main.c b/src/main.c
--- a/src/main.c
+++ b/src/main.c
@@ -556,11 +556,17 @@ vim_main2(void)
*/
if (params.edit_type == EDIT_QF)
{
+ char_u *enc = NULL;
+
+# ifdef FEAT_MBYTE
+ /* Use 'eenc' if it is set. Otherwise use 'menc'. */
+ enc = (*p_eenc != NUL) ? p_eenc : 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);
diff --git a/src/option.c b/src/option.c
--- a/src/option.c
+++ b/src/option.c
@@ -97,6 +97,9 @@
# define PV_DEF OPT_BOTH(OPT_BUF(BV_DEF))
# define PV_INC OPT_BOTH(OPT_BUF(BV_INC))
#endif
+#ifdef FEAT_MBYTE
+# define PV_EENC OPT_BOTH(OPT_BUF(BV_EENC))
+#endif
#define PV_EOL OPT_BUF(BV_EOL)
#define PV_FIXEOL OPT_BUF(BV_FIXEOL)
#define PV_EP OPT_BOTH(OPT_BUF(BV_EP))
@@ -116,6 +119,9 @@
#ifdef FEAT_AUTOCMD
# define PV_FT OPT_BUF(BV_FT)
#endif
+#ifdef FEAT_MBYTE
+# define PV_GENC OPT_BOTH(OPT_BUF(BV_GENC))
+#endif
#define PV_IMI OPT_BUF(BV_IMI)
#define PV_IMS OPT_BUF(BV_IMS)
#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
@@ -138,6 +144,9 @@
# 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)
@@ -1083,6 +1092,15 @@ static struct vimoption options[] =
{"errorbells", "eb", P_BOOL|P_VI_DEF,
(char_u *)&p_eb, PV_NONE,
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
+ {"errfileencoding", "eenc", P_STRING|P_VI_DEF,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_eenc, PV_EENC,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ SCRIPTID_INIT},
{"errorfile", "ef", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
#ifdef FEAT_QUICKFIX
(char_u *)&p_ef, PV_NONE,
@@ -1284,6 +1302,15 @@ static struct vimoption options[] =
{(char_u *)NULL, (char_u *)0L}
#endif
SCRIPTID_INIT},
+ {"grepencoding","genc", P_STRING|P_VI_DEF,
+#ifdef FEAT_MBYTE
+ (char_u *)&p_genc, PV_GENC,
+ {(char_u *)"", (char_u *)0L}
+#else
+ (char_u *)NULL, PV_NONE,
+ {(char_u *)0L, (char_u *)0L}
+#endif
+ SCRIPTID_INIT},
{"grepprg", "gp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
#ifdef FEAT_QUICKFIX
(char_u *)&p_gp, PV_GP,
@@ -1800,6 +1827,15 @@ static struct vimoption options[] =
{(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,
#ifdef FEAT_QUICKFIX
(char_u *)&p_mp, PV_MP,
@@ -5558,6 +5594,11 @@ 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_eenc);
+ check_string_option(&buf->b_p_genc);
+ check_string_option(&buf->b_p_menc);
+#endif
}
/*
@@ -6155,7 +6196,8 @@ did_set_string_option(
#ifdef FEAT_MBYTE
/* 'encoding' and 'fileencoding' */
- else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc)
+ else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc
+ || gvarp == &p_eenc || gvarp == &p_genc || gvarp == &p_menc)
{
if (gvarp == &p_fenc)
{
@@ -10232,6 +10274,17 @@ unset_global_local_option(char_u *name,
clear_string_option(&buf->b_p_lw);
break;
#endif
+#ifdef FEAT_MBYTE
+ case PV_EENC:
+ clear_string_option(&buf->b_p_eenc);
+ break;
+ case PV_GENC:
+ clear_string_option(&buf->b_p_genc);
+ break;
+ case PV_MENC:
+ clear_string_option(&buf->b_p_menc);
+ break;
+#endif
}
}
@@ -10284,6 +10337,11 @@ get_varp_scope(struct vimoption *p, int
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_EENC: return (char_u *)&(curbuf->b_p_eenc);
+ case PV_GENC: return (char_u *)&(curbuf->b_p_genc);
+ case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
+#endif
}
return NULL; /* "cannot happen" */
}
@@ -10357,6 +10415,14 @@ 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_EENC: return *curbuf->b_p_eenc != NUL
+ ? (char_u *)&(curbuf->b_p_eenc) : p->var;
+ case PV_GENC: return *curbuf->b_p_genc != NUL
+ ? (char_u *)&(curbuf->b_p_genc) : p->var;
+ 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);
@@ -10957,6 +11023,11 @@ buf_copy_options(buf_T *buf, int flags)
#ifdef FEAT_LISP
buf->b_p_lw = empty_option;
#endif
+#ifdef FEAT_MBYTE
+ buf->b_p_eenc = empty_option;
+ buf->b_p_genc = empty_option;
+ buf->b_p_menc = empty_option;
+#endif
/*
* Don't copy the options set by ex_help(), use the saved values,
diff --git a/src/option.h b/src/option.h
--- a/src/option.h
+++ b/src/option.h
@@ -465,6 +465,9 @@ EXTERN char_u *p_ead; /* 'eadirection'
#endif
EXTERN int p_ea; /* 'equalalways' */
EXTERN char_u *p_ep; /* 'equalprg' */
+#ifdef FEAT_MBYTE
+EXTERN char_u *p_eenc; /* 'errfileencoding' */
+#endif
EXTERN int p_eb; /* 'errorbells' */
#ifdef FEAT_QUICKFIX
EXTERN char_u *p_ef; /* 'errorfile' */
@@ -509,6 +512,9 @@ EXTERN char_u *p_fp; /* 'formatprg' */
EXTERN int p_fs; /* 'fsync' */
#endif
EXTERN int p_gd; /* 'gdefault' */
+#ifdef FEAT_MBYTE
+EXTERN char_u *p_genc; /* 'grepencoding' */
+#endif
#ifdef FEAT_PRINTER
EXTERN char_u *p_pdev; /* 'printdevice' */
# ifdef FEAT_POSTSCRIPT
@@ -630,6 +636,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' */
@@ -1024,6 +1033,9 @@ enum
, BV_DEF
, BV_INC
#endif
+#ifdef FEAT_MBYTE
+ , BV_EENC
+#endif
, BV_EOL
, BV_FIXEOL
, BV_EP
@@ -1039,6 +1051,9 @@ enum
#ifdef FEAT_AUTOCMD
, BV_FT
#endif
+#ifdef FEAT_MBYTE
+ , BV_GENC
+#endif
, BV_IMI
, BV_IMS
#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
@@ -1061,6 +1076,9 @@ enum
, BV_LISP
, BV_LW
#endif
+#ifdef FEAT_MBYTE
+ , BV_MENC
+#endif
, BV_MA
, BV_ML
, BV_MOD
diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro
--- a/src/proto/quickfix.pro
+++ b/src/proto/quickfix.pro
@@ -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);
diff --git a/src/quickfix.c b/src/quickfix.c
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -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,10 +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};
+ NULL, 0, 0, NULL};
qffields_T fields = {NULL, NULL, 0, 0L, 0, FALSE, NULL, 0, 0, 0};
#ifdef FEAT_WINDOWS
qfline_T *old_last = NULL;
@@ -1119,7 +1146,14 @@ qf_init_ext(
static char_u *last_efm = NULL;
int retval = -1; /* default: return error flag */
int status;
-
+#ifdef FEAT_MBYTE
+ vimconv_T vc;
+
+ vc.vc_type = CONV_NONE;
+ if (enc != NULL && *enc != NUL)
+ convert_setup(&vc, enc, p_enc);
+ state.vc = &vc;
+#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 +1320,10 @@ qf_init_end:
#ifdef FEAT_WINDOWS
qf_update_buffer(qi, old_last);
#endif
+#ifdef FEAT_MBYTE
+ if (vc.vc_type != CONV_NONE)
+ convert_setup(&vc, NULL, NULL);
+#endif
return retval;
}
@@ -3431,6 +3469,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 +3503,18 @@ ex_make(exarg_T *eap)
# endif
}
#endif
+#ifdef FEAT_MBYTE
+ if ((eap->cmdidx != CMD_make) && (eap->cmdidx != CMD_lmake))
+ {
+ /* Use 'genc' for grep commands if it is set. */
+ if (*curbuf->b_p_genc != NUL)
+ enc = curbuf->b_p_genc;
+ else if (*p_genc != NUL)
+ enc = p_genc;
+ }
+ if (enc == NULL)
+ 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 +3562,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 +3901,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 +3926,17 @@ ex_cfile(exarg_T *eap)
if (au_name != NULL)
apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, FALSE, curbuf);
#endif
+#ifdef FEAT_MBYTE
+ /* Use 'eenc' if it is set. Otherwise use 'menc'. */
+ if (*curbuf->b_p_eenc != NUL)
+ enc = curbuf->b_p_eenc;
+ else if (*p_eenc != NUL)
+ enc = p_eenc;
+ else if (*curbuf->b_p_menc != NUL)
+ enc = curbuf->b_p_menc;
+ else
+ enc = p_menc;
+#endif
#ifdef FEAT_BROWSE
if (cmdmod.browse)
{
@@ -3901,7 +3964,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 +4990,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 +5058,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)
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -2068,6 +2068,9 @@ struct file_buffer
char_u *b_p_cfu; /* 'completefunc' */
char_u *b_p_ofu; /* 'omnifunc' */
#endif
+#ifdef FEAT_MBYTE
+ char_u *b_p_eenc; /* 'errfileencoding' */
+#endif
int b_p_eol; /* 'endofline' */
int b_p_fixeol; /* 'fixendofline' */
int b_p_et; /* 'expandtab' */
@@ -2082,6 +2085,9 @@ struct file_buffer
#endif
char_u *b_p_fo; /* 'formatoptions' */
char_u *b_p_flp; /* 'formatlistpat' */
+#ifdef FEAT_MBYTE
+ char_u *b_p_genc; /* 'grepencoding' */
+#endif
int b_p_inf; /* 'infercase' */
char_u *b_p_isk; /* 'iskeyword' */
#ifdef FEAT_FIND_ID
@@ -2108,6 +2114,9 @@ struct file_buffer
#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' */
int b_p_ml_nobin; /* b_p_ml saved for binary mode */
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -164,6 +164,7 @@ NEW_TESTS = test_arglist.res \
test_job_fails.res \
test_json.res \
test_langmap.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
--- /dev/null
+++ b/src/testdir/test_makeencoding.py
@@ -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
--- /dev/null
+++ b/src/testdir/test_makeencoding.vim
@@ -0,0 +1,156 @@
+" Tests for 'errfileencoding', 'grepencoding' and '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 with 'makeencoding' and 'errfileencoding'.
+func Test_getfile()
+ set errorfile=Xerror.txt
+ set errorformat=%f(%l)\ :\ %m
+
+ " :cgetfile with 'makeencoding'
+ set errfileencoding=
+ 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 with 'makeencoding'
+ set errfileencoding=
+ 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
+
+ " :cgetfile with 'errfileencoding'
+ set makeencoding=
+ for enc in keys(s:message_tbl)
+ let &errfileencoding = 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 with 'errfileencoding'
+ set makeencoding=
+ for enc in keys(s:message_tbl)
+ let &errfileencoding = 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 with 'makeencoding' and 'grepencoding'.
+func Test_grep()
+ let &grepprg = s:python
+ set grepformat=%f(%l)\ :\ %m
+
+ " :grep with 'makeencoding'
+ set grepencoding=
+ 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 with 'makeencoding'
+ set grepencoding=
+ 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
+
+ " :grep with 'grepencoding'
+ set makeencoding=
+ for enc in keys(s:message_tbl)
+ let &grepencoding = enc
+ exec "silent grep! " . s:script . " " . enc
+ copen
+ call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+ \ getline('.'))
+ cclose
+ endfor
+
+ " :lgrep with 'grepencoding'
+ set makeencoding=
+ for enc in keys(s:message_tbl)
+ let &grepencoding = 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 with 'makeencoding'.
+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