Codificação incorreta ao chamar shell

9

Eu estava experimentando um diagrama do DOT e tentei fazer o seguinte:

:! dot -Tpng -oFab.png %

Ocorreu um erro porque meu nome de arquivo tem um caractere especial (" ó" em "Fabricación"):

C:\windows\system32\cmd.exe /c ( dot -Tpng -oFab.png Fabricaci├│n.gv)
Error: dot: can't open Fabricaci├│n.gv
shell returned 2
Hit any key to close this window...

Como você pode ver, o caractere especial está sendo alterado para " ├│". Isso ocorre com o vim e o gVim 7.4 em Win7 e NTFS, portanto, presumo que o nome do arquivo esteja em UTF16 . Suponho também que, ao invocar o shell / cmd, o nome do arquivo esteja sendo interpretado como outra codificação (obrigado ao Carpetsmoker por apontar o padrão para a página de código 850 ).

Como posso consertar isso?

Claro, posso simplesmente renomear o arquivo, mas gostaria de saber por que isso acontece e como corrigi-lo.

Atualização : Acabei de encontrar esta pergunta no superuser.SE (graças ao feedback de @ ChristianBrabandt ), mas também não parece ajudar.

Roflo
fonte
11
Estou curioso para saber se você receberia o mesmo erro usando o Vim na linha de comando no Cygwin ou MobaXterm (ambientes portáteis semelhantes ao Unix para Windows). Eu suspeito que não. Pode haver uma maneira de corrigir isso para que o Windows cmdaceite o nome do arquivo, mas instalar um ambiente semelhante ao Unix seria o meu tratamento preferido.
Wildcard
2
Pelo que li, o padrão para cmd.exenão é unicode, mas página de código 850 . Veja também esta resposta .
Martin Tournoij 03/04
Obrigado @Carpetsmoker. Tomei a liberdade de atualizar minha pergunta com as informações que você forneceu.
Roflo 04/04
Não tenho certeza absoluta, mas você pode querer ajustar a opção 'termencoding'.
Christian Brabandt
@ChristianBrabandt A menos que eu esteja fazendo algo errado, isso não parece ajudar. Tentei configurar o tenc para latin1, utf8 e cp850. Ninguém parece fazer o truque.
Roflo

Respostas:

2

Resposta curta

O problema está dot.exe. O GraphViz pode abrir arquivos com caminhos Unicode no Linux, mas não no Windows, a menos que (talvez) se compilado com o Visual Studio 2005.

Pesquisa

A página de código está definida como 850, codificação Vim como UTF-8.

insira a descrição da imagem aqui

Não dá exatamente o mesmo erro, mas dot.exeparece receber um argumento errado. Tentei passar o mesmo nome de arquivo para o outro programa.

insira a descrição da imagem aqui

E funcionou perfeitamente. A execução de ambos dot.exee typediretamente de cmd.exefornece o mesmo resultado, portanto, nem o Console do Windows nem o Vim são o problema. A próxima coisa que poderia causar esse erro foi dot.exeela mesma. Minha suspeita era que ele simplesmente não sabia como lidar com os argumentos codificados em Unicode corretamente, como nem todos os comandos do console fazem:

https://ss64.com/nt/chcp.html

Se você precisar de suporte Unicode completo, use o PowerShell. Ainda há suporte MUITO limitado ao Unicode no shell do CMD, a tubulação, o redirecionamento e a maioria dos comandos ainda são apenas ANSI. Os únicos comandos que funcionam são DIR, FOR / F e TYPE; isso permite ler e gravar (UTF-16LE / BOM) arquivos e nomes de arquivos, mas não muito mais.

Pesquisei na Web se há suporte para Unicode no GraphViz e descobri que ele suporta arquivos Unicode, mas nada sobre o suporte a Unicode para os nomes de arquivos. Também não encontrei nenhum relatório no rastreador de erros do GraphViz nem postagens no fórum sobre alguém mais interessado em ler um arquivo nomeado Unicode. Então eu procurei na fonte. Aqui está o que é o dot.exeponto de entrada:

graphviz-2.40.1\cmd\dot\dot.c

int main(int argc, char **argv)
{
    . . .

/* --------------------> ARGS ARE BEING PASSED HERE */
    gvParseArgs(Gvc, argc, argv);

    . . .

Seguindo argvpela toca do coelho:graphviz-2.40.1\lib\common\args.c

int gvParseArgs(GVC_t *gvc, int argc, char** argv)
{
    int rv;
    if ((argc = neato_extra_args(gvc, argc, argv)) < 0)    return (1-argc);
    if ((argc = fdp_extra_args(gvc, argc, argv)) < 0)      return (1-argc);
    if ((argc = memtest_extra_args(gvc, argc, argv)) < 0)  return (1-argc);
    if ((argc = config_extra_args(gvc, argc, argv)) < 0)   return (1-argc);

/* -------------------->  HERE GO ALL NON-FLAG ARTUMENTS */
    if ((rv = dotneato_args_initialize(gvc, argc, argv)))  return rv;

    if (Verbose) gvplugin_write_status(gvc);
    return 0;
}

graphviz-2.40.1\lib\common\input.c

int dotneato_args_initialize(GVC_t * gvc, int argc, char **argv)
{
    for (i = 1; i < argc; i++) {
        if (argv[i] && argv[i][0] == '-') {

            . . .

/* -------------------->  JUST CASUALLY COPYING CHAR POINTERS */
        } else if (argv[i])
            gvc->input_filenames[nfiles++] = argv[i];
    }

E finalmente graphviz-2.40.1\lib\common\input.c

graph_t *gvNextInputGraph(GVC_t *gvc)
{
    . . . .

/* -------------------->  OPENING THE FILES FOR READ WITH FOPEN */
    while ((fn = gvc->input_filenames[fidx++]) && !(fp = fopen(fn, "r")))  {

        . . .

    }

Como o MDSN afirma:

A função fopen abre o arquivo especificado pelo nome do arquivo. _wfopen é uma versão de caractere amplo do fopen ; os argumentos para _wfopen são cadeias de caracteres largos. _wfopen e fopen se comportam de maneira idêntica. O simples uso de _wfopen não afeta o conjunto de caracteres codificados usado no fluxo de arquivos.

No Visual C ++ 2005, o fopen suporta fluxos de arquivos Unicode.

Infelizmente, a única opção existente é renomear o arquivo.


fonte