2502 if chompline != stripline: |
2503 if chompline != stripline: |
2503 yield (chompline[len(stripline):], 'diff.trailingwhitespace') |
2504 yield (chompline[len(stripline):], 'diff.trailingwhitespace') |
2504 if chompline != line: |
2505 if chompline != line: |
2505 yield (line[len(chompline):], '') |
2506 yield (line[len(chompline):], '') |
2506 |
2507 |
|
2508 def diffsinglehunkinline(hunklines): |
|
2509 """yield tokens for a list of lines in a single hunk, with inline colors""" |
|
2510 # prepare deleted, and inserted content |
|
2511 a = '' |
|
2512 b = '' |
|
2513 for line in hunklines: |
|
2514 if line[0] == '-': |
|
2515 a += line[1:] |
|
2516 elif line[0] == '+': |
|
2517 b += line[1:] |
|
2518 else: |
|
2519 raise error.ProgrammingError('unexpected hunk line: %s' % line) |
|
2520 # fast path: if either side is empty, use diffsinglehunk |
|
2521 if not a or not b: |
|
2522 for t in diffsinglehunk(hunklines): |
|
2523 yield t |
|
2524 return |
|
2525 # re-split the content into words |
|
2526 al = wordsplitter.findall(a) |
|
2527 bl = wordsplitter.findall(b) |
|
2528 # re-arrange the words to lines since the diff algorithm is line-based |
|
2529 aln = [s if s == '\n' else s + '\n' for s in al] |
|
2530 bln = [s if s == '\n' else s + '\n' for s in bl] |
|
2531 an = ''.join(aln) |
|
2532 bn = ''.join(bln) |
|
2533 # run the diff algorithm, prepare atokens and btokens |
|
2534 atokens = [] |
|
2535 btokens = [] |
|
2536 blocks = mdiff.allblocks(an, bn, lines1=aln, lines2=bln) |
|
2537 for (a1, a2, b1, b2), btype in blocks: |
|
2538 changed = btype == '!' |
|
2539 for token in mdiff.splitnewlines(''.join(al[a1:a2])): |
|
2540 atokens.append((changed, token)) |
|
2541 for token in mdiff.splitnewlines(''.join(bl[b1:b2])): |
|
2542 btokens.append((changed, token)) |
|
2543 |
|
2544 # yield deleted tokens, then inserted ones |
|
2545 for prefix, label, tokens in [('-', 'diff.deleted', atokens), |
|
2546 ('+', 'diff.inserted', btokens)]: |
|
2547 nextisnewline = True |
|
2548 for changed, token in tokens: |
|
2549 if nextisnewline: |
|
2550 yield (prefix, label) |
|
2551 nextisnewline = False |
|
2552 # special handling line end |
|
2553 isendofline = token.endswith('\n') |
|
2554 if isendofline: |
|
2555 chomp = token[:-1] # chomp |
|
2556 token = chomp.rstrip() # detect spaces at the end |
|
2557 endspaces = chomp[len(token):] |
|
2558 # scan tabs |
|
2559 for maybetab in tabsplitter.findall(token): |
|
2560 if '\t' == maybetab[0]: |
|
2561 currentlabel = 'diff.tab' |
|
2562 else: |
|
2563 if changed: |
|
2564 currentlabel = label + '.changed' |
|
2565 else: |
|
2566 currentlabel = label + '.unchanged' |
|
2567 yield (maybetab, currentlabel) |
|
2568 if isendofline: |
|
2569 if endspaces: |
|
2570 yield (endspaces, 'diff.trailingwhitespace') |
|
2571 yield ('\n', '') |
|
2572 nextisnewline = True |
|
2573 |
2507 def difflabel(func, *args, **kw): |
2574 def difflabel(func, *args, **kw): |
2508 '''yields 2-tuples of (output, label) based on the output of func()''' |
2575 '''yields 2-tuples of (output, label) based on the output of func()''' |
|
2576 if kw.get(r'opts') and kw[r'opts'].worddiff: |
|
2577 dodiffhunk = diffsinglehunkinline |
|
2578 else: |
|
2579 dodiffhunk = diffsinglehunk |
2509 headprefixes = [('diff', 'diff.diffline'), |
2580 headprefixes = [('diff', 'diff.diffline'), |
2510 ('copy', 'diff.extended'), |
2581 ('copy', 'diff.extended'), |
2511 ('rename', 'diff.extended'), |
2582 ('rename', 'diff.extended'), |
2512 ('old', 'diff.extended'), |
2583 ('old', 'diff.extended'), |
2513 ('new', 'diff.extended'), |
2584 ('new', 'diff.extended'), |