comparison mercurial/patch.py @ 38630:e1987261dd05

patch: don't separate \r and \n when colorizing diff output When displaying diffs, \r at the end of a line is treated as trailing whitespace. This causes an ANSI escape code to be inserted between \r and \n. Some programs, such as less since version 530 (maybe earlier, but at least not version 487) displays ^M when it encounters a lone \r. This causes a lot of noise in diff output on Windows, where \r\n is used to terminate lines. We avoid that by treating both \n and \r\n as end of line when considering trailing whitespace.
author Sune Foldager <cryo@cyanite.org>
date Tue, 10 Jul 2018 13:18:34 +0200
parents 1c93e0237a24
children 59af0c7d103f
comparison
equal deleted inserted replaced
38629:38dfd308fe9d 38630:e1987261dd05
2403 2403
2404 def diffsinglehunk(hunklines): 2404 def diffsinglehunk(hunklines):
2405 """yield tokens for a list of lines in a single hunk""" 2405 """yield tokens for a list of lines in a single hunk"""
2406 for line in hunklines: 2406 for line in hunklines:
2407 # chomp 2407 # chomp
2408 chompline = line.rstrip('\n') 2408 chompline = line.rstrip('\r\n')
2409 # highlight tabs and trailing whitespace 2409 # highlight tabs and trailing whitespace
2410 stripline = chompline.rstrip() 2410 stripline = chompline.rstrip()
2411 if line.startswith('-'): 2411 if line.startswith('-'):
2412 label = 'diff.deleted' 2412 label = 'diff.deleted'
2413 elif line.startswith('+'): 2413 elif line.startswith('+'):
2471 nextisnewline = False 2471 nextisnewline = False
2472 # special handling line end 2472 # special handling line end
2473 isendofline = token.endswith('\n') 2473 isendofline = token.endswith('\n')
2474 if isendofline: 2474 if isendofline:
2475 chomp = token[:-1] # chomp 2475 chomp = token[:-1] # chomp
2476 if chomp.endswith('\r'):
2477 chomp = chomp[:-1]
2478 endofline = token[len(chomp):]
2476 token = chomp.rstrip() # detect spaces at the end 2479 token = chomp.rstrip() # detect spaces at the end
2477 endspaces = chomp[len(token):] 2480 endspaces = chomp[len(token):]
2478 # scan tabs 2481 # scan tabs
2479 for maybetab in tabsplitter.findall(token): 2482 for maybetab in tabsplitter.findall(token):
2480 if '\t' == maybetab[0]: 2483 if '\t' == maybetab[0]:
2486 currentlabel = label + '.unchanged' 2489 currentlabel = label + '.unchanged'
2487 yield (maybetab, currentlabel) 2490 yield (maybetab, currentlabel)
2488 if isendofline: 2491 if isendofline:
2489 if endspaces: 2492 if endspaces:
2490 yield (endspaces, 'diff.trailingwhitespace') 2493 yield (endspaces, 'diff.trailingwhitespace')
2491 yield ('\n', '') 2494 yield (endofline, '')
2492 nextisnewline = True 2495 nextisnewline = True
2493 2496
2494 def difflabel(func, *args, **kw): 2497 def difflabel(func, *args, **kw):
2495 '''yields 2-tuples of (output, label) based on the output of func()''' 2498 '''yields 2-tuples of (output, label) based on the output of func()'''
2496 if kw.get(r'opts') and kw[r'opts'].worddiff: 2499 if kw.get(r'opts') and kw[r'opts'].worddiff: