[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/nhexl-mode 8310ad1 13/23: * nhexl-mode/nhexl-mode.el: I
From: |
Stefan Monnier |
Subject: |
[elpa] externals/nhexl-mode 8310ad1 13/23: * nhexl-mode/nhexl-mode.el: Improve multi-window behavior |
Date: |
Sat, 28 Nov 2020 18:35:44 -0500 (EST) |
branch: externals/nhexl-mode
commit 8310ad131e15ec4a1249ea4f80026f612d4ec977
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>
* nhexl-mode/nhexl-mode.el: Improve multi-window behavior
(nhexl--nibble) <var>: Remove.
(nhexl--nibbles): New var to replace it.
(nhexl--nibble) <fun>: Return the nibble offset for the selected window.
(nhexl--nibble-set): Set the nibble offset for the selected window.
(nhexl-mouse-set-point): New command.
(nhexl-mode-map): Bind it.
(nhexl--point): Move.
(nhexl--jit): Simplify back.
(nhexl--window-config-change): New function.
(nhexl-mode): Use it for window-configuration-change-hook.
Immediately adjust to width if applicable.
---
nhexl-mode.el | 119 +++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 89 insertions(+), 30 deletions(-)
diff --git a/nhexl-mode.el b/nhexl-mode.el
index 509e0a1..e3c8384 100644
--- a/nhexl-mode.el
+++ b/nhexl-mode.el
@@ -4,7 +4,7 @@
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: data
-;; Version: 0.7
+;; Version: 0.8
;; Package-Requires: ((emacs "24.4") (cl-lib "0.5"))
;; This program is free software; you can redistribute it and/or modify
@@ -49,7 +49,17 @@
;; search them with Isearch.
;;; Todo:
-;; - Clicks on the hex side should put point at the right place.
+;; - When the buffer is displayed in various windows, the "cursor" in the hex
+;; area only reflects one of the window-points. Fixing this is rather
+;; painful tho:
+;; - for every cursor, we need an extra overlay with the `window'
+;; property with its own `before-string'.
+;; - because that overlay won't *replace* the normal overlay (the one
+;; without the `window' property), we will need to *remove* that
+;; overlay (lest we get 2 before-strings) and replace it with N overlays
+;; with a `window' property (for all N other windows that don't have
+;; their cursor on this line).
+;; FWIW, the original `hexl-mode' has the same kind of problem.
;;; Code:
@@ -90,10 +100,7 @@ Otherwise they are applied unconditionally."
(aset dt ?\t [?␉])
dt))
-(defvar nhexl--saved-vars nil)
-(make-variable-buffer-local 'nhexl--saved-vars)
-(defvar nhexl--point nil)
-(make-variable-buffer-local 'nhexl--point)
+(defvar-local nhexl--saved-vars nil)
;;;; Nibble editing minor mode
@@ -120,18 +127,35 @@ Otherwise they are applied unconditionally."
(kill-local-variable 'cursor-type))
(nhexl--refresh-cursor))
-(defvar-local nhexl--nibble nil)
+(defvar-local nhexl--nibbles nil
+ "Nibble state of the various `point's.
+List of elements of the form (WINDOW OFFSET POINT TICKS),
+where WINDOW can be nil (for the `point' of the buffer itself);
+OFFSET is the nibble-position within the byte at POINT (0 = leftmost);
+and TICKS is the `buffer-chars-modified-tick' for which this was valid.")
(defun nhexl--nibble (&optional pos)
- (or (and (eq (or pos (point)) (nth 1 nhexl--nibble))
- (eq (buffer-chars-modified-tick) (nth 2 nhexl--nibble))
- (nth 0 nhexl--nibble))
- (progn
- (setq nhexl--nibble nil)
- 0)))
+ (let ((cwin (if (eq (current-buffer) (window-buffer)) (selected-window)))
+ (data ()))
+ (dolist (n nhexl--nibbles)
+ (let ((nwin (car n)))
+ (cond
+ ((eq cwin nwin) (setq data n))
+ ((eq (current-buffer) (window-buffer nwin)) nil)
+ (t (setq nhexl--nibbles (delq n nhexl--nibbles))))))
+ (or (and (eq (or pos (point)) (nth 2 data))
+ (eq (buffer-chars-modified-tick) (nth 3 data))
+ (nth 1 data))
+ (progn
+ (setq nhexl--nibbles (delq data nhexl--nibbles))
+ 0))))
(defun nhexl--nibble-set (n)
- (setq nhexl--nibble (list n (point) (buffer-chars-modified-tick))))
+ (let* ((cwin (if (eq (current-buffer) (window-buffer)) (selected-window)))
+ (data (assq cwin nhexl--nibbles)))
+ (unless data
+ (push (setq data (list cwin)) nhexl--nibbles))
+ (setcdr data (list n (point) (buffer-chars-modified-tick)))))
(defsubst nhexl--line-width ()
(if (integerp nhexl-line-width) nhexl-line-width 16))
@@ -302,9 +326,12 @@ existing text, if needed with
`nhexl-overwrite-clear-byte'."
;; but benefit from an ad-hoc implementation.
(define-key map [remap scroll-up-command] #'nhexl-scroll-up)
(define-key map [remap scroll-down-command] #'nhexl-scroll-down)
+ (define-key map [remap mouse-set-point] #'nhexl-mouse-set-point)
;; FIXME: Find a key binding for nhexl-nibble-edit-mode!
map))
+(defvar-local nhexl--point nil)
+
;;;###autoload
(define-minor-mode nhexl-mode
"Minor mode to edit files via hex-dump format"
@@ -318,8 +345,8 @@ existing text, if needed with `nhexl-overwrite-clear-byte'."
(jit-lock-unregister #'nhexl--jit)
(remove-hook 'after-change-functions #'nhexl--change-function 'local)
(remove-hook 'post-command-hook #'nhexl--post-command 'local)
- ;;(remove-hook 'window-configuration-change-hook
- ;; #'nhexl--window-config-change t)
+ (remove-hook 'window-configuration-change-hook
+ #'nhexl--window-config-change t)
(remove-hook 'window-size-change-functions #'nhexl--window-size-change)
(remove-function (local 'isearch-search-fun-function)
#'nhexl--isearch-search-fun)
@@ -355,11 +382,15 @@ existing text, if needed with
`nhexl-overwrite-clear-byte'."
(add-hook 'change-major-mode-hook (lambda () (nhexl-mode -1)) nil 'local)
(add-hook 'post-command-hook #'nhexl--post-command nil 'local)
(add-hook 'after-change-functions #'nhexl--change-function nil 'local)
- ;; (add-hook 'window-configuration-change-hook
- ;; #'nhexl--window-config-change nil 'local)
+ (add-hook 'window-configuration-change-hook
+ #'nhexl--window-config-change nil 'local)
(add-hook 'window-size-change-functions #'nhexl--window-size-change)
(add-function :around (local 'isearch-search-fun-function)
- #'nhexl--isearch-search-fun)))
+ #'nhexl--isearch-search-fun)
+ ;; FIXME: We should delay this to after running the minor-mode hook.
+ (when (and (eq t (default-value 'nhexl-line-width))
+ (eq (current-buffer) (window-buffer)))
+ (nhexl--adjust-to-width))))
(defun nhexl-next-line (&optional arg)
"Move cursor vertically down ARG lines."
@@ -425,6 +456,37 @@ existing text, if needed with
`nhexl-overwrite-clear-byte'."
(nhexl-next-line arg)
(set-window-start nil (min (point-max) nws)))))))
+(defun nhexl-mouse-set-point (event)
+ "Move point to the position clicked on with the mouse."
+ ;; This will select the window if needed and move point to the beginning of
+ ;; the line.
+ (interactive "e")
+ ;; (cl-assert (eq last-))
+ (let* ((posn (event-end event))
+ (str-data (posn-string posn))
+ (addr-offset (eval-when-compile
+ (+ 1 ;for LF
+ 9 ;for "<address>:"
+ 1)))) ;for the following (stretch)space
+ (cond
+ ((and (consp str-data) (stringp (car str-data))
+ (> (length (car str-data)) addr-offset)
+ (eq ?\n (aref (car str-data) 0))
+ (integerp (cdr str-data)) (> (cdr str-data) addr-offset))
+ (let* ((hexchars (- (cdr str-data) addr-offset))
+ ;; FIXME: Calculations here go wrong in the presence of
+ ;; chars with code > 255.
+ (hex-no-spaces (- hexchars (/ (1+ hexchars) 5)))
+ (bytes (min (/ hex-no-spaces 2)
+ ;; Bound, for clicks between the hex and ascii areas.
+ (1- (nhexl--line-width)))))
+ (posn-set-point posn)
+ (forward-char bytes)
+ (when nhexl-nibble-edit-mode
+ (let* ((nibble (- hex-no-spaces (* bytes 2))))
+ (nhexl--nibble-set (min nibble 1))))))
+ (t (call-interactively #'mouse-set-point)))))
+
(defun nhexl--change-function (beg end len)
;; Round modifications up-to the hexl-line length since nhexl--jit will need
;; to modify the overlay that covers that text.
@@ -549,8 +611,7 @@ existing text, if needed with `nhexl-overwrite-clear-byte'."
(defun nhexl--jit (from to)
(let ((zero (save-restriction (widen) (point-min)))
- (lw (nhexl--line-width))
- (has-cursor (and (<= from nhexl--point) (< nhexl--point to))))
+ (lw (nhexl--line-width)))
(setq from (max (point-min)
(+ zero (* (truncate (- from zero) lw) lw))))
(setq to (min (point-max)
@@ -575,7 +636,7 @@ existing text, if needed with `nhexl-overwrite-clear-byte'."
(let* ((next (+ from lw))
(ol (make-overlay from next))
- (s (nhexl--make-line from next zero)))
+ (s (nhexl--make-line from next zero nhexl--point)))
(overlay-put ol 'nhexl t)
(overlay-put ol (if nhexl-obey-font-lock 'font-lock-face 'face)
'hexl-ascii-region)
@@ -586,14 +647,6 @@ existing text, if needed with
`nhexl-overwrite-clear-byte'."
(overlay-put ol 'priority most-negative-fixnum)
(overlay-put ol 'before-string s)
(setq from next)))
-
- (when has-cursor
- (let ((ols (overlays-at nhexl--point))
- ol)
- (dolist (o ols) (if (overlay-get o 'nhexl) (setq ol o)))
- (overlay-put ol 'before-string
- (nhexl--make-line (overlay-start ol) (overlay-end ol)
- zero nhexl--point))))
))
(defun nhexl--refresh-cursor (&optional pos)
@@ -734,6 +787,12 @@ existing text, if needed with
`nhexl-overwrite-clear-byte'."
(when (buffer-local-value 'nhexl-mode (window-buffer win))
(with-selected-window win (nhexl--adjust-to-width))))))
+(defun nhexl--window-config-change ()
+ ;; Doing it only from `window-size-change-functions' is not sufficient
+ ;; because it's not run when you set-window-buffer.
+ (when (eq t (default-value 'nhexl-line-width))
+ (nhexl--adjust-to-width)))
+
(defun nhexl--adjust-to-width ()
;; FIXME: What should we do with buffers displayed in several windows of
;; different width?
- [elpa] externals/nhexl-mode cd15bed 04/23: * nhexl-mode.el: Use cl-lib, (continued)
- [elpa] externals/nhexl-mode cd15bed 04/23: * nhexl-mode.el: Use cl-lib, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 26fe10c 06/23: * nhexl-mode.el: Add our own line-movement functions, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 80d9a10 11/23: * nhexl-mode/nhexl-mode.el (nhexl-line-width): Allow dynamic adjust, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 485c2c1 05/23: * nhexl-mode.el (nhexl-nibble-edit-mode): New minor mode, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 5ae7dc1 07/23: * nhexl-mode.el (nhexl-overwrite-only-mode): New minor mode., Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 4ec0242 08/23: * nhexl-mode.el: Bump version number for new release, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 25704c9 10/23: * nhexl-mode/nhexl-mode.el: Let isearch look for addresses as well, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 16b716f 03/23: nhexl-mode.el: Fix last change., Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode e2450fd 09/23: * nhexl-mode.el: Hide undisplayable chars by default, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 1082cc6 12/23: * nhexl-mode/nhexl-mode.el: Fix minor issues, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 8310ad1 13/23: * nhexl-mode/nhexl-mode.el: Improve multi-window behavior,
Stefan Monnier <=
- [elpa] externals/nhexl-mode 1cb2581 14/23: * nhexl-mode/nhexl-mode.el: Get rid of the spurious top empty line, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 42110aa 16/23: * nhexl-mode.el: Improve handling of mouse events, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode fa39048 17/23: * nhexl-mode.el: Add isearch and highlight to hex area, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 9549cf5 21/23: * packages/nhexl-mode/nhexl-mode.el (nhexl-separate-line): New user config, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode ec80692 22/23: * packages/nhexl-mode/nhexl-mode.el (nhexl-mode-map): Remap EOL/BOL, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 903f1b6 23/23: * .gitignore: New file, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 6c31e4e 15/23: * nhexl-mode.el: Make C-u use hexadecimal, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode d8fa839 18/23: * nhexl-mode/nhexl-mode.el: Fix performance bug#33708, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode c0dac99 20/23: * packages/nhexl-mode/nhexl-mode.el (nhexl-group-size): New user config, Stefan Monnier, 2020/11/28
- [elpa] externals/nhexl-mode 630f003 19/23: * nhexl-mode.el (nhexl-nibble-self-insert): Obey overwrite-mode, Stefan Monnier, 2020/11/28