Mã lisp sau đây đặt một mục "Chế độ tìm kiếm Hexl" vào menu "Hexl".
Mục menu đó (de-) kích hoạt chế độ nhỏ hexl-isearch-mode
. Nếu bạn kích hoạt chế độ isearch
tìm kiếm đó trong dữ liệu nhị phân thay vì bộ đệm hexl.
Chuỗi tìm kiếm được đọc với read
. Vì vậy, tất cả các chuỗi thoát cho chuỗi lisp làm việc. Để làm ví dụ, bạn có thể tìm kiếm \x0a\x0d
hoặc \^M\n
tìm kiếm kết thúc dòng dos.
Mã không hoàn hảo.
Giả sử bạn tìm kiếm một chuỗi ELF\x01
chỉ xảy ra ở đầu tệp. Hơn nữa, giả sử có một chuỗi ELf\x00
sau này trong nhị phân. Sau đó, khi bạn đến ELF\x0
bằng cách gõ Emacs sẽ tìm thấy kết quả khớp sau và nếu bạn tiếp tục gõ ELF\x01
Emacs nghĩ rằng không có sự xuất hiện của chuỗi đó vì nó đã đến ELF\x0
sau trong tệp hơn ELF\x01
. Đó là giá trị để thực hiện một tìm kiếm chồng chéo trong trường hợp như vậy. (Sự cố đó đã được khắc phục trong phiên bản git của gói .)
Chỉ chuỗi byte được chiếu sáng chính xác trong bộ đệm hexl chứ không phải biểu diễn chuỗi ở phía bên tay phải.
Nếu chuỗi tìm kiếm kéo dài hai dòng trong bộ đệm hexl, biểu diễn chuỗi ở cuối dòng và địa chỉ ở đầu dòng cũng được tô sáng. Đó không phải là vì chúng thuộc về trận đấu mà bởi vì chúng nằm trong cách làm nổi bật chuỗi byte.
(require 'hexl)
(defvar-local hexl-isearch-raw-buffer nil
"Buffer with the dehexlified content of the hexl buffer for hexl-isearch-mode.
This variable is set in the original hexl-mode buffer.")
(defvar-local hexl-isearch-original-buffer nil
"This variable is set in the buffer with the dehexlified content.
It points to the corresponding hexl buffer.")
(defun hexl-address (position)
"Return address of hexl buffer POSITION."
(save-excursion
(goto-char position)
(hexl-current-address)))
(defun hexl-isearch-startup ()
"Prepare hexl buffer for `hexl-isearch'."
(let ((original-buf (current-buffer)))
(setq-local hexl-isearch-raw-buffer (generate-new-buffer " hexl"))
(setq-local isearch-search-fun-function (lambda () #'hexl-isearch-fun))
(with-current-buffer hexl-isearch-raw-buffer
(set-buffer-multibyte nil)
(setq-local hexl-isearch-original-buffer original-buf)
(insert-buffer-substring original-buf 1 (buffer-size original-buf))
(dehexlify-buffer))))
(defun hexl-isearch-end ()
"Cleanup after `hexl-isearch'."
(let ((isearch-raw-buffer hexl-isearch-raw-buffer))
(setq-local hexl-isearch-raw-buffer nil)
(when (buffer-live-p isearch-raw-buffer)
(kill-buffer isearch-raw-buffer))))
(defun hexl-isearch-fun (string &optional bound noerror count)
"Search for byte sequence of STRING in hexl buffer.
The arguments BOUND and NOERROR work like in `search-forward'."
(when bound (setq bound (1+ (hexl-address bound))))
(setq string (read (concat "\"" string "\"")))
(let ((point (1+ (hexl-current-address)))
match-data)
(with-current-buffer hexl-isearch-raw-buffer
(goto-char point)
(setq point (funcall (if isearch-forward #'re-search-forward #'re-search-backward)
(if isearch-regexp
string
(regexp-quote string))
bound noerror count))
(setq match-data (match-data t nil t)))
(when point
(prog1
(hexl-goto-address (1- point))
(set-match-data
(mapcar (lambda (el)
(if (integerp el)
(hexl-address-to-marker (1- el))
el))
match-data))))))
(define-minor-mode hexl-isearch-mode
"Search for binary string with isearch in hexl buffer."
:lighter " hi"
(if hexl-isearch-mode
(progn
(setq-local isearch-search-fun-function #'hexl-isearch-fun)
(add-hook 'isearch-mode-hook #'hexl-isearch-startup t t)
(add-hook 'isearch-mode-end-hook #'hexl-isearch-end t t))
(setq-local isearch-search-fun-function #'isearch-search-fun-default)
(remove-hook 'isearch-mode-hook #'hexl-isearch-startup t)
(remove-hook 'isearch-mode-end-hook #'hexl-isearch-end t)))
(easy-menu-add-item hexl-mode-map '(menu-bar Hexl)
["Hexl Isearch Mode" (if hexl-isearch-mode (hexl-isearch-mode -1) (hexl-isearch-mode)) :style toggle :selected hexl-isearch-mode] "Go to address")