├── .gitignore ├── README.md └── palimpsest.el /.gitignore: -------------------------------------------------------------------------------- 1 | *trash* 2 | *~ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Palimpsest 2 | ========== 3 | 4 | ## Definition 5 | 6 | From Wikipedia: 7 | 8 | >A palimpsest (/ˈpælɪmpsɛst/) is a manuscript page from a scroll or book from which the text has been scraped or washed off and which can be used again. The word "palimpsest" comes through Latin palimpsēstus from Ancient Greek παλίμψηστος (palímpsestos, “scratched or scraped again”) originally compounded from πάλιν (palin, “again”) and ψάω (psao, “I scrape”) literally meaning “scraped clean and used again”. Romans wrote on wax-coated tablets that could be smoothed and reused, and a passing use of the term "palimpsest" by Cicero seems to refer to this practice. 9 | 10 | >The term has come to be used in similar context in a variety of disciplines, notably architectural archaeology. 11 | 12 | ## Purpose 13 | 14 | This minor mode for Emacs provides several strategies to remove text without permanently deleting it. Namely, it provides the following capabilities: 15 | 16 | - Send selected text to the bottom of the buffer 17 | - Send selected text to the top of the buffer 18 | - Send selected text to a trash file 19 | 20 | Much like code, the process of writing text is a progression of revisions where content gets transformed and refined. During these iterations, it is often desirable to move text instead of deleting it: you may have written a sentence that doesn't belong in the paragraph you're editing right now, but it might fit somewhere else. Since you don't know where exactly, you'd like to put it out of the way, not discard it entirely. Palimpsest saves you from the traveling back and forth between your current position and the bottom of your document (or another *draft* or *trash* document). 21 | 22 | Next time you're writing fiction, non-fiction, a journalistic piece or a blog post using Emacs, give palimpsest-mode a try. You might even try it while coding in a functional language, moving stuff around sprightly, aided by an abstraction reminiscent of the Read-Eval-Print loop, yet completely orthogonal. 23 | 24 | ## Installation 25 | 26 | ### Installing with el-get 27 | 28 | Nothing to do (except declaring `palimpsest-mode` along with your packages). 29 | 30 | ### Installing with ELPA 31 | 32 | Please make sure you have MELPA in your package archives. 33 | 34 | ("melpa" . "http://melpa.milkbox.net/packages/") 35 | 36 | ### Installing manually 37 | 38 | Just put the palimpsest.el anywhere on your load path (or load the file manually). `M-x palimpsest-mode` will toggle it on or off. 39 | 40 | If you want palimpsest to load automatically when writing textual files, andd the following in your init file. 41 | 42 | (add-hook 'text-mode-hook 'palimpsest-mode) 43 | 44 | ## Usage 45 | 46 | - M-x palimpsest-move-region-to-bottom 47 | - M-x palimpsest-move-region-to-top 48 | - M-x palimpsest-move-region-to-trash 49 | 50 | Keyboard shortcuts are provided: 51 | 52 | - C-c C-r: Send selected text to bottom of buffer 53 | - C-c C-s: Send selected text to top of buffer 54 | - C-c C-q: Send selected text to trash file 55 | 56 | ## Configuration 57 | 58 | Configuration options are available in palimpsest's customization group. 59 | You are able to: 60 | 61 | - Reassign key bindings. 62 | - Define your preferred suffix for the *trash* (or *draft*) file. 63 | - Define a string or character prefix that will gets inserted alongside the text you're moving. 64 | 65 | P.S. [Follow][follow_me] me on Twitter. 66 | 67 | [follow_me]: https://twitter.com/intent/user?screen_name=danielszmu "Follow @danielszmu" 68 | -------------------------------------------------------------------------------- /palimpsest.el: -------------------------------------------------------------------------------- 1 | ;;; palimpsest.el --- Various deletion strategies when editing 2 | ;;; text that should elude total oblivion. Implemented as a minor mode. 3 | 4 | ;; Copyright (C) 2013 Daniel Szmulewicz 5 | 6 | ;; Author: Daniel Szmulewicz 7 | 8 | ;; Version: 1.1 9 | 10 | ;;; Documentation: 11 | ;; 12 | ;; This minor mode provides several strategies to remove text without 13 | ;; permanently deleting it, useful to prose / fiction writers. 14 | ;; Namely, it provides the following capabilities: 15 | ;; 16 | ;; - Send selected text to the bottom of the file 17 | ;; - Send selected text to a trash file 18 | ;; 19 | 20 | ;;; Legal: 21 | ;; 22 | ;; This file is NOT part of GNU Emacs. 23 | ;; 24 | ;; This file is free software; you can redistribute it and/or modify 25 | ;; it under the terms of the GNU General Public License as published 26 | ;; by the Free Software Foundation; either version 3 of the License, 27 | ;; or (at your option) any later version. 28 | 29 | ;; This file is distributed in the hope that it will be useful, 30 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | ;; GNU General Public License for more details. 33 | 34 | ;; You should have received a copy of the GNU General Public License 35 | ;; along with GNU Emacs; see the file COPYING. If not, write to 36 | ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 37 | ;; Boston, MA 02111-1307, USA. 38 | 39 | ;; See for a copy of the GNU General 40 | ;; Public License. 41 | 42 | 43 | ;;; Code: 44 | 45 | ;;;;;;;;;;;;;;;;;;; 46 | ;; Customization ;; 47 | ;;;;;;;;;;;;;;;;;;; 48 | 49 | (defconst palimpsest-keymap (make-sparse-keymap) "Keymap used in palimpsest mode.") 50 | 51 | (defgroup palimpsest nil 52 | "Customization group for `palimpsest-mode'." 53 | :group 'convenience) 54 | 55 | (defcustom palimpsest-send-bottom "C-c C-r" 56 | "Keybinding to send selected text to the bottom of the current buffer. Defaults to \\ \\[palimpsest-move-region-to-bottom]." 57 | :group 'palimpsest 58 | :set (lambda (symbol value) 59 | (custom-set-default symbol value) 60 | (define-key palimpsest-keymap (kbd palimpsest-send-bottom) 'palimpsest-move-region-to-bottom)) 61 | :type 'string) 62 | 63 | (defcustom palimpsest-send-top "C-c C-s" 64 | "Keybinding to send selected text to the top of the current buffer. Defaults to \\ \\[palimpsest-move-region-to-top]." 65 | :group 'palimpsest 66 | :set (lambda (symbol value) 67 | (custom-set-default symbol value) 68 | (define-key palimpsest-keymap (kbd palimpsest-send-top) 'palimpsest-move-region-to-top)) 69 | :type 'string) 70 | 71 | (defcustom palimpsest-trash-key "C-c C-q" 72 | "Keybinding to send selected text to the trash. Defaults to \\ \\[palimpsest-move-region-to-trash]." 73 | :group 'palimpsest 74 | :set (lambda (symbol value) 75 | (custom-set-default symbol value) 76 | (define-key palimpsest-keymap (kbd palimpsest-trash-key) 'palimpsest-move-region-to-trash)) 77 | :type 'string) 78 | 79 | (defcustom palimpsest-trash-file-suffix ".trash" 80 | "This is the suffix for the trash filename." 81 | :group 'palimpsest 82 | :type 'string) 83 | 84 | (defcustom palimpsest-prefix "" 85 | "Prefix the yanked text snippet with a customizable string." 86 | :group 'palimpsest 87 | :type '(choice (string :tag "Prefix as string") (character :tag "Prefix as character"))) 88 | 89 | ;;;;;;;;;;;;;;;;; 90 | ;; Move region ;; 91 | ;;;;;;;;;;;;;;;;; 92 | 93 | (defun palimpsest-move-region-to-dest (start end dest) 94 | "Move text between START and END to buffer's desired position, otherwise known as DEST." 95 | (let ((count (count-words-region start end))) 96 | (save-excursion 97 | (kill-region start end) 98 | (goto-char (funcall dest)) 99 | (insert palimpsest-prefix) 100 | (yank) 101 | (newline)) 102 | (push-mark (point)) 103 | (message "Moved %s words" count))) 104 | 105 | (defun palimpsest-move-region-to-top (start end) 106 | "Move text between START and END to top of buffer." 107 | (interactive "r") 108 | (if (use-region-p) 109 | (palimpsest-move-region-to-dest start end 'point-min) 110 | (message "No region selected"))) 111 | 112 | ;; Custom move region to bottom 113 | (defun palimpsest-move-region-to-bottom (start end) 114 | "Move text between START and END to bottom of buffer." 115 | (interactive "r") 116 | (if (use-region-p) 117 | (palimpsest-move-region-to-dest start end 'point-max) 118 | (message "No region selected"))) 119 | 120 | (defun palimpsest-move-region-to-trash (start end) 121 | "Move text between START and END to associated trash buffer." 122 | (interactive "r") 123 | (if (use-region-p) 124 | (if buffer-file-truename 125 | (let* ((trash-buffer (concat (file-name-sans-extension (buffer-name)) palimpsest-trash-file-suffix "." (file-name-extension (buffer-file-name)))) 126 | (trash-file (expand-file-name trash-buffer)) 127 | (oldbuf (current-buffer))) 128 | (save-excursion 129 | (if (file-exists-p trash-file) (find-file trash-file)) 130 | (set-buffer (get-buffer-create trash-buffer)) 131 | (set-visited-file-name trash-file) 132 | (goto-char (point-min)) 133 | (insert palimpsest-prefix) 134 | (insert-buffer-substring oldbuf start end) 135 | (newline) 136 | (save-buffer) 137 | (write-file buffer-file-truename)) 138 | (kill-region start end) 139 | (switch-to-buffer oldbuf)) 140 | (message "Please save buffer first.")) 141 | (message "No region selected"))) 142 | 143 | ;;;###autoload 144 | (define-minor-mode palimpsest-mode 145 | "Toggle palimpsest mode. 146 | Interactively with no argument, this command toggles the mode. You can customize 147 | this minor mode, see option `palimpsest-mode'." 148 | :init-value nil 149 | ;; The indicator for the mode line. 150 | :lighter " Palimpsest" 151 | ;; The minor mode bindings. 152 | :keymap palimpsest-keymap 153 | :global nil 154 | :group 'palimpsest) 155 | 156 | (provide 'palimpsest) 157 | ;;; palimpsest.el ends here 158 | --------------------------------------------------------------------------------