O código lisp a seguir coloca uma entrada "Hexl Isearch Mode" no menu "Hexl".
Esse item de menu (des-) ativa o modo secundário hexl-isearch-mode. Se você ativar esse modo, isearchprocurará nos dados binários em vez do buffer hexl.
A cadeia de pesquisa é lida com read. Portanto, todas as seqüências de escape para strings lisp funcionam. Como exemplo, você pode procurar \x0a\x0dou \^M\npesquisar por finais da linha dos.
O código não é perfeito.
Digamos que você pesquise uma string ELF\x01que só ocorra no início de um arquivo. Além disso, suponha que exista uma string ELf\x00posteriormente no binário. Então, quando você ELF\x0digitar o Emacs, encontrará a correspondência posterior e, se continuar digitando, o ELF\x01Emacs acha que não há ocorrências dessa string, porque ela já chegou ao ELF\x0que vem depois no arquivo ELF\x01. Vale a pena fazer uma pesquisa sobreposta nesse caso. (Esse problema já foi corrigido na versão git do pacote .)
Somente a sequência de bytes é iluminada corretamente no buffer hexl, e não na representação de string no lado direito.
Se a cadeia de pesquisa se estender por duas linhas no buffer hexl, a representação da cadeia no final da linha e o endereço no início da linha também serão destacados. Isso não ocorre porque eles pertencem à correspondência, mas porque eles estão no caminho ao destacar a sequência de bytes.
(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")