Preflight part 2

I have continued to work on my Preflight script over the last day or two. After I posted about it I changed the output using the Rich library to add some command line pizzaz to it.

Jazz hands!

The new layout uses the Box layout object in Rich to draw an ASCII style box around the output. There are 19 different styles that you can use and those styles also apply to the Table object.

More code

After I was finished with the first version of the script I decided to add a new feature. I wanted to display a table with all of the Markdown files and an indicator of the draft status of each file. It seemed as if the simplest was to enable this was to presume that the user wanted this preflight table unless they used a -f flag and then provided a file name. So it was off to argparse to see what I could do to enable that.

The file already had a positional filename argument declared so I removed that and added an entry for the new flag.

1parser.add_argument(
2    "-f",
3    "--filename",
4    type=str,
5    help="The name of the markdown file.",
6    required=False,
7    default="all",
8)

So if no flag is sent then the argument defaults to the value all and this is what we can use to test to see if the user has supplied the flag and a filename.

1if args.filename == "all":
2    preflightAll(args.content)
3else:
4    preflightFile(args.content, args.filename)

split

I am not a fan of big files. I find then difficult to navigate and I also find that there is often no reason for them. When possible I like to split logical sections of code out into their own files. In this case I added _preflight_all.py and _preflight_file.py to hold the code for each case. Those functions need to be imported before they can be called.

1from _preflight_file import preflightFile
2from _preflight_all import preflightAll

The _preflight_file.py file now has the original logic I wrote previously and _preflight_all.py has new code to read through the directory and then pull in the frontmatter from each file to create a table.

The table is built using the Rich Table object. The documentation implies that you need to print it to a Rich Console object and that is what I have done in my code.

1    console = Console()
2    table = Table(title="Blog post status")
3
4    table.add_column("Title", justify="left")
5    table.add_column("Status", justify="center")

The Table is as easy to use as that. Ironically, it is perhaps the simplest display object in Rich to use.

With the table started the code then gets all of the Markdown files in the directory and then gets the title and draft values from the frontmatter. In any other language you would probably have to test the files but python has the delightful glob function. Combined with sorted() it means that a single line gets me an alphabetical list of all of the Markdown files. The frontmatter library loads each file and then extracts the YAML. This is used to then create each row in the table.

 1    mdFiles = sorted(filePath.glob("*.md"))
 2
 3    for post in mdFiles:
 4        blogPost = frontmatter.load(post)
 5        status = blogPost["draft"]
 6        title = blogPost["title"]
 7
 8        # make a table row
 9        displayItem = Text("◼︎", style="green4")
10        if status:
11            displayItem = Text("◼︎", style="red3")
12
13        table.add_row(title, displayItem)
14
15    console.print()
16    console.print(table)

Giving this delightful display.

A table

The only complication in the entire file was iterating over the sorted list. I was trying to use with and it wasn’t working correctly. I am not sure why but that is the reading assignment for this evening.

As with all my other coding projects, I used Jupyter Library to fiddle with code until I determined what I needed to use to get the results I wanted. It is an eminently valuable tool.

Next I will be adding a flag to just show a table of the files that are drafts. I need to read through the argparse docs to see how to make a flag a condition of the positional argument.