Pergunta

Estou usando o Mercurial (especificamente o TortoiseHg no Windows) para fazer o controle de versão do código VBA.Qualquer pessoa que já tenha tentado isso sabe que o VBA altera o caso de cada variável em um projeto sempre que qualquer declaração dessa variável é alterada em qualquer lugar do projeto (independentemente do escopo).Isso torna o controle de versão um pesadelo.

Eu gostaria de ignorar alterações de maiúsculas e minúsculas no meu código-fonte ao realizar diferenças.Qual é a maneira mais fácil de fazer isso?(alguma opção de comparação que está faltando, um utilitário de comparação externo, mais alguma coisa?)

OBSERVAÇÃO:Não estou falando sobre como lidar com 'nomes de arquivos que não diferenciam maiúsculas de minúsculas' (sim, estou falando com você, Google...)

Foi útil?

Solução

Você pode fazer isso ao comparar o consumo na tela usando o Extensão ExtDiff.

  [extensions]
  hgext.extdiff =

  [extdiff]
  # add new command that runs GNU diff(1) in case-insensitive mode
  cmd.mydiff = diff
  opts.mydiff = -i

Então você correria hg mydiff na linha de comando.Isso, é claro, requer que você tenha um binário diff instalado, seja do GNU ou outro.

No entanto, isso não será tão útil quanto você gostaria, porque internamente, é claro, o Mercurial não pode ignorar maiúsculas e minúsculas - ele está pegando o hash criptográfico do conteúdo do arquivo, e isso não permite espaço de manobra.Então, se você configurar isso, você fará hg mydiff, e não vejo alterações e, em seguida, faça hg commit e veja mudanças em todo o lugar.

Então você pode fazer isso funcionar na tela, mas não fundamentalmente.

Uma opção seria encontrar um limpador de código visual básico, semelhante ao indent para linguagens semelhantes a C, que normaliza maiúsculas de minúsculas e as executa em um gancho de commit mercurial.Assim, pelo menos todo o código que vai para o controle de origem será consistente e você poderá diferenciar as revisões com precisão.

Outras dicas

Se você concordar em ter seu código em letras minúsculas, digamos, então você pode empregar o codificar/decodificar ganchos por esta.Funcionaria assim:

[encode]
*.vba = tr A-Z a-z

Isso vai codificar o conteúdo do arquivo em letras minúsculas sempre que você fizer um commit.As diferenças também são calculadas com base na versão codificada (repositório) dos arquivos.

Considere um arquivo que contém

hello

Alterando-o em sua cópia de trabalho para

Hello World

vai dar uma diferença de

% hg diff
diff --git a/a.txt b/a.txt
--- a/a.txt
+++ b/a.txt
@@ -1,1 +1,1 @@
-hello
+hello world

Observe como o "H" e o "W" maiúsculos foram ignorados.

Eu realmente não sei nada sobre código VBA, então não tenho 100% de certeza de que esta solução funcione para você.Mas espero que possa ser um ponto de partida.

Uma desvantagem é que você precisará definir esta regra de codificação para todos os seus repositórios.O reposicionamentos extensão pode ajudá-lo aqui.

Aqui está a solução que decidi.Está longe do ideal, mas é melhor que as outras alternativas que considerei.

Criei um script Autohotkey que faz o seguinte:

  • reverte arquivos do MS Access em um repositório com alterações detectadas (para arquivos .orig)
  • lê no arquivo .orig (aquele com as alterações)
  • lê o arquivo existente (aquele que já está no repositório)
  • converte o texto de ambos os arquivos para minúsculas
  • compara o conteúdo em minúsculas dos arquivos
  • se os arquivos ainda forem diferentes, o arquivo .orig será restaurado para que possa ser enviado ao repositório
  • se os arquivos forem iguais (ou seja, eles diferem apenas no caso de o arquivo .orig ser excluído porque não nos importamos com essas alterações)

Para arquivos que possuem alterações reais que nos interessam, ainda vejo as alterações de caso que foram feitas também.Se isso resultar em muito ruído, abro o arquivo em uma ferramenta de comparação que permite comparações sem distinção entre maiúsculas e minúsculas (por exemplo, kdiff).

Não é uma solução perfeita, mas elimina cerca de 90% da frustração para mim.

Aqui está meu roteiro.Observe que o script inclui outro script Autohotkey, ConsoleApp.ahk, que fornece uma função chamada, ConsoleApp_RunWait().Este é um script de terceiros que não funciona mais muito bem com AHK de 64 bits, por isso não o incluí como parte da minha resposta.Qualquer função AHK que execute uma linha de comando e retorne a saída como uma string será suficiente.

; This script checks an MS Access source directory and reverts all files whose only modifications are to the 
; case of the characters within the file.

#Include %A_ScriptDir%\ConsoleApp.ahk
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Allow for custom path to hg (support for moving to TortoiseHg 2.0)
IniRead hg, %A_ScriptDir%\LocalSettings\Settings.cfg, TortoiseHg, hg_path, hg

if 0 < 1  ; The left side of a non-expression if-statement is always the name of a variable.
{
    MsgBox Usage:`n`HgIgnoreCase DirectoryWithFilesToScrub
    ExitApp
}

SrcDir = %1%
StringReplace SrcDir, SrcDir, ", , All

StringRight test, SrcDir, 1 ; add trailing slash if necessary
ifnotequal test, \
    SrcDir = %SrcDir%\

RestoreOriginals(SrcDir)
RevertCaseChangeModifiedFiles(SrcDir)

RevertCaseChangeModifiedFiles(SrcDir) {
global hg
    includes =  -I "*.form" -I "*.bas" -I "*.report" -I "*.table"
    cmdline = %hg% revert --all %includes%

    ;Don't revert items that have been removed completely
    Loop 3
    {
        Result := ConsoleApp_RunWait(hg . " status -nrd " . includes, SrcDir)
        If (Result)
            Break
    }
    Loop parse, Result, `n, `r
    {
        if (A_LoopField)
            cmdline = %cmdline% -X "%A_LoopField%"
    }
    Result =
    ;msgbox %cmdline%
    ;revert all modified forms, reports, and code modules
    Loop 3
    {

        Result := ConsoleApp_RunWait(cmdline, SrcDir)
        If (Result)
            Break
    }
    ;MsgBox %Result%

    Loop parse, Result, `n, `r
    {
        StringLeft FileStatus, A_LoopField, 9
        If (FileStatus = "reverting")
        {
            StringMid FName, A_LoopField, 11
            FullPath = %SrcDir%%FName%
            ToolTip Checking %FullPath%
            RestoreIfNotEqual(FullPath, FullPath . ".orig")
        }
    }
    ToolTip
}

RestoreIfNotEqual(FName, FNameOrig) {
    FileRead File1, %FName%
    FileRead File2, %FNameOrig%

    StringLower File1, File1
    StringLower File2, File2
    ;MsgBox %FName%`n%FNameOrig%
    If (File1 = File2)
        FileDelete %FNameOrig%
    Else
        FileMove %FNameOrig%, %FName%, 1
}

RestoreOriginals(SrcDir) {
    Loop %SrcDir%*.orig
    {
        ;MsgBox %A_LoopFileLongPath%`n%NewName%
        NewName := SubStr(A_LoopFileLongPath, 1, -5)
        FileMove %A_LoopFileLongPath%, %NewName%, 1
    }
    while FileExist(SrcDir . "*.orig")
        Sleep 10
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top