【问题标题】:Where can I find the patience diff implemented?我在哪里可以找到实施的耐心差异?
【发布时间】:2013-04-10 14:01:17
【问题描述】:

Bram Cohen 的耐心差异在 bazaar 中作为默认差异和 git diff 的一个选项在这个网站上得到了很好的回答,但我发现很难找到一个独立的独立程序来实现这个特定的差异算法.

例如,我想将耐心差异应用于 perforce 差异,并且通过规范的“frobnitz”代码示例非常清楚耐心差异如何更好:

右侧的终端调用了带有--patience 标志的git diff

我还设置了diff-highlight perl 脚本,它的工作是在这些行的第一个和最后一个不同部分之间的匹配行上反转颜色。左边有一个例子,这并没有太大帮助,但我会让它滑动,因为至少那里有 is 那个分号......无论如何,改进 diff-highlight 脚本不是这个问题的主题。

除了在哪里可以找到独立的耐心差异之外,如果有人知道如何使 perforce p4 使用外部差异程序,那也是必须要做的事情。

【问题讨论】:

  • 什么,我用 git 在两个文件上运行它?这看起来很糟糕。我从来没有想到过。我现在看到这很好用,我肯定会使用它。但是很多系统都没有安装git...

标签: git version-control diff perforce


【解决方案1】:

它可能不像我想要的那样理想,但从实际的角度来看,这个解决方案非常好(这是一个非常好的视角)。

git diff --no-index --patience file1 file2 完成这项工作。 (感谢@StevenPenny)

$P4DIFF 变量定义了外部差异...我们只是将git diff --patience --no-index 填入其中。

【讨论】:

    【解决方案2】:

    我冒昧地将耐心移植到somewhat standalone library,它是用 C# 编写的。图书馆还处于早期阶段。它主要是一个逐行端口;所以希望它具有 Python 的大部分稳定性。

    请记住,patience 只查找最长的公共子序列(在差异术语中,这意味着文件中未更改的部分)。你需要determine the additions and removals yourself

    还请记住,在 Bazaar 存储库中,也有 Python 和 C 中的实现(同样,这些实现仅解决 LCS 问题):

    • C version:似乎更看重性能而不是清晰度,通过阅读您将无法轻易理解算法。 Python 互操作还有很多代码开销。
    • Python version:算法的参考实现。似乎更重视清晰度而不是性能。

    如果您需要编写自己的实现,我建议您先移植 Python 版本,然后查看 C 实现以了解如何加快速度。

    Git仓库里应该也有实现的,但是我没搜过。

    【讨论】:

    • 从那以后,我开始在 C++ 中找到 here 的逐个字符差异实现,以及我自己的许多(utf8 和二进制相关)增强功能。我称它为sift。希望有一天它会被揭露给世界。感谢您分享您的版本! (我的可能实际上会失败 w.r.t. 做一个真正的耐心差异,尽管它在 frobnitz 示例中表现良好)
    • @StevenLu 很高兴,很高兴你来对了。我很想知道你所做的一些改进的效果是什么(如果你在 GitHub 项目上打开了问题)。
    • 我实际上刚刚发现了这个:github.com/leutloff/diff-match-patch-cpp-stl 现在我得到的是基于wstring 的稍旧版本,我无法正确转换它以使用string。但是我不认为有太大的限制,因为它确实完全支持 utf-8(而且我不确定非宽 string 实现如何以了解代码点的方式处理 utf8)。
    【解决方案3】:

    Cohen 自己的 Python 实现只需要稍作调整(如下)即可独立运行。它在两个文件中,我通过谷歌搜索“difflib 耐心”找到了其中的副本:

    http://stuff.mit.edu/afs/athena/system/i386_deb50/os/usr/share/pyshared/bzrlib/patiencediff.pyhttp://stuff.mit.edu/afs/athena/system/i386_deb50/os/usr/share/pyshared/bzrlib/_patiencediff_py.py

    第一个文件可以像 diff 一样从命令行运行。第二个是内部循环的 Python 实现。 (单个文件??读者练习!)在 bzrlib 中,还有一个内部循环的 C 实现。

    这里(在程序本身的帮助下)是我让它们独立运行的补丁:

    Sandy$ patiencediff.py --patience orig/patiencediff.py patiencediff.py
    --- orig/patiencediff.py
    +++ patiencediff.py
    @@ -15,14 +15,20 @@
     # along with this program; if not, write to the Free Software
     # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
    +try:
    +    from bzrlib.lazy_import import lazy_import
    +    lazy_import(globals(), """
    +    import os
    +    import sys
    +    import time
    +    import difflib
    +    """)
    +except:
    +    import os
    +    import sys
    +    import time
    +    import difflib
    
    -from bzrlib.lazy_import import lazy_import
    -lazy_import(globals(), """
    -import os
    -import sys
    -import time
    -import difflib
    -""")
    
    
     __all__ = ['PatienceSequenceMatcher', 'unified_diff', 'unified_diff_files']
    @@ -135,11 +141,18 @@
             PatienceSequenceMatcher_c as PatienceSequenceMatcher
             )
     except ImportError:
    -    from bzrlib._patiencediff_py import (
    -        unique_lcs_py as unique_lcs,
    -        recurse_matches_py as recurse_matches,
    -        PatienceSequenceMatcher_py as PatienceSequenceMatcher
    -        )
    +    try:
    +        from bzrlib._patiencediff_py import (
    +            unique_lcs_py as unique_lcs,
    +            recurse_matches_py as recurse_matches,
    +            PatienceSequenceMatcher_py as PatienceSequenceMatcher
    +            )
    +    except ImportError:
    +        from _patiencediff_py import (
    +            unique_lcs_py as unique_lcs,
    +            recurse_matches_py as recurse_matches,
    +            PatienceSequenceMatcher_py as PatienceSequenceMatcher
    +            )
    
    
     def main(args):
    Sandy$ patiencediff.py --patience orig/_patiencediff_py.py _patiencediff_py.py
    --- orig/_patiencediff_py.py
    +++ _patiencediff_py.py
    @@ -15,11 +15,16 @@
     # along with this program; if not, write to the Free Software
     # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
    -
    +from __future__ import print_function
     from bisect import bisect
     import difflib
    
    -from bzrlib.trace import mutter
    +try:
    +    from bzrlib.trace import mutter
    +except:
    +    import sys
    +    def mutter(msg):
    +        print (msg, file=sys.stderr)
    
    
     __all__ = ['PatienceSequenceMatcher', 'unified_diff', 'unified_diff_files']
    Sandy$
    

    【讨论】:

    • 这是完美的 - 谢谢!我在 tiac 或 GitHub 上没有看到已修补的独立版本 - 你有没有在任何地方发布它?如果没有,有机会我会的:)。
    • 我还没有补丁文件的副本,但我相信您可以使用“补丁”实用程序将上面的补丁应用于原始文件。
    • 我错过了你的部分问题。不,我从来没有将它们合并到一个文件中。
    • 这里现在有一个独立版本:github.com/breezy-team/patiencediff
    【解决方案4】:

    patiencediff 的 Bazaar 实现也可作为单独的 Python 模块使用。

    【讨论】:

      【解决方案5】:

      对于 javascript 实现,增强了 PatienceDiff 以确定可能移动的行(称为“PatienceDiffPlus”),请参阅https://github.com/jonTrent/PatienceDiff

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-11
        • 2023-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-11
        • 2019-07-31
        相关资源
        最近更新 更多