So, after ditching pomodoros and creating ketchup.el I noticed a problem with my workflow. Let me start with explaining what it looks like. Warning: a long-ish story follows.
When I’m at the office and I’m “in the flow”, it doesn’t bother me that instead of taking a break after 25 minutes, I work for, say, 35 minutes. But the situation is very different in the morning. For over 3 years now I’ve been using a system where I plan my morning very precisely – it is an extremely valuable time, since everyone else at home is sleeping and so I can focus. Also, my morning schedule is very repetitive now (which I consider a good thing). Of course, it’s all tied to Beeminder and my personal productivity system, so – for example – today (when I’m writing this) I have to weigh myself before 5:15, then spend 25 minutes writing before 5:45, then spend 25 minutes learning before 6:15, and then buy groceries before 6:45. This is all quite optimized – for example, the grocery store where I live opens at 6:00, but experience taught me that sometimes many customers come exactly then, so I have to wait in a line. By trial and error I found out that at about 6:15-6:25 there are usually fewer customers there, so I planned my morning around that fact to minimize time spent waiting in the line. After I’m back with the groceries, I commit the changes in my Org mode files to Git and run my backup script so that my files are safe, take a look at my Org agenda for the day and that’s it – when all this is done, my son needs to get up, eat his breakfast etc. in order to get to school on time, so the focused time is over. The next item in the schedule is leaving home with him until 7:25 – we have about 4 minutes to get to the bus stop and the bus to school leaves at about 7:30-7:32 (depending on the traffic), so we have a small buffer (and in fact, catching the next bus is also enough to get to school on time, so the buffer is actually even a bit larger). You get the idea – this is all very thoughtfully planned. And before you raise the objection that I’m making a robot out of an 8-year-old kid, let me assure you that I’m not – I’m also doing my best to stay flexible, so that if something unexpected happens (and it sometimes does) and we leave home at 7:35 instead of 7:25, that’s ok, too. The lesson for my boy is not “we have to stick to our schedule no matter what”, but rather “this schedule exists so that we don’t have to be nervous about getting to school on time” and “it has buffers built-in so that even if we leave 10 minutes later, we’ll still get there before the classes begin”. (Also, “a bit of play time is also included, even in the morning before school”, which teaches a great lesson – if you plan your time well, mornings can be also fun instead of just stressful!) In fact, this very rigid structure does not make me feel like a mindless robot following orders even if it’s followed to a minute. Quite the contrary – it gives me very nice feeling of satisfaction and a huge motivation boost. Looking past my morning at about 6:15 every morning and realizing that I spent almost an hour working on projects I find personally valuable (95% of the time, I work on my personal things in the mornings) feels great. Before I implemented this system, it sometimes happened that I managed to get up early, all pumped up about how the morning is going to be productive, and then wasted half of it reading emails or thinking what I should do next. That was very frustrating! Now I hardly ever need to make these decisions – they are already made the day before, so I don’t suffer from analysis paralysis. Also, instead of a giant, terrifying deadline for some project looming a few weeks (or months) from now, I have a small and friendly deadline every morning. (“Friendly” here means that if I occasionally miss it by getting up later or just being lazy and not doing what I have planned, it doesn’t really matter much – my projects move on every week anyway, so not working on them for one day every few weeks is nothing bad.) This way I get all the good things deadlines bring (a feeling of motivation and urgency) without the bad things (serious consequences of missing them). What’s not to like?
Ok, back on topic. Can you see where the problem is? Now that I don’t use tomato.el anymore, I don’t get the notification that 25 minutes have passed since I started working. But that is crucial in the morning, since then I don’t have the luxury of working longer than these 25 minutes. On the other hand, this is explicitly what I don’t want when I’m at the office!
My first thought was to use the Org timer and start it manually when I start working in the 25-minute slot in the morning. I added this lambda to my Org-related hydra:
(lambda () (interactive) (when org-timer-start-time (org-timer-stop)) (org-timer-set-timer 25))
(I probably should have made it a named function – I don’t usually like interactive lambdas, but I find them acceptable in places like hydras.) It’s a simple wrapper around Org timer, always setting it to 25 minutes. It’s far from ideal, though. When a timer is already running, it just cancels it and says “Timer stopped”. What if I have a timer (for some reason) and don’t want to cancel it? And even if not, I don’t like polluting the echo area and the *Messages*
buffer. The most important problem, however, is that I need to remember to use it.
Of course, then it hit me. This is Emacs, folks! It can do whatever I want! Why not retain the notification after 25 minutes, but only, say, when starting clocking on a ketchup-enabled goal between 4:00 and 8:00? (I very rarely start working before 5:00, but sometimes I do, so let’s have a nice buffer even if for some reason I start working really early. Also, at 8:00 I’m usually on my way to the office, so it seems a nice cut-off moment between the “work in shorter bursts before actual work” and “more time do do focused stuff at work”.) Of course, I don’t want to make this part of ketchup.el
, it’s extremely specific to my personal workflow, and ketchup.el
might be useful for someone else. How do I do that? I could reuse the Org timer (again), with its drawbacks I mentioned, or I can set up a generic Emacs timer to do what I want (like I did with tomato.el). At first, I wanted to go with the Org timer because it’s simple and the probability that I use it for anything else early in the morning is extremely low. Then I took a look at org-timer.el
and org-clock.el
and decided that run-with-timer
is simple enough that I would use it.
My code here is very simplistic and proof-of-concept-ish. For example, I decided against turning the feature into a minor mode. As I said, this is something that I don’t expect anyone but me to use, and I don’t expect myself to ever want to turn it off, so there’s no point. The code only supports starting and ending the “morning” at full hours (4 and 8 in my case). On the other hand, I decided not to hardcode these hours and make them into a defcustom
– if I ever want to change these hours, I won’t have to look for them in the code, they’ll be easy to find.
(defcustom ketchup-morning-morning '(4 . 7) "Hours demarcating the morning, as a cons.") (defvar ketchup-morning-work-stretch (* ketchup-stretch-duration ketchup-stretch-step)) (defvar ketchup-morning--timer) (defun ketchup-morning-run-timer () "Run a 25 minutes timer, but only between in the morning." (when (and (org-entry-get (point) "ketchup" t) (<= (car ketchup-morning-morning) (decoded-time-hour (decode-time (current-time))) (cdr ketchup-morning-morning))) (setq ketchup-morning--timer (run-with-timer (* ketchup-morning-work-stretch 60) nil #'org-notify (format "%s minutes have passed" ketchup-morning-work-stretch) org-clock-sound)))) (defun ketchup-morning-cancel-timer () "Cancel the morning ketchup timer" (when (timerp ketchup-morning--timer) (cancel-timer ketchup-morning--timer))) (add-hook 'org-clock-in-hook #'ketchup-morning-run-timer) (add-hook 'org-clock-out-hook #'ketchup-morning-cancel-timer) (add-hook 'org-clock-cancel-hook #'ketchup-morning-cancel-timer)
As you can see, nothing really mysterious happens here. As usual, if you think you’d like to be able to code little sweet utilities like this for yourself, I highly recommend two sources – the fantastic book Introduction to programming in Emacs Lisp by the late Robert J. Chassell, which will teach you the basics of Emacs Lisp, and my ebook Hacking your way around in Emacs, which covers some more advanced stuff (and comes with a 60-days refund policy in case you are disappointed with it).
Have fun using Emacs and automating your workflow!
CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode