Skip to content

Instantly share code, notes, and snippets.

@grzs
Forked from mtmtcode/auto-rsync.el
Last active February 6, 2023 22:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grzs/61220178b6c4b5f8bc9aeb20c9600aca to your computer and use it in GitHub Desktop.
Save grzs/61220178b6c4b5f8bc9aeb20c9600aca to your computer and use it in GitHub Desktop.
auto-rsync.el - Emacs minor mode to execute rsync automaticlly
;;; auto-rsync-mode -- minor mode for auto rsync
;;
;; Author: @l3msh0
;;
;;; Example
;;
;; (require 'auto-rsync)
;; (auto-rsync-mode t)
;; (setq auto-rsync-dir-alist
;; '(("/path/to/src1/" . "/path/to/dest1/")
;; ("/path/to/src2/" . "username@hostname:/path/to/dest2/")))
;; (add-to-list auto-rsync-exclude-patterns-alist '("git" "*~" ".git"))
;; (setq auto-rsync-excludes-alist
;; '(("/path/to/src1/" . "default")
;; ("/path/to/src2/" . "git")))
;;; Customize
;;
(defgroup auto-rsync nil "Auto rsync")
(defcustom auto-rsync-command "rsync" "rsync command path" :group 'auto-rsync)
(defcustom auto-rsync-flags '("-azq") "rsync command flags" :group 'auto-rsync)
;;; TODO
;;
;; open remote counterpart
;;
(defvar auto-rsync-dir-alist nil "Pair of rsync source and destination dir")
(defvar auto-rsync-dir-ssh-port-alist nil "Per source dir list of flags")
(defvar auto-rsync-exclude-patterns-alist '(("default" "*~")) "Sets of exclude patterns")
(defvar auto-rsync-excludes-alist nil "Pair of rsync source and exclude set")
;;; Code
(defun auto-rsync-excludes (list)
"Assembles a list of --exclude options"
(let (result)
(dolist (elt list result)
(setq elt (concat "'" elt "'"))
(setq result (append (list "--exclude" elt) result)))))
(defun auto-rsync-exec-rsync ()
"execute rsync if editing file path matches src dir"
(interactive)
(let* ((normalized-alist (mapcar (lambda (x) (cons (file-name-as-directory (expand-file-name (car x)))
(cdr x)))
auto-rsync-dir-alist))
(sync-pair (assoc buffer-file-name normalized-alist
(lambda (dirname filename) (eq 0 (string-match dirname filename)))))
;; excludes
(normalized-excludes-alist (mapcar (lambda (x) (cons (file-name-as-directory (expand-file-name (car x)))
(cdr x)))
auto-rsync-excludes-alist))
(excludes-key (cdr (assoc buffer-file-name normalized-excludes-alist
(lambda (dirname filename) (eq 0 (string-match dirname filename))))))
(excludes (cdr (assoc excludes-key auto-rsync-exclude-patterns-alist)))
;; ssh port
(normalized-dir-ssh-port-alist (mapcar (lambda (x) (cons (file-name-as-directory (expand-file-name (car x)))
(cdr x)))
auto-rsync-dir-ssh-port-alist))
(dir-ssh-port (cdr (assoc buffer-file-name normalized-dir-ssh-port-alist
(lambda (dirname filename) (eq 0 (string-match dirname filename))))))
;; rsync options
(rsync-options-list (if excludes
(append auto-rsync-flags (auto-rsync-excludes excludes))
auto-rsync-flags))
(rsync-options-list (if dir-ssh-port
(cons (format "-e 'ssh -p %s'" dir-ssh-port) rsync-options-list) rsync-options-list))
(rsync-options (string-join rsync-options-list " ")))
(when sync-pair
(save-window-excursion
;; avoid annoying shell comannd window
(shell-command (format "%s %s %s %s &" auto-rsync-command rsync-options (car sync-pair) (cdr sync-pair)) nil))
)))
(define-minor-mode auto-rsync-mode
"automatically execute rsync when editing file's path matches `auto-rsync-dir-alist`"
:lighter " rsync"
:global t
(cond (auto-rsync-mode
(add-hook 'after-save-hook 'auto-rsync-exec-rsync))
(t
(remove-hook 'after-save-hook 'auto-rsync-exec-rsync))))
(provide 'auto-rsync)
@trfx
Copy link

trfx commented Nov 28, 2022

Hey Janos, thanks for this, worked like a charm out of the box! --Tamas

@grzs
Copy link
Author

grzs commented Nov 28, 2022

Great to hear! Credit also goes to @mtmtcode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment