Archive

All published posts

2524 posts latest post 2026-07-21 simple view
Publishing rhythm
Jun 2026 | 26 posts

How to vimgrep over hidden files.

I needed to delete all build pipeline steps that were named upload docs. I currently have about 60 projects running from the same template all running very similar builds. In the past I’ve scripted out migrations for large changes like this, they involved writing a python script that would load the yaml file into a dictionary, find the corresponding steps make the change and write it back out.

Today’s job was much simplar, just delete the step, were all steps are surrounded by newlines. My first thought was to just open all files in vim and run dap. I just needed to get these files:positions into my quickfix. My issue is that all the builds reside within hidden directories by convention.

The issue #

variability

After searching through all the projects it was clear that all the steps were in their own paragraph, though I was not 100% confident enough to completely automate it, and the word upload docs was in the paragraph.

some were a two liner

- name: upload docs
  script: aws s3 ...

Some had a variation in the name

- name: upload docs to s3
  script: aws s3 ...

some were more than 2 lines.

- name: upload docs
  script: |
    aws s3 ...

some used a different command.

- name: upload docs
  script: |
    python ...

Templates are great #

but they change

Templates are amazing, and tools like cookiecutter and copier are essential in my workflow, but those templates change over time. Some things are a constant, and others like this one are an ever evolving beast until they are tamed into something the team is happy with.

vimgrep over hidden files #

I know all the files that I care to search for are called build.yml, and they are in a hidden directory.

:args `fd -H build.yml`
:vimgrep /upload docs/ ##

Once opened as a buffer by using args, and a handy fd command I can vimgrep over all the open buffers using ##

Open buffers are represented by ##

Now I can just dap and :cnext my way through the list of changes that I have, and know that I hit every one of them when I am at the end of my list. And can double check this in about 10s by scrolling back through the quickfix list.

Vim points achieved #

You’re not a true vim enthusiast until you have spent 10 minutes writing a blog post about how vim saved you 5 minutes. Check out all the other times this has happened to me in the vim tag.

image from Dall-e

a sprinter edging out his opponent by Dall-e

It’s about time to release Markata 0.3.0. I’ve had 8 pre-releases since the last release, but more importantly it has about 3 months of updates. Many of which are just cleaning up bad practices that were showing up as hot spots on my pyinstrument reports

Markata started off partly as a python developer frustrated with using nodejs for everything, and a desire to learn how to make frameworks in pluggy. Little did I know how flexible pluggy would make it. It started out just as my blog generator, but has turned into quite a bit more.

Over time this side project has grown some warts and some of them were now becoming a big enough issue it was time to cut them out.

Let’s compare #

I like to use my tils articles for examples and tests like this as there are enough articles for a good test, but they are pretty short and quick to render.

mkdir ~/git/tils/tils
cp  ~/git/waylonwalker.com/pages/til/ ~/tils/tils -r
cd ~/git/tils/tils

running tils on 0.2.0 #

At the time of writing this is the current version of markata, so just make a new venv and run it.

python3 -m venv .venv --prompt $(basename $PWD)
pip install markata
markata clean
markata build

cold tils: 14.523 warm tils: 1.028

running tils on 0.3.0b8 #

python3 -m venv .venv --prompt $(basename $PWD)
# --pre installs pre-releases that include a b in their version name
pip install markata --pre
markata clean
markata build

cold tils: 11.551 (+20%) warm tils: 0.860 (+16%)

pyinstrument #

These measurements were taken with pyinstrument mostly out of convenience since there is already a pyinstrument hook built in, but also because I like pyinstrument.

pyinstrument-markata==0.3.0b8-tils-hot.webp

Here is the pyinstrument report from the last run.

My Machine #

This comparison was not very exhaustive. It was ran on my pretty new to me Ryzen 5 3600 machine.

neofetch-8-21-2022.webp

The changes #

Most of these changes revolve in how the lifecycle is ran. It was trying to be extra cautious and run previous steps for you if it thought it might be needes, in reality it was rerunning a few steps multiple times no matter what.

The other thing I turned off by default, but can be opted into, is beautifulasoup’s prettify. That was one of the slower steps ran on my site.

0.3.0 #

It should be out by the time you see this, I wanted to compare the changes I had made and make sure that it was still making forward progress and thought I would share the results.

Check out stable-diffusion [1] by CompVis [2]. It’s a well-crafted project with great potential. A latent text-to-image diffusion model References: [1]: https://github.com/CompVis/stable-diffusion [2]: https://github.com/CompVis

Deliberative #

People exceptionally talented in the Deliberative theme are best described by the serious care they take in making decisions or choices. They anticipate obstacles.

I am risk-adverse. I want everything well thought out and calculated before I make any sort of change. I have never gambled in my life and just the thought of it makes me anxious.

Aim it #

I can use this as a strength to plan out potential issues and prevent them. I do this quite often with my role in infrastructure.

I need to make sure that I use deadlines to keep this as a strength and not hinderence.

Automation #

One of the biggest ways that I utilize this skill is automation. I am all about automating things, not just because I don’t want to do the manual work, but I am not sure when I am going to need to do something again.

Check out archlinux [1] and their project aur [2]. ⚠️⚠️Experimental aur [3].git [4] mirror⚠️⚠️ (read-only mirror) References: [1]: https://github.com/archlinux [2]: https://github.com/archlinux/aur [3]: /aur/ [4]: /glossary/git/

A common meta thing that I need in python is to find the version of a package. Most of the time I reach for package_name.__version__, but that does not always work.

but not all projects have a __version__ #

In searching the internet for an answer nearly every one of them pointed me to __version__. This works for most projects, but is simply a convention, its not required. Not all projects implement a __version__, but most do. I’ve never seen it lie to me, but there is nothing stopping someone from shipping mismatched versions.

If you maintain a project ship a __version__ #

I appreciate it

While its not required its super handy and easy for anyone to remember off the top of their head. It makes it easy to start debugging differences between what you have vs what you see somewhere else. You can do this by dropping a __version__ variable inside your __init__.py file.

## __init__.py
__version__ = 1.0.0

SO #

stack overflow saves the day

Special thanks to this Stack Overflow post for answering this question for me.

So what do you do… #

importlib

Your next option is to reach into the package metadata of the package that you are interested in, and this has changed over time as highlighted in the stack overflow post.

for Python >= 3.8:

from importlib.metadata import version

version('markata')
# `0.3.0.b4`

I only really use python >= 3.8 these days, but if you need to implement it for an older version check out the stack overflow post.

Another option.. #

use the command line

Another common option uses pip at the command line.

❯ pip show markata
Name: markata
Version: 0.3.0b4
Summary: Static site generator plugins all the way down.
Home-page: https://markata.dev
Author: Waylon Walker
Author-email: [email protected]
License: MIT
Location: /home/waylon/git/waylonwalker.com/.venv/lib/python3.11/site-packages
Requires: anyconfig, beautifulsoup4, checksumdir, diskcache, feedgen, jinja2, more-itertools, pathspec, pillow, pluggy, pymdown-extensions, python-frontmatter, pytz, rich, textual, toml, typer
Required-by:

And if the package implements a command line its common to ship a version command such as --version or -V.

❯ markata --version
Markata CLI Version: 0.3.0.b4

Why did I need to do this? #

Well we have a cli tool that wraps around piptools and we wanted to include the version of piptools in the comments that it produces dynamically. This is why I wanted to dynamically grab the version inside python without shelling out to pip show. Now along with the version of our internal tool you will get the version of piptools even though piptools does not ship a __version__ variable.

Fin #

In the end, I am glad I learned that its so easy to use the more accurate package metadata, but still appreciate packages shipping __version__ for all of us n00b’s out here.

Check out gum [1] by charmbracelet [2]. It’s a well-crafted project with great potential. A tool for glamorous shell scripts 🎀 References: [1]: https://github.com/charmbracelet/gum [2]: https://github.com/charmbracelet
Check out crossposter [1] by Mr-Destructive [2]. It’s a well-crafted project with great potential. Crosspost your articles to dev.to, codenewbie.org, medium.com and hashnode.com with a single shellscript / python package References: [1]: https://github.com/Mr-Destructive/crossposter [2]: https://github.com/Mr-Destructive

The one reason I switched to arch

The community, that’s it, end of post, roll the credits. I’m a tinkerer # [1] I am a tinkerer, I am not going to run a stock desktop manager, mostly becuase that’s just not how my brain works. I need to tweak everything to fit my needs. Grantid I have not spent much time in many full fledged linux desktop environments. They are far more customizable than windows ever will be, I absolutely love that about them. Inevitibly I end up in a situation where I hit a wall, it just won’t do what I want it to do, or my lack of understanding what came wtih it holds me back. minimal # [2] I love minimal installs. I love just building up my system from the bottom up with things that I like, I understand, and that I can script. I’m a noob # [3] I spend a lot of my time in the terminal. I’d like to think I know how to use a linux command line for software development really well, but there are a lot of things that I still dont know all that well, mostly because I don’t need to. The AUR # [5]...
Just starred moonlight-qt [1] by moonlight-stream [2]. It’s an exciting project with a lot to offer. GameStream client for PCs (Windows, Mac, Linux, and Steam Link) References: [1]: https://github.com/moonlight-stream/moonlight-qt [2]: https://github.com/moonlight-stream
I recently discovered moonlight-docs [1] by moonlight-stream [2], and it’s truly impressive. Moonlight Documentation References: [1]: https://github.com/moonlight-stream/moonlight-docs [2]: https://github.com/moonlight-stream
I like deresmos’s [1] project xrandr-manager [2]. Manage dual display on Linux References: [1]: https://github.com/deresmos [2]: https://github.com/deresmos/xrandr-manager
If you’re into interesting projects, don’t miss out on xpadneo [1], created by atar-axis [2]. Advanced Linux Driver for Xbox One Wireless Controller (shipped with Xbox One S) References: [1]: https://github.com/atar-axis/xpadneo [2]: https://github.com/atar-axis
I came across Launcher-Curseforge [1] from ShayBox [2], and it’s packed with great features and ideas. Integrates the CF Modpack install button to any MMC based launcher References: [1]: https://github.com/ShayBox/Launcher-Curseforge [2]: https://github.com/ShayBox
Astronaut doing a mic drop with explosion

Recently I added two new bash/zsh aliases to make my git experience just a tad better.

trackme #

Most of our work repos were recently migrated to new remote urls, we scriped out the update to all of the repos, but I was left with a tracking error for all of my open branches. To easily resolve this I just made an alias so that I can just run trackme anytime I see this error.

There is no tracking information for the current branch.
    Please specify which branch you want to merge with.
    See git-pull(1) for details

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream develop origin/<branch>

getting the branch #

The following command will always return the currently checked out branch name.

git symbolic-ref --short HEAD

Injecting this into the suggested git command as a subshell gives us this alias that when ran with trackme will automatically fix tracking for my branch.

alias trackme='git branch --set-upstream-to=origin/$(git symbolic-ref --short HEAD)'

rebasemain #

I sometimes get a bit lazy at checking main for changes before submitting any prs, so again I made a quick shell alias that will rebase main into my branch before I open a pr.

alias rebasemain='git pull origin main --rebase'

The Aliases #

Here are both of the alias’s, feel free to steal and modify them into your dotfiles. If you are uniniatiated a common starting place to put these is either in your ~/.bashrch or ~/.zshrc depending on your shell of choice.

alias trackme='git branch --set-upstream-to=origin/$(git symbolic-ref --short HEAD)'
alias rebasemain='git pull origin main --rebase'
Check out pip-tools [1] by jazzband [2]. It’s a well-crafted project with great potential. A set of tools to keep your pinned Python dependencies fresh. References: [1]: https://github.com/jazzband/pip-tools [2]: https://github.com/jazzband

So many terminal applications bind q to exit, even the python debugger, its muscle memory for me. But to exit ipython I have to type out exit<ENTER>. This is fine, but since q is muscle memory for me I get this error a few times per day.

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ <ipython-input-1-2b66fd261ee5>:1 in <module>                                                     │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
NameError: name 'q' is not defined

After digging way too deep into how IPython implements its ExitAutoCall I realized there was a very simple solution here. IPython automatically imports all the scripts you put in your profile directory, all I needed was to create ~/.ipython/profile_default/startup/q.py with the following.

q = exit

It was that simple. This is not a game changer by any means, but I will now see one less error in my workflow. I just press q<Enter> and I am out, without error.

It’s no secret that I love automation, and lately my templating framework of choice has been copier. One hiccup I recently ran into was having spaces in my templated directory names. This makes it harder to run commands against as you need to escape them, and if they end up in a url you end up with ugly %20 all over.

Cookiecutter has the solution #

Yes the solution comes from a competing templating framework.

I install copier with pipx, so I need to inject cookiecutter in to my copier environment to use the slugify filter.

pipx inject copier cookiecutter

If you are using a normal virtual environment you can just pip install it.

pip install copier cookiecutter

add the extension to your template #

copier.yml

Now to enable the extension you need to declare it in your copier.yml file in your template.

_jinja_extensions:
    - cookiecutter.extensions.SlugifyExtension

Use it | slugify #

use-it

Now to use it, anywhere that you want to slugify a variable, you just pipe it into slugify.

❯ tree .
.
├── copier.yml
├── README.md
└── {{ site_name|slugify }}
    └── markata.toml.jinja

1 directory, 3 files

Here is a slimmed down version of what the copier.yml looks like.

site_name:
  type: str
  help: What is the name of your site, this shows in seo description and the site title.
  default: Din Djarin

_jinja_extensions:
    - cookiecutter.extensions.SlugifyExtension

Results #

Running the template looks a bit like this.

copier-cookiecutter-slugify.webp

straight from their docs #

The next section is straight from the cookiecutter docs

Slugify extension #

The cookiecutter.extensions.SlugifyExtension extension provides a slugify filter in templates that converts string into its dashed (“slugified”) version:

{% "It's a random version" | slugify %}

Would output:

it-s-a-random-version

It is different from a mere replace of spaces since it also treats some special characters differently such as ' in the example above. The function accepts all arguments that can be passed to the slugify function of python-slugify_. For example to change the output from it-s-a-random-version to it_s_a_random_version, the separator parameter would be passed: slugify(separator='_').

I came across box-cli-maker [1] from box-cli-maker [2], and it’s packed with great features and ideas. Render highly customizable boxes in the terminal References: [1]: https://github.com/box-cli-maker/box-cli-maker [2]: https://github.com/box-cli-maker
box-cli-maker [1] by Delta456 [2] is a game-changer in its space. Excited to see how it evolves. Make Highly Customized Boxes for CLI References: [1]: https://github.com/Delta456/box-cli-maker [2]: https://github.com/Delta456

Textual has devtools in the upcoming css branch, and its pretty awesome!

It’s still early #

Textual is still very early and not really ready for prime time, but it’s quite amazing how easy some things such as creating keybindings is. The docs are coming, but missing right now so if you want to use textual be ready for reading source code and examples.

On to the devtools #

As @willmcgugan shows in this tweet it’s pretty easy to setup, it requires having two terminals open, or using tmux, and currently you have to use the css branch.

https://twitter.com/willmcgugan/status/1531294412696956930

Why does textual need its own devtools #

Textual is a tui application framework. Unlike when you are building cli applications, when the tui takes over the terminal in full screen there is no where to print statement debug, and breakpoints don’t work.

getting the css branch #

In the future it will likely be in main and not need this, but for now you need to get the css branch to get devtools.

git clone https://github.com/Textualize/textual
git fetch --alll
git checkout css

install in a virtual environment #

Now you can create a virtual environment, feel free to use whatever virtual environment tool you want, venv is built in to most python distributions though, and should just be there.

python3 -m venv .venv --prompt textual
source .venv/bin/activate
pip install .

Now that we have textual installed #

Once textual is installed you can open up the devtools by running textual console.

textual console
textual-console.webp
I’m really excited about minesweeper [1], an amazing project by NotUnlikeTheWaves [2]. It’s worth exploring! A minesweeper in the terminal written in Golang with Bubbletea References: [1]: https://github.com/NotUnlikeTheWaves/minesweeper [2]: https://github.com/NotUnlikeTheWaves
The work on gh-eco [1] by jrnxf [2]. 🦎 gh cli extension to explore the ecosystem References: [1]: https://github.com/jrnxf/gh-eco [2]: https://github.com/jrnxf

Using Different versions of python with pipx | pyenv

[1] I love using pipx for automatic virtual environment [2] management of my globally installed python cli applications, but sometimes the application is not compatible with your globally installed pipx Which version of python is pipx using?? # [3] This one took me a minute to figure out at first, please let me know if there is a better way. I am pretty certain that this is not the ideal way, but it works. My first technique was to make a package that printed out sys.version. # what version of python does the global pipx use? pipx run --spec git+https://github.com/waylonwalker/pyvers pyvers # what version of python does the local pipx use? python -m pipx run --spec git+https://github.com/waylonwalker/pyvers pyvers Let’s setup some other versions of python with pyenv # [4] If you don’t already have pyenv [5] installed, you can follow their install instructions [6] to get it. pyenv install 3.8.13 pyenv install 3.10.5 I usually require a virtual environment # [7] I set the PIP...
2 min read
Check out Cveinnt [1] and their project LiveTerm [2]. 💻 Build terminal styled websites in minutes! References: [1]: https://github.com/Cveinnt [2]: https://github.com/Cveinnt/LiveTerm
curl [1] has done a fantastic job with curl [2]. Highly recommend taking a look. A command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features References: [1]: https://github.com/curl [2]: https://github.com/curl/curl

LIVE-REPLAY - Python dev | Markata todoui | 4/6/2022

https://youtu.be/-42A5210HYo Super fun steam Broadcasted live on Twitch – Watch live at https://www.twitch.tv/waylonwalker We worked on markata todoui, a command tui trello board written in python using only markdown files to store the data. I love markdown and I want to make this my workflow. During this stream we get RAIDED by TEEJ_DV! and chat about tmux a bit before calling the changes to markata-tui good and signing off. - dotfiles: https://github.com/WaylonWalker/devtainer - today’s project: https://github.com/WaylonWalker/markata-todoui - website: https://waylonwalker.com/
The work on fish-lf-icons [1] by joshmedeski [2]. Fish plugin to add Nerd Font icon support to the lf terminal file manager References: [1]: https://github.com/joshmedeski/fish-lf-icons [2]: https://github.com/joshmedeski
If you’re into interesting projects, don’t miss out on wish-lists [1], created by pypeaday [2]. amazon wish lists replacement References: [1]: https://github.com/pypeaday/wish-lists [2]: https://github.com/pypeaday
I’m really excited about typeshed [1], an amazing project by python [2]. It’s worth exploring! Collection of library stubs for Python, with static types References: [1]: https://github.com/python/typeshed [2]: https://github.com/python
If you’re into interesting projects, don’t miss out on mypy [1], created by python [2]. Optional static typing for Python References: [1]: https://github.com/python/mypy [2]: https://github.com/python
I’m impressed by devshell [1] from numtide [2]. Per project developer environments References: [1]: https://github.com/numtide/devshell [2]: https://github.com/numtide
The work on pyscript [1] by pyscript [2]. PyScript is an open source platform for Python in the browser. Try PyScript: https://pyscript.com Examples: https://tinyurl.com/pyscript-examples Community: https://discord.gg/HxvBtukrg2 References: [1]: https://github.com/pyscript/pyscript [2]: https://github.com/pyscript
Check out pypeaday [1] and their project tdarr [2]. tdarr setup References: [1]: https://github.com/pypeaday [2]: https://github.com/pypeaday/tdarr
If you’re into interesting projects, don’t miss out on skedulord [1], created by koaning [2]. captures logs and makes cron more fun References: [1]: https://github.com/koaning/skedulord [2]: https://github.com/koaning

How I Quickly Capture Screenshots directly into My Blog

When I am creating blog posts it’s often helpful to add screenshots to them to illustrate what I see on my screen. Sometimes I lack good screenshots in my posts because it just takes more effort than I have in the moment, and I prioritize making content over making perfect content. Making Screenshots # [1] When I have something to take a screenshot of, I need to take the shot, optimize the image, often convert it to a better format, publish it, and create a the img tag in my blog. - take screenshot - optimize - conversion - publish - create img tag Created in 🐍Python # [2] I created this tool for myself in python because that is what I am most familiar with, but realistically most of what I am calling are shell scripts that I could do in just about any language. Install my screenshot tool # [3] My screenshot tool is quite hacky and not configurable, but works wonderfully for me. If you like it and want to use it, make it configurable or fork it. For now it lives on GitHub...
3 min read

Copier < 6.0.0b0 considered dangerous

Copier is a fantastic templating library written in python, but older versions have a dangerous bug if you are using it inside of existing directories. !!UPDATE # [1] As of May 15, 2022, the stable release of copier now includes these changes, if you have not already make sure you update. This is a PSA # [2] I Use copier several times per day and get fantastic benefit from this project, this post is not intended to crap all over copier in any way, but is rather a PSA for other users who do use copier like I do so that they know the dangers of using copier inside an existing directory. The issue # [3] The fix # [4] https://github.com/copier-org/copier/pull/273 As of the time of writing this version is still in beta, if you still want to use copier with existing directtories, I’d strongly encourage you to install the --pre release. pipx install copier --pip-args='--pre' confirm # [5] copier --version # copier 6.0.0b0 My update commit # [6] https://github.com/WaylonWalker/de...
nvim-notify [1] by rcarriga [2] is a game-changer in its space. Excited to see how it evolves. A fancy, configurable, notification manager for NeoVim References: [1]: https://github.com/rcarriga/nvim-notify [2]: https://github.com/rcarriga
I came across smart-sec-cam [1] from scottbarnesg [2], and it’s packed with great features and ideas. A privacy-focused, intelligent security camera system. References: [1]: https://github.com/scottbarnesg/smart-sec-cam [2]: https://github.com/scottbarnesg
Current /carry April 2022
EDC from April 2022
I came across cli [1] from httpie [2], and it’s packed with great features and ideas. 🥧 HTTPie CLI — modern, user-friendly command-line HTTP client for the API era. JSON support, colors, sessions, downloads, plugins & more. References: [1]: https://github.com/httpie/cli [2]: https://github.com/httpie

PyOhio CFP's

Here are some CFP’s that I used for PyOhio 2022. https://pretalx.com/pyohio-2022/cfp Idea to blog post in minutes - Shorter # [1] Markata is a plugins all the way down static site generator, that covers all the things you need to go from markdown to a blog site out of the box. Since it’s plugins all the way down you can also rip out all the default plugins, and do something completely different with the lifecycle. Lets build a whole blog site in 5 minutes. Add Kedro to your Pandas Workflow - Short # [2] Sometimes python scripts/notebooks take a long time to run, let kedro automatically save your datasets so that you can maintain your production code with ease. Lets take a pipeline with an issue 30 minutes in and solve the issue in 5 mintues. References: [1]: #idea-to-blog-post-in-minutes---shorter [2]: #add-kedro-to-your-pandas-workflow---short
Check out nbdd0121 [1] and their project wsld [2]. WSL Daemon - Stable X11 connection and time synchronisation for WSL2 References: [1]: https://github.com/nbdd0121 [2]: https://github.com/nbdd0121/wsld
Just starred dunk [1] by darrenburns [2]. It’s an exciting project with a lot to offer. Prettier git [3] diffs in the terminal 🎨 References: [1]: https://github.com/darrenburns/dunk [2]: https://github.com/darrenburns [3]: /glossary/git/
If you’re into interesting projects, don’t miss out on dagger [1], created by dagger [2]. An engine to run your pipelines in containers References: [1]: https://github.com/dagger/dagger [2]: https://github.com/dagger
Gramformer [1] by PrithivirajDamodaran [2] is a game-changer in its space. Excited to see how it evolves. A framework for detecting, highlighting and correcting grammatical errors on natural language text. Created by Prithiviraj Damodaran. Open to pull requests and other forms of collaboration. References: [1]: https://github.com/PrithivirajDamodaran/Gramformer [2]: https://github.com/PrithivirajDamodaran
I like WaylonWalker’s [1] project markata [2]. A plugins all the way down static site generator written in python. Plugins all the way down means that you can completely change the behavior of how it works by swapping plugins, installing new ones, or creating your own all in python. References: [1]: https://github.com/WaylonWalker [2]: https://github.com/WaylonWalker/markata
Check out eyeseast [1] and their project python-frontmatter [2]. Parse and manage posts with YAML (or other) frontmatter References: [1]: https://github.com/eyeseast [2]: https://github.com/eyeseast/python-frontmatter
I came across awesome-tuis [1] from rothgar [2], and it’s packed with great features and ideas. List of projects that provide terminal user interfaces References: [1]: https://github.com/rothgar/awesome-tuis [2]: https://github.com/rothgar
I’m impressed by markdown-styles [1] from mixu [2]. Markdown to static HTML [3] generator and multiple CSS themes for Markdown References: [1]: https://github.com/mixu/markdown-styles [2]: https://github.com/mixu [3]: /html/