Annotate projects in Emacs
Every now and then I've wished to write comments on files in a project, but I've
never found a good way to do that. annotate.el and org-annotate-file both
collect annotations in a central place (in my
$HOME), while marginalia puts
annotations in files next to the source files but in a format that's rather
cryptic and tends to be messed up when attached to multiple lines. None of them
is ideal, I'd like the format to be org-mode, but not in a central file. At the
same time having one annotation file per source file is simply too much.
I tried wrapping
and taking advantage of elisp's dynamic binding. However, it opens the
annotation file in the current window, and I'd really like to split the window
and open the annotations the right. Rather than trying to sort of "work it out
backwards" I decided to write a small package and use as much of the
org-annotate-file.el as possible.
First off I decided that I want the annotation file to be called
(defvar org-projectile-annotate-file-name "projectile-annotations.org" "The name of the file to store project annotations.")
Then I wanted a slightly modified version of
wanted it to respect the root of the project.
(defun org-projectile-annotate--file-show-section (storage-file) "Add or show annotation entry in STORAGE-FILE and return the buffer." ;; modified version of org-annotate-file-show-section (let* ((proj-root (projectile-project-root)) (filename (file-relative-name buffer-file-name proj-root)) (line (buffer-substring-no-properties (point-at-bol) (point-at-eol))) (annotation-buffer (find-file-noselect storage-file))) (with-current-buffer annotation-buffer (org-annotate-file-annotate filename line)) annotation-buffer))
The main function can then simply work out where the file with annotations
should be located and call
(defun org-projectile-annotate () (interactive) (let ((annot-fn (file-name-concat (projectile-project-root) org-projectile-annotate-file-name))) (set-window-buffer (split-window-right) (org-projectile-annotate--file-show-section annot-fn))))
When testing it all out I noticed that
org-store-link makes a link with a
search text. In my case it would be much better to have links with line numbers.
I found there's a hook to modify the behaviour of
org-create-file-search-functions. So I wrote a function to get the kind of
links I want, but only when the project annotation file is open in a buffer.
(defun org-projectile-annotate-file-search-func () "A function returning the current line number when called in a project while the project annotation file is open. This function is designed for use in the hook 'org-create-file-search-functions'. It changes the behaviour of 'org-store-link' so it constructs a link with a line number instead of a search string." ;; TODO: find a way to make the link description nicer (when (and (projectile-project-p) (get-buffer-window org-projectile-annotate-file-name)) (number-to-string (line-number-at-pos))))
That's it, now I only have to wait until the next time I want to comment on a project to see if it improves my way of working.