emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master fccc196: * nhexl-mode.el (nhexl-overwrite-only-mode): New


From: Stefan Monnier
Subject: [elpa] master fccc196: * nhexl-mode.el (nhexl-overwrite-only-mode): New minor mode.
Date: Sun, 15 Apr 2018 15:10:01 -0400 (EDT)

branch: master
commit fccc19666d30a0643942e6a35e6223d03ef42c76
Author: Stefan Monnier <address@hidden>
Commit: Stefan Monnier <address@hidden>

    * nhexl-mode.el (nhexl-overwrite-only-mode): New minor mode.
---
 packages/nhexl-mode/nhexl-mode.el | 110 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 105 insertions(+), 5 deletions(-)

diff --git a/packages/nhexl-mode/nhexl-mode.el 
b/packages/nhexl-mode/nhexl-mode.el
index f125bfc..ca12ed2 100644
--- a/packages/nhexl-mode/nhexl-mode.el
+++ b/packages/nhexl-mode/nhexl-mode.el
@@ -33,10 +33,16 @@
 ;; In theory it could also work just fine even on very large buffers,
 ;; although in practice it seems to make the display engine suffer.
 ;;
-;; It also comes with a "nibble editor" mode (M-x nhexl-nibble-edit-mode),
-;; where the cursor pretends to advance by nibbles (4-bit) and the
-;; self-insertion keys (which only work for hex-digits) will only modify the
-;; nibble under point.
+;; It also comes with:
+;;
+;; - `nhexl-nibble-edit-mode': a "nibble editor" minor mode.
+;;   where the cursor pretends to advance by nibbles (4-bit) and the
+;;   self-insertion keys (which only work for hex-digits) will only modify the
+;;   nibble under point.
+;;
+;; - `nhexl-overwrite-only-mode': a minor mode to try and avoid moving text.
+;;   In this minor mode, not only self-inserting keys overwrite existing
+;;   text, but commands like `yank' and `kill-region' as well.
 
 ;;; Todo:
 ;; - Clicks on the hex side should put point at the right place.
@@ -151,7 +157,101 @@
     (if (= max nib) nil
       (backward-char 1)
       (nhexl--nibble-set (1+ nib)))))
-    
+
+;;;; No insertion/deletion minor mode
+
+(defvar nhexl-overwrite-clear-byte ?\000
+  "Byte to use to replace deleted content.")
+
+(defvar nhexl-overwrite-only-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [remap yank] #'nhexl-overwrite-yank)
+    (define-key map [remap yank-pop] #'nhexl-overwrite-yank-pop)
+    (define-key map [remap kill-region] #'nhexl-overwrite-kill-region)
+    (define-key map [remap delete-char] #'nhexl-overwrite-delete-char)
+    (define-key map [remap backward-delete-char-untabify]
+      #'nhexl-overwrite-backward-delete-char)
+    map))
+
+(defun nhexl-overwrite-backward-delete-char (&optional arg)
+  "Delete ARG chars backward by overwriting them.
+Uses `nhexl-overwrite-clear-byte'."
+  (interactive "p")
+  (unless arg (setq arg 1))
+  (if (< arg 0)
+      (nhexl-overwrite-delete-char (- arg))
+    (forward-char (- arg))
+    (save-excursion
+      (insert-char nhexl-overwrite-clear-byte arg)
+      (delete-char arg))))
+
+(defun nhexl-overwrite-delete-char (&optional arg)
+  "Delete ARG chars forward by overwriting them.
+Uses `nhexl-overwrite-clear-byte'."
+  (interactive "p")
+  (unless arg (setq arg 1))
+  (if (< arg 0)
+      (nhexl-overwrite-backward-delete-char (- arg))
+    (insert-char nhexl-overwrite-clear-byte arg)
+    (delete-char arg)))
+
+(defun nhexl-overwrite-kill-region (beg end &optional region)
+  "Kill the region, replacing it with `nhexl-overwrite-clear-byte'."
+  (interactive (list (mark) (point) 'region))
+  (copy-region-as-kill beg end region)
+  (barf-if-buffer-read-only)
+  (pcase-dolist (`(,beg . ,end)
+                 (if region (funcall region-extract-function 'bounds)
+                   (list beg end)))
+    (goto-char beg)
+    (nhexl-overwrite-delete-char (- end beg))))
+
+(defun nhexl-overwrite--yank-wrapper (fun)
+  ;; FIXME? doesn't work when yanking things like rectangles.
+  (let ((orig-size (buffer-size)))
+    (funcall fun)
+    (let* ((inserted (- (buffer-size) orig-size))
+           (deleted (delete-and-extract-region
+                     (point)
+                     (min (point-max) (+ (point) inserted)))))
+      (unless yank-undo-function
+        (setq yank-undo-function #'delete-region))
+      (add-function :before yank-undo-function
+                    (lambda (_beg end)
+                      (save-excursion
+                        (goto-char end)
+                        (insert deleted)))))))
+
+(defun nhexl-overwrite-yank (&optional arg)
+  "Like `yank' but overwriting existing text."
+  (interactive "*P")
+  (nhexl-overwrite--yank-wrapper (lambda () (yank arg))))
+
+(defun nhexl-overwrite-yank-pop (&optional arg)
+  "Like `yank-pop' but overwriting existing text."
+  (interactive "*P")
+  (nhexl-overwrite--yank-wrapper (lambda () (yank-pop arg))))
+
+(defvar-local nhexl--overwrite-save-settings nil)
+
+(define-minor-mode nhexl-overwrite-only-mode
+  "Minor mode where text is only overwritten.
+Insertion/deletion is avoided where possible and replaced by overwriting
+existing text, if needed with `nhexl-overwrite-clear-byte'."
+  :lighter nil
+  (cond
+   (nhexl-overwrite-only-mode
+    (push (cons 'overwrite-mode overwrite-mode)
+          nhexl--overwrite-save-settings)
+    (setq-local overwrite-mode 'overwrite-mode-binary)
+    (setq-local overwrite-mode-binary " OnlyOvwrt"))
+   (t
+    (pcase-dolist (`(,var . ,val)
+                   (prog1 nhexl--overwrite-save-settings
+                     (setq nhexl--overwrite-save-settings nil)))
+      (set var val))
+    (kill-local-variable 'overwrite-mode-binary))))
+
 ;;;; Main minor mode
 
 (defvar nhexl-mode-map



reply via email to

[Prev in Thread] Current Thread [Next in Thread]