Groundhog Day Resolutions - May 2021

April turned out to be even busier than March, so I wasn't able to spend as much time on personal projects as I would have liked.

April's primary goals

1. Create a playable prototype of something

I have the basics of a text adventure engine working, but there's a lot more to do before I'd consider it playable.

2. Release the new version of Craft Roulette

Didn't even touch this. Not a huge loss, but I really wanted to get it done and off my list.

3. Contribute to another free software project

I contributed some changes to zetteldeft.

April's secondary goals

1. Run 115 miles

I stuck pretty close to my running plan, with only a few exceptions due to injury. I feel like I peaked a little early, but we'll see how things go on race day.

2. Plan version 1.1 of Writing PHP with Emacs

I have a list of things I want to include in version 1.1, and I've started research for this new content.

Primary goals for May

1. Run a marathon

Due to Covid-19 this was delayed by two months, so I've been training in some form or another for six months now. It's still not going to be quite what I wanted (no crowds are allowed at the finish) but at least I won't be alone this time.

Secondary goals for May

1. Write more

The last few weeks have been pretty slim on writing. I have a dozen or so post ideas, but inspiration really dried up as work got busier. I'd like to get back in a decent rhythm this month.

2. Finish my Atari ST text adventure

I have some ideas for it, and I have the basics of the engine down. There are still lots of puzzles to create - and a lot of writing to do - but it's getting there. I'd like a playable version online by June.


Automatically changing an org task's state when clocking time

In "how I get work done with Emacs and org-mode" I talked about how I manually switch a task to IN-PROGRESS when I start working on it. It's not a huge inconvenience, but I did wonder if I could configure Emacs to do it for me.

Of course there's a feature for that.

There are two variables that can be used to configure org's behaviour when clocking time:

org-clock-in-switch-to-state
The state to change a task to when clocking in.
org-clock-out-switch-to-state
The state to change to when clocking out.

Both of these variables can either be a string which will be the new state, or they can be a function. If they're a function it must accept ONE parameter - the task's current state - and return the state to switch to.

In practice it looks like this:

;; Always change the task to IN-PROGRESS.
(setq org-clock-in-switch-to-state "IN-PROGRESS")

;; Use a function to decide what to change the state to.
(setq org-clock-in-switch-to-state #'sodaware/switch-task-on-clock-start)

(defun sodaware/switch-task-on-clock-start (task-state)
  "Change a task to 'IN-PROGRESS' when TASK-STATE is 'TODO'."
  (if (string= task-state "TODO")
      "IN-PROGRESS"
      task-state))

It's a small change, but it smooths out a slight wrinkle in my workflow.


How I get work done with Emacs and org-mode

I've been a freelance developer for 12 years, and Emacs has been at the center of my working environment for 10 of those. I use it for a lot of things - including writing this post - but today I'm concentrating on my workflow.

Here's how I use Emacs and org-mode during a regular day.

The packages

There are two of packages that are central to my daily routine: org-mode and projectile.

org itself is a text markup language with a lot of extras that make it great for organizing work. org-mode allows Emacs to extract this information and use it for scheduling tasks, estimating task effort, tracking time, and a whole bunch of other things. I remember reading that org is a gateway drug that leads to Emacs - that was certainly the case for me.

projectile adds functions for navigating between projects and files. A project in the world of projectile is a file directory, which is usually a git working directory in my case. In a typical day I can work on a dozen different projects, so being able to quickly jump between them is extremely helpful.

I use a lot of other packages when doing actual work, but these two keep me organized and allow me to quickly get to where I need to be.

The setup

All of my org files live in "~/Documents/org/" and are synchronized between my desktop and laptop.

Each client has their own .org file with headlines for each project that I'm working on. I also have inbox.org which I use for capturing new tasks, and goals.org which contains my monthly goals.

Major personal projects also have their own org files, although I'm slowly transitioning to per-project "TODO.org" files instead.

All of these files are added to the org-agenda-files list so that they show up in my org agenda.

;; For Emacs versions < 25
(setq org-agenda-files
      (find-lisp-find-files "~/Documents/org" "\.org$"))

;; For version >= 25
(setq org-agenda-files
      (directory-files-recursively "~/Documents/org/" "\\.org$"))

Update: thank you to kaiwen1 on reddit for letting me know about directory-files-recursively.

The agenda

The org agenda is a powerful way to display tasks from across multiple files. Agendas can be filtered to a time period, urgency, project, and much more.

My daily agenda looks something like this 1:

An example org-agenda

This view has 5 columns that display the following information:

  1. Category - For freelance clients I use the client name, followed by the project. This looks something like client:project. Personal projects use just the project slug.
  2. Estimate - I try to keep individual tasks on this list to under 2 hours. If it's longer than that, it probably means I haven't broken it down enough.
  3. Scheduled date or deadline - When this is task is due or if I've scheduled it for a particular day.
  4. Task name - This contains the task status, its priority, and its name.
  5. Tag - This is used to identify project and client tasks, and also to store my monthly goals. I used to use this for GTD-style contexts, but seeing as 99% of my work is at the computer I didn't get much use from it.

The configuration for these columns is fairly simple:

(use-package org-agenda
  :after org
  :custom
  (org-agenda-prefix-format '((agenda . " %i %-20:c%?-12t%-6e% s")
			      (todo   . " %i %-20:c %-6e")
			      (tags   . " %i %-20:c")
			      (search . " %i %-20:c"))))

And the actual agenda configuration (without the code to display my monthly goals) looks like this:

(setq org-agenda-custom-commands
      '(("d" "Today's Tasks"
	 ((agenda "" ((org-agenda-span 1)
		      (org-agenda-overriding-header "Today's Tasks")))))))

To view my daily agenda, I'll run M-x org-agenda (which I have bound to C-c a) and then select d for the "Today's Tasks" view. It shows me everything I have scheduled for the day, as well as due and upcoming deadlines.

The day plan

At the start of the day I'll open my agenda and choose which tasks to work on, based on due date and priority. I'll then block out time to work on them on my paper day plan. I'll always leave some extra room for tasks that will pop up during the day.

The day planner itself is really simple and looks a bit like this (shortened to save space):

  Monday Tuesday Wednesday Thursday Friday
9-10 Task A        
10-11 Task B        
11-12 Task C        
12-1 Lunch        
1-2          
2-3 Task C        

I split my work day into blocks of one hour to make things easier; I've tried slots of 30 minutes long, but that felt less flexible and quickly fell apart if something came up. I use red for billable tasks, green for personal projects, and orange for essentials like exercise and eating.

Although org-agenda can be used to create day plans that are similar to this, I prefer having a paper copy in front of me. It lets me get a quick overview of how busy the day is going to be, as well as how much is going to be spent on billable time vs personal projects.

Adding new tasks

I generally deal with two kinds of task: proactive, and reactive.

Proactive tasks are things I've already planned out; I can choose when to work on them, and I know when they're due and what urgency level they are.

Reactive tasks are when emails/calls/chat messages come in and I need to do something about them. They may be urgent and need doing ASAP, or they may end up on the proactive list.

We'll start with reactive tasks first.

An example non-urgent request would be something like "We're wanting to add a new report to <product> by next month. Design and documentation attached"2.

I'll open up the org file for this client, jump to the appropriate project node, and add a new sub-task for this request. In this example it would look a bit like this:

* TODO Create new "days without an accident" report [0/4]
  DEADLINE: <2021-04-30 Fri>
** TODO Email person re: new report
   SCHEDULED: <2021-04-15 Thu>
** TODO Create markup for new report
** TODO Add data backend to new report
** TODO Deploy new report to staging for tests

I'd also break down each sub-task into individual steps and add estimates, but that's a topic for another day.

Once this is done, the first task will show up on my daily agenda. My weekly agenda will also have a reminder that there's an upcoming deadline.

For scheduling proactive tasks I'll read through my list of tasks and assign dates as needed. org-agenda can search for top-level TODO items and filter them by category and context. It can also list "stuck" projects that don't have an assigned next action.

Working on a task

When it's time to work on a task, I'll use org's clock timer to track the time I spend on it. Starting work looks like this:

  • I highlight the task in the agenda.
  • Hit <enter> to jump to its entry in the appropriate file.
  • Switch the task to IN-PROGRESS.
  • Start clocking time with C-c C-x C-i.
  • Navigate to the project with C-c p p.
  • Choose the file I need to be working on and start.
  • Use C-c C-x C-o to stop the clock once I'm done or need to switch.

I know all the previous steps sound like a lot, but going from my agenda to working on a task only takes a few seconds.

Emacs also supports bookmarks, so if I want to start on something immediately the next day, I'll leave a bookmark in the right spot so I can jump straight to it.

Tasks in org have a keyword at the start to indicate their status. I use the following keywords:

  • TODO - A task that I need to do.
  • IN-PROGRESS - A task that I've started and is actively being worked on.
  • TESTING - A task that is being tested and reviewed by the client.
  • WAITING - A task where I'm waiting on something - could be more information about what needs doing, or it could need an external party to review it.
  • TO-DEPLOY - It's done and ready and waiting to deploy at a specific date & time.
  • DONE - It is done and nothing needs doing on it again.
  • CANCELLED - The task/project was cancelled for one reason or another.

Because org-agenda can search for keywords, it's easy for me to check for various tasks during my weekly review. For example, I can check through the WAITING list and see if I need to follow up on anything.

I also use org for detailed project planning; it's great for breaking down a task into chunks, adding estimates, and assigning to milestones. But this post is already boring long enough so I'll save that for another day.

~~~
If you found this helpful and would like to read more content like it, follow me on Twitter.

Footnotes:

1

I've been doing this job for 12 years but it's really hard to come up with imaginary tasks.

2

At least with made up examples they include all the info I need first time.


Moving text around in Emacs using move-text

move-text is a simple Emacs package that lets you move a line or region around using M + and M + . It's not limited to plain text buffers - you can move lines of source code around too.

In practice it looks like this:

Moving text around

I prefer to use Control + Shift with the up and down arrow keys, so my configuration looks like this:

(use-package move-text
  :bind
  (("C-S-<up>"   . move-text-up)
   ("C-S-<down>" . move-text-down)))

Cutting and pasting a region is usually quicker, but for shuffling a few lines around this method is quick enough.


Groundhog Day Resolutions - April 2021

March was a very busy week for freelance development, so it was hard to make time for a lot of these.

March's primary goals

1. Finish version 1.0 of Writing PHP with Emacs

I added the final chapters on setting up Emacs for WordPress, Symfony, Drupal, and Laravel development. There are some more details I want to add, but the basics are done.

2. Complete another session of deliberate practice

I created a small animation test using GodLib, a C library for creating Atari ST games and demos. It was much closer

3. Finish version 0.3 of Craft Roulette

The final part of the "add craft" form is complete and everything is ready for production.

4. Contribute to a free software project

I contributed some changes to the BlitzMax website and I'm working on some additions to Zetteldeft.

March's secondary goals

1. Run 120 miles

One run was canceled due to storms, but outside of that I stuck to my plan. I don't feel fitter, but my times have improved from last year so something must be working.

2. Read a book

I didn't even pick up a book, let alone read one.

3. Add detail pages to my secondary goals

I added pages for a handful of goals, but not enough.

Primary goals for April

1. Create a playable prototype of something

There are a couple of little demos I've been working on and want to finish up. I'd like to release something playable in April.

2. Release the new version of Craft Roulette

It's ready for release, but I'll probably polish a few more bits and pieces before deployment.

3. Contribute to another free software project

I was working on a couple of extra changes this month, and there are some other projects I've seen that I'd like to contribute to.

Secondary goals for April

1. Run 115 miles

April is the peak of my long runs, followed by tapering before race day. I am ready for training to be over.

2. Plan version 1.1 of Writing PHP with Emacs

There are plenty of parts of the book I want to improve, and there are some new chapters I want to write. By next month I'd like to have a roadmap of future improvements.