Emacs Archiver
Thursday, September 19, 2024
Table of Contents
Org Archiver
A major paint point in using org mode's archive functionality in Emacs is that the archive doesn't mirror the tree structure of the source files, which means that every archived heading is at the top level of the org tree. So I created this package to archive org headings with the ancestors of the heading, and merge them with the existing archive tree structure.
Figure 1: Demo of Archiver Package
This package allows you to archive headings into your agenda file in such a way that the ancestors will also be archived. And if some of the ancestors exist in the archive already, the newly archived headings will be merged with the tree structure of the archive.
Installation
Clone the repository in your preferred destination.
cd ~/path/to
git clone https://github.com/Duncan-Britt/emacs-archiver.git
Add the following to your config, specifying the path to the cloned repository and the path to your agenda archive file.
(use-package archiver :load-path "~/path/to/emacs-archiver/" :after org :init (setq *archiver-agenda-archive-location* (expand-file-name "~/path/to/your/agenda_archive.org")) :bind (:map org-mode-map ("C-c C-x C-a" . archiver-archive-heading)))
File Archiver
Like the home, the home directory tends to become cluttered. I was accumulating files and folders that I no longer used, but wasn't ready to get delete permanently. So I created a shell script which allows me to move files into an ~/archive
directory where the file path mirrors that of the location from whence it came. Importantly, archiving sibling files and folders won't create duplicates or clobber existing directories in the archive.
#!/bin/bash # Archive directory ARCHIVE_DIR="$HOME/archive" # Check if a file or directory is specified if [ -z "$1" ]; then echo "Usage: archive <file-or-directory>" exit 1 fi # File or directory to archive TARGET="$1" # Get the current directory relative to home if [ "$(pwd)" == "$HOME" ]; then CURRENT_DIR="" else CURRENT_DIR=$(pwd | sed "s|^$HOME/||") fi # Construct the full path of the target if [ -z "$CURRENT_DIR" ]; then RELATIVE_TARGET_PATH="$TARGET" else RELATIVE_TARGET_PATH="$CURRENT_DIR/$TARGET" fi # Construct the destination directory in the archive DEST_DIR="$ARCHIVE_DIR/$(dirname "$RELATIVE_TARGET_PATH")" # Create the destination directory if it doesn't exist mkdir -p "$DEST_DIR" # Check if the target is a directory if [ -d "$TARGET" ]; then # Use rsync to merge directories if the target is a directory rsync -a "$TARGET/" "$DEST_DIR/$(basename "$TARGET")/" # Remove the original directory after merging rm -rf "$TARGET" else # Move the target to the archive directory if it's a file mv "$TARGET" "$DEST_DIR/" fi echo "Archived '$TARGET' to '$DEST_DIR/'."
I also created a little emacs lisp script to archive the open file.
(defvar my-archive-dir "~/archive" "Directory where files will be archived.") (defun archiver-archive-open-file () "Move the current file to the archive directory." (interactive) (if (buffer-file-name) (let* ((file-path (buffer-file-name)) (relative-path (file-relative-name file-path (getenv "HOME"))) (archive-path (expand-file-name relative-path my-archive-dir))) (if (file-exists-p file-path) (progn (save-buffer) (make-directory (file-name-directory archive-path) t) (rename-file file-path archive-path t) (kill-buffer) (message "Archived: %s" archive-path)) (message "File does not exist: %s" file-path))) (message "No file is associated with this buffer.")))