VIMderbare Kodierungen

Der vim kommt wunderbar mit Dateien zurecht, die in ISO-8859-1 (Latin-1) kodiert sind. Aber auch Dateien, die in UTF-8, mit oder ohne Byte-Order-Marker, in UTF-16, UTF-32 oder auch koi8-r vorliegen, sind kein Problem. Wenn man weiss, an welchen Optionen man drehen muss.

Fünf Hebel für eine Klappe

Der vim unterscheidet zwischen der Kodierung des Textes, der internen Kodierung und der Kodierung der Ausgabe. Entsprechend gibt es auch die drei Optionen fileencoding, encoding und termencoding. Dazu kommt noch eine Option für die Erkennung der Kodierung von Dateien (fileencodings) und eine globale Einstellung, welche Kodierung neue Dateien haben sollen (global fileencoding).

Damit die beschriebenen Optionen im vim zur Verfügung stehen, muss der vim mit der Option +multi_byte gebaut worden sein. Ob das der Fall ist, kann man der Ausgabe von vim --version entnehmen.

Internes

Zunächst sollte der vim so konfiguriert werden, dass er alle Kodierungen verlustfrei bearbeiten und so gut wie möglich darstellen kann. Dazu sollte encoding auf den Wert utf-8 gesetzt werden. Dieser Wert kann auch benutzt werden, wenn man kein UTF-8 benutzen will, es wird dabei lediglich die Darstellung des Texts im Speicher bestimmt. UTF-8 hat den Vorteil, dass normales ASCII nicht konvertiert werden muss und jeder andere Zeichensatz dennoch ohne Konvertierungsfehler dargestellt werden kann.

Anschliessend sollte man termencoding so einstellen, wie das benutzte Terminal eingestellt ist. Für die meisten Terminals ist das latin1, für modern eingestellte Terminals ist es utf-8. (Wer sich nicht sicher ist, gibt echo -n "ä" | wc -c ein. Eine 1 deutet auf Latin-1, eine 2 auf UTF-8 hin.)

Neue Welten

Wenn der vim einen neuen Puffer anlegt, dann wird diesem die Kodierung zugewiesen, die in der globalen fileencoding eingetragen ist. Wer neue Texte also im Normalfall in UTF-8 erstellen will, der sollte in seiner .vimrc die Zeile setglobal fileencoding=utf-8 haben, wer Latin-1 bevorzugt wird setglobal fileencoding=latin1 benutzen und so weiter.

Wenn man doch einmal einen Text in einer anderen Kodierung erstellen (oder die Kodierung ändern) will, dann kann man einfach das lokale fileencoding des Puffers ändern und danach die Datei speichern. Vim verhält sich hier in Hinsicht auf die Kodierung genau so, wie er es auch beim fileformat für die Zeilenenden tut.

Alte Hüte

Lädt man eine Datei in vim, so versucht der Editor, die Kodierung der Datei zu erkennen. Hierzu wird versucht, die Datei in einer bestimmten Kodierung zu interpretieren. Die erste Kodierung, bei der dieser Versuch gelingt, wird als Kodierung der Datei angenommen. Welche Kodierungen beim Laden getestet werden gibt die Variable fileencodings (mit s!) an. Hier gibt man die Liste der zu testenden Kodierungen getrennt durch Kommata an. Bei mir ist die Reihenfolge ucs-bom,utf-8,latin1. Vim prüft damit zunächst, ob es eine Unicode-Datei mit „Byte Order Marker“ (BOM) ist, danach versucht vim UTF-8 auszuschliessen und sollte UTF-8 ausgeschlossen werden können, dann wird die Datei als Latin-1 interpretiert.

Bei fileencodings ist etwas Vorsicht angeraten: Der vim versucht die Kodierungen der Reihe nach auszuschliessen, d.h. die erste Kodierung, die nicht ausgeschlossen werden kann, wird gewählt. Einer Datei, die die 4 Bytes „Test“ enthält, fehlt zwar der BOM, aber sie ist sowohl gültiges UTF-8 als auch gültiges Latin-1. Bei meiner Einstellung würde hier also UTF-8 gewinnen.

Zusammenfassung

Meine Einstellungen sind:

set encoding=utf-8
set fileencoding=
setglobal fileencoding=utf-8
set fileencodings=ucs-bom,utf-8,latin1
set termencoding=latin1

Damit erreicht man folgendes Verhalten:

Der letzte Punkt ist nicht ganz offensichtlich, wird aber schnell klar, wenn man sich die Latin-1-Kodierung ansieht: Latin-1 besteht aus 256 Acht-Bit-Zeichen. Das bedeutet, jedes mögliche 8-Bit-Byte ist gleichzeitig ein gültiges Latin-1-Zeichen. Die Überprüfung vom vim, ob die Kodierung Latin-1 sein kann wird also immer ergeben, dass die Datei Latin-1 sein könnte. Latin-1 wird folglich immer akzeptiert, wenn die beiden anderen die Datei abweisen.