#python Page 1 of 1 (8 posts) — ArchiveFeed

Blogging is low on the priority list at the moment, thanks to school. The preliminary classes for the master’s degree are going well. I’m writing assembly for my computer systems class, and I have to say, I really like assembly. (No sarcasm.) It’s beautiful and simple in a way I didn’t expect. I don’t see myself using it much, but it’s a good tool for the belt.

Unrelated to school, I’ve been dabbling more with Rust and Go. I’m not a huge fan of Go’s syntax, but I’m going to write a few web services in it — maybe a replacement engine for this blog — and see if my opinion changes. (The goal is to see if single-binary deployment is worth it, as an alternative to Python and Django for small web things.)

Rust, on the other hand, hits a sweet spot for me with general syntax and with language features (pattern matching, particularly). I can easily see myself using it for anything where I would have used C or C++. (And it has more promise than D or Nim.) The plan is still to use Rust when I finally get around to writing Ink and related tools.

(I should probably add that I still plan to keep using Python, though perhaps not as often. We’ll see.)

Oh, one last thing: with Press, I realized a few days ago that it’s a good candidate for the first implementation of Low Ink (a JSON-based page description language that compiles to PDF). I’ll be re-architecting that part of Press so that it uses Low Ink. Also hoping to finish up the text part of Press (HarfBuzz, etc.) soon so that it’s usable for more than just basic drawing. (I’m dealing with font subsetting and encoding stuff at the moment.)

I’ve renamed inkpdf to Press (as in printing press).

I reached the point where creating the PDF manually is no longer feasible, so I’ve been working on getting Press to a point where I can implement the PDF generation. The basic structure is in place, sans the PDF part. (That’s next.)

Here’s what a Press script looks like right now:

from press import Press

p = Press('output.pdf', width=6*Press.INCH, height=11*Press.INCH,
          margin=1*Press.INCH)

# Horizontal borders at top and bottom of page
p.stroke('#000')
p.pen(1.0)
p.line(p.page_min_x, p.page_min_y, p.page_max_x, p.page_min_y)
p.line(p.page_max_x, p.page_min_y, p.page_max_x, p.page_max_y)

# Page 2
p.page(2)
p.layer('base')
p.stroke(rgb=(1, 0, 0))
p.line(150, 150, 300, 300)
p.layer('fg')
p.stroke(hsl=(0, 0.5, 0.8))
p.line(300, 300, 450, 150)

# Go back and add another line to page 1
p.page(1)
p.stroke('#025')
p.line(p.page_min_x, p.page_min_y, p.page_min_x, p.page_max_y)

p.save() # this doesn't work yet

You can also do something like this:

with Press('output2.pdf', size=Press.LETTER,
           margin=(0.5*Press.INCH, 1.0*Press.INCH),
           inner_margin=0.5*Press.INCH,
           outer_margin=1.25*Press.INCH,
           bleed=.125*Press.INCH) as p:
    p.line(50, 50, 250, 50)
    # And so on

(Context manager, inner/outer margin, bleed, built-in paper sizes.)

Up next: adding more primitives, designing the font selection mechanism, getting it to generate an actual PDF, embedding fonts, using arbitrary Unicode code points, integrating HarfBuzz, etc.

Lifter is “a lightweight query engine for Python iterables.” Looks nice. One of their examples:

# vanilla Python
results = [
    user for user in users
    if user['age'] == 26 and user['is_active']
]

# lifter
results = manager.filter(User.age == 26, User.is_active == True)

Momentum

I’m getting back into blogging about in-progress projects, because otherwise I hardly blog at all. Expect posts soon about the following coding projects, all at varying stages of completion:

  • Vinci (notebook app)
  • Bookshelf (successor to Bookkeeper)
  • Codex (successor to Unbindery)
  • Quill (successor to Codex, sort of)
  • Storybook (writing app)
  • Speed (desktop writing app)
  • Liszt (todo list app)
  • Endless (mindmapping app)
  • Botswana 2 (revamp of Botswana)

Brief sidenote: I switched a while back to Python/Django, and I’m very glad I did. I can often get to a working prototype within only an hour or two. Back in my younger days I wanted to write everything myself from the ground up, but I see now that I was foolish. Life is short. I’d rather focus on the interesting parts — the app itself — and let the framework handle the routine grunt work.

Momentum

Momentum is the app I’d like to introduce today. It’s a web app written in Django, started back in January to help me track my goals.

More specifically, I wanted something that would help me spend more time reading scriptures and writing fiction. I don’t always have a free half-hour, though, so I needed something to track little bits of time throughout the day, and Momentum was born. I’ve been using it pretty much every single day since then.

Here’s what it looks like on my phone (with dummy data):

momentum.png

Some quick notes:

  • It currently supports tracking minutes, times, or words per day.
  • When I reach a particular goal, it disappears from the list for the rest of the day so I can focus on the goals I haven’t yet reached. (This is a change I made last night, actually.)
  • If I don’t make any progress toward a goal at all within a set time period, the goal goes stale and turns red. (There’s a system-wide stale period setting and each goal can also have its own.) I started using this staleness idea in Bookshelf (more on that in a later post) and it’s been motivating enough that I ported it to Momentum.
  • It supports folders. I have Projects and Health folders, where I have specific projects (stories/apps I’m working on), and things like squats and pushups.
  • Right now you have to add/edit goals via the Django admin. It works but isn’t as nice as something in-app. I just need to get around to doing this, since this is the main thing keeping it from being releasable.
  • The code is on GitHub as usual. Again, this is unreleased, in-progress code, YMMV, grain of salt, etc.

Fledge

Introducing Fledge, a file processing language/shell written in Python. I wrote it for two reasons: first, as an experiment with an idea that I’ll explain in a moment, and second, because I can’t for the life of me ever remember how to do batch find-and-replace in text files on the command line. (And yes, I could have written a script to help me with the latter. In fact, I did. I just can’t ever remember what it’s called. I … may have issues.)

Anyway, the idea is that you select the files first, then execute one or more actions on them, rather than the normal way round. For example:

with my-book.text
split on /CHAPTER/ to chapter-%%.text
replace /CHAPTER/Chapter/
trim

That splits my-book.text out on a regex to chapter-01.text, chapter-02.text, etc., does a batch find-and-replace on all those chapter files, and then trims them of whitespace at the beginning and end of each file. The alternative would be something like this, assuming you had split, replace, and trim scripts:

$ split my-book.text "/CHAPTER/" "chapter-%%.text"
$ replace chapter-*.text "/CHAPTER/Chapter/"
$ trim chapter-*.text

So, instead of having to specify which files you’re working on at every step of the way, with Fledge you just do it at the beginning and that selection is used for whatever subsequent actions you perform.

Some more examples

with *.jpg where size != 0
rename page-%%%.text starting with 0

This gets all the non-zero image files in the directory and renames them sequentially to page-000.jpg, page-001.jpg, etc.

alias {mtp} ~/Documents/mtp
with **/*.jpg
convert to png
deselect DSC*
move to {mtp}

This finds all the JPEG files recursively under the current directory, converts them to PNG, deselects everything that starts with DSC, and moves the rest of the PNGs to ~/Documents/mtp.

More about Fledge

The fl script can either execute a script of Fledge actions contained in a file or, if you run it without arguments, it loads an interactive shell.

There are a number of built-in Fledge actions (listed in the README), mostly geared towards working with text and image files, but you can write custom actions (which live in ~/.fledge/actions) to do pretty much anything. (Keeping in mind that in general these would be things you want to do to a large number of files.)

How I’m using it

I use it to help prep image scans of journals and personal histories and stuff to upload to Unbindery for transcription (which, incidentally, I’ve been thinking about paring down to a much simpler, more focused app aimed at family history transcription). I also use it for ebook production (splitting Project Gutenberg files into chapters to be made into EPUBs, doing batch substitutions, etc.) and for Mormon Artist (resizing and renaming images, mostly).

So far, I like it. It’s still very much a work in progress (as I write this I’m realizing rename probably should be rename to for consistency), but I can actually remember these commands. And for situations where I’m doing a lot of sequential actions on multiple files (as in ebook production), it’s nice not having to re-specify everything every step.

Goodbye, PHP

Yesterday I came across an article on PHP’s bad design practices that woke me up a little. I started using Python a couple years ago on some projects and I’ve loved it. Pure delight. It’s not a perfect language, but it feels so good to me. Coding is more fun and things just come together. It’s uncanny.

I don’t know why I’ve put up with using PHP all this while. My sole reason for writing apps like Bookkeeper, Donne, and Unbindery in PHP instead of Python was that it’s easier for people to deploy PHP on shared hosting, but I don’t think that’s as much of an issue these days.

So, FYI, I’ll be using Python instead of PHP for coding projects going forward.

md2epub

An itch scratched: md2epub, a Python script for making an EPUB out of Markdown files.

All it takes is a simple book file, which gives the script some basic metadata about the book and then lists the files that need to be included. The script runs Markdown on the files and makes an EPUB.

# Sample book file for md2epub
# 9 Jun 2010

Title: My Sample Book
Author: John Doe
Language: en-US
URL: /books/my-sample-book/
CSS: content/style.css

# Chapters
Foreword | content/foreword.text
Chapter 1 | content/chapter_1.text
Chapter 2 | content/chapter_2.text
Chapter 3 | content/chapter_3.text

# Images to be included
Images: images/illustration1.jpg, images/illustration2.jpg
Image: images/illustration4.jpg

And then you just run “md2epub myfile.book” and voila, instant EPUB. I’ve already used it on my Pearl of Great Price reader’s edition (which I’ll be releasing shortly) and it works like a charm.

Last but not least, the code is based on my friend Matt’s script GetBook.py. (And, in fact, that’s where I got the idea for this script.)