I'm trying to combine two features of vim, but it doesn't seem to be possible.
1: vim -
The first feature is invoking vim with a single-dash argument, which causes vim to read stdin and use the resulting text as the contents of the initial scratch buffer. (Fun fact: vim then uses stderr to attach to the terminal.) For example:
printf 'a\xC0b'| vim -;
The above will cause the initial buffer to have contents aÀb
with 'fileencoding'
set to latin1.
The second feature is forcing vim to interpret a file's text in a character encoding different from what vim's autodetection algorithm would settle on. This can be done by running :e ++enc=X
where X
is the desired encoding. Irrelevantly, I'm also interested in using the ++bad=keep
edit option to specify handling of encoding-invalid bytes. So, for example, running :e ++enc=utf-8 ++bad=keep
will cause vim to reload the current file assuming its contents comprise UTF-8 text, and keeping bytes that are invalid UTF-8 in the buffer (as opposed to stripping them or replacing them with a valid character, the latter being vim's default).
The problem
The problem is that the :e
command only works on unmodified non-scratch buffers, since it reloads the entire file from disk. The modification state is not the critical roadblock here, since I could easily :setlocal nomod
, but I don't see any way around the scratchness problem. The :e
command simply cannot be used in a scratch buffer, since there's no disk file to reload.
Based on my thinking, when loading a file at startup by specifying it as an argument on the shell command-line, I really think there should be some way of communicating to vim how it should interpret the file's text before it loads it the first time, since there's no point in letting vim autodetect an incorrect encoding and then fixing it up after-the-fact by reloading the entire file with an :e
command. I think this should apply whether you're reading from stdin or loading one or more disk files at startup, but obviously it's more of a problem for the stdin case, since :e
can't work for a scratch buffer, as I described a moment ago.
Here are some things I've tried, knowing they wouldn't work:
printf 'a\xC0b'| vim - ++enc=utf-8 ++bad=keep; ## E492: Not an editor command: +enc=utf-8
printf 'a\xC0b'| vim - -c 'e ++enc=utf-8 ++bad=keep'; ## E37: No write since last change
printf 'a\xC0b'| vim - -c 'e! ++enc=utf-8 ++bad=keep'; ## E32: No file name
printf 'a\xC0b'| vim - -c 'setlocal nomod| e ++enc=utf-8 ++bad=keep'; ## E32: No file name
Solution idea
I've thought of one indirect solution, but it's not as convenient as a direct solution would be.
Basically, instead of running the text-generation command in the shell and piping it to vim, I'll run the text-generation command from vim and read its output into a readymade scratch buffer using :r
, which fortunately supports the same ++opt
interpretation options as :e
. Something like this:
:r ++enc=utf-8 ++bad=keep !printf 'a\xC0b';
Vim displays the resulting UTF-8 buffer as a<c0>b
.
This works, but it's just not as convenient as it could be. I reiterate my earlier point that there should be some way of specifying the initial encoding interpretation at startup, whether reading from stdin or from a disk file. I'm not aware of such a mechanism, but I'm holding out an ounce of hope that a more knowledgeable vim user will know of a way to do this.