From 6e75e155262d3d268d5ab6bf764910b96621c588 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Wed, 21 Apr 2021 01:20:08 -0700 Subject: [PATCH] `yaclog init` command --- yaclog/changelog.py | 28 +++++++++++++---------- yaclog/cli/__init__.py | 0 yaclog/cli/__main__.py | 52 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 yaclog/cli/__init__.py create mode 100644 yaclog/cli/__main__.py diff --git a/yaclog/changelog.py b/yaclog/changelog.py index 18ca4c5..464b293 100644 --- a/yaclog/changelog.py +++ b/yaclog/changelog.py @@ -29,6 +29,8 @@ under2_regex = re.compile(r'^-+\s*$') bullet_regex = re.compile(r'^[-+*]') linkid_regex = re.compile(r'^\[(?P\S*)]:\s*(?P.*)') +default_header = '# Changelog\n\nAll notable changes to this project will be documented in this file' + def _strip_link(token): if link_literal := re.fullmatch(r'\[(.*?)]\((.*?)\)', token): @@ -112,26 +114,28 @@ class VersionEntry: class Changelog: - def __init__(self, path: os.PathLike): + def __init__(self, path: os.PathLike = None): self.path = path self.header = '' self.versions = [] + self.links = {} + + if not os.path.exists(path): + self.header = default_header + return # Read file with open(path, 'r') as fp: - self.lines = fp.readlines() + lines = fp.readlines() section = '' in_block = False in_code = False - self.links = {} - - links = {} segments: List[Tuple[int, List[str], str]] = [] header_segments = [] - for line_no, line in enumerate(self.lines): + for line_no, line in enumerate(lines): if in_code: # this is the contents of a code block segments[-1][1].append(line) @@ -168,7 +172,7 @@ class Changelog: elif match := linkid_regex.match(line): # this is a link definition in the form '[id]: link', so add it to the link table - links[match['link_id'].lower()] = match['link'] + self.links[match['link_id'].lower()] = match['link'] elif line.isspace(): # skip empty lines @@ -241,18 +245,18 @@ class Changelog: if match := re.fullmatch(r'\[(.*)]', version.name): # ref-matched link link_id = match[1].lower() - if link_id in links: - version.link = links.pop(link_id) + if link_id in self.links: + version.link = self.links.pop(link_id) version.link_id = None version.name = match[1] - elif version.link_id in links: + elif version.link_id in self.links: # id-matched link - version.link = links.pop(version.link_id) + version.link = self.links.pop(version.link_id) # strip whitespace from header self.header = _join_markdown(header_segments) - self.links = links + self.links = self.links def write(self, path: os.PathLike = None): if path is None: diff --git a/yaclog/cli/__init__.py b/yaclog/cli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/yaclog/cli/__main__.py b/yaclog/cli/__main__.py new file mode 100644 index 0000000..20d5c04 --- /dev/null +++ b/yaclog/cli/__main__.py @@ -0,0 +1,52 @@ +# yaclog: 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 click +import yaclog +import os.path + + +@click.group() +@click.option('--path', envvar='YACLOG_PATH', default='CHANGELOG.md', + type=click.Path(dir_okay=False, writable=True, readable=True)) +@click.version_option() +@click.pass_context +def cli(ctx, path): + ctx.obj = path + + if not (ctx.invoked_subcommand == 'init' or os.path.exists(path)): + # if the path doesnt exist, then ask if we can create it + if click.confirm(f'Changelog file {path} does not exist. Would you like to create it?'): + ctx.invoke('init') + else: + return + + +@cli.command('init') +@click.pass_context +def init(ctx): + path = ctx.parent.params['path'] + + if os.path.exists(path) and not click.confirm( + f'Changelog file {path} already exists. Would you like to overwrite it?'): + return + + yaclog.Changelog(path).write() + print(f'Created new changelog file at {path}') + + +if __name__ == '__main__': + cli()