From 71fb8cfd0c3c32f65655dd1763a8df1b9d598835 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 10:36:11 +0200 Subject: [PATCH 01/12] removed lines that did nothing --- novel_stats/novel_stats.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index 3bc1034..86a7f61 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -2,8 +2,6 @@ import collections -import os -import string import sys @@ -45,8 +43,6 @@ def main(): chapter_number = int(line[len(CHAPTER_MARKER):]) word_count_by_chapter[chapter_number] = 1 # Start at one, because the chapter number itself counts as a word. - if chapter_number in status_by_chapter: - word_count_by_status[chapter_status] += 1 elif line.startswith(STATUS_MARKER): status_by_chapter[chapter_number] = line[len(STATUS_MARKER):].strip('()\n') elif line.startswith(ACT_MARKER): From c549f0fc7f6d06c1b7202693a3f10cb4ec94fda9 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 10:36:58 +0200 Subject: [PATCH 02/12] added support for markdown comments --- novel_stats/novel_stats.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index 86a7f61..b4b19f2 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -8,6 +8,7 @@ import sys CHAPTER_MARKER = '## ' STATUS_MARKER = '[status]: # ' ACT_MARKER = '[act]: # ' +COMMENT_MARKER = '[//]: # ' def count_words(line): @@ -48,6 +49,8 @@ def main(): elif line.startswith(ACT_MARKER): act_number = int(line[len(ACT_MARKER):].strip('()\n')) word_count_by_act[act_number] = 1 + elif line.startswith(COMMENT_MARKER): + pass else: line_word_count = count_words(line) word_count_by_chapter[chapter_number] += line_word_count From 70e9dd1b98556e44e666c0ab73966c17a70011fb Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 10:41:03 +0200 Subject: [PATCH 03/12] Allow act/chapter titles changed chapter_number and act_number to chapter_heading and act_heading --- novel_stats/novel_stats.py | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index b4b19f2..899740d 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -26,8 +26,8 @@ def count_words(line): def main(): arguments = sys.argv[1:] filename = arguments[0] - chapter_number = None - act_number = None + chapter_heading = None + act_heading = None total_word_count = 0 word_count_by_chapter = collections.defaultdict(int) word_count_by_status = collections.defaultdict(int) @@ -36,44 +36,44 @@ def main(): for line in open(filename).readlines(): if line.startswith(CHAPTER_MARKER): - word_count_by_act[act_number] += word_count_by_chapter[chapter_number] - total_word_count += word_count_by_chapter[chapter_number] - if chapter_number in status_by_chapter: - word_count_by_status[status_by_chapter[chapter_number]] += 1 + word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] + total_word_count += word_count_by_chapter[chapter_heading] + if chapter_heading in status_by_chapter: + word_count_by_status[status_by_chapter[chapter_heading]] += 1 - chapter_number = int(line[len(CHAPTER_MARKER):]) + chapter_heading = line[len(CHAPTER_MARKER):].strip('()\n') - word_count_by_chapter[chapter_number] = 1 # Start at one, because the chapter number itself counts as a word. + word_count_by_chapter[chapter_heading] = count_words(chapter_heading) # Count the words in chapter heading, because the chapter number and title count as words. elif line.startswith(STATUS_MARKER): - status_by_chapter[chapter_number] = line[len(STATUS_MARKER):].strip('()\n') + status_by_chapter[chapter_heading] = line[len(STATUS_MARKER):].strip('()\n') elif line.startswith(ACT_MARKER): - act_number = int(line[len(ACT_MARKER):].strip('()\n')) - word_count_by_act[act_number] = 1 + act_heading = line[len(ACT_MARKER):].strip('()\n') + word_count_by_act[act_heading] = count_words(act_heading) elif line.startswith(COMMENT_MARKER): pass else: line_word_count = count_words(line) - word_count_by_chapter[chapter_number] += line_word_count + word_count_by_chapter[chapter_heading] += line_word_count - if chapter_number in status_by_chapter: - word_count_by_status[status_by_chapter[chapter_number]] += line_word_count + if chapter_heading in status_by_chapter: + word_count_by_status[status_by_chapter[chapter_heading]] += line_word_count # Do some final accounting after the last chapter. - word_count_by_act[act_number] += word_count_by_chapter[chapter_number] - total_word_count += word_count_by_chapter[chapter_number] - if chapter_number in status_by_chapter: - word_count_by_status[status_by_chapter[chapter_number]] += 1 + word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] + total_word_count += word_count_by_chapter[chapter_heading] + if chapter_heading in status_by_chapter: + word_count_by_status[status_by_chapter[chapter_heading]] += 1 # Print out word counts. - for chapter_number, chapter_word_count in word_count_by_chapter.items(): - if chapter_number is None: + for chapter_heading, chapter_word_count in word_count_by_chapter.items(): + if chapter_heading is None: continue - chapter_status = status_by_chapter.get(chapter_number) + chapter_status = status_by_chapter.get(chapter_heading) print( 'chapter {}: {:,} words{}'.format( - chapter_number, + chapter_heading, chapter_word_count, ' ({})'.format(chapter_status) if chapter_status else '', ) @@ -81,11 +81,11 @@ def main(): print() - for act_number, act_word_count in word_count_by_act.items(): - if act_number is None: + for act_heading, act_word_count in word_count_by_act.items(): + if act_heading is None: continue - print('act {}: {:,} words (~{}%)'.format(act_number, act_word_count, act_word_count * 100 // total_word_count)) + print('act {}: {:,} words (~{}%)'.format(act_heading, act_word_count, act_word_count * 100 // total_word_count)) for status, status_word_count in word_count_by_status.items(): print('{}: {:,} words (~{}%)'.format(status, status_word_count, status_word_count * 100 // total_word_count)) From dcfea89ec73e53c0f61c0ea37cb950238b31becd Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 11:24:36 +0200 Subject: [PATCH 04/12] Added multi-status chapter support --- novel_stats/novel_stats.py | 40 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index 899740d..b390794 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -33,19 +33,26 @@ def main(): word_count_by_status = collections.defaultdict(int) word_count_by_act = collections.defaultdict(int) status_by_chapter = {} + current_status = None for line in open(filename).readlines(): if line.startswith(CHAPTER_MARKER): word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] total_word_count += word_count_by_chapter[chapter_heading] - if chapter_heading in status_by_chapter: - word_count_by_status[status_by_chapter[chapter_heading]] += 1 chapter_heading = line[len(CHAPTER_MARKER):].strip('()\n') word_count_by_chapter[chapter_heading] = count_words(chapter_heading) # Count the words in chapter heading, because the chapter number and title count as words. + + status_by_chapter[chapter_heading] = collections.defaultdict(int) + current_status = None elif line.startswith(STATUS_MARKER): - status_by_chapter[chapter_heading] = line[len(STATUS_MARKER):].strip('()\n') + if current_status == None: + current_status = line[len(STATUS_MARKER):].strip('()\n') + status_by_chapter[chapter_heading][current_status] = count_words(chapter_heading) + else: + current_status = line[len(STATUS_MARKER):].strip('()\n') + status_by_chapter[chapter_heading][current_status] += 0 elif line.startswith(ACT_MARKER): act_heading = line[len(ACT_MARKER):].strip('()\n') word_count_by_act[act_heading] = count_words(act_heading) @@ -55,29 +62,32 @@ def main(): line_word_count = count_words(line) word_count_by_chapter[chapter_heading] += line_word_count - if chapter_heading in status_by_chapter: - word_count_by_status[status_by_chapter[chapter_heading]] += line_word_count + if current_status: + word_count_by_status[current_status] += line_word_count + status_by_chapter[chapter_heading][current_status] += line_word_count # Do some final accounting after the last chapter. word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] total_word_count += word_count_by_chapter[chapter_heading] - if chapter_heading in status_by_chapter: - word_count_by_status[status_by_chapter[chapter_heading]] += 1 # Print out word counts. for chapter_heading, chapter_word_count in word_count_by_chapter.items(): if chapter_heading is None: continue - chapter_status = status_by_chapter.get(chapter_heading) - print( - 'chapter {}: {:,} words{}'.format( - chapter_heading, - chapter_word_count, - ' ({})'.format(chapter_status) if chapter_status else '', - ) - ) + if len(status_by_chapter[chapter_heading]) > 1: + print(f'chapter {chapter_heading}:') + + for chapter_status, status_count in status_by_chapter[chapter_heading].items(): + print(f'\t {status_count:,} ({chapter_status})') + print(f'\t {chapter_word_count:,} words (total)') + elif len(status_by_chapter[chapter_heading]) == 1: + chapter_status = list(status_by_chapter[chapter_heading].keys())[0] + print(f'chapter {chapter_heading}: {chapter_word_count:,} ({chapter_status})') + else: + print(f'chapter {chapter_heading}: {chapter_word_count:,}') + print() From 93b3af2c3bd224c0acda763dfa5677a26d02d39d Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 11:37:33 +0200 Subject: [PATCH 05/12] Added mdpp support --- novel_stats/novel_stats.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index b390794..51a10c8 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -3,6 +3,7 @@ import collections import sys +import os CHAPTER_MARKER = '## ' @@ -26,6 +27,14 @@ def count_words(line): def main(): arguments = sys.argv[1:] filename = arguments[0] + tmpfilename = None + + if '-pp' in arguments: + import MarkdownPP + tmpfilename = f'.tmp-{os.getpid}.md' + MarkdownPP.MarkdownPP(input=open(filename), output=open(tmpfilename,'w'), modules=list(MarkdownPP.modules)) + filename = tmpfilename + chapter_heading = None act_heading = None total_word_count = 0 @@ -101,6 +110,9 @@ def main(): print('{}: {:,} words (~{}%)'.format(status, status_word_count, status_word_count * 100 // total_word_count)) print('total: {:,} words'.format(total_word_count)) + + if tmpfilename: + os.remove(tmpfilename) if __name__ == '__main__': From d79e3f5b803616757cd52e6b262c7aff30e549a2 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 11:54:19 +0200 Subject: [PATCH 06/12] Made chapter/act summaries optional --- novel_stats/novel_stats.py | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index 51a10c8..9bae732 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -79,32 +79,34 @@ def main(): word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] total_word_count += word_count_by_chapter[chapter_heading] - # Print out word counts. - for chapter_heading, chapter_word_count in word_count_by_chapter.items(): - if chapter_heading is None: - continue + if '-c' in arguments or '--chapter' in arguments: + # Print out word counts. + for chapter_heading, chapter_word_count in word_count_by_chapter.items(): + if chapter_heading is None: + continue + if len(status_by_chapter[chapter_heading]) > 1: + print(f'chapter {chapter_heading}:') - if len(status_by_chapter[chapter_heading]) > 1: - print(f'chapter {chapter_heading}:') + for chapter_status, status_count in status_by_chapter[chapter_heading].items(): + print(f'\t {status_count:,} ({chapter_status})') + print(f'\t {chapter_word_count:,} words (total)') + elif len(status_by_chapter[chapter_heading]) == 1: + chapter_status = list(status_by_chapter[chapter_heading].keys())[0] + print(f'chapter {chapter_heading}: {chapter_word_count:,} ({chapter_status})') + else: + print(f'chapter {chapter_heading}: {chapter_word_count:,}') - for chapter_status, status_count in status_by_chapter[chapter_heading].items(): - print(f'\t {status_count:,} ({chapter_status})') - print(f'\t {chapter_word_count:,} words (total)') - elif len(status_by_chapter[chapter_heading]) == 1: - chapter_status = list(status_by_chapter[chapter_heading].keys())[0] - print(f'chapter {chapter_heading}: {chapter_word_count:,} ({chapter_status})') - else: - print(f'chapter {chapter_heading}: {chapter_word_count:,}') + print() + if '-a' in arguments or '--act' in arguments: + for act_heading, act_word_count in word_count_by_act.items(): + if act_heading is None: + continue - print() + print('act {}: {:,} words (~{}%)'.format(act_heading, act_word_count, act_word_count * 100 // total_word_count)) - for act_heading, act_word_count in word_count_by_act.items(): - if act_heading is None: - continue - - print('act {}: {:,} words (~{}%)'.format(act_heading, act_word_count, act_word_count * 100 // total_word_count)) + print() for status, status_word_count in word_count_by_status.items(): print('{}: {:,} words (~{}%)'.format(status, status_word_count, status_word_count * 100 // total_word_count)) From e3a47d74252c8dfd5e20317b6782c2b72b7cf313 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 14:28:13 +0200 Subject: [PATCH 07/12] Commented my changes + swapped to tempfile library --- novel_stats/novel_stats.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index 9bae732..326df3c 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -3,13 +3,12 @@ import collections import sys -import os CHAPTER_MARKER = '## ' STATUS_MARKER = '[status]: # ' ACT_MARKER = '[act]: # ' -COMMENT_MARKER = '[//]: # ' +COMMENT_MARKER = '[//]: # ' # Strandard markdown comment marker, supported by pandoc and calibre's ebook-convert def count_words(line): @@ -27,13 +26,17 @@ def count_words(line): def main(): arguments = sys.argv[1:] filename = arguments[0] - tmpfilename = None + mdfile = None if '-pp' in arguments: - import MarkdownPP - tmpfilename = f'.tmp-{os.getpid}.md' - MarkdownPP.MarkdownPP(input=open(filename), output=open(tmpfilename,'w'), modules=list(MarkdownPP.modules)) - filename = tmpfilename + # -pp flag to allow Markdown Preprocessing primarily to allow multi-file novel formatting + # this is implemented using a temporary file created using python's buit-in tempfile library + import MarkdownPP, tempfile + mdfile = tempfile.TemporaryFile(mode='w+') + MarkdownPP.MarkdownPP(input=open(filename), output=mdfile, modules=list(MarkdownPP.modules)) + mdfile.seek(0) + else: + mdfile = open(filename) chapter_heading = None act_heading = None @@ -44,7 +47,7 @@ def main(): status_by_chapter = {} current_status = None - for line in open(filename).readlines(): + for line in mdfile.readlines(): if line.startswith(CHAPTER_MARKER): word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] total_word_count += word_count_by_chapter[chapter_heading] @@ -55,7 +58,7 @@ def main(): status_by_chapter[chapter_heading] = collections.defaultdict(int) current_status = None - elif line.startswith(STATUS_MARKER): + elif line.startswith(STATUS_MARKER): # Modified to allow multiple statuses in a single chapter, can swap back and forth. if current_status == None: current_status = line[len(STATUS_MARKER):].strip('()\n') status_by_chapter[chapter_heading][current_status] = count_words(chapter_heading) @@ -65,7 +68,7 @@ def main(): elif line.startswith(ACT_MARKER): act_heading = line[len(ACT_MARKER):].strip('()\n') word_count_by_act[act_heading] = count_words(act_heading) - elif line.startswith(COMMENT_MARKER): + elif line.startswith(COMMENT_MARKER): # don't count the words in a comment pass else: line_word_count = count_words(line) @@ -79,8 +82,7 @@ def main(): word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] total_word_count += word_count_by_chapter[chapter_heading] - if '-c' in arguments or '--chapter' in arguments: - # Print out word counts. + if '-c' in arguments or '--chapter' in arguments: # -c or --chapter to give a chapter-by-chapter word count summary for chapter_heading, chapter_word_count in word_count_by_chapter.items(): if chapter_heading is None: continue @@ -99,7 +101,7 @@ def main(): print() - if '-a' in arguments or '--act' in arguments: + if '-a' in arguments or '--act' in arguments: # -a or --act to give an act-by-act word count summary for act_heading, act_word_count in word_count_by_act.items(): if act_heading is None: continue @@ -109,12 +111,11 @@ def main(): print() for status, status_word_count in word_count_by_status.items(): - print('{}: {:,} words (~{}%)'.format(status, status_word_count, status_word_count * 100 // total_word_count)) + print(f'{status}: {status_word_count:,} words (~{status_word_count * 100 // total_word_count}%)') - print('total: {:,} words'.format(total_word_count)) + print(f'total: {total_word_count:,} words') - if tmpfilename: - os.remove(tmpfilename) + mdfile.close() if __name__ == '__main__': From 93340fb3f45b7ea0f19303adaab07f8456e082a5 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 15:37:18 +0200 Subject: [PATCH 08/12] moved mdfile.close() --- novel_stats/novel_stats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/novel_stats/novel_stats.py b/novel_stats/novel_stats.py index 326df3c..9b88db4 100755 --- a/novel_stats/novel_stats.py +++ b/novel_stats/novel_stats.py @@ -78,6 +78,8 @@ def main(): word_count_by_status[current_status] += line_word_count status_by_chapter[chapter_heading][current_status] += line_word_count + mdfile.close() + # Do some final accounting after the last chapter. word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading] total_word_count += word_count_by_chapter[chapter_heading] @@ -114,8 +116,6 @@ def main(): print(f'{status}: {status_word_count:,} words (~{status_word_count * 100 // total_word_count}%)') print(f'total: {total_word_count:,} words') - - mdfile.close() if __name__ == '__main__': From 73e538e8f0eb0ab17f865937f6c0330859fc1e98 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 18:59:15 +0200 Subject: [PATCH 09/12] added a multi-file example --- example/Chapter1.md | 17 +++++++++++++++++ example/Chapter2.md | 16 ++++++++++++++++ example/Chapter3.md | 17 +++++++++++++++++ example/Chapter4.md | 13 +++++++++++++ example/Chapter5.md | 19 +++++++++++++++++++ example/novel.mdpp | 8 ++++++++ 6 files changed, 90 insertions(+) create mode 100644 example/Chapter1.md create mode 100644 example/Chapter2.md create mode 100644 example/Chapter3.md create mode 100644 example/Chapter4.md create mode 100644 example/Chapter5.md create mode 100644 example/novel.mdpp diff --git a/example/Chapter1.md b/example/Chapter1.md new file mode 100644 index 0000000..4017814 --- /dev/null +++ b/example/Chapter1.md @@ -0,0 +1,17 @@ +## 1 Lorem + +[status]: # (drafted) +[act]: # (1) + +*Lorem* ipsum dolor sit amet, consectetur adipiscing elit. Ut cursus malesuada leo. Phasellus justo orci, auctor ac maximus vitae, aliquet ornare urna. Etiam porttitor tristique ligula, et dictum mauris consequat vel. Curabitur fringilla velit posuere, imperdiet mauris auctor, varius nibh. Vestibulum sed mauris maximus, vehicula leo sit amet, sodales enim. Maecenas tempor nibh nec egestas aliquam. Proin non nibh eget tellus porttitor pharetra. Phasellus hendrerit, nunc quis lobortis finibus, lacus massa lobortis justo, sit amet vulputate urna magna sit amet dui. Ut facilisis sem orci, sit amet dignissim ligula rutrum quis. Nulla iaculis urna eget varius pellentesque. Nulla pulvinar orci sollicitudin consequat volutpat. Nullam tempus lectus sed est lacinia, et blandit odio tempor. In in quam luctus, convallis sem nec, dapibus elit. Nunc ornare, neque sodales maximus faucibus, lectus velit tincidunt elit, eu blandit nulla turpis sit amet ex. Curabitur ullamcorper mi non quam pharetra, eget cursus sem dapibus. + +**Nullam** ac elementum arcu, eu congue orci. Sed blandit quam non vulputate porta. Donec laoreet metus sit amet ex feugiat, in scelerisque est varius. Curabitur nec elit vel ante consequat gravida. ***Aliquam* ultrices** dolor vel eros hendrerit condimentum. Donec efficitur turpis quis eros viverra venenatis. Praesent ultricies dolor nec justo consectetur consectetur. + +[status]: # (dev edited) + +***Maecenas* nec** mi sapien. Vestibulum tortor tortor, feugiat in est nec, vestibulum faucibus magna. Pellentesque elementum elit sed metus ornare lobortis. Nunc molestie, justo id ultricies elementum, nibh libero suscipit massa, feugiat pharetra felis mi ut lacus. Pellentesque ornare pretium mi, in commodo nulla dignissim vel. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus sed dolor ut mi mattis sagittis vitae ac dolor. Integer tincidunt diam sapien, vitae tincidunt neque semper sit amet. Cras mi risus, faucibus et lacinia et, eleifend sed nunc. Sed faucibus consectetur justo, non accumsan orci imperdiet quis. + +Sed sed porta ante. Sed viverra dui sit amet eros rutrum volutpat. Aliquam eu nulla congue, cursus lectus sit amet, congue tellus. Maecenas id aliquam libero. Maecenas ultrices blandit aliquam. Sed pretium ut ipsum eu pharetra. Nullam at nunc vitae erat luctus varius non auctor felis. Ut vel dignissim nibh, sit amet gravida mauris. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur id lobortis erat. Etiam facilisis turpis ut libero cursus, sit amet cursus diam hendrerit. Sed nisi lacus, semper quis ante ac, dictum ullamcorper lacus. Aenean vel gravida mauris, a egestas nisi. + +Quisque fermentum sagittis mi. Aliquam erat volutpat. Sed vehicula quam non nunc porta sagittis. Phasellus eu dignissim arcu, non volutpat quam. Vestibulum aliquam leo eget justo pulvinar placerat. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed sed lacus tempus, tempus dui sed, lobortis magna. Vivamus dui eros, eleifend id ipsum eget, tincidunt porta metus. Pellentesque efficitur pharetra arcu nec auctor. Pellentesque euismod tincidunt risus, vel blandit leo iaculis et. Sed pellentesque lectus nisi, at faucibus purus laoreet in. Curabitur rhoncus lobortis blandit. Nulla et imperdiet risus, eu facilisis arcu. Ut tincidunt justo in eros vehicula feugiat. + diff --git a/example/Chapter2.md b/example/Chapter2.md new file mode 100644 index 0000000..3193625 --- /dev/null +++ b/example/Chapter2.md @@ -0,0 +1,16 @@ +## 2 Ipsum + +[status]: # (dev edited) + +Nullam id cursus velit, et lobortis est. Sed consequat diam risus, ac +hendrerit mauris facilisis vitae. Vestibulum blandit enim nibh, ut vehicula +augue hendrerit sit amet. Proin gravida elit quis erat dapibus ornare. Etiam +suscipit eget tortor eget facilisis. Phasellus finibus nunc quis urna +ultricies elementum. Quisque faucibus pharetra augue eu consectetur. Proin +vehicula, nisl ac maximus volutpat, turpis orci imperdiet quam, ac tempor erat +lectus in leo. Nullam et efficitur ipsum. Nulla felis turpis, blandit ultrices +eros venenatis, sagittis convallis lectus. + + +[//]: # (Testing out a comment) + diff --git a/example/Chapter3.md b/example/Chapter3.md new file mode 100644 index 0000000..8fe543a --- /dev/null +++ b/example/Chapter3.md @@ -0,0 +1,17 @@ +## 3 Dolor + +[act]: # (2) + +Mauris eu orci at velit scelerisque feugiat nec tristique nunc. Curabitur vel +dolor imperdiet, iaculis nunc sit amet, volutpat sapien. Phasellus enim ipsum, +varius a sollicitudin a, dapibus id magna. Etiam vitae sollicitudin orci. +Vivamus dapibus lacinia risus eu pellentesque. Lorem ipsum dolor sit amet, +consectetur adipiscing elit. Donec ut nisl non mi suscipit scelerisque. +Curabitur quis accumsan velit, ac convallis lectus. Curabitur aliquet nisi et +magna tincidunt, in euismod orci rutrum. Aliquam sed erat eget ipsum +sollicitudin mollis. Donec accumsan euismod rhoncus. Proin molestie ut mauris +quis egestas. Sed cursus varius leo at suscipit. Aenean ultricies sodales mi, +non varius ex laoreet quis. Morbi a nisl fringilla lorem mollis consequat et +id ex. + + diff --git a/example/Chapter4.md b/example/Chapter4.md new file mode 100644 index 0000000..50e0eb3 --- /dev/null +++ b/example/Chapter4.md @@ -0,0 +1,13 @@ +## 4 Sit + +Sed eget metus tristique, tincidunt purus non, euismod massa. Class aptent +taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. +Vestibulum egestas scelerisque neque. Pellentesque et ultrices lorem, at +mattis enim. Nam sit amet quam sapien. Maecenas fringilla nisl sit amet ipsum +feugiat condimentum. Praesent ac justo placerat, ornare lectus quis, volutpat +turpis. Etiam eu blandit nibh. Sed tincidunt facilisis massa vitae mattis. +Pellentesque vitae lectus et massa sollicitudin varius. Proin varius libero eu +elit mollis egestas. Ut interdum lacus tempor velit ullamcorper, quis +consequat tortor lobortis. Donec pulvinar pretium quam eu fringilla. + + diff --git a/example/Chapter5.md b/example/Chapter5.md new file mode 100644 index 0000000..525cf45 --- /dev/null +++ b/example/Chapter5.md @@ -0,0 +1,19 @@ +## 5 Amet + +[status]: # (drafted) +[act]: # (3) + +Cras eget egestas enim. Donec faucibus lacus malesuada magna bibendum, eget +molestie purus gravida. Vivamus leo erat, dapibus non tristique a, fringilla +eget felis. Phasellus efficitur, nibh eu sollicitudin tristique, urna tellus +ultricies ligula, sit amet facilisis libero risus sodales dolor. Quisque nec +tortor a ligula porttitor egestas et vel dui. Integer lorem sem, luctus vel +enim ac, rhoncus vestibulum urna. Maecenas eu sem id eros interdum congue. +Nunc quis turpis id nibh aliquam varius eget eget tortor. Morbi faucibus nisi +sit amet arcu sollicitudin, sit amet luctus lorem pulvinar. Aliquam velit +nulla, viverra a turpis eget, venenatis hendrerit sapien. Aliquam a sem +vehicula, tempor purus non, fringilla felis. Ut venenatis massa lacus, et +malesuada leo vehicula vitae. In vel nunc id metus semper ornare. Duis quis +tellus eleifend, tristique ex sit amet, mattis ligula. + + diff --git a/example/novel.mdpp b/example/novel.mdpp new file mode 100644 index 0000000..2685f1b --- /dev/null +++ b/example/novel.mdpp @@ -0,0 +1,8 @@ +# Title of the Novel +### Author Name + +!INCLUDE "Chapter1.md" +!INCLUDE "Chapter2.md" +!INCLUDE "Chapter3.md" +!INCLUDE "Chapter4.md" +!INCLUDE "Chapter5.md" \ No newline at end of file From 9266c546644b921e7713cbbe6ed21dd0a6de8eda Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 19:22:29 +0200 Subject: [PATCH 10/12] Changed multi-file example name --- example/{novel.mdpp => multi_file.mdpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename example/{novel.mdpp => multi_file.mdpp} (100%) diff --git a/example/novel.mdpp b/example/multi_file.mdpp similarity index 100% rename from example/novel.mdpp rename to example/multi_file.mdpp From 44426edb78f369408d8a250a695df79a81f9686a Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 19:22:38 +0200 Subject: [PATCH 11/12] Updated the README --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 4b519eb..b56040f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ novel-stats produces word count statistics for novels written in Markdown -format, including total word count, per-chapter word counts, per-act word -counts, and counts by chapter "status." You might find this useful if you're +format, including total word count, word count by status, and optionally +per-chapter and per-act word counts. You might find this useful if you're already using tools like Git and Markdown processing as part of your writing workflow (or are looking to start) and want some basic statistics about your novel as you're writing it. @@ -9,21 +9,27 @@ novel-stats is fairly particular about the format of the novel and doesn't currently include much in the way of error checking. Word counts may not be exact. -Example output: +Example output with no optional data: ```bash $ novel-stats example.md -chapter 1: 103 words (drafted) -chapter 2: 83 words (dev edited) -chapter 3: 115 words -chapter 4: 96 words -chapter 5: 136 words (drafted) +drafted: 237 words (~43%) +dev edited: 82 words (~15%) +total: 539 words +``` -act 1: 187 words (~34%) -act 2: 212 words (~39%) -act 3: 137 words (~25%) -drafted: 239 words (~44%) -dev edited: 83 words (~15%) +Example output with chapter data: + +```bash +$ novel-stats example.md -c +chapter 1: 103 (drafted) +chapter 2: 83 (dev edited) +chapter 3: 115 +chapter 4: 96 +chapter 5: 136 (drafted) + +drafted: 237 words (~43%) +dev edited: 82 words (~15%) total: 539 words ``` @@ -43,6 +49,25 @@ easier): pip3 install --editable /path/to/novel-stats ``` +```bash + novel-stats multi_file.mdpp -pp -c -a +chapter 1 Lorem: + 203 (drafted) + 303 (dev edited) + 506 words (total) +chapter 2 Ipsum: 84 (dev edited) +chapter 3 Dolor: 116 +chapter 4 Sit: 97 +chapter 5 Amet: 137 (drafted) + +act 1: 591 words (~62%) +act 2: 214 words (~22%) +act 3: 138 words (~14%) + +drafted: 336 words (~35%) +dev edited: 385 words (~40%) +total: 946 words +``` ## Usage @@ -50,9 +75,18 @@ novel-stats takes a single argument: The path to your novel file in markdown format. For instance: ```bash -novel-stats /path/to/your/novel.md +novel-stats /path/to/your/novel.md[pp] [-c/--chapter] [-a/--act] [-pp] ``` +### Optional flags + +* -c or --chapter — output chapter-by-chapter breakdown of word counts, +including how many words in each chapter are tagged with which status +* -a or --act — output act-by-act breakdown of word counts (total only) +* --pp — run markdown pre-processor, this allows for a multi-file input +(e.g. each chapter in its own file), but requires the MarkdownPP python +library. + ## Markdown format You'll need to format your novel in the expected format for novel-stats to @@ -126,11 +160,43 @@ If you do use this feature, you should set the status at the top of each chapter, before the actual chapter contents (and after any chapter status). +### Comments + +Comments, such as outlining notes for yourself, can be added anywhere using: + +```yaml +[//]: # This text is completely ignored. +``` + +These words will not count towards the word count + + +### Multi-file support + +Splitting your novel into multiple files is supported using the `MarkdownPP` +python library. To include a secondary file inside the main one, simply use + +```yaml +!INCLUDE "OtherFile.md" +``` + +and add the `-pp` flag to novel-stats. + ### Example novel -novel-stats includes an example Markdown file `example.md` that illustrates -the expected Markdown format. Try it out: +novel-stats includes two examples: +1. Markdown file `example.md` that illustrates the expected Markdown format +for a single file. Try it out: + +```bash +$ novel-stats example.md ``` -novel-stats example.md + +2. A 6 file example in the `example` folder with the main file +`multi_file.mdpp`. You can try this one out with + +```bash +$ cd example +$ novel-stats multi_file.mdpp -pp ``` From 9fb1025a024ec54fec517a52a3dcdd1d6e18dce4 Mon Sep 17 00:00:00 2001 From: Dmytro Yeroshkin Date: Fri, 22 Oct 2021 19:59:05 +0200 Subject: [PATCH 12/12] Fixed mistake in readme --- README.md | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index b56040f..dcbd044 100644 --- a/README.md +++ b/README.md @@ -33,24 +33,10 @@ dev edited: 82 words (~15%) total: 539 words ``` -## Installation - -Start by cloning the project with git. Then install it with Python's `pip`. -Example: +Example with multi-file markdown: ```bash -pip3 install /path/to/novel-stats -``` - -Or, if you'd like to install it "editable" (making development/updates -easier): - -```bash -pip3 install --editable /path/to/novel-stats -``` - -```bash - novel-stats multi_file.mdpp -pp -c -a +$ novel-stats multi_file.mdpp -pp -c -a chapter 1 Lorem: 203 (drafted) 303 (dev edited) @@ -69,6 +55,22 @@ dev edited: 385 words (~40%) total: 946 words ``` +## Installation + +Start by cloning the project with git. Then install it with Python's `pip`. +Example: + +```bash +pip3 install /path/to/novel-stats +``` + +Or, if you'd like to install it "editable" (making development/updates +easier): + +```bash +pip3 install --editable /path/to/novel-stats +``` + ## Usage novel-stats takes a single argument: The path to your novel file in markdown