問題描述
在Windows使用gVim時發現開啟的中文文字檔出現亂碼,很容易知道因為是是utf-8編碼的文字檔,在預設使用cp950編碼的Windows上開啟,因編碼不同,自然是亂碼。直覺上這問題應該好解決,設置Vim使用utf-8即可:
:set encoding=utf-8
試了沒問題,因為我習慣用utf-8,所以在 _vimrc 加入 set encoding=utf-8重啟Vim後我卻發現,這回輪到命令選單變成亂碼,即使再加入langmenu的設置後重開Vim也是:
set langmenu=zh_TW.UTF-8
此時 :set all 的顯示結果中也出現 langmenu=zh_TW.UTF-8 ,但選單是亂碼。langmenu必須在menu載入之前做好設置,故要加在 _vimrc 中。但如果真要在執行Vim時切換選單語言,做法像是先移除選單,重新設置langmenu,重讀選單語言翻譯[1]:
:source $VIMRUNTIME/delmenu.vim
:set langmenu=zh_TW.UTF-8
:source $VIMRUNTIME/menu.vim
上述delmenu.vim用來移除選單;menu.vim用來翻譯選單語言,而語言檔在 $VIMRUNTIME/lang 中,其中有個README.TXT中有些說明。我試著這樣做之後選單上的中文字則是可正常顯示,不清楚為何設在 _vimrc中會造成亂碼,懷疑是否bug?
另一個觀察到的現象則是編輯的檔案名稱若有中文,暫存的swap檔與最終存檔時,檔名也可能出現亂碼。
我開始懷疑encoding選項影響的層面似乎比我想像的多,而我須要的是希望在讀、寫文件時做正確編碼,之後查了一下,發現果然如此。編碼方面的問題倒不難解決,反而是命令選單的亂碼現象困擾了好一陣子。
在無法解決命令選單亂碼的期間,只好先暫時做個補救的措施,後來花不少時間排查,才發現命令選單亂碼的成因,終於得以解決。
綜合以上,簡單說是二個問題:一、未正確設置Vim的文件編碼,導致中文文件內容,或中文檔名出現亂碼;二、gVim命令選單,即GUI界面的中文呈現亂碼。
本文談論以下幾點,並在最後附上參考連結:
- 針對上述第二問題,我採用的暫時措施。
- 上述第二問題的成因。
- 設置編碼。解決上述第一個問題。
- Vim與編碼有關的幾個設置。
- 與編碼相關的幾個問題。
- Vim與語言顯示有關的幾個設置。
- 其他
1. 解決gVim界面選單亂碼的暫時措施
上面已提到如何在執行Vim時切換選單語言,但每回都要這麼做也有點麻煩。因我很少用gVim上的選單,所以我採用的方式就是不顯示選單,亂碼自然就看不到了。在_vimrc中加入:
set guioption=M
2. gVim選單亂碼的成因
發現這成因算是有點偶然,原本是懷疑別種因素造成問題,想在Virtual Box上的另一個Windows環境做測試與驗證,在兩個環境上做些比較之後,我發現出問題的機器上還有其他設定項目是VBox機器所沒有的,於是改變懷疑的對象,從中逐一測試,終於發現兇手。雖然不清楚真正的原因是什麼,但設置項目的順序不同,結果會有差異。_vimrc設置檔中原本有不少項目,其中有這兩項:
syntax on
filetype plugin indent on
把 set encoding 放在它們的後面,gVim選單會出現亂碼。把這二項移到 set encoding 的後面去,選單亂碼的現象就不見了。也就是只要這二項中的任一項出現在 set encoding 的前頭,選單就會出現亂碼。要特別提醒一下,這奇怪的現象只在Windows上出現,在Ubuntu並不會。
3. 正確的編碼設置
就自己的使用情況而言,像這樣就可以了:
set encoding=utf-8
set fileencodings=utf-8,cp950,cp936,gb18030,latin1
這樣既可編輯utf-8編碼的文件,也可編輯cp950編碼的文件。若須要其他編碼,可查一下 :help encoding-values ,自行加到fileencodings列表中,像:
- big5:也就是cp950的別名,正體中文。
- cp936:簡體中文。
- gb18030:大陸製訂且通用的一種Unicode變體。
- cp932:日文。
- cp949:韓文。
ucs-bom,utf-8,cp950,cp936,gb18030,euc-jp,euc-kr,latin1
4. 編碼相關設置
以下解釋幾個與編碼相關的設置:- encoding
- fileencoding
- fileencodings
- termencoding
encoding 或 enc
預設為 "latin1" 或來自$LANG的值。設定Vim內部所用的字元編碼。適用在buffer, register中的文字、表達式中的字串、存在viminfo中的文字等等……。設定Vim工作可用的字元種類。
變更此選項並不會改變Vim中既有文字的編碼。它能導致non-ASCII文字變無效。正常應該保持預設值,或在Vim啟動時設定。
檔案的字元編碼可不同於 'encoding',此由 'fileencoding' 指定。轉換是以iconv()或以 'charconvert' 指定時完成。
正常時 'encoding' 會與目前 locale 相同。如果Vim認得環境設定,預設是如此。如果 'encoding' 不是設成目前 locale,必須設置'termencoding'以轉換(終端機畫面中)打字或顯示的文字。
使用"unicode", "ucs-2" 或 "ucs-4"時,Vim內部用utf-8。
fileencoding 或 fenc
預設為空字串。設置本buffer檔案的字元編碼。當'fileencoding'與'encoding'不同時,在寫入檔案時做轉換。讀取的轉換見後述。
當'fileencoding'為空,使用與'encoding'相同的值(即讀或寫檔案時並不做轉換)。
轉換也發生在'encoding'與'fileencoding'都是Unicode編碼,且'fileencoding'不是utf-8。那是因為內部的Unicode都是存成utf-8。
注意像在utf-8轉換成cp950時,其中的Unicode字元會丟失變成?符號。
當讀取檔案時,'fileencoding'的設定會來自'fileencodings'。要讀取某編碼,但設定'fileencoding'卻無作用時,使用 ++enc 參數(見後述)。一例外:當'fileencodings'是空的,則使用'fileencoding'的值。
新檔案,使用'fileencoding'的globle value。可以這麼設它:
:setglobal fenc=utf-8
在開始編輯檔案之後才設此選項時,設定'modified'選項(即此檔被視為已修改)。當'modifialbe'關閉時,無法變更此選項。註:在6.0版前,此選項指定了整個Vim的編碼,現在則是改用'encoding'。舊式簡稱 'fe' 也不再使用。在網路上查這類資料時,要注意也許找到的是這類已過時的舊資料。
fileencodings 或 fencs
預設為"ucs-bom";當'encoding'設成Unicode值時,則是"ucs-bom,utf-8,default,latin1"。這是在開始編輯既有檔案時,所考慮採用的字元編碼列表。在讀取檔案時,Vim試著用第一個編碼。若出錯,再試列表中的下一個。找到可用的編碼時,'fileencoding'就設為這編碼;若失敗則設成空字串,意即使用'encoding'的值。
當使用 ++enc 參數時,就不採用'fileencodings'的值。
'fileencodings'不用在新檔案,新檔用'fileencoding'的global value,見上述。
"default"使用來自環境的編碼。此即'encoding'的預設值。
設定此選項要直到下次讀取檔案時才會生效。
termencoding 與 tenc
預設為空字串;GTK+ GUI則是"utf-8"。終端機用的編碼,指定鍵盤所產生與顯示上的字元編碼。在GUI,它只用在鍵盤,'encoding'用在顯示。但這不適用於GTK+ GUI,它強迫使用"utf-8"。在Win32 GUI與console版本,不使用此選項,因Win32系統總是傳送Unicode字元。
空白時,使用與'encoding'相同的編碼。
5. 與編碼相關的幾個問題
存檔時指定使用不同編碼
例如目前正編輯著以cp950編碼的文件,要另存新檔並採用utf-8編碼:
:w ++enc=utf-8 new_filename.txt
要注意若原本utf-8編輯的檔案,要轉換存成cp950時,其中若有Unicode中的字會失效。編碼辨識錯誤
開啟既有文件時難免會搞錯編碼,在此情況下,如果自己清楚文件的編碼,可自行指定:
:edit ++enc=cp950 traditional_chinese.txt
6. 語言相關設置
界面及語言相關的設置項目:- language
- langmenu
- guioption
language
顯示/設置語言,包含訊息、時間格式:
:language {name}
可支援的語言名稱,在Unix上,可見locale -a顯示/設置訊息語言,可用來額外設置與language不同的訊息語言,如果想讓二者不同的話:
:language message
langmenu
選單語言,預設是英文。若環境設置正確,且有可用的語言檔,會自動轉譯成本地語言。你也可以自行設定想要的語言。例如把界面選單的語言改為英文,即預設的語言:
:set langmenu=none
guioption
不顯示界面選單:
:set guioption=M
也可簡寫為:
:set go=M
想顯示界面選單則把上述的M改為m。7. 其他
在處理以上問題的過程,還發現幾個設置值得記錄一下,暫且記在此處,來日若有必要再做調整。set guifont
如果在gVim編輯文字無法正常顯示Unicode字元,可設置GUI畫面所用的字型,換個支援Unicode的字型。最簡單的方式利用"Edit/Select Font..."所顯示的字型對話盒試好想要的字型,然後看字型名稱:
:set guifont
接著可以在gvimrc加入使用此字型的設置。例,在Windows上,使用Courier New字型:
:set guifont=courier_new:h12
以滑鼠顏色指示中文輸入法開關狀態
在Vim中使用中文輸入法時經常有的困擾,就是不慎在中文輸入啟用的狀態下打Vim命令。這有不同的解決方式,其中之一是利用游標來指示輸入法狀態以減輕這困擾。這裡提到的方法只適用於Windows上的gVim,並使用安裝成內置式的中文輸入法,並不適於可攜式的。在gvimrc中加入以下設置:
if has('multi_byte_ime')
highlight Cursor guifg=NONE guibg=Green
highlight CursorIM guifg=NONE guibg=Purple
endif
這段的作用是在判斷出有多位元的IME,像中文輸入法時,在啟用輸入法時,游標顯示為紫色,關閉時則變成綠色。參考連結
- https://vimhelp.org/usr_45.txt.html#usr_45.txt
- https://vimhelp.org/options.txt.html#options.txt
- http://edyfox.codecarver.org/html/vim_fileencodings_detection.html
- https://vimhelp.org/mlang.txt.html#%3Alanguage
- https://vimhelp.org/mbyte.txt.html
沒有留言:
張貼留言