Rework a bunch of scripts into a single website script
This commit is contained in:
parent
f83c6ebbe5
commit
a9f52aad98
12 changed files with 275 additions and 92 deletions
0
scripts/erynwells_me/__init__.py
Normal file
0
scripts/erynwells_me/__init__.py
Normal file
12
scripts/erynwells_me/blog.py
Normal file
12
scripts/erynwells_me/blog.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import datetime
|
||||
import os.path as osp
|
||||
from typing import Optional
|
||||
from . import paths
|
||||
|
||||
|
||||
def post_path(name, *, year: Optional[int] = None):
|
||||
if not year:
|
||||
year = datetime.date.today().year
|
||||
return osp.join(paths.content_path(), 'blog', str(year), name)
|
||||
33
scripts/erynwells_me/dates.py
Normal file
33
scripts/erynwells_me/dates.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env python3
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import datetime
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def next_sunday_noon(from_date: Optional[datetime.date] = None) -> datetime.datetime:
|
||||
'''
|
||||
Return a `datetime` for noon on the upcoming Sunday. Use today if no
|
||||
`from_date` is given.
|
||||
'''
|
||||
|
||||
today = from_date or datetime.date.today()
|
||||
|
||||
current_weekday = today.weekday()
|
||||
if current_weekday == 6:
|
||||
days_to_next_sunday = 6
|
||||
else:
|
||||
days_to_next_sunday = 6 - current_weekday
|
||||
|
||||
delta = datetime.timedelta(days=days_to_next_sunday)
|
||||
|
||||
noon = datetime.time(hour=12)
|
||||
|
||||
timezone = datetime.datetime.now().astimezone().tzinfo
|
||||
next_sunday_noon = datetime.datetime.combine(
|
||||
today + delta,
|
||||
noon,
|
||||
tzinfo=timezone
|
||||
)
|
||||
|
||||
return next_sunday_noon
|
||||
12
scripts/erynwells_me/metadata.py
Normal file
12
scripts/erynwells_me/metadata.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def slugify(s: str) -> str:
|
||||
'''Process a string into something suitable to be a page slug.'''
|
||||
s = s.strip().lower()
|
||||
s = re.sub(r'\s+', '-', s)
|
||||
s = re.sub(r'[‘’“”"\'()]', '', s)
|
||||
return s
|
||||
19
scripts/erynwells_me/paths.py
Normal file
19
scripts/erynwells_me/paths.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import os.path as osp
|
||||
|
||||
|
||||
def content_path() -> str:
|
||||
'''Return the path to the content directory.'''
|
||||
path = osp.abspath(osp.join(osp.dirname(__file__), '..', '..', 'content'))
|
||||
assert osp.isdir(path)
|
||||
return path
|
||||
|
||||
|
||||
def blog_path() -> str:
|
||||
return osp.join(content_path(), 'blog')
|
||||
|
||||
|
||||
def photos_path() -> str:
|
||||
return osp.join(content_path(), 'photos')
|
||||
1
scripts/erynwells_me/scripting/__init__.py
Normal file
1
scripts/erynwells_me/scripting/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .command import Command
|
||||
24
scripts/erynwells_me/scripting/command.py
Normal file
24
scripts/erynwells_me/scripting/command.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import argparse
|
||||
import re
|
||||
|
||||
class Command:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
class_name = self.__class__.__name__
|
||||
if class_name.endswith('Command'):
|
||||
trimmed_class_name = class_name.removesuffix('Command')
|
||||
hyphenated_name = re.sub(r'\B([A-Z])', r'-\1', trimmed_class_name)
|
||||
return hyphenated_name.lower()
|
||||
return class_name.lower()
|
||||
|
||||
@property
|
||||
def help(self) -> str:
|
||||
return ''
|
||||
|
||||
def add_arguments(self, _: argparse.ArgumentParser):
|
||||
raise NotImplementedError()
|
||||
88
scripts/erynwells_me/weeknotes.py
Normal file
88
scripts/erynwells_me/weeknotes.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/env python3.12
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Optional
|
||||
from . import blog
|
||||
from .dates import next_sunday_noon
|
||||
from .scripting import Command
|
||||
|
||||
|
||||
class WeeknotesCommand(Command):
|
||||
@staticmethod
|
||||
def weeknotes_filename(year: str, week: str) -> str:
|
||||
return f'weeknotes-{year}w{week}.md'
|
||||
|
||||
@staticmethod
|
||||
def weeknotes_path(*, week_number: Optional[int] = None):
|
||||
if week_number:
|
||||
year = datetime.datetime.now().year
|
||||
week_number_str = str(week_number)
|
||||
else:
|
||||
next_sunday = next_sunday_noon()
|
||||
year = next_sunday.year
|
||||
week_number_str = next_sunday.strftime('%V')
|
||||
|
||||
return blog.post_path(WeeknotesCommand.weeknotes_filename(
|
||||
str(year),
|
||||
week_number_str
|
||||
))
|
||||
|
||||
@property
|
||||
def help(self) -> str:
|
||||
return 'Work with weeknotes posts'
|
||||
|
||||
def add_arguments(self, parser: argparse.ArgumentParser):
|
||||
commands = parser.add_subparsers(title='Weeknotes', required=True)
|
||||
|
||||
convert_command = commands.add_parser(
|
||||
'convert',
|
||||
help='Convert a post from a single file to a page bundle and vice versa'
|
||||
)
|
||||
convert_command.set_defaults(handler=self.handle_convert_command)
|
||||
|
||||
edit_command = commands.add_parser(
|
||||
'edit',
|
||||
help="Edit the current week's weeknotes post"
|
||||
)
|
||||
edit_command.add_argument(
|
||||
'--editor', '-e',
|
||||
default=os.environ.get('EDITOR', 'nvim'),
|
||||
)
|
||||
edit_command.add_argument('--week', '-w')
|
||||
edit_command.set_defaults(handler=self.handle_edit_command)
|
||||
|
||||
show_command = commands.add_parser(
|
||||
'show',
|
||||
aliases=['print'],
|
||||
help="Print a path to the current week's weeknotes post",
|
||||
)
|
||||
show_command.add_argument('--week', '-w')
|
||||
show_command.add_argument('--date', action='store_true')
|
||||
show_command.set_defaults(handler=self.handle_show_command)
|
||||
|
||||
def handle_convert_command(self, _: argparse.Namespace):
|
||||
raise NotImplementedError()
|
||||
|
||||
def handle_edit_command(self, args: argparse.Namespace):
|
||||
path = WeeknotesCommand.weeknotes_path(week_number=args.week)
|
||||
subprocess.run(
|
||||
f'{args.editor} "{path}"',
|
||||
stdin=sys.stdin,
|
||||
stdout=sys.stdout,
|
||||
stderr=sys.stderr,
|
||||
env=os.environ,
|
||||
shell=True,
|
||||
)
|
||||
|
||||
def handle_show_command(self, args: argparse.Namespace):
|
||||
if args.date:
|
||||
if args.week:
|
||||
raise NotImplementedError('Cannot print date with specified week number')
|
||||
print(next_sunday_noon().isoformat())
|
||||
else:
|
||||
print(WeeknotesCommand.weeknotes_path(week_number=args.week))
|
||||
Loading…
Add table
Add a link
Reference in a new issue