def _char_diff(self, old, new, transition, fmt=lambda c: c):
differ = difflib.ndiff(old, new)<EOL>dtype = None<EOL>line = []<EOL>while True:<EOL><INDENT>d = next(differ, (None,))<EOL>if d[<NUM_LIT:0>] != dtype:<EOL><INDENT>line += transition(dtype, d[<NUM_LIT:0>])<EOL>dtype = d[<NUM_LIT:0>]<EOL><DEDENT>if dtype is None:<EOL><INDENT>break<EOL><DEDENT>if d[<NUM_LIT:2>] == "<STR_LIT:\n>":<EOL><INDENT>if dtype != "<STR_LIT:U+0020>":<EOL><INDENT>self._warn_chars.add((dtype, "<STR_LIT>"))<EOL>line += [fmt(r"<STR_LIT:\n>"), transition(dtype, "<STR_LIT:U+0020>")]<EOL><DEDENT>if dtype != "<STR_LIT:->":<EOL><INDENT>yield "<STR_LIT>".join(line)<EOL>line.clear()<EOL><DEDENT>line.append(transition("<STR_LIT:U+0020>", dtype))<EOL><DEDENT>elif dtype != "<STR_LIT:U+0020>" and d[<NUM_LIT:2>] == "<STR_LIT:\t>":<EOL><INDENT>line.append(fmt("<STR_LIT>"))<EOL>self._warn_chars.add((dtype, "<STR_LIT>"))<EOL><DEDENT>else:<EOL><INDENT>line.append(fmt(d[<NUM_LIT:2>]))<EOL><DEDENT><DEDENT>last = "<STR_LIT>".join(line)<EOL>if re.sub(r"<STR_LIT>", "<STR_LIT>", last):<EOL><INDENT>yield last<EOL><DEDENT>
Returns a char-based diff between `old` and `new` where each character
is formatted by `fmt` and transitions between blocks are determined by `transition`.