super-save-0.4.0/0000755000175000017500000000000014535037335013447 5ustar dogslegdogslegsuper-save-0.4.0/README.md0000644000175000017500000001154214535037335014731 0ustar dogslegdogsleg[![License GPL 3][badge-license]][copying] [![MELPA][melpa-badge]][melpa-package] [![MELPA Stable][melpa-stable-badge]][melpa-stable-package] # super-save super-save auto-saves your buffers, when certain events happen - e.g. you switch between buffers, an Emacs frame loses focus, etc. You can think of it as both something that augments and replaces the standard `auto-save-mode`. ## Installation Available on all major `package.el` community maintained repos - [MELPA Stable][] and [MELPA][] repos. MELPA Stable is recommended as it has the latest stable version. MELPA has a development snapshot for users who don't mind breakage but don't want to run from a git checkout. You can install `super-save` using the following command: M-x package-install [RET] super-save [RET] or if you'd rather keep it in your dotfiles: ```el (unless (package-installed-p 'super-save) (package-refresh-contents) (package-install 'super-save)) ``` If the installation doesn't work try refreshing the package list: M-x package-refresh-contents ### use-package If you're into `use-package` you can use the following snippet: ```el (use-package super-save :ensure t :config (super-save-mode +1)) ``` ### Emacs Prelude super-save started its life as the extraction of a similar functionality I had originally developed for [Emacs Prelude](https://github.com/bbatsov/prelude) and the package is bundled with Prelude. ## Usage Add the following to your Emacs config to enable `super-save`: ```el (super-save-mode +1) ``` If you want to enable the additional feature of auto-saving buffers when Emacs is idle, add the following as well: ```el (setq super-save-auto-save-when-idle t) ``` At this point you can probably switch off the built-in `auto-save-mode` (unless you really care about its backups): ```el (setq auto-save-default nil) ``` ## Configuration super-save will save files on command (e.g. `switch-to-buffer`) and hook triggers (e.g. `focus-out-hook`). Both of those are configurable via `super-save-triggers` and `super-save-hook-triggers`. Here's a couple of examples: ```el ;; add integration with ace-window (add-to-list 'super-save-triggers 'ace-window) ;; save on find-file (add-to-list 'super-save-hook-triggers 'find-file-hook) ``` You can turn off `super-save` for remote files like this: ```el (setq super-save-remote-files nil) ``` Sometimes you might want to exclude specific files from super-save. You can achieve this via `super-save-exclude`, for example: ```el (setq super-save-exclude '(".gpg")) ``` You can add predicate to `super-save-predicates`, this predicates must not take arguments and return nil, when current buffer shouldn't save. If predicate don't know needle of save file, then predicate must return t. Following example stop `super-save`, when current file in Markdown mode: ```el (add-to-list 'super-save-predicates (lambda () (not (eq major-mode 'markdown-mode)))) ``` When saving a file automatically, Emacs will display a message in the `*Messages*` buffer and in the echo area. If you want to suppress these messages, you can set `super-save-silent` to `t`. ```el ;; Save silently (setq super-save-silent t) ``` The `super-save-delete-trailing-whitespace` variable can be used to enable deleting trailing white spaces before saving (via Emacs' `delete-trailing-whitespace`). ```el ;; Enable deleting trailing white spaces before saving (setq super-save-delete-trailing-whitespace t) ;; Enable deleting trailing white spaces before saving (except for the current line) (setq super-save-delete-trailing-whitespace 'except-current-line) ``` By default, `super-save` will automatically save only the current buffer, if you want to save all open buffers you can set `super-save-all-buffers` to `t`. Setting this to `t` can be interesting when you make indirect buffer edits, like when editing `grep`s results with `occur-mode` and `occur-edit-mode`, or when running a project-wide search and replace with `project-query-replace-regexp` and so on. In these cases, we can indirectly edit several buffers without actually visiting or switching to these buffers. Hence, this option allow to automatically save these buffers, even when they aren't visible in any window. ## License Copyright © 2015-2023 Bozhidar Batsov and [contributors][]. Distributed under the GNU General Public License; type C-h C-c to view it. [badge-license]: https://img.shields.io/badge/license-GPL_3-green.svg [melpa-badge]: http://melpa.org/packages/super-save-badge.svg [melpa-stable-badge]: http://stable.melpa.org/packages/super-save-badge.svg [melpa-package]: http://melpa.org/#/super-save [melpa-stable-package]: http://stable.melpa.org/#/super-save [COPYING]: http://www.gnu.org/copyleft/gpl.html [contributors]: https://github.com/bbatsov/super-save/contributors [melpa]: http://melpa.org [melpa stable]: http://stable.melpa.org super-save-0.4.0/CONTRIBUTING.md0000644000175000017500000000270114535037335015700 0ustar dogslegdogsleg# Contributing If you discover issues, have ideas for improvements or new features, or want to contribute a new module, please report them to the [issue tracker][1] of the repository or submit a pull request. Please, try to follow these guidelines when you do so. ## Issue reporting * Check that the issue has not already been reported. * Check that the issue has not already been fixed in the latest code (a.k.a. `master`). * Be clear, concise and precise in your description of the problem. * Open an issue with a descriptive title and a summary in grammatically correct, complete sentences. * Include any relevant code to the issue summary. ## Pull requests * Read [how to properly contribute to open source projects on Github][2]. * Use a topic branch to easily amend a pull request later, if necessary. * Write [good commit messages][3]. * Mention related tickets in the commit messages (e.g. `[Fix #N] Add missing autoload cookies`) * Use the same coding conventions as the rest of the project. * Verify your Emacs Lisp code with `checkdoc` (C-c ? d). * Open a [pull request][4] that relates to *only* one subject with a clear title and description in grammatically correct, complete sentences. [1]: https://github.com/bbatsov/super-save/issues [2]: http://gun.io/blog/how-to-github-fork-branch-and-pull-request [3]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html [4]: https://help.github.com/articles/using-pull-requests super-save-0.4.0/super-save.el0000644000175000017500000002141014535037335016061 0ustar dogslegdogsleg;;; super-save.el --- Auto-save buffers, based on your activity. -*- lexical-binding: t -*- ;; Copyright © 2015-2023 Bozhidar Batsov ;; Author: Bozhidar Batsov ;; URL: https://github.com/bbatsov/super-save ;; Keywords: convenience ;; Version: 0.4.0 ;; Package-Requires: ((emacs "25.1")) ;; This file is NOT part of GNU Emacs. ;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; super-save saves buffers when they lose focus. ;; ;;; Code: (require 'seq) (defgroup super-save nil "Smart-saving of buffers." :group 'tools :group 'convenience) (defvar super-save-mode-map (make-sparse-keymap) "super-save mode's keymap.") (defcustom super-save-triggers '(switch-to-buffer other-window windmove-up windmove-down windmove-left windmove-right next-buffer previous-buffer) "A list of commands which would trigger `super-save-command'." :group 'super-save :type '(repeat symbol) :package-version '(super-save . "0.1.0")) (defcustom super-save-hook-triggers '(mouse-leave-buffer-hook focus-out-hook) "A list of hooks which would trigger `super-save-command'." :group 'super-save :type '(repeat symbol) :package-version '(super-save . "0.3.0")) (defcustom super-save-auto-save-when-idle nil "Save automatically when Emacs is idle." :group 'super-save :type 'boolean :package-version '(super-save . "0.2.0")) (defcustom super-save-all-buffers nil "Auto-save all buffers, not just the current one. Setting this to t can be interesting when you make indirect buffer edits, like when editing `grep's results with `occur-mode' and 'occur-edit-mode', or when running a project-wide search and replace with `project-query-replace-regexp' and so on. In these cases, we can indirectly edit several buffers without actually visiting or switching to these buffers. Hence, this option allow to automatically save these buffers, even when they aren't visible in any window." :group 'super-save :type 'boolean :package-version '(super-save . "0.4.0")) (defcustom super-save-idle-duration 5 "Delay in seconds for which Emacs has to be idle before auto-saving. See `super-save-auto-save-when-idle'." :group 'super-save :type 'integer :package-version '(super-save . "0.2.0")) (defcustom super-save-remote-files t "Save remote files when t, ignore them otherwise." :group 'super-save :type 'boolean :package-version '(super-save . "0.3.0")) (defcustom super-save-silent nil "Save silently, don't display any message." :group 'super-save :type 'boolean :package-version '(super-save . "0.4.0")) (defcustom super-save-delete-trailing-whitespace nil "Controls whether to delete the trailing whitespace before saving. Set to 'except-current-line if you want to avoid the current line." :group 'super-save :type '(choice (boolean :tag "Enable/disable deleting trailing whitespace for the whole buffer.") (symbol :tag "Delete trailing whitespace except the current line." except-current-line)) :package-version '(super-save . "0.4.0")) (defcustom super-save-exclude nil "A list of regexps for `buffer-file-name' excluded from super-save. When a `buffer-file-name' matches any of the regexps it is ignored." :group 'super-save :type '(repeat (choice regexp)) :package-version '(super-save . "0.4.0")) (defcustom super-save-max-buffer-size nil "Maximal size of buffer (in characters), for which super-save work. Exists mostly because saving constantly huge buffers can be slow in some cases. Set to 0 or nil to disable." :group 'super-save :type 'integer :package-version '(super-save . "0.4.0")) (defcustom super-save-predicates '((lambda () buffer-file-name) (lambda () (buffer-modified-p (current-buffer))) (lambda () (file-writable-p buffer-file-name)) (lambda () (if (and super-save-max-buffer-size (> super-save-max-buffer-size 0)) (< (buffer-size) super-save-max-buffer-size) t)) (lambda () (if (file-remote-p buffer-file-name) super-save-remote-files t)) (lambda () (super-save-include-p buffer-file-name))) "Predicates, which return nil, when the buffer doesn't need to be saved. Predicate functions don't take any arguments. If a predicate doesn't know whether this buffer needs to be super-saved or not, then it must return t." :group 'super-save :type 'integer :package-version '(super-save . "0.4.0")) (defun super-save-include-p (filename) "Return non-nil if FILENAME doesn't match any of the `super-save-exclude'." (not (seq-some (lambda (regexp) (string-match-p regexp filename)) super-save-exclude))) (defun super-save-p () "Return t when current buffer should be saved, otherwise return nil. This function relies on the variable `super-save-predicates'." (seq-every-p #'funcall super-save-predicates)) (defun super-save-delete-trailing-whitespace-maybe () "Delete trailing whitespace, optionally avoiding the current line. See `super-save-delete-trailing-whitespace'." (cond ((eq super-save-delete-trailing-whitespace 'except-current-line) (let ((start (line-beginning-position)) (current (point))) (save-excursion (when (< (point-min) start) (save-restriction (narrow-to-region (point-min) (1- start)) (delete-trailing-whitespace))) (when (> (point-max) current) (save-restriction (narrow-to-region current (point-max)) (delete-trailing-whitespace)))))) (super-save-delete-trailing-whitespace (delete-trailing-whitespace)))) (defun super-save-buffer (buffer) "Save BUFFER if needed, super-save style." (with-current-buffer buffer (save-excursion (when (super-save-p) (super-save-delete-trailing-whitespace-maybe) (if super-save-silent (with-temp-message "" (let ((inhibit-message t) (inhibit-redisplay t) (message-log-max nil)) (basic-save-buffer))) (basic-save-buffer)))))) (defun super-save-command () "Save the relevant buffers if needed. When `super-save-all-buffers' is non-nil, save all modified buffers, else, save only the current buffer." (mapc #'super-save-buffer (if super-save-all-buffers (buffer-list) (list (current-buffer))))) (defvar super-save-idle-timer) (defun super-save-command-advice (&rest _args) "A simple wrapper around `super-save-command' that's advice-friendly." (super-save-command)) (defun super-save-advise-trigger-commands () "Apply super-save advice to the commands listed in `super-save-triggers'." (mapc (lambda (command) (advice-add command :before #'super-save-command-advice)) super-save-triggers)) (defun super-save-remove-advice-from-trigger-commands () "Remove super-save advice from to the commands listed in `super-save-triggers'." (mapc (lambda (command) (advice-remove command #'super-save-command-advice)) super-save-triggers)) (defun super-save-initialize-idle-timer () "Initialize super-save idle timer if `super-save-auto-save-when-idle' is true." (setq super-save-idle-timer (when super-save-auto-save-when-idle (run-with-idle-timer super-save-idle-duration t #'super-save-command)))) (defun super-save-stop-idle-timer () "Stop super-save idle timer if `super-save-idle-timer' is set." (when super-save-idle-timer (cancel-timer super-save-idle-timer))) (defun super-save-initialize () "Setup super-save's advices and hooks." (super-save-advise-trigger-commands) (super-save-initialize-idle-timer) (dolist (hook super-save-hook-triggers) (add-hook hook #'super-save-command))) (defun super-save-stop () "Cleanup super-save's advices and hooks." (super-save-remove-advice-from-trigger-commands) (super-save-stop-idle-timer) (dolist (hook super-save-hook-triggers) (remove-hook hook #'super-save-command))) ;;;###autoload (define-minor-mode super-save-mode "A minor mode that saves your Emacs buffers when they lose focus." :lighter " super-save" :keymap super-save-mode-map :group 'super-save :global t (cond (super-save-mode (super-save-initialize)) (t (super-save-stop)))) (provide 'super-save) ;;; super-save.el ends here super-save-0.4.0/changelog.md0000644000175000017500000000420314535037335015717 0ustar dogslegdogsleg# Changelog ## master (unreleased) ## 0.4.0 (2023-12-09) ### New features - Make super-save checks customizable via `super-save-predicates`. - Introduce defcustom `super-save-max-buffer-size` as a way to avoid auto-saving big files. - Introduce defcustom `super-save-exclude` (a list of regular expression) as a way to filter out certain buffer names from being auto-saved. - [#43](https://github.com/bbatsov/crux/issues/43) Introduce `super-save-silent` to avoid printing messages in the `*Messages*` buffer or in the echo area. - [#43](https://github.com/bbatsov/crux/issues/43) Introduce `super-save-delete-trailing-whitespace` which defaults to `nil` and accepts `t` to run `delete-trailing-whitespace` before saving the buffer. This variable accepts only the symbol `except-current-line` to delete trailing white spaces from all lines except the current one. This can be useful when we are in the middle of writing some thing and we add a space at the end, in this case, we more likely need the space to stay there instead of deleting it. - [#44](https://github.com/bbatsov/crux/issues/44) & [#20](https://github.com/bbatsov/crux/issues/20) Introduce `super-save-all-buffers` to save all modified buffers instead of only the current one. ## 0.3.0 (2018-09-29) ### New features - [#16](https://github.com/bbatsov/crux/issues/16): Make this of hook triggers customizable (see `super-save-hook-triggers`). - [#18](https://github.com/bbatsov/crux/issues/18): Make it possible to disable super-save for remote files (see `super-save-remote-files`). ### Changes - Make `super-save-triggers` a list of symbols (it used to be a list of strings). - Trigger super-save on `next-buffer` and `previous-buffer`. ## 0.2.0 (2016-02-21) ### New features - [#3](https://github.com/bbatsov/crux/issues/3): Turn super-save into a global minor-mode (`super-save-mode`). - Add some functionality for auto-saving buffers when Emacs is idle (disabled by default). ## 0.1.0 (2016-02-11) Initial release. Most of super-save was an extraction of a similar functionality I had originally developed for [Emacs Prelude](https://github.com/bbatsov/prelude).