Skip to content

Instantly share code, notes, and snippets.

@ajdavis
Created March 13, 2015 20:12
Show Gist options
  • Save ajdavis/2540493e7ff86755c381 to your computer and use it in GitHub Desktop.
Save ajdavis/2540493e7ff86755c381 to your computer and use it in GitHub Desktop.
Put uncrustify and uncrustify.cfg in your ~/bin and run this to uncrustify changed lines in your file.
#!/usr/bin/env python
import difflib
import subprocess
import shutil
import sys
from os import getcwd
from os.path import normpath, expanduser, join, exists
from git import Repo # pip install gitpython
path = sys.argv[1]
full_path = normpath(expanduser(join(getcwd(), path)))
repo = Repo(getcwd(), search_parent_directories=True)
no_sha = '0' * 40
def commits_and_lines():
line_no = 0
for commit, lines in repo.blame(None, full_path):
for _ in lines:
yield commit, line_no
line_no += 1
def uncommitted_lines():
for commit, line_no in commits_and_lines():
if commit.hexsha == no_sha:
yield line_no
def uncrustify(path):
subprocess.check_output([
expanduser('~/bin/uncrustify'),
'-c',
expanduser('~/bin/uncrustify.cfg'),
path,
])
output_path = '%s.uncrustify' % path
assert exists(output_path), output_path
return output_path
uls = set(uncommitted_lines())
uncrustified_path = uncrustify(full_path)
lines = list(open(full_path).readlines())
uncrustified_lines = list(open(uncrustified_path).readlines())
matcher = difflib.SequenceMatcher(a=lines, b=uncrustified_lines)
shutil.copy(full_path, full_path + '.bak')
def save():
with open(full_path, 'w') as f:
f.write(''.join(lines))
for tag, i1, i2, j1, j2 in reversed(matcher.get_opcodes()):
if tag == 'equal':
continue
if tag == 'replace' and set(range(i1, i2)).issubset(uls):
lines[i1:i2] = uncrustified_lines[j1:j2]
save()
elif tag == 'insert' and i1 in uls:
lines[i1:i2] = uncrustified_lines[j1:j2]
save()
elif tag == 'delete' and set(range(i1, i2)).issubset(uls):
del lines[i1:i2]
save()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment