Vim Tips Wiki
(Change to TipImported template + severe manual clean)
m (correct script template use)
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{review}}
 
 
{{TipImported
 
{{TipImported
 
|id=911
 
|id=911
 
|previous=910
 
|previous=910
 
|next=912
 
|next=912
|created=April 12, 2005
+
|created=2005
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Wu Yongwei
 
|author=Wu Yongwei
 
|version=6.0
 
|version=6.0
 
|rating=5/6
 
|rating=5/6
  +
|category1=Encoding
  +
|category2=
 
}}
 
}}
Currently fileencoding does not work well in a modeline. When Vim sees the fileencoding setting, the file has already been read, and only output will be affected. That will cause even more trouble as, for example, if the default encoding is latin1 and the modeline has <tt>fileencoding=utf-8</tt>, then the resulting file will be a utf-8 file converted as latin1 to utf-8 again.
+
Currently fileencoding does not work well in a modeline. When Vim sees the fileencoding setting, the file has already been read, so setting 'fileencoding' in a modeline normally has no effect until you write the file. That will cause even more trouble as, for example, if the default encoding is latin1 and the modeline has <code>fileencoding=utf-8</code>, then the resulting file will be a utf-8 file converted as latin1 to utf-8 again.
   
  +
Vim does as best as it can to detect your encoding, if you place its name in your 'fileencodings' option. However, Vim cannot distinguish between multiple 8-bit encodings, so only the first one of those will be used. You can install a plugin like {{script|id=2721|text=AutoFenc}} to automatically detect the correct encoding in many cases where 'fileencodings' fails, but you can also just add a few lines to your .[[vimrc]] to allow modelines to work as intended:
I have these lines in vimrc to workaround this problem:
 
   
 
<pre>
 
<pre>
 
function! CheckFileEncoding()
 
function! CheckFileEncoding()
if &amp;modified &amp;&amp; &amp;fileencoding != ''
+
if exists('b:fenc_at_read') && &fileencoding != b:fenc_at_read
exec 'e! ++enc=' . &amp;fileencoding
+
exec 'e! ++enc=' . &fileencoding
  +
unlet b:fenc_at_read
 
endif
 
endif
 
endfunction
 
endfunction
  +
au BufRead *.txt let b:fenc_at_read=&fileencoding
 
au BufWinEnter *.txt call CheckFileEncoding()
 
au BufWinEnter *.txt call CheckFileEncoding()
 
</pre>
 
</pre>
   
Change the "*.txt" part if wanted. You may also want to put <tt>set encoding=utf-8</tt> (to edit files of different encodings simultaneously) and "language messages en" (display all menus and messages in English) in your vimrc file.
+
Change the "*.txt" part if wanted. See [[Working with Unicode]] if your Vim is not yet configured for working with multiple encodings.
   
  +
This script will store off the fileencoding which Vim detects after reading the file, but before processing modelines, and then compare it to the fileencoding after processing modelines. If they differ, it will re-read the file with the new fileencoding value. For this step <code>:e!</code> must be used, because when the fileencoding changes the buffer is marked as modified. This is made less dangerous because we unlet the stored fileencoding value, so that we only issue the <code>e!</code> command if this is the first time BufWinEnter fired after reading the file.
==Comments==
 
For me, the 'fileencodings' option is a nice way to make Vim determine fileencoding itself. So the main topic of the tip is not so actual. But 'language messages en' -- that's very nice, I didn't know I can do that.
 
   
  +
==See also==
----
 
  +
* [[Detect encoding from the charset specified in HTML files]]
Of course, fileencodings is very useful, but it cannot handle some cases, e.g., one wants to edit simultaneously GB2312- and BIG5-encoded files. Fileencodings cannot distinguish between 8-bit encodings.
 
   
 
==Comments==
----
 
What the script does is:
 
 
If the file is modified (&amp;modified; because "set fileencoding" is done after loading the file) and fileencoding is set (&amp;fileencoding != ''), then reload the file regardless of the changed state (e!) with the specified encoding (++enc=).
 
 
A command string like "e! ++enc=utf-8" will be produced by "'e! ++enc=' . &amp;fileencoding", and then executed.
 
 
----
 
This breaks the following use case:
 
 
<pre>
 
vim foo.c (where foo.c might not contain a modeline with an fenc)
 
(modify foo.c)
 
:e bar.c
 
:b1 (to switch back to foo.c)
 
</pre>
 
 
Now foo.c's modifications were lost, because BufWinEnter is fired under more circumstances than just initial file load.
 
 
Recommendation -- do the following to ensure this is only done on initial buffer read:
 
 
<pre>
 
au BufReadPost * let b:reloadcheck = 1
 
au BufWinEnter * if exists('b:reloadcheck') | unlet b:reloadcheck | if &amp;mod != 0 &amp;&amp; &amp;fenc != "" | exe 'e! ++enc=' . &amp;fenc | endif | endif
 
</pre>
 
 
----
 
[[Category:Encoding]]
 

Latest revision as of 19:40, 11 September 2012

Tip 911 Printable Monobook Previous Next

created 2005 · complexity intermediate · author Wu Yongwei · version 6.0


Currently fileencoding does not work well in a modeline. When Vim sees the fileencoding setting, the file has already been read, so setting 'fileencoding' in a modeline normally has no effect until you write the file. That will cause even more trouble as, for example, if the default encoding is latin1 and the modeline has fileencoding=utf-8, then the resulting file will be a utf-8 file converted as latin1 to utf-8 again.

Vim does as best as it can to detect your encoding, if you place its name in your 'fileencodings' option. However, Vim cannot distinguish between multiple 8-bit encodings, so only the first one of those will be used. You can install a plugin like AutoFenc to automatically detect the correct encoding in many cases where 'fileencodings' fails, but you can also just add a few lines to your .vimrc to allow modelines to work as intended:

function! CheckFileEncoding()
  if exists('b:fenc_at_read') && &fileencoding != b:fenc_at_read
    exec 'e! ++enc=' . &fileencoding
    unlet b:fenc_at_read
  endif
endfunction
au BufRead     *.txt let b:fenc_at_read=&fileencoding
au BufWinEnter *.txt call CheckFileEncoding()

Change the "*.txt" part if wanted. See Working with Unicode if your Vim is not yet configured for working with multiple encodings.

This script will store off the fileencoding which Vim detects after reading the file, but before processing modelines, and then compare it to the fileencoding after processing modelines. If they differ, it will re-read the file with the new fileencoding value. For this step :e! must be used, because when the fileencoding changes the buffer is marked as modified. This is made less dangerous because we unlet the stored fileencoding value, so that we only issue the e! command if this is the first time BufWinEnter fired after reading the file.

See also[]

Comments[]