diff options
| author | Vivek Dasmohapatra | 2012-04-12 17:58:53 +0200 |
|---|---|---|
| committer | Lars Magne Ingebrigtsen | 2012-04-12 17:58:53 +0200 |
| commit | 0d15b5ba4d6ef49b2cc398dca9181acb353658d1 (patch) | |
| tree | 626fe94875fe75b16216f925a40900da54acca19 | |
| parent | 64a440db710570f2a38cb604ad876d35bc99daab (diff) | |
| download | emacs-0d15b5ba4d6ef49b2cc398dca9181acb353658d1.tar.gz emacs-0d15b5ba4d6ef49b2cc398dca9181acb353658d1.zip | |
Allow the user to alter the bit grouping in hexl.el
* hexl.el (hexl-bits): New variable.
(hexl-options): Mention the variable in the doc string.
(hexl-rulerise): New function.
(hexl-line-displen): New function
(hexl-mode): Mention the new variable.
(hexl-mode, hexl-current-address, hexl-current-address): Use the
displen.
(hexl-ascii-start-column): New function.
(hexl-address-to-marker, hexl-beginning-of-line, hexl-options)
(hexl-insert-char, hexl-mode-ruler): Use the displen.
Fixes: debbugs:4941
| -rw-r--r-- | lisp/ChangeLog | 13 | ||||
| -rw-r--r-- | lisp/hexl.el | 105 |
2 files changed, 93 insertions, 25 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1f6b7d3dfaf..0e50a9e7ada 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,16 @@ | |||
| 1 | 2012-04-12 Vivek Dasmohapatra <vivek@etla.org> | ||
| 2 | |||
| 3 | * hexl.el (hexl-bits): New variable. | ||
| 4 | (hexl-options): Mention the variable in the doc string. | ||
| 5 | (hexl-rulerise): New function. | ||
| 6 | (hexl-line-displen): New function | ||
| 7 | (hexl-mode): Mention the new variable. | ||
| 8 | (hexl-mode, hexl-current-address, hexl-current-address): Use the | ||
| 9 | displen. | ||
| 10 | (hexl-ascii-start-column): New function. | ||
| 11 | (hexl-address-to-marker, hexl-beginning-of-line, hexl-options) | ||
| 12 | (hexl-insert-char, hexl-mode-ruler): Use the displen (bug#4941). | ||
| 13 | |||
| 1 | 2012-04-12 Agustín Martín Domingo <agustin.martin@hispalinux.es> | 14 | 2012-04-12 Agustín Martín Domingo <agustin.martin@hispalinux.es> |
| 2 | 15 | ||
| 3 | * textmodes/flyspell.el (flyspell-large-region): For hunspell, use | 16 | * textmodes/flyspell.el (flyspell-large-region): For hunspell, use |
diff --git a/lisp/hexl.el b/lisp/hexl.el index 538d218e38e..db4f3319b79 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el | |||
| @@ -51,6 +51,13 @@ | |||
| 51 | "Edit a file in a hex dump format using the hexl filter." | 51 | "Edit a file in a hex dump format using the hexl filter." |
| 52 | :group 'data) | 52 | :group 'data) |
| 53 | 53 | ||
| 54 | (defcustom hexl-bits 16 | ||
| 55 | "The bit grouping that hexl will use." | ||
| 56 | :type '(choice (const 8 ) | ||
| 57 | (const 16) | ||
| 58 | (const 32) | ||
| 59 | (const 64)) | ||
| 60 | :group 'hexl) | ||
| 54 | 61 | ||
| 55 | (defcustom hexl-program "hexl" | 62 | (defcustom hexl-program "hexl" |
| 56 | "The program that will hexlify and dehexlify its stdin. | 63 | "The program that will hexlify and dehexlify its stdin. |
| @@ -67,7 +74,9 @@ and \"-de\" when dehexlifying a buffer." | |||
| 67 | 74 | ||
| 68 | (defcustom hexl-options (format "-hex %s" hexl-iso) | 75 | (defcustom hexl-options (format "-hex %s" hexl-iso) |
| 69 | "Space separated options to `hexl-program' that suit your needs. | 76 | "Space separated options to `hexl-program' that suit your needs. |
| 70 | Quoting cannot be used, so the arguments cannot themselves contain spaces." | 77 | Quoting cannot be used, so the arguments cannot themselves contain spaces. |
| 78 | If you wish to set the `-group-by-X-bits' options, set `hexl-bits' instead, | ||
| 79 | as that will override any bit grouping options set here." | ||
| 71 | :type 'string | 80 | :type 'string |
| 72 | :group 'hexl) | 81 | :group 'hexl) |
| 73 | 82 | ||
| @@ -212,10 +221,34 @@ Quoting cannot be used, so the arguments cannot themselves contain spaces." | |||
| 212 | (2 'hexl-ascii-region t t))) | 221 | (2 'hexl-ascii-region t t))) |
| 213 | "Font lock keywords used in `hexl-mode'.") | 222 | "Font lock keywords used in `hexl-mode'.") |
| 214 | 223 | ||
| 224 | (defun hexl-rulerise (string bits) | ||
| 225 | (let ((size (/ bits 4)) (strlen (length string)) (pos 0) (ruler "")) | ||
| 226 | (while (< pos strlen) | ||
| 227 | (setq ruler (concat ruler " " (substring string pos (+ pos size)))) | ||
| 228 | (setq pos (+ pos size))) | ||
| 229 | (substring ruler 1) )) | ||
| 230 | |||
| 231 | (defvar hexl-rulers | ||
| 232 | (mapcar | ||
| 233 | (lambda (bits) | ||
| 234 | (cons bits | ||
| 235 | (concat " 87654321 " | ||
| 236 | (hexl-rulerise "00112233445566778899aabbccddeeff" bits) | ||
| 237 | " 0123456789abcdef"))) | ||
| 238 | '(8 16 32 64))) | ||
| 215 | ;; routines | 239 | ;; routines |
| 216 | 240 | ||
| 217 | (put 'hexl-mode 'mode-class 'special) | 241 | (put 'hexl-mode 'mode-class 'special) |
| 218 | 242 | ||
| 243 | ;; 10 chars for the "address: " | ||
| 244 | ;; 32 chars for the hexlified bytes | ||
| 245 | ;; 1 char for the space | ||
| 246 | ;; 16 chars for the character display | ||
| 247 | ;; X chars for the spaces (128 bits divided by the hexl-bits) | ||
| 248 | ;; 1 char for the newline. | ||
| 249 | (defun hexl-line-displen () | ||
| 250 | "The length of a hexl display line (varies with `hexl-bits')." | ||
| 251 | (+ 60 (/ 128 (or hexl-bits 16)))) | ||
| 219 | 252 | ||
| 220 | (defun hexl-mode--minor-mode-p (var) | 253 | (defun hexl-mode--minor-mode-p (var) |
| 221 | (memq var '(ruler-mode hl-line-mode))) | 254 | (memq var '(ruler-mode hl-line-mode))) |
| @@ -248,7 +281,7 @@ using the function `hexlify-buffer'. | |||
| 248 | Each line in the buffer has an \"address\" (displayed in hexadecimal) | 281 | Each line in the buffer has an \"address\" (displayed in hexadecimal) |
| 249 | representing the offset into the file that the characters on this line | 282 | representing the offset into the file that the characters on this line |
| 250 | are at and 16 characters from the file (displayed as hexadecimal | 283 | are at and 16 characters from the file (displayed as hexadecimal |
| 251 | values grouped every 16 bits) and as their ASCII values. | 284 | values grouped every `hexl-bits' bits) and as their ASCII values. |
| 252 | 285 | ||
| 253 | If any of the characters (displayed as ASCII characters) are | 286 | If any of the characters (displayed as ASCII characters) are |
| 254 | unprintable (control or meta characters) they will be replaced as | 287 | unprintable (control or meta characters) they will be replaced as |
| @@ -330,10 +363,7 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode. | |||
| 330 | (hexlify-buffer) | 363 | (hexlify-buffer) |
| 331 | (restore-buffer-modified-p modified)) | 364 | (restore-buffer-modified-p modified)) |
| 332 | (set (make-local-variable 'hexl-max-address) | 365 | (set (make-local-variable 'hexl-max-address) |
| 333 | (let* ((full-lines (/ (buffer-size) 68)) | 366 | (+ (* (/ (1- (buffer-size)) (hexl-line-displen)) 16) 15)) |
| 334 | (last-line (% (buffer-size) 68)) | ||
| 335 | (last-line-bytes (% last-line 52))) | ||
| 336 | (+ last-line-bytes (* full-lines 16) -1))) | ||
| 337 | (condition-case nil | 367 | (condition-case nil |
| 338 | (hexl-goto-address original-point) | 368 | (hexl-goto-address original-point) |
| 339 | (error nil))) | 369 | (error nil))) |
| @@ -510,17 +540,20 @@ Ask the user for confirmation." | |||
| 510 | (defun hexl-current-address (&optional validate) | 540 | (defun hexl-current-address (&optional validate) |
| 511 | "Return current hexl-address." | 541 | "Return current hexl-address." |
| 512 | (interactive) | 542 | (interactive) |
| 513 | (let ((current-column (- (% (- (point) (point-min) -1) 68) 11)) | 543 | (let ((current-column |
| 544 | (- (% (- (point) (point-min) -1) (hexl-line-displen)) 11)) | ||
| 514 | (hexl-address 0)) | 545 | (hexl-address 0)) |
| 515 | (if (< current-column 0) | 546 | (if (< current-column 0) |
| 516 | (if validate | 547 | (if validate |
| 517 | (error "Point is not on a character in the file") | 548 | (error "Point is not on a character in the file") |
| 518 | (setq current-column 0))) | 549 | (setq current-column 0))) |
| 519 | (setq hexl-address | 550 | (setq hexl-address |
| 520 | (+ (* (/ (- (point) (point-min) -1) 68) 16) | 551 | (+ (* (/ (- (point) (point-min) -1) |
| 521 | (if (>= current-column 41) | 552 | (hexl-line-displen)) 16) |
| 522 | (- current-column 41) | 553 | (if (>= current-column (- (hexl-ascii-start-column) 10)) |
| 523 | (/ (- current-column (/ current-column 5)) 2)))) | 554 | (- current-column (- (hexl-ascii-start-column) 10)) |
| 555 | (/ (- current-column | ||
| 556 | (/ current-column (1+ (/ hexl-bits 4)))) 2)))) | ||
| 524 | (when (called-interactively-p 'interactive) | 557 | (when (called-interactively-p 'interactive) |
| 525 | (message "Current address is %d/0x%08x" hexl-address hexl-address)) | 558 | (message "Current address is %d/0x%08x" hexl-address hexl-address)) |
| 526 | hexl-address)) | 559 | hexl-address)) |
| @@ -531,10 +564,18 @@ This function is intended to be used as eldoc callback." | |||
| 531 | (let ((addr (hexl-current-address))) | 564 | (let ((addr (hexl-current-address))) |
| 532 | (format "Current address is %d/0x%08x" addr addr))) | 565 | (format "Current address is %d/0x%08x" addr addr))) |
| 533 | 566 | ||
| 567 | (defun hexl-ascii-start-column () | ||
| 568 | "Column at which the ascii portion of the hexl display starts." | ||
| 569 | (+ 43 (/ 128 hexl-bits))) | ||
| 570 | |||
| 534 | (defun hexl-address-to-marker (address) | 571 | (defun hexl-address-to-marker (address) |
| 535 | "Return buffer position for ADDRESS." | 572 | "Return buffer position for ADDRESS." |
| 536 | (interactive "nAddress: ") | 573 | (interactive "nAddress: ") |
| 537 | (+ (* (/ address 16) 68) 10 (point-min) (/ (* (% address 16) 5) 2))) | 574 | (let ((N (* (% address 16) 2))) |
| 575 | (+ (* (/ address 16) (hexl-line-displen)) ; hexl line no * display length | ||
| 576 | 10 ; 10 chars for the "address: " prefix | ||
| 577 | (point-min) ; base offset (point usually starts at 1, not 0) | ||
| 578 | (+ N (/ N (/ hexl-bits 4))) )) ) ; char offset into hexl display line | ||
| 538 | 579 | ||
| 539 | (defun hexl-goto-address (address) | 580 | (defun hexl-goto-address (address) |
| 540 | "Go to hexl-mode (decimal) address ADDRESS. | 581 | "Go to hexl-mode (decimal) address ADDRESS. |
| @@ -700,7 +741,7 @@ With prefix arg N, puts point N bytes of the way from the true beginning." | |||
| 700 | (defun hexl-beginning-of-line () | 741 | (defun hexl-beginning-of-line () |
| 701 | "Goto beginning of line in hexl mode." | 742 | "Goto beginning of line in hexl mode." |
| 702 | (interactive) | 743 | (interactive) |
| 703 | (goto-char (+ (* (/ (point) 68) 68) 11))) | 744 | (goto-char (+ (* (/ (point) (hexl-line-displen)) (hexl-line-displen)) 11))) |
| 704 | 745 | ||
| 705 | (defun hexl-end-of-line () | 746 | (defun hexl-end-of-line () |
| 706 | "Goto end of line in hexl mode." | 747 | "Goto end of line in hexl mode." |
| @@ -776,6 +817,17 @@ You may also type octal digits, to insert a character with that code." | |||
| 776 | 817 | ||
| 777 | ;00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789ABCDEF | 818 | ;00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789ABCDEF |
| 778 | 819 | ||
| 820 | (defun hexl-options (&optional test) | ||
| 821 | "Combine `hexl-bits' with `hexl-options', altering `hexl-options' as needed | ||
| 822 | to produce the command line options to pass to the hexl command." | ||
| 823 | (let ((opts (or test hexl-options))) | ||
| 824 | (when (memq hexl-bits '(8 16 32 64)) | ||
| 825 | (when (string-match "\\(.*\\)-group-by-[0-9]+-bits\\(.*\\)" opts) | ||
| 826 | (setq opts (concat (match-string 1 opts) | ||
| 827 | (match-string 2 opts)))) | ||
| 828 | (setq opts (format "%s -group-by-%d-bits " opts hexl-bits)) ) | ||
| 829 | opts)) | ||
| 830 | |||
| 779 | ;;;###autoload | 831 | ;;;###autoload |
| 780 | (defun hexlify-buffer () | 832 | (defun hexlify-buffer () |
| 781 | "Convert a binary buffer to hexl format. | 833 | "Convert a binary buffer to hexl format. |
| @@ -798,7 +850,7 @@ This discards the buffer's undo information." | |||
| 798 | (mapcar (lambda (s) | 850 | (mapcar (lambda (s) |
| 799 | (if (not (multibyte-string-p s)) s | 851 | (if (not (multibyte-string-p s)) s |
| 800 | (encode-coding-string s locale-coding-system))) | 852 | (encode-coding-string s locale-coding-system))) |
| 801 | (split-string hexl-options))) | 853 | (split-string (hexl-options)))) |
| 802 | (if (> (point) (hexl-address-to-marker hexl-max-address)) | 854 | (if (> (point) (hexl-address-to-marker hexl-max-address)) |
| 803 | (hexl-goto-address hexl-max-address)))) | 855 | (hexl-goto-address hexl-max-address)))) |
| 804 | 856 | ||
| @@ -815,7 +867,7 @@ This discards the buffer's undo information." | |||
| 815 | (buffer-undo-list t)) | 867 | (buffer-undo-list t)) |
| 816 | (apply 'call-process-region (point-min) (point-max) | 868 | (apply 'call-process-region (point-min) (point-max) |
| 817 | (expand-file-name hexl-program exec-directory) | 869 | (expand-file-name hexl-program exec-directory) |
| 818 | t t nil "-de" (split-string hexl-options)))) | 870 | t t nil "-de" (split-string (hexl-options))))) |
| 819 | 871 | ||
| 820 | (defun hexl-char-after-point () | 872 | (defun hexl-char-after-point () |
| 821 | "Return char for ASCII hex digits at point." | 873 | "Return char for ASCII hex digits at point." |
| @@ -912,12 +964,15 @@ CH must be a unibyte character whose value is between 0 and 255." | |||
| 912 | (let ((address (hexl-current-address t))) | 964 | (let ((address (hexl-current-address t))) |
| 913 | (while (> num 0) | 965 | (while (> num 0) |
| 914 | (let ((hex-position | 966 | (let ((hex-position |
| 915 | (+ (* (/ address 16) 68) | 967 | (+ (* (/ address 16) (hexl-line-displen)) |
| 916 | 10 (point-min) | 968 | 10 (point-min) |
| 917 | (* 2 (% address 16)) | 969 | (* 2 (% address 16)) |
| 918 | (/ (% address 16) 2))) | 970 | (/ (% address 16) 2))) |
| 919 | (ascii-position | 971 | (ascii-position |
| 920 | (+ (* (/ address 16) 68) 51 (point-min) (% address 16))) | 972 | (+ (* (/ address 16) (hexl-line-displen)) |
| 973 | (hexl-ascii-start-column) | ||
| 974 | (point-min) | ||
| 975 | (% address 16))) | ||
| 921 | at-ascii-position) | 976 | at-ascii-position) |
| 922 | (if (= (point) ascii-position) | 977 | (if (= (point) ascii-position) |
| 923 | (setq at-ascii-position t)) | 978 | (setq at-ascii-position t)) |
| @@ -933,7 +988,7 @@ CH must be a unibyte character whose value is between 0 and 255." | |||
| 933 | (if at-ascii-position | 988 | (if at-ascii-position |
| 934 | (progn | 989 | (progn |
| 935 | (beginning-of-line) | 990 | (beginning-of-line) |
| 936 | (forward-char 51) | 991 | (forward-char (hexl-ascii-start-column)) |
| 937 | (forward-char (% address 16))))) | 992 | (forward-char (% address 16))))) |
| 938 | (setq num (1- num))))) | 993 | (setq num (1- num))))) |
| 939 | 994 | ||
| @@ -1041,7 +1096,7 @@ This function is assumed to be used as callback function for `hl-line-mode'." | |||
| 1041 | 1096 | ||
| 1042 | (defun hexl-follow-ascii-find () | 1097 | (defun hexl-follow-ascii-find () |
| 1043 | "Find and highlight the ASCII element corresponding to current point." | 1098 | "Find and highlight the ASCII element corresponding to current point." |
| 1044 | (let ((pos (+ 51 | 1099 | (let ((pos (+ (hexl-ascii-start-column) |
| 1045 | (- (point) (current-column)) | 1100 | (- (point) (current-column)) |
| 1046 | (mod (hexl-current-address) 16)))) | 1101 | (mod (hexl-current-address) 16)))) |
| 1047 | (move-overlay hexl-ascii-overlay pos (1+ pos)) | 1102 | (move-overlay hexl-ascii-overlay pos (1+ pos)) |
| @@ -1050,7 +1105,7 @@ This function is assumed to be used as callback function for `hl-line-mode'." | |||
| 1050 | (defun hexl-mode-ruler () | 1105 | (defun hexl-mode-ruler () |
| 1051 | "Return a string ruler for hexl mode." | 1106 | "Return a string ruler for hexl mode." |
| 1052 | (let* ((highlight (mod (hexl-current-address) 16)) | 1107 | (let* ((highlight (mod (hexl-current-address) 16)) |
| 1053 | (s " 87654321 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789abcdef") | 1108 | (s (cdr (assq hexl-bits hexl-rulers))) |
| 1054 | (pos 0)) | 1109 | (pos 0)) |
| 1055 | (set-text-properties 0 (length s) nil s) | 1110 | (set-text-properties 0 (length s) nil s) |
| 1056 | ;; Turn spaces in the header into stretch specs so they work | 1111 | ;; Turn spaces in the header into stretch specs so they work |
| @@ -1062,12 +1117,12 @@ This function is assumed to be used as callback function for `hl-line-mode'." | |||
| 1062 | `(space :align-to ,(1- pos)) | 1117 | `(space :align-to ,(1- pos)) |
| 1063 | s)) | 1118 | s)) |
| 1064 | ;; Highlight the current column. | 1119 | ;; Highlight the current column. |
| 1065 | (put-text-property (+ 11 (/ (* 5 highlight) 2)) | 1120 | (let ( (offset (+ (* 2 highlight) (/ (* 8 highlight) hexl-bits))) ) |
| 1066 | (+ 13 (/ (* 5 highlight) 2)) | 1121 | (put-text-property (+ 11 offset) (+ 13 offset) 'face 'highlight s)) |
| 1067 | 'face 'highlight s) | ||
| 1068 | ;; Highlight the current ascii column | 1122 | ;; Highlight the current ascii column |
| 1069 | (put-text-property (+ 13 39 highlight) (+ 13 40 highlight) | 1123 | (put-text-property (+ (hexl-ascii-start-column) highlight 1) |
| 1070 | 'face 'highlight s) | 1124 | (+ (hexl-ascii-start-column) highlight 2) |
| 1125 | 'face 'highlight s) | ||
| 1071 | s)) | 1126 | s)) |
| 1072 | 1127 | ||
| 1073 | ;; startup stuff. | 1128 | ;; startup stuff. |