There are usually two files I creat when starting a new project: a TODO.org file
for organizing tasks, and a
CHANGELOG file for keeping tabs on what I've
done. I don't limit myself to only writing about direct file changes; I also use
it to keep notes about overall changes I've made.
Here's a snippet from the CHANGELOG I use for this site:
It's not exactly thrilling stuff, but it's handy when looking over traffic numbers to see if any changes I made worked. Or not.
change-log-mode works fine without additional configuration, but there are a
few options to tweak. I also wrote some functions to add projectile integration.
Configuring your name and email address
add-change-log-entry will insert a new date heading with your name and
There are two variables to modify what is inserted:
add-log-full-name- The full name to use.
add-log-mailing-address- The email address to use.
Something like this will set both of variables:
(setq add-log-full-name "My name" add-log-mailing-address "firstname.lastname@example.org")
Emacs will attempt to figure your name or email if either of these are
Configuring the default file name
change-log-mode looks for "ChangeLog" by default, but I use
change-log-default-name will modify this behaviour:
(setq change-log-default-name "CHANGELOG")
Configuring indentation sizes
The default indentation width is a little large for my tastes, so I add this to my configuration file to narrow things:
(add-hook 'change-log-mode-hook (lambda () (make-local-variable 'tab-width) (make-local-variable 'left-margin) (setq tab-width 2 left-margin 2)))
Alternatively these can be set inside a ".dir-locals.el" file if you don't want to change the global behaviour:
((change-log-mode . ((tab-width . 2) (left-margin . 2))))
Adding projectile integration
I use projectile a lot, so I wanted to make it easier to add log entries from within a project. I wrote two functions for this:
- This opens the CHANGELOG file for the current projectile project.
- This works the same way as
add-change-log-entry, but it automatically selects the project CHANGELOG instead of prompting for a file name.
The full code is below:
(defun sodaware/project-changelog-path () "Get the full path to the current project's changelog file, or NIL if not found." (let ((change-log-file (concat (projectile-project-root) (file-name-nondirectory change-log-default-name)))) (if (file-exists-p change-log-file) change-log-file nil))) (defun sodaware/projectile-goto-project-changelog () "Open the CHANGELOG for the current project." (interactive) (let ((change-log-file (sodaware/project-changelog-path))) (if change-log-file (find-file change-log-file) (message "Project does not contain a changelog file.")))) (defun sodaware/projectile-add-to-project-changelog () "Add a new entry to the CHANGELOG for the current project." (interactive) (let ((change-log-file (sodaware/project-changelog-path))) (if change-log-file (progn (find-file change-log-file) (add-change-log-entry)) (message "Project does not contain a changelog file."))))
I added key bindings for both of these functions because I don't want to type that much:
(use-package projectile :diminish projectile-mode :bind (:map projectile-mode-map ("C-c p G" . sodaware/projectile-goto-project-changelog) ("C-c p L" . sodaware/projectile-add-to-project-changelog)) :config (projectile-mode) :custom (projectile-keymap-prefix (kbd "C-c p")) (projectile-enable-caching t) (projectile-completion-system 'default))