# yaclog-ksp: yet another changelog tool # Copyright (c) 2021. Andrew Cassidy # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import pathlib import re import click import yaclog from yaclog_ksp.cfgnode import ConfigNode @click.command() @click.option('--path', envvar='YACLOG_PATH', default='CHANGELOG.md', show_default=True, type=click.Path(dir_okay=False, writable=True, readable=True), help='Location of the changelog file.') @click.option('-o', '--output', 'outpath', default=None, type=click.Path(writable=True, dir_okay=False), help="Output file to write to. Uses 'GameData/{name}/Versioning/{name}ChangeLog.cfg' by default.") @click.option('-n', '--name', help="The name of the mod. Derived from the current directory by default.") @click.version_option() def main(path, outpath, name): """ Converts markdown changelogs to KSP changelog configs.""" if not name: # try to guess name from current directory pathname = pathlib.Path.cwd().name.removeprefix('KSP-') modslug = str.join('', [s.title() for s in re.split(r'[ _-]+', pathname)]) segments = re.findall(r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))', modslug) name = segments[0] + [' ' + s for s in segments[1:]] else: modslug = str.join('', [s.title() for s in re.split(r'[ _-]+', name)]) if not outpath: # default is in GameData/{name}/Versioning/{name}ChangeLog.cfg outpath = pathlib.Path('GameData', modslug, 'Versioning', modslug + 'ChangeLog.cfg') log = yaclog.read(path) node = ConfigNode() # find metadata table rows for key, value in re.findall(r'^\|(?P[^\n-]*?)\|(?P[^\n-]*?)\|$', log.preamble, flags=re.MULTILINE): key = key.strip() value = value.strip() if key.strip(':-'): node.add_value(key, value) # if modname not in metadata, then add it here if not node.has_value('modName'): node.add_value('modName', name) # iterate through all versions for version in log.versions: v_node = node.add_new_node('VERSION') v_node.add_value('version', version.name) # add date if version.date: v_node.add_value('versionDate', str(version.date)) # check for KSP version tag and add it for tag in version.tags: if match := re.match(r'KSP (?P.*)', tag): v_node.add_value('versionKSP', match['versionKSP']) break # add entries for section, entries in version.sections.items(): for entry in entries: bullets = re.findall(r'^[\t ]*[-+*] (.*?)$', entry, flags=re.MULTILINE) if len(bullets) < 1: # not a bullet point, but a paragraph. all one string change = entry.replace('\n', ' ') subchanges = [] else: # bullet point, may have sub points change = bullets[0] subchanges = bullets[1:] if section or len(subchanges) > 0: e_node = v_node.add_new_node('CHANGE') if section: # KerbalChangelog only actually cares about the first character, # so dont bother correcting "Fixed"->"Fix", etc e_node.add_value('type', section.title()) e_node.add_value('change', change) for sc in subchanges: e_node.add_value('subchange', sc) else: v_node.add_value('change', change) with open(outpath, 'w') as fp: fp.write('// Changelog file generated by yaclog-ksp (https://github.com/drewcassidy/yaclog-ksp)\n') fp.write('KERBALCHANGELOG\n') fp.write(str(node)) print(f'wrote output to {outpath}') if __name__ == '__main__': main()