Category Archives: emacs

Automatically revert buffers

If you want Emacs to automatically update a buffer if a file changes on disk, then add the following to your emacs config file

;; auto revert mode
(global-auto-revert-mode 1)

Of course, if your buffer has unsaved changes when the file changes on disk, then Emacs will prompt you and your changes won’t be lost.

This mode only applies to buffers associated with files on the disk, but I like to have my dired view updated if the contents of a directory change. This is accomplished with the following code:

;; auto refresh dired when file changes
(add-hook 'dired-mode-hook 'auto-revert-mode)

Speedy sorting in dired with dired-quick-sort

The package dired-quick-sort gives you a pop-up menu with lots of useful options to sort your dired view by name, time, size and extension, and optionally group all of the directories together at the top of the listing. This can be a bit fiddly and dired-quick-sort makes it really easy.

Install the package with

(use-package dired-quick-sort
  :ensure t
  :config
  (dired-quick-sort-setup))

and then hit S in a dired buffer to bring up the sorting menu. Your sorting choice is then remembered for new dired buffers.

Export org-mode headlines to separate files

I was recently managing a set of interviews and I had my notes on all of the candidates in a single org file, with each candidate under their own top-level headline:

* J Kepler
 - Nice work on orbits

* I Newton
 - Versatile
 - Hard to work with

* C Sagan
 - Good communication skills

However, I wanted to generate a separate pdf file for each candidate that I could circulate to interviewers (since each interviewer was only interviewing a subset of applicants).

I came across this stackexchange answer that demonstrated how to build a function to export top level headlines to separate files. There are a few variations on that page, and I put together the slightly tweaked version below. All of the credit goes to stackexchange user itsjeyd for a very detailed answer. In my version I hard code it to export to pdf, save the file first, and apply the export options from the parent file to each of the new files that are created. The new files have a name taken from the headline, with spaces replaced by underscores, unless the :EXPORT_FILE_NAME: property is set for a headline.

;; export headlines to separate files
;; http://emacs.stackexchange.com/questions/2259/how-to-export-top-level-headings-of-org-mode-buffer-to-separate-files
(defun org-export-headlines-to-pdf ()
  "Export all subtrees that are *not* tagged with :noexport: to
separate files.

Subtrees that do not have the :EXPORT_FILE_NAME: property set
are exported to a filename derived from the headline text."
  (interactive)
  (save-buffer)
  (let ((modifiedp (buffer-modified-p)))
    (save-excursion
      (goto-char (point-min))
      (goto-char (re-search-forward "^*"))
      (set-mark (line-beginning-position))
      (goto-char (point-max))
      (org-map-entries
       (lambda ()
         (let ((export-file (org-entry-get (point) "EXPORT_FILE_NAME")))
           (unless export-file
             (org-set-property
              "EXPORT_FILE_NAME"
              (replace-regexp-in-string " " "_" (nth 4 (org-heading-components)))))
           (deactivate-mark)
           (org-latex-export-to-pdf nil t)
           (unless export-file (org-delete-property "EXPORT_FILE_NAME"))
           (set-buffer-modified-p modifiedp)))
       "-noexport" 'region-start-level))))

Add multiple cursors with mouse clicks

I’ve written before about the wonderful multiple-cursors package. Usually I use it by hitting M-. (defined using the setup below) to fire off multiple cursors on successive lines or on successive occurrences of the current string (if some text is selected). I also use M-, if I want to remove some of those cursors. This covers 99% of my use of multiple cursors.

However, occasionally, the best way to get the cursors where you want them is with the mouse. With the following code, C-S-<left mouse click> adds a new cursor.

(use-package multiple-cursors
  :ensure t
  :bind (("M-." . mc/mark-next-like-this)
         ("M-," . mc/unmark-next-like-this)
         ("C-S-<mouse-1>" . mc/add-cursor-on-click)))

Some useful mu4e shortcuts

I wrote recently about setting up a custom key map, and there are a couple of shortcuts for mu4e functions that I use very often with that key map.

With the following code I define c in my key map to compose a new email. Since I previously set C-1 to be the prefix for my map, then C-1 c is the full keybinding. This works globally so I can start a new email from anywhere in Emacs with C-1 c.

I then supercharge the keybinding by using it to add a CC to an email if I am already composing one. This is done by binding C-1 c in the mu4e-compose-mode-map to message-goto-cc. So now C-1 c starts a new email unless I am already writing an email in which case it adds a CC instead.

While I am at it, I also add s to my keymap for mu4e-headers-search so I can use C-1 s to launch a search of my emails from anywhere in Emacs.

;; bjm-map is already  bound to the prefix C-1
;; use C-1 c to compose a new email
(define-key bjm-map (kbd "c") 'mu4e-compose-new)
;; use C-1 c for add cc if already in composition mode
(define-key mu4e-compose-mode-map (kbd "C-1 c") 'message-goto-cc)
;; add search
(define-key bjm-map (kbd "s") 'mu4e-headers-search)

Batch-edit file permissions in dired

I’ve written before about using the editing features in dired (AKA wdired) to do neat things like redirect symlinks. I recently discovered that by adding the following option to your emacs config file:

;; allow editing file permissions
(setq wdired-allow-to-change-permissions t)

then you can also edit the file permissions directly in the dired buffer.

Here’s a quick animated example where I want to set group write permissions for all the pdf files in a particular directory. I use several tools to make this really easy:

  1. I used dired-narrow to filter the view down to just the pdf files
  2. I use C-x C-q to make the dired buffer editable
  3. I move to the group write permission spot on the first line and then use multiple cursors to add a cursor for each line
  4. I hit w to set the write permission, RET to quit multiple cursors, and C-c C-c to make the change permanent

dired-file-permissions.gif

Customise the reply quote string in mu4e

You know the bit of text that appears before the quoted email when you reply to someone? Of course you can customise this in mu4e. By default a quoted reply will be preceded with something like

"On Mon, 30 Jan 2017, Joe Bloggs wrote:"

I wanted to include the time and email address of the sender, so I customised the variable message-citation-line-format as follows

;; customize the reply-quote-string
(setq message-citation-line-format "On %a %d %b %Y at %R, %f wrote:\n")
;; choose to use the formatted string
(setq message-citation-line-function 'message-insert-formatted-citation-line)

which translates to something like this

On Mon 30 Jan 2017 at 19:17, Joe Bloggs <joebloggs@domain.com> wrote:

The formatting options can be found by looking up the help for the variable with C-h v message-citation-line-format.

Sadly, this change broke my function to extract the sender name for my email template. Here is an updated version:

;; function to return first name of email recipients
;; used by yasnippet
;; inspired by
;;http://blog.binchen.org/posts/how-to-use-yasnippets-to-produce-email-templates-in-emacs.html
(defun bjm/mu4e-get-names-for-yasnippet ()
  "Return comma separated string of names for an email"
  (interactive)
  (let ((email-name "") str email-string email-list email-name2 tmpname)
    (save-excursion
      (goto-char (point-min))
      ;; first line in email could be some hidden line containing NO to field
      (setq str (buffer-substring-no-properties (point-min) (point-max))))
    ;; take name from TO field - match series of names
    (when (string-match "^To: \"?\\(.+\\)" str)
      (setq email-string (match-string 1 str)))
    ;;split to list by comma
    (setq email-list (split-string email-string " *, *"))
    ;;loop over emails
    (dolist (tmpstr email-list)
      ;;get first word of email string
      (setq tmpname (car (split-string tmpstr " ")))
      ;;remove whitespace or ""
      (setq tmpname (replace-regexp-in-string "[ \"]" "" tmpname))
      ;;join to string
      (setq email-name
            (concat email-name ", " tmpname)))
    ;;remove initial comma
    (setq email-name (replace-regexp-in-string "^, " "" email-name))

    ;;see if we want to use the name in the FROM field
    ;;get name in FROM field if available, but only if there is only
    ;;one name in TO field
    (if (< (length email-list) 2)
        (when (string-match "^On.+, \\([^ ,\n]+\\).+wrote:$" str)
          (progn
            (setq email-name2 (match-string 1 str))
            ;;prefer name in FROM field if TO field has "@"
            (when (string-match "@" email-name)
              (setq email-name email-name2))
            )))
    email-name))

A shortcut to my favourite org-mode agenda view

As I have mentioned before in my tutorial about todo lists and scheduled tasks in org-mode, my preferred way to view my agenda is to use C-c a n to view a list of my scheduled tasks with unscheduled tasks below that.

I wanted to make a shorter keybinding for this view and I found this advice on how to achieve this. We just need to define a simple helper function like so

;;keybinding for favourite agenda view
;; http://emacs.stackexchange.com/questions/864/how-to-bind-a-key-to-a-specific-agenda-command-list-in-org-mode
(defun org-agenda-show-agenda-and-todo (&optional arg)
  (interactive "P")
  (org-agenda arg "n"))

I then add this to my personal key map

(define-key bjm-map (kbd "a") 'org-agenda-show-agenda-and-todo)

and I can pull up my agenda with C-1 a. You might not want to use the same keybinding as me, but maybe you’ll find the idea helpful.

How I view my google calendar agenda in Emacs

JCS over on Irreal describes a couple of ways of syncing a google calendar with your org-mode agenda. I prefer to keep my google calendar separate from my agenda, as I use the latter to track tasks rather than appointments. I still want to see my google calendar agenda in Emacs though so I have a fairly simple work around.

I use gcalcli to access my google calendar from the command line, and run it as a cron job using gcalcli agenda and redirecting the output to a file. Then in Emacs I have a simple function to display the contents of that file.

Firstly though, the output of gcalcli contains ansi colour codes to colour-code the calendars in the agenda. Emacs won’t display these colours unless we tell it to. We use the following code to define a function display-ansi-colors to do this for us (source):

;; define function to display ansi colours for a buffer
;; http://stackoverflow.com/questions/23378271/how-do-i-display-ansi-color-codes-in-emacs-for-any-mode
(require 'ansi-color)
(defun display-ansi-colors ()
  (interactive)
  (ansi-color-apply-on-region (point-min) (point-max)))

Now, here is the code to display the agenda:

(defun bjm/open-gcal-agenda ()
  "Open my google calendar agenda file. The agenda is displayed in the buffer *gcal*."
  (interactive)
  ;; set name of calendar buffer and location of file containing my agenda
  (let ((tmp-buff-name "*gcal*") (cal-file (expand-file-name "/homeb/bjm/tmp/gcal")))
    ;; switch to calendar buffer
    (switch-to-buffer tmp-buff-name)
    ;; turn off read only to overwrite if buffer exists
    (read-only-mode -1)
    ;; clear buffer
    (erase-buffer)
    ;; insert agenda file
    (insert-file-contents cal-file)
    ;; turn on colours
    (display-ansi-colors)
    ;; turn on special mode
    (special-mode)
    ;; turn off line wrapping
    (visual-line-mode -1)))

There are a couple of points worth noting here…

Firstly, I could easily just call gcalcli on a timer in Emacs, but I use the agenda file for other things so it is helpful to do that externally.

Secondly, after inserting the contents of the agenda file to the buffer I set it to special mode, which is basically a read only mode with some common key bindings, and is useful for buffers that are not associated with editing files. Related to this, I call the buffer *gcal*, which follows the convention that buffers not associated with files have names starting and ending with *.

Now by calling my bjm/open-gcal-agenda function, I see something like this:

gcal-agenda.png