↓ Skip to Content Start of content

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.


Configuring bug-reference mode from within org-mode

A few weeks ago I learnt about bug-reference-mode, a neat little Emacs minor-mode that automatically links text to a bug tracker. A few of my projects use bug trackers or GitHub issues, and different clients often have their own systems.

There are two variables that I usually want to set for bug-reference-mode:

bug-reference-url-format
The URL of an individual bug, with %s used as a placeholder for the bug ID.
bug-reference-bug-regexp
The regular expression that finds bug ID references. This is usually something like #1234.

I use directory local variables1 for a lot of projects, but Emacs also supports file local variables for more fine-grained settings. org-mode has its own syntax for setting file local variables, so I needed to adjust things slightly to get it all working.

Setting local variables for a bug tracker looks like this:

# Local Variables:
# mode: org
# bug-reference-url-format: "https://example.org/tasks/%s"
# bug-reference-bug-regexp: "\\(#\\)\\([0-9]\\{8\\}\\)"
# End:

On my first attempt I skipped the Local Variables: and End: keywords, but they are needed for org to pick these variables up.

Footnotes:

1

These are variables that are set for all files in a directory and its sub-directories.


Extracting zetteldeft notes

I've been using zetteldeft to manage my notes for about six months now. Recently I've been wanting to reorganize my notes as some of them don't follow the zettelkasten principal of one idea per note.

Okay, most of them don't follow that principal if I'm honest about it.

I wanted to slice up my existing notes into smaller files and then link them all together. In my mind the process would go something like:

  1. Highlight the region to extract.
  2. Enter a title for the new note.
  3. Emacs would automatically move the text to the new note and insert a link where it used to be.

Emacs macros are handy for this kind of repeatable behaviour, so I started recording with an example note.

However, I quickly ran into a roadblock due to zetteldeft's behaviour when creating a new note. zetteldeft will create a file, insert the title, and save the file name to the Emacs kill ring. This meant any text I'd copied would be overwritten by the note title.

I decided to abandon the macro method and use a dedicated function instead. I wrote a little function called sodaware/zd-extract-region-to-note that extracts a highlighted region to a new note:

(defun sodaware/zd-extract-region-to-note (title)
  "Extract the marked region to a new note with TITLE."
  (interactive (list (read-string "Note title: ")))
  (let* ((deft-use-filename-as-title t)
	 (note-id (zetteldeft-generate-id title))
	 (note-filename (concat note-id zetteldeft-id-filename-separator title))
	 (note-text     (kill-region (region-beginning) (region-end))))
    (save-excursion
      (deft-new-file-named note-filename)
      (zetteldeft--insert-title title)
      (insert "\n\n")
      (yank)
      (save-buffer)
      (when (featurep 'evil) (evil-insert-state)))
    (sodaware/zd-insert-link note-filename title)))

(defun sodaware/zd-insert-link (note title)
  "Insert a link to NOTE with TITLE as its link text."
  (interactive)
  (insert (format "[[zdlink:%s][%s]]" note title)))

I use the zdlink protocol for my links, but the sodaware/zd-insert-link function can be modified to use any kind of link. Eventually I'd like this to be controlled via a variable.

I'd also like a function that returns focus to the original note after extraction, but for now I'm pretty happy with how things work.


Displaying my monthly goals in org-agenda

Each month I set primary and secondary goals as part of my Groundhog Day Resolutions process. Setting goals is good, but I have a nasty habit of forgetting about them until a few days before they're due. Not good.

To combat this issue I wanted to add my goals somewhere I would see them every day: my org agenda.

My daily agenda display currently looks like this (minus client/private tasks):

My initial org-agenda

I wanted to keep the same agenda information, but with my monthly goals at the top so that I can't ignore them.

Thankfully org-agenda can be configured to show different views and agendas via the org-agenda-custom-commands variable.

The first step was to create a place to store my goals. I created an org file with TODO entries for each goal, all stored under a headline for the month. These entries are tagged with :GHD: so they can be filtered, and I added an :ACTIVE: tag for the current month.

The finished goals.org is laid out like this:

* TODO March 2021 [0/7] :GHD:ACTIVE:
** TODO [#A] Finish version 1.0 of Writing PHP with Emacs
** TODO [#A] Complete another session of deliberate practice
** TODO [#A] Finish version 0.3 of Craft Roulette
** TODO [#A] Contribute to a free software project
** TODO [#C] Run 120 miles
** TODO [#C] Read a book
** TODO [#C] Add detail pages to my secondary goals

The tag properties are inherited from the parent for each child goal, which makes setting the active month much simpler.

My first attempt used A and B for the priorities, but org-agenda gives all tasks a priority of B by default so the month headline was showing in the final view. Using A and C for my primary and secondary goals fixes this.

The custom agenda is made up of three parts:

  1. A list of primary goals.
  2. A list of secondary goals.
  3. The regular org agenda which shows scheduled tasks and deadlines.

I used the tags-todo command to list goals; it can filter tasks by file, tag, and priority which makes it perfect for the job. The configuration to show my primary goals is fairly simple:

(tags-todo "GHD+ACTIVE+PRIORITY=\"A\""
	   ((org-agenda-files '("~/org/goals.org"))))

This displays all TODO items in my "~/org/goals.org" file that have :GHD: and :ACTIVE: tags AND a priority of A. To display secondary goals, all I need to do is replace the priority with C.

After the tags-todo command I use the agenda command with the timespan set to one day/one week depending on the view.

The finished configuration looks like this (with a little modification for brevity/online readability):

(setq org-agenda-custom-commands
'(("d" "Today's Tasks"
	((tags-todo
	  "GHD+ACTIVE+PRIORITY=\"A\""
	  ((org-agenda-files '("~/org/goals.org"))
	   (org-agenda-overriding-header "Primary goals this month")))
	 (tags-todo
	  "GHD+ACTIVE+PRIORITY=\"C\""
	  ((org-agenda-files '("~/org/goals.org"))
	   (org-agenda-overriding-header "Secondary goals this month")))
	 (agenda "" ((org-agenda-span 1)
		     (org-agenda-overriding-header "Today")))))

  ("w" "This Week's Tasks"
       ((tags-todo
	 "GHD+ACTIVE+PRIORITY=\"A\""
	 ((org-agenda-files '("~/org/goals.org"))
	  (org-agenda-overriding-header "Primary goals this month")))
	(tags-todo
	 "GHD+ACTIVE+PRIORITY=\"C\""
	 ((org-agenda-files '("~/org/goals.org"))
	  (org-agenda-overriding-header "Secondary goals this month")))
	(agenda))))
)

I can now view a daily agenda using C-c a d, or a weekly one using C-c a w, and the agenda has both sets of goals at the top:

The new and improved org-agenda

Now I have no excuse for forgetting them.