7.7 KiB

Notes on Emacs

This is a small collection of Emacs related posts and documentation by other authors that I find useful.

Random Notes

Parsing with org-element   IRREAL

The other day, I saw this query on the reddit Emacs subreddit. I already have solutions for this type of problem but I'm always interested in the how people use Org mode to record and report data so I followed the link that primitiveinds provided for his solution to generating time reports.

Even if, like me, you already have your time tracking and reporting needs under control, primitiveinds' solution is worth looking at for its own sake. It works by looking for CLOCK entries in an Org buffer and accumulating the relevant information in the CLOCK line as well data about the associated task. That might seem like it would require routine but tedious text manipulation but primitiveinds leverages the org-element functionality to easily handle the task.

He starts by calling org-element-parse-buffer to generate a tree representation of the Org buffer. Then he uses org-element-map to examine each CLOCK element (and only CLOCK elements) to extract the necessary information. It's a great technique that can easily be adapted for other parsing of Org data. The code that primitiveinds presents is easy to follow and he provides a nice explanation of what it's doing.

If you need to programmatically examine Org data for further processing, you should take a look at primitiveinds' post. It's definitely worth a read.


The relevant code:

 '(("date" "project" "hours" "task"))
 (let ((ast (org-element-parse-buffer 'element)))
   (org-element-map ast 'clock
     (lambda (x)
       (let* ((val (org-element-property :value x))
              (task (org-element-property :parent (org-element-property :parent x))))
         `(,(let ((year (org-element-property :year-start val))
                  (month (calendar-month-name
                          (org-element-property :month-start val)))
                  (day (org-element-property :day-start val)))
              ;; (insert (org-element-property :raw-value val))
              (format "%s %s, %s" month day year))
           ,(org-element-property :PROJECT task)
           ,(org-element-property :duration x)
           ,(org-element-property :title task)
 '(("" "total:" ":=vsum(@2..@-1);T" "")))

Fractals in Emacs

From https://nullprogram.com/blog/2012/09/14/

(defun sierpinski (s)
  (pop-to-buffer (get-buffer-create "*sierpinski*"))
  (fundamental-mode) (erase-buffer)
  (labels ((fill-p (x y)
                   (cond ((or (zerop x) (zerop y)) "0")
                         ((and (= 1 (mod x 3)) (= 1 (mod y 3))) "1")
                         (t (fill-p (/ x 3) (/ y 3))))))
    (insert (format "P1\n%d %d\n" s s))
    (dotimes (y s) (dotimes (x s) (insert (fill-p x y) " "))))

(defun mandelbrot ()
  (pop-to-buffer (get-buffer-create "*mandelbrot*"))
  (let ((w 400) (h 300) (d 32))
    (fundamental-mode) (erase-buffer)
    (set-buffer-multibyte nil)
    (insert (format "P6\n%d %d\n255\n" w h))
    (dotimes (y h)
      (dotimes (x w)
        (let* ((cx (* 1.5 (/ (- x (/ w 1.45)) w 0.45)))
               (cy (* 1.5 (/ (- y (/ h 2.0)) h 0.5)))
               (zr 0) (zi 0)
               (v (dotimes (i d d)
                    (if (> (+ (* zr zr) (* zi zi)) 4) (return i)
                      (psetq zr (+ (* zr zr) (- (* zi zi)) cx)
                             zi (+ (* (* zr zi) 2) cy))))))
          (insert-char (floor (* 256 (/ v 1.0 d))) 3))))

Gnus and notmuch

Currently working: notmuch for nnmaildir backend. However, I also have a local nnimap-backend, which uses Maildir format locally. It would be nice to have this working with notmuch as well.

Relevant functions:

Goes over the results of notmuch (stored in the buffer *nnir* (with an additional leading space) and decides which lines to keep;
a server-local variable to decide what to remove from the lines in *nnir*.

Inserting a function definition   CHUA

From Sacha Chua.

While nudging jcs to add a definition of jcs-insert-url to the blog post about Making Things Easier, I realized it might be handy to have a quick function for inserting a function definition without thinking about where it's defined. This tries to use the definition from the source, and it can fall back to using the stored function definition if necessary. There's probably a better way to do this, but this was small and fun to write. =)

Naturally, I used it to insert itself:

(defun my/org-insert-defun (function)
  "Inserts an Org source block with the definition for FUNCTION."
  (interactive (find-function-read))
  (let* ((buffer-point (condition-case nil
                           (find-definition-noselect function nil)
                         (error nil)))
         (new-buf (car buffer-point))
         (new-point (cdr buffer-point))
    (if buffer-point
      (with-current-buffer new-buf ;; Try to get original definition
          (goto-char new-point)
          (setq definition (buffer-substring-no-properties
                            (save-excursion (end-of-defun) (point))))))
      ;; Fallback: Print function definition
      (setq definition (concat (prin1-to-string
                                (symbol-function function))
    (insert "#+begin_src emacs-lisp\n" definition "#+end_src\n")))

Tramping into GCloud instances from within emacs   IRREAL

From https://gist.github.com/jackrusher/36c80a2fd6a8fe8ddf46bc7e408ae1f9 via Irreal.

;; make sure you've set your default project with:
;; gcloud config set project <project-name>

(require 'tramp)
(add-to-list 'tramp-methods
    (tramp-login-program        "gcloud compute ssh")
    (tramp-login-args           (("%h")))
    (tramp-async-args           (("-q")))
    (tramp-remote-shell         "/bin/sh")
    (tramp-remote-shell-args    ("-c"))
    (tramp-gw-args              (("-o" "GlobalKnownHostsFile=/dev/null")
                                 ("-o" "UserKnownHostsFile=/dev/null")
                                 ("-o" "StrictHostKeyChecking=no")))
    (tramp-default-port         22)))

;; ... after which it's as easy as:
;; C-x C-f /gcssh:compute-instance:/path/to/filename.clj

Finding the largest Emacs buffer

I found this somewhere, but forget where …

Approach: sort all buffers by size.

(mapcar (lambda (x)
          (list x (buffer-size x)))
        (cl-sort (buffer-list)
                 (lambda (x y)
                   (< (buffer-size y) (buffer-size x)))))

Emacs reencode buffers with other encoding

  • Use the function revert-buffer-with-coding-system to re-open a buffer in another encoding.
  • Customize the variable file-coding-system-alist to control whether certain files should always be opened with a specific encoding.