Skip to content

Instantly share code, notes, and snippets.

@reagle
Last active August 1, 2024 14:24
Show Gist options
  • Save reagle/8984a874291f3cab33d89b59f75d413d to your computer and use it in GitHub Desktop.
Save reagle/8984a874291f3cab33d89b59f75d413d to your computer and use it in GitHub Desktop.
Sublime Text 4 plugin that counts the number of words in a markdown section and leaves the count in a comment after the heading.
import re
import sublime
import sublime_plugin
class UpdateSectionsWordCountCommand(sublime_plugin.TextCommand):
"""A Sublime Text command that updates word counts in markdown section headings."""
def run(self, edit):
view = self.view
content = view.substr(sublime.Region(0, view.size()))
updated_content = self._process_content(content)
if content != updated_content:
view.replace(edit, sublime.Region(0, view.size()), updated_content)
print("Content updated")
else:
print("No changes needed")
def _process_content(self, content):
pattern = r'^(#+\s+.*?)(?:\s*<!--.*?-->)?\n((?:(?!^#)[\s\S])*)'
return re.sub(pattern, self._update_section, content, flags=re.MULTILINE)
def _update_section(self, match):
heading = match.group(1)
content = match.group(2)
word_count = self._count_words(content)
print(f"Updating section: {heading.strip()} - {word_count} words")
return f"{heading} <!-- {word_count} words -->\n{content}"
@staticmethod
def _count_words(text):
return len(re.findall(r'\w+', text))
# 2024-07-26: this creates an unwanted item in the undo history associated with
# editing the word count comments.
# class UpdateSectionsWordCountListener(sublime_plugin.EventListener):
# """An event listener that triggers word count update before saving markdown files.
# """
# def on_pre_save(self, view):
# if view.file_name() and view.file_name().endswith('.md'):
# view.run_command('update_sections_word_count')
class UpdateMarkdownSectionsWordCountCommand(sublime_plugin.WindowCommand):
"""A window command to manually trigger word count update for markdown files."""
def run(self):
view = self.window.active_view()
if view and view.file_name() and view.file_name().endswith('.md'):
view.run_command('update_sections_word_count')
def is_enabled(self):
view = self.window.active_view()
return view and view.file_name() and view.file_name().endswith('.md')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment