Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 710538
Collapse All | Expand All

(-)a/README.rst (-3 / +36 lines)
Lines 5-13 Ydiff Link Here
5
   :target: https://travis-ci.org/ymattw/ydiff
5
   :target: https://travis-ci.org/ymattw/ydiff
6
   :alt: Build status
6
   :alt: Build status
7
7
8
Term based tool to view *colored*, *incremental* diff in a *Git/Mercurial/Svn*
8
Term based tool to view *colored*, *incremental* diff in a version controlled
9
workspace or from stdin, with *side by side* (similar to ``diff -y``) and *auto
9
workspace (supports Git, Mercurial, Perforce and Svn so far) or from stdin,
10
pager* support. Requires python (>= 2.5.0) and ``less``.
10
with *side by side* (similar to ``diff -y``) and *auto pager* support. Requires
11
python (>= 2.5.0) and ``less``.
11
12
12
.. image:: https://raw.github.com/ymattw/ydiff/gh-pages/img/default.png
13
.. image:: https://raw.github.com/ymattw/ydiff/gh-pages/img/default.png
13
   :alt: default
14
   :alt: default
Lines 61-66 You can also install with Homebrew on Mac. (Thanks to `@josa42`_, Link Here
61
62
62
    brew install ydiff
63
    brew install ydiff
63
64
65
66
Install on Fedora
67
~~~~~~~~~~~~~~~~~
68
69
On Fedora, you can install ydiff with dnf.
70
71
.. code-block:: bash
72
73
    dnf install ydiff
74
    
75
Install on FreeBSD
76
~~~~~~~~~~~~~~~~~~
77
78
On FreeBSD, you can install ydiff with pkg.
79
80
.. code-block:: bash
81
82
    pkg install ydiff
83
64
Download directly
84
Download directly
65
~~~~~~~~~~~~~~~~~
85
~~~~~~~~~~~~~~~~~
66
86
Lines 96-101 Type ``ydiff -h`` to show usage:: Link Here
96
      -c M, --color=M      colorize mode 'auto' (default), 'always', or 'never'
116
      -c M, --color=M      colorize mode 'auto' (default), 'always', or 'never'
97
      -t N, --tab-width=N  convert tab characters to this many spaces (default: 8)
117
      -t N, --tab-width=N  convert tab characters to this many spaces (default: 8)
98
      --wrap               wrap long lines in side-by-side view
118
      --wrap               wrap long lines in side-by-side view
119
      -p M, --pager=M      pager application, suggested values are 'less' or 'cat'
120
      -o M, --pager-options=M
121
                           options to supply to pager application
99
122
100
      Note:
123
      Note:
101
        Option parser will stop on first unknown option and pass them down to
124
        Option parser will stop on first unknown option and pass them down to
Lines 148-153 as follows: Link Here
148
    ydiff_dir=$(dirname $(which ydiff))
171
    ydiff_dir=$(dirname $(which ydiff))
149
    ln -s "${ydiff_dir}/ydiff" "${ydiff_dir}/git-ydiff"
172
    ln -s "${ydiff_dir}/ydiff" "${ydiff_dir}/git-ydiff"
150
173
174
Utilize a specific pager application:
175
176
.. code-block:: bash
177
178
    ydiff                           # default pager - less
179
    LESS_OPTS='-FRSX --shift 1'
180
    ydiff -p less -o "${LESS_OPTS}" # emulate default pager
181
    ydiff -p /usr/bin/less          # custom pager
182
    ydiff -p cat                    # non-paging ANSI processor for colorizing
183
151
Pipe in a diff:
184
Pipe in a diff:
152
185
153
.. code-block:: bash
186
.. code-block:: bash
(-)a/ydiff.py (-39 / +70 lines)
Lines 59-65 COLORS = { Link Here
59
    'lightcyan'     : '\x1b[1;36m',
59
    'lightcyan'     : '\x1b[1;36m',
60
}
60
}
61
61
62
# Keys for revision control probe, diff and log with diff
62
# Keys for revision control probe, diff and log (optional) with diff
63
VCS_INFO = {
63
VCS_INFO = {
64
    'Git': {
64
    'Git': {
65
        'probe': ['git', 'rev-parse'],
65
        'probe': ['git', 'rev-parse'],
Lines 71-76 VCS_INFO = { Link Here
71
        'diff': ['hg', 'diff'],
71
        'diff': ['hg', 'diff'],
72
        'log': ['hg', 'log', '--patch'],
72
        'log': ['hg', 'log', '--patch'],
73
    },
73
    },
74
    'Perforce': {
75
        'probe': ['p4', 'dirs', '.'],
76
        'diff': ['p4', 'diff'],
77
        'log': None,
78
    },
74
    'Svn': {
79
    'Svn': {
75
        'probe': ['svn', 'info'],
80
        'probe': ['svn', 'info'],
76
        'diff': ['svn', 'diff'],
81
        'diff': ['svn', 'diff'],
Lines 79-84 VCS_INFO = { Link Here
79
}
84
}
80
85
81
86
87
def revision_control_probe():
88
    """Returns version control name (key in VCS_INFO) or None."""
89
    for vcs_name, ops in VCS_INFO.items():
90
        if check_command_status(ops.get('probe')):
91
            return vcs_name
92
93
94
def revision_control_diff(vcs_name, args):
95
    """Return diff from revision control system."""
96
    cmd = VCS_INFO[vcs_name]['diff']
97
    return subprocess.Popen(cmd + args, stdout=subprocess.PIPE).stdout
98
99
100
def revision_control_log(vcs_name, args):
101
    """Return log from revision control system or None."""
102
    cmd = VCS_INFO[vcs_name].get('log')
103
    if cmd is not None:
104
        return subprocess.Popen(cmd + args, stdout=subprocess.PIPE).stdout
105
106
82
def colorize(text, start_color, end_color='reset'):
107
def colorize(text, start_color, end_color='reset'):
83
    return COLORS[start_color] + text + COLORS[end_color]
108
    return COLORS[start_color] + text + COLORS[end_color]
84
109
Lines 299-306 class PatchStream(object): Link Here
299
    def __iter__(self):
324
    def __iter__(self):
300
        for line in self._stream_header:
325
        for line in self._stream_header:
301
            yield line
326
            yield line
302
        for line in self._diff_hdl:
327
        try:
303
            yield line
328
            for line in self._diff_hdl:
329
                yield line
330
        except RuntimeError:
331
            return
304
332
305
333
306
class PatchStreamForwarder(object):
334
class PatchStreamForwarder(object):
Lines 715-724 def markup_to_pager(stream, opts): Link Here
715
    See issue #30 (https://github.com/ymattw/ydiff/issues/30) for more
743
    See issue #30 (https://github.com/ymattw/ydiff/issues/30) for more
716
    information.
744
    information.
717
    """
745
    """
718
    pager_cmd = ['less']
746
    pager_cmd = [opts.pager]
719
    if not os.getenv('LESS'):
747
    pager_opts = (opts.pager_options.split(' ')
720
        # Args stolen from git source: github.com/git/git/blob/master/pager.c
748
                  if opts.pager_options is not None
721
        pager_cmd.extend(['-FRSX', '--shift 1'])
749
                  else None)
750
751
    if opts.pager is None:
752
        pager_cmd = ['less']
753
        if not os.getenv('LESS') and not opts.pager_options:
754
            # Args stolen from git source:
755
            # github.com/git/git/blob/master/pager.c
756
            pager_opts = ['-FRSX', '--shift 1']
757
758
    pager_opts = pager_opts if pager_opts is not None else []
759
    pager_cmd.extend(pager_opts)
722
    pager = subprocess.Popen(
760
    pager = subprocess.Popen(
723
        pager_cmd, stdin=subprocess.PIPE, stdout=sys.stdout)
761
        pager_cmd, stdin=subprocess.PIPE, stdout=sys.stdout)
724
762
Lines 743-764 def check_command_status(arguments): Link Here
743
        return False
781
        return False
744
782
745
783
746
def revision_control_diff(args):
747
    """Return diff from revision control system."""
748
    for _, ops in VCS_INFO.items():
749
        if check_command_status(ops['probe']):
750
            return subprocess.Popen(
751
                ops['diff'] + args, stdout=subprocess.PIPE).stdout
752
753
754
def revision_control_log(args):
755
    """Return log from revision control system."""
756
    for _, ops in VCS_INFO.items():
757
        if check_command_status(ops['probe']):
758
            return subprocess.Popen(
759
                ops['log'] + args, stdout=subprocess.PIPE).stdout
760
761
762
def decode(line):
784
def decode(line):
763
    """Decode UTF-8 if necessary."""
785
    """Decode UTF-8 if necessary."""
764
    if isinstance(line, unicode):
786
    if isinstance(line, unicode):
Lines 815-822 def main(): Link Here
815
                rargs.insert(parsed_num, '--')
837
                rargs.insert(parsed_num, '--')
816
            OptionParser._process_args(self, largs, rargs, values)
838
            OptionParser._process_args(self, largs, rargs, values)
817
839
818
    supported_vcs = sorted(VCS_INFO.keys())
819
820
    usage = """%prog [options] [file|dir ...]"""
840
    usage = """%prog [options] [file|dir ...]"""
821
    parser = PassThroughOptionParser(
841
    parser = PassThroughOptionParser(
822
        usage=usage, description=META_INFO['description'],
842
        usage=usage, description=META_INFO['description'],
Lines 840-845 def main(): Link Here
840
    parser.add_option(
860
    parser.add_option(
841
        '', '--wrap', action='store_true',
861
        '', '--wrap', action='store_true',
842
        help='wrap long lines in side-by-side view')
862
        help='wrap long lines in side-by-side view')
863
    parser.add_option(
864
        '-p', '--pager', metavar='M',
865
        help="""pager application, suggested values are 'less' """
866
             """or 'cat'""")
867
    parser.add_option(
868
        '-o', '--pager-options', metavar='M',
869
        help="""options to supply to pager application""")
843
870
844
    # Hack: use OptionGroup text for extra help message after option list
871
    # Hack: use OptionGroup text for extra help message after option list
845
    option_group = OptionGroup(
872
    option_group = OptionGroup(
Lines 864-885 def main(): Link Here
864
891
865
    opts, args = parser.parse_args(ydiff_opts + sys.argv[1:])
892
    opts, args = parser.parse_args(ydiff_opts + sys.argv[1:])
866
893
867
    if opts.log:
894
    if not sys.stdin.isatty():
868
        diff_hdl = revision_control_log(args)
869
        if not diff_hdl:
870
            sys.stderr.write(('*** Not in a supported workspace, supported '
871
                              'are: %s\n') % ', '.join(supported_vcs))
872
            return 1
873
    elif sys.stdin.isatty():
874
        diff_hdl = revision_control_diff(args)
875
        if not diff_hdl:
876
            sys.stderr.write(('*** Not in a supported workspace, supported '
877
                              'are: %s\n\n') % ', '.join(supported_vcs))
878
            parser.print_help()
879
            return 1
880
    else:
881
        diff_hdl = (sys.stdin.buffer if hasattr(sys.stdin, 'buffer')
895
        diff_hdl = (sys.stdin.buffer if hasattr(sys.stdin, 'buffer')
882
                    else sys.stdin)
896
                    else sys.stdin)
897
    else:
898
        vcs_name = revision_control_probe()
899
        if vcs_name is None:
900
            supported_vcs = ', '.join(sorted(VCS_INFO.keys()))
901
            sys.stderr.write('*** Not in a supported workspace, supported are:'
902
                             ' %s\n' % supported_vcs)
903
            return 1
904
905
        if opts.log:
906
            diff_hdl = revision_control_log(vcs_name, args)
907
            if diff_hdl is None:
908
                sys.stderr.write('*** %s does not support log command.\n' %
909
                                 vcs_name)
910
                return 1
911
        else:
912
            # 'diff' is a must have feature.
913
            diff_hdl = revision_control_diff(vcs_name, args)
883
914
884
    stream = PatchStream(diff_hdl)
915
    stream = PatchStream(diff_hdl)
885
916

Return to bug 710538