VIM, Windows, quickfix - fight against compiler encoding

    There is an instrumental computer with Windows and assembler for one wonderful but specific processor. For convenience, a VIM-based working environment was set up - syntax highlighting, calling the preprocessor, assembler and linker via make with parsing error messages, ctags with code jumping. But there is a nuance - the issuance of messages: make is in Russian. Of course, in console Russian, cp866. And the assembler sources and the VIM locale are cp1251. And what to do?

    Bring all encoding - text files and VIM locales - to cp866 due to one compiler? Not even funny. Guess from the context about the meaning of the error? So far I have done so. Tired of it. We need to figure it out, spend a couple of evenings and forget about this annoying misunderstanding.

    The quickfix system works: the make output gets to the error file, the numbers of the wrong lines of code and the type of error are picked out from it, the cursor after compilation is immediately put in the right place. It’s not easy to understand the essence of the error:

    fig.  1

    And the command: cope does not help in reading, although it allows you to jump on erroneous lines of code:

    fig.  2

    Note: The makeef = error.err option is used for example (to shorten the make command line displayed), although it is usually empty by default, and the make error file is created in TEMP.

    It would seem - what nonsense! We’ll fix the encoding option ... But no - it’s a global infection. Therefore, the encoding will change everywhere, in all open buffers, including the source window. Comments in Russian Khan. VIM messages itself too.

    fig.  3fig.  4

    You can try: set encoding = cp866 manually, you can stick this in $ VIM / vimfile / ftplugin / qf.vim so that it works by the command: cope. You can even try: setlocal - will not help.

    It’s impossible to change the encoding in a single buffer, we’ll try to transcode the error file itself. To do this, look at the help, and find that when you call: make, the following sequence is executed:
    1. When the 'autowrite' option is enabled, all modified buffers are written.
    2. The error file name is calculated according to the value of the 'makeef' option. If the value of the 'makeef' option does not contain "##", then an existing file with that name will be deleted.
    3. The program starts with the name specified in the value of the 'makeprg' option (default: “make”) with an optional set of [arguments], the output of which is redirected to the error file (in Unix, the output is also displayed on the screen).
    4. An error file is being read using the value of the 'errorformat' option.
    5. If the modifier [!] Is not set, then a move to the first error from the list occurs.
    6. The error file is deleted.
    7. Now you can navigate the error list with commands like: cnext and: cprevious.

    It turns out, when you open the qf buffer with the command: cope, the error file no longer exists. You can try to return it in an obscure way - in $ VIM / vimfile / ftplugin / qf.vim write

    setlocal encoding=cp866
    setlocal fileencoding=cp1251
    w! ./error.err
    setlocal encoding=cp1251
    

    That is, when you open the qf buffer with the command: cope, change the encoding, insert the encoding for the file, write a new error file, and return the encoding back. By the way, local can be omitted here - it is still useless. Now you can manually install the new error file: cf ./error.err.

    fig.  5

    Ugly, uncomfortable and a lot of extra hand movements. It turns out, after each compilation, you must first: cope, then: ccl, then: cf ./error.err and again: cope. If you try to insert this all into qf.vim, you will get a frantic recursion that VIM will strangle on its own. And: cope behaves somehow strange: extra sticks are added at the beginning of lines, even reluctance to figure out the reasons.

    fig.  6

    Okay, then let's try to catch the moment not near reading the error file, but closer to the compiler output. Let's see the help again:
    The ": make" command executes the program specified in the value of the 'makeprg' option. This happens by calling the command from the shell specified in the value of the 'shell' option. In other words, almost the same thing happens when you enter the command

    ":!{значение_makeprg} [аргументы] {значение_shellpipe} {файл_ошибок}".

    Here {makeprg_value} is the string value of the 'makeprg' option. You can use any program you need, not just make.

    The exclamation point ":! {Command}" requires the specified {command} to be executed in the shell. This means that catching the event that occurs with the file during execution: make will fail. Hope to use the auto team collapsed. But giving up early. Let's take a closer look at
    'shellpipe' 'sp' string (default: ">", "| tee", "| & tee" or
    			        "2> & 1 | tee")
    			global option
    	The option is used to specify the line that forces the shell
    	put the output of the ": make" command into the error file. 
    

    It turned out that my VIM defaults to shellpipe =>% s 2> $ 1. It seems that there is an opportunity to take an external command line utility and somehow put it in the middle of this shellpipe.

    Take iconv , which is in the GnuWin32 project on the libiconv page . It can receive data from a file or from a console stream. I put it in C: \ bin \, where make, ctags, 7z, a couple of auxiliary batch files and a couple of dlls already lie. Do not forget about the dependencies (Dependencies, namely libintl3.dll, is on the utility page).

    Played with the command line separately from VIM to figure out how to feed input and options. Then I tried the same thing, but already on the VIM command line. Somewhere from the second or third attempt something happened:

    :set shellpipe=\|c:\\bin\\iconv\\iconv.exe\ -c\ -f\ CP866\ -t\ CP1251>%s\ 2>&1
    

    The pipe character, spaces, and backslashes in the full path to the utility are escaped with backslashes. As for the full path - you can, of course, not pervert like that, but write the path to iconv in PATH, but for some time I personally don’t like this method: four IDE / CAD on the working computer have make, which are not completely compatible with each other, and all are written in PATH. Full paths are more reliable.

    In general, it worked. I wrote the specified line (without a colon at the beginning) to the file $ VIM / vimfile / ftplugin / a6403.vim. Now the “shell pipe” is changed to transcoding only when opening this particular cunning file type. Here is the result:

    fig.  7fig.  8

    Russian comments in the source are readable, error messages are also jumped by errors. The solution is not ideal:
    • I had to use a third-party utility with built-in conversion tools. Excuse: Not particularly scary in this case - to use a third-party compiler, and third-party ctags, and third-party make anyway. Well, there are more files in my c: \ bin \ ...
    • The shellpipe option is global; it will be applied to all buffers. Excuse: if you do not open the files of this specific assembler - no one will feel. If you open and simultaneously work in other simultaneously open buffers with another translator, English-speaking compilers will be purple (checked), Russian-speaking compilers (on cp866) will only be beneficial.

    To eliminate the second drawback, you can locally (setlocal) override the makeprg option, after adding make a special “stub” in the form of a sequence of “$ *”, which will be replaced by command line arguments, and calling iconv. Then you can leave the shellpipe free. And the vertical bar will have to be shielded already with three backslashes: one for the command: set, the second - to escape the third one needed when parsing the command.

    setlocal makeprg=c:\bin\make.exe\ $*\ \\\|c:\\bin\\iconv\\iconv.exe\ -c\ -f\ CP866\ -t\ CP1251
    

    I did not find a more successful way on various kinds of Internet. In fact, I did not find any way. Maybe I was so unlucky alone? But if at least the very idea of ​​introducing a team into the team helps, I will be pleased.

    Also popular now: