#!/usr/bin/env python """ Sort the library file like KiCad does, to minimize diffs """ import os import re import sys import pprint def get_groups_in_order(lines): order = ['#', 'DEF', 'F0' , 'F1', 'F2', 'F3', 'DRAW', 'A', 'S', 'T', 'P', 'X', 'ENDDRAW', 'ENDDEF', ] for this in order: yield([x for x in lines if x.startswith(this)]) def sort_chunk(lines): res = [] for this in get_groups_in_order(lines): if not this: continue if this[0].startswith('#'): res += this else: # secondary sort of elements in a group sortfun = None if this[0].startswith('T'): sortfun = lambda x: (x.split(' ')[8]) # text if this[0].startswith('X'): sortfun = lambda x: (x.split(' ')[2]) # pin if this[0].startswith('S'): sortfun = lambda x: (int(x.split(' ')[1]), int(x.split(' ')[2]), int(x.split(' ')[3]), int(x.split(' ')[4]), ) if this[0].startswith('P'): sortfun = lambda x: (int(x.split(' ')[1]), int(x.split(' ')[5]), int(x.split(' ')[6]), int(x.split(' ')[7]), int(x.split(' ')[8]), ) if this[0].startswith('A'): sortfun = lambda x: (int(x.split(' ')[1]), int(x.split(' ')[2]), ) if sortfun: try: this = sorted(this, key=sortfun) except ValueError: pass #if this[0].startswith('P'): # # XXX HACK WHILE DEVELOPING TO MINIMIZE DIFF # for t in range(len(this)): # if not this[t][-3:] in [' N\n', ' f\n', ' F\n'): # this[t] = this[t][:-1] + ' N\n' res += this return res def chunk_file(fd): res = [] for this in fd.readlines(): res += [this] if this.startswith('ENDDEF'): if res[0] != '#\n': res = ['#\n'] + res name = res[1].split(' ')[1][:-1] sorted_lines = sort_chunk(res) yield(name, ''.join(sorted_lines)) res = [] def sort_symbols(fn_in, fn_out, refdes): in_ = open(fn_in) out = open(fn_out, 'w') fn = os.path.basename(fn_in) print('Remapping symbols in in {}'.format(fn)) header = in_.readline() + in_.readline() symbols = {} for k, v in sorted(chunk_file(in_)): symbols[k] = v out.write(header) for k in sorted(symbols.keys()): out.write(symbols[k]) out.write('#\n#End Library\n') return True def main(libs): refdes = {} for this in sorted(libs): if sort_symbols(this, this + '.tmp', refdes): os.rename(this + '.tmp', this) return True if __name__ == '__main__': try: if len(sys.argv) == 0: sys.stderr.write('Syntax: sort-symbols.py *.lib\n') sys.exit(1) libs = [x for x in sys.argv if x.endswith('.lib')] res = main(libs) if res: sys.exit(0) sys.exit(1) except KeyboardInterrupt: pass