;;; jao-borgmatic.el --- Simple access to borgmatic -*- lexical-binding: t; -*- ;; Copyright (C) 2022 jao ;; Author: jao ;; Keywords: convenience ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; An emacs front-end for borgmatic ;;; Code: (defconst jao-borgmatic--buffer "*borgmatic*") (defun jao-borgmatic--buffer () (get-buffer-create jao-borgmatic--buffer)) (defvar jao-borgmatic-extract-path "/tmp/borgmatic") (defvar jao-borgmatic-mode-map (let ((map (make-keymap))) (suppress-keymap map) (define-key map [?q] 'bury-buffer) (define-key map [?n] 'next-line) (define-key map [?p] 'previous-line) (define-key map [?g] 'jao-borgmatic-list) (define-key map [?x] 'jao-borgmatic-extract) (define-key map [?c] 'jao-borgmatic-check) (define-key map [?d] 'jao-borgmatic-delete) map)) ;;;###autoload (defun jao-borgmatic-mode () "A very simple mode to show the output of borgmatic commands." (interactive) (kill-all-local-variables) (buffer-disable-undo) (use-local-map jao-borgmatic-mode-map) ;; (setq-local font-lock-defaults '(jao-borgmatic-font-lock-keywords)) (setq-local truncate-lines t) (setq-local next-line-add-newlines nil) (setq major-mode 'jao-borgmatic-mode) (setq mode-name "borgmatic") (read-only-mode 1)) (defun jao-borgmatic--do (things &optional buffer) "Execute a borgmatic command THINGS in the given BUFFER." (let ((b (or buffer (pop-to-buffer (get-buffer-create jao-borgmatic--buffer))))) (let ((inhibit-read-only t) (cmd (format "borgmatic %s" things))) (unless buffer (with-current-buffer b (delete-region (point-min) (point-max)))) (message "Running: %s ...." cmd) (shell-command cmd b) (message "")))) (defun jao-borgmatic--archive-at-point () (save-excursion (beginning-of-line) (when (looking-at "- \\([^ ]+\\)") (match-string-no-properties 1)))) (defvar jao-borgmatic--archive-history nil) (defvar-local jao-borgmatic--archives nil) (defun jao-borgmatic--archives (&optional retrieve) (or (and (not retrieve) jao-borgmatic--archives) (let ((c (shell-command-to-string "borgmatic list --format '{archive} {time}*'"))) (setq jao-borgmatic--archives (cdr (split-string c "\\*\\|\n")))))) (defun jao-borgmatic--read-archive (&optional retrieve) (car (split-string (completing-read "Archive: " (jao-borgmatic--archives retrieve) nil nil nil 'jao-borgmatic--archive-history (jao-borgmatic--archive-at-point))))) ;;;###autoload (defun jao-borgmatic-list () (interactive) (with-current-buffer (jao-borgmatic--buffer) (jao-borgmatic-mode) (let ((inhibit-read-only t) (archives (with-temp-message "Retrieving archives list..." (jao-borgmatic--archives t)))) (delete-region (point-min) (point-max)) (insert "Archives: \n\n") (dolist (a archives) (unless (string-blank-p a) (insert "- " a "\n"))) (insert "\n" (with-temp-buffer (jao-borgmatic--do "info" (current-buffer)) (buffer-string))))) (pop-to-buffer (jao-borgmatic--buffer)) (goto-line 3)) (defconst jao-borgmatic--extract-output " *borgmatic output*") (defun jao-borgmatic--extract-sentinel (paths) (lambda (proc &rest _) (when (and (eq (process-status proc) 'exit) (y-or-n-p "Borg extraction finished, show?")) (if (eq (process-exit-status proc) 0) (let ((d (file-name-directory (car paths)))) (dired (expand-file-name d jao-borgmatic-extract-path))) (pop-to-buffer jao-borgmatic--extract-output))))) (defvar jao-borgmatic--extract-history nil) ;;;###autoload (defun jao-borgmatic-extract () (interactive) (let* ((archive (jao-borgmatic--read-archive)) (path (read-string "Path(s) (e.g. home/jao/emacs.d/init.el): " nil 'jao-borgmatic--extract-history)) (paths (if (string-blank-p path) (not (or (y-or-n-p "Extract the full archive?") (error "Cancelled"))) (split-string path))) (default-directory jao-borgmatic-extract-path)) (make-directory default-directory t) (message "Extracting %s/%s to directory %s in the background" archive path default-directory) (make-process :name "borgmatic-extract" :buffer jao-borgmatic--extract-output :command (append `("borgmatic" "extract" "--archive" ,archive "--destination" ,default-directory) (when paths (cons "--path" paths))) :sentinel (jao-borgmatic--extract-sentinel paths) :stderr nil))) (provide 'jao-borgmatic) ;;; jao-borgmatic.el ends here