我正在使用Mercurial(特别是Windows上的TortoiseHg)来对VBA代码进行版本控制。任何试过这个的人都知道,只要在项目的任何地方(无论范围如何)改变了该变量的声明,VBA就会改变整个项目中每个变量的大小写。它使版本控制成为一场噩梦。
我想在执行差异时忽略我的源代码中的大小写更改。最简单的方法是什么? (我缺少的差异的一些选项,外部差异实用程序,还有其他什么?)
注意:我不是在谈论处理'不区分大小写的文件名'(是的,我正在和你谈论谷歌......)
答案 0 :(得分:7)
您可以使用ExtDiff Extension为屏幕消费进行差异化时执行此操作。
[extensions]
hgext.extdiff =
[extdiff]
# add new command that runs GNU diff(1) in case-insensitive mode
cmd.mydiff = diff
opts.mydiff = -i
然后从命令行运行hg mydiff
。当然,这需要你安装diff二进制文件,无论是gnu还是其他。
然而,这并不像你想要的那样有用,因为在内部,当然,Mercurial不能忽略大小写 - 它正在采用文件内容的加密哈希,而那些不允许摆动空间。因此,如果您完成此设置,则会执行hg mydiff
,并且看不到任何更改,然后执行hg commit
并查看所有地方的更改。
因此,您可以在屏幕上进行此项工作,但不能从根本上进行。
一种选择是找到一个可视化的基本代码清理程序,类似于类似C语言的indent
,它标准化变量case并在mercurial commit hook中运行它。那么至少所有进入源代码控制的代码都是一致的,你可以准确地区分修订。
答案 1 :(得分:2)
如果您可以将所有代码都设置为小写,那么您可以使用encode/decode hooks来实现此目的。它会像这样工作:
[encode]
*.vba = tr A-Z a-z
每当您执行提交时,这将以小写形式编码文件内容。差异也是基于文件的编码(存储库)版本计算的。
考虑包含
的文件hello
将工作副本中的更改为
Hello World
会给出差异
% hg diff
diff --git a/a.txt b/a.txt
--- a/a.txt
+++ b/a.txt
@@ -1,1 +1,1 @@
-hello
+hello world
注意资本“H”和“W”是如何被忽略的。
我对VBA代码一无所知,所以我不能100%确定这个解决方案适合你。但我希望它可以成为一个起点。
一个缺点是您需要为所有存储库设置此编码规则。 reposettings扩展程序可以为您提供帮助。
答案 2 :(得分:2)
这是我已经解决的解决方案。它远非理想,但比我考虑过的其他替代品更好。
我创建了一个执行以下操作的Autohotkey脚本:
对于我们关心的实际更改的文件,我仍然会看到所做的大小写更改。如果这会导致很多噪音,我会在比较工具中打开文件,该工具允许不区分大小写的比较(例如,kdiff)。
这不是一个完美的解决方案,但它消除了我90%的挫折感。
这是我的剧本。请注意,该脚本包含另一个Autohotkey脚本ConsoleApp.ahk,该脚本提供名为ConsoleApp_RunWait()
的函数。这是第三方脚本,64位AHK不能很好地工作,所以我不把它作为我答案的一部分。任何执行命令行并将输出作为字符串返回的AHK函数就足够了。
; 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
}