Skip to content

Instantly share code, notes, and snippets.

@DanielVF
Created March 20, 2023 13:53
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielVF/71123df4f6e1eaef451d898f6ec7421d to your computer and use it in GitHub Desktop.
Save DanielVF/71123df4f6e1eaef451d898f6ec7421d to your computer and use it in GitHub Desktop.
Visualize Code Changes

This vis code is not generalized - you will need to change it to extra the code you want.

Get changes:

git log --pretty=format:%H --reverse NAMEOFBRANCH -- contracts/vault/VaultCore.sol | xargs -n 1 -I {} git show {}:contracts/contracts/vault/VaultCore.sol | grep -A 150 'function NAME_OF_FUNCTION' >versions.txt
python animate.py
ffmpeg \
  -framerate 10 \
  -pattern_type glob \
  -i 'foo-*.png' \
  -r 10 \
  -vf "fps=10,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
  out.gif \
;
import re
import pygments
import pygments.lexers
import pygments.formatters
import difflib
from PIL import Image, ImageDraw, ImageFont
BORDER = 60
BG = "#372922"
def decomment(s):
s = re.sub(r'//.*|/\*\*.*| \* .+|\*/', '', s)
s = re.sub("\n *\n *\n","\n\n", s)
s = re.sub("\n *\n *\n","\n\n", s)
s = re.sub("\n *\n *\n","\n\n", s)
s = re.sub("\n *\n *\n","\n\n", s)
s = re.sub("\n *\n *\n","\n\n", s)
return s
contents = open("versions.txt").read()
versions = []
for raw in contents.split("\n--\n"):
print("----")
v = raw.split("function totalValue()")
# v = v[0].split("function dripperAvailableFunds()")
print(decomment(v[0]))
versions.append(decomment(v[0]))
# Define the Pygments lexer and formatter
lexer = pygments.lexers.get_lexer_by_name('solidity')
base = Image.new('RGB', (1800, 1400))
imd = ImageDraw.Draw(base)
imd.rectangle(((0,0),(base.width,base.height)),BG)
# Highlight the code and generate the image
start = 27
old_code = versions[start-1]
for i, code in enumerate(versions):
if i < start:
continue
n = i - start
# Generate a list of differences between the two strings
differ = difflib.Differ()
diff = list(differ.compare(old_code.splitlines(), code.splitlines()))
changed_lines = [i for i, line in enumerate(diff) if line.startswith("+") or line.startswith("?")]
deleted_lines = [i for i, line in enumerate(diff) if line.startswith("-") or line.startswith("?")]
print(changed_lines)
formatter = pygments.formatters.ImageFormatter(font_name='Menlo', font_size=10, hl_lines=changed_lines, hl_color="#23f9ab")
image_data = pygments.highlight(code, lexer, formatter)
old_formatter = pygments.formatters.ImageFormatter(font_name='Menlo', font_size=10, hl_lines=deleted_lines, hl_color="#f923ab")
old_image_data = pygments.highlight(code, lexer, old_formatter)
with open("tmp.png", "wb") as f:
f.write(image_data)
with open("tmp2.png", "wb") as f:
f.write(old_image_data)
with Image.open("tmp.png") as f:
with Image.open("tmp2.png") as f2:
base.paste(base, (-40, 0))
imd = ImageDraw.Draw(base)
imd.rectangle(((800,0),(2000,2000)),BG)
imd.rectangle(((800,base.height-f.height-BORDER),(1350,base.height-BORDER)),'#f8f8f8')
if i != start:
base.paste(f2, (800-40,base.height-f2.height-BORDER))
base.paste(f, (800,base.height-f.height-BORDER))
base.save("foo-{0:05d}.png".format(i), "PNG")
old_code = code
for q in range(0,3):
formatter = pygments.formatters.ImageFormatter(font_name='Menlo', font_size=10)
image_data = pygments.highlight(code, lexer, formatter)
with open("tmp.png", "wb") as f:
f.write(image_data)
with Image.open("tmp.png") as f:
base.paste(base, (0, 0))
imd = ImageDraw.Draw(base)
imd.rectangle(((800,0),(2000,2000)),BG)
imd.rectangle(((800,base.height-f.height-BORDER),(1350,base.height-BORDER)),'#f8f8f8')
base.paste(f, (800,base.height-f.height-BORDER))
base.save("foo-{0:05d}.png".format(i+1+q), "PNG")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment