Pregunta ¿Cómo puedo emular la búsqueda de Vim * en GNU Emacs?


En Vim, la tecla * en el modo normal busca la palabra debajo del cursor. En GNU Emacs, el equivalente nativo más cercano sería:

C-s C-w

Pero eso no es lo mismo. Abre el mini búfer de búsqueda incremental y copia desde el cursor en el búfer actual hasta el final de la palabra. En Vim buscarías la palabra completa, incluso si estás en medio de la palabra cuando presionas *.

He cocinado un poco de elisp para hacer algo similar:

(defun find-word-under-cursor (arg)
  (interactive "p")
  (if (looking-at "\\<") () (re-search-backward "\\<" (point-min)))
  (isearch-forward))

Que trota hacia atrás hasta el comienzo de la palabra antes de disparar la búsqueda. Lo he vinculado a C- +, que es fácil de escribir en mi teclado y similar a *, así que cuando escribo C-+ C-w copia desde el comienzo de la palabra al mini-buffer de búsqueda.

Sin embargo, esto todavía no es perfecto. Lo ideal sería regexp buscar "\<" word "\>" para no mostrar coincidencias parciales (la búsqueda de la palabra "barra" no debe coincidir con "foobar", solo "barra" en sí misma). Intenté usar search-forward-regexp y concat'ing \ <>, pero esto no se ajusta al archivo, no resalta las coincidencias y generalmente es bastante cojo. Una función isearch- * parece ser la mejor opción, pero no se comportan bien cuando se escriben.

¿Algunas ideas? ¿Alguien puede ofrecer alguna mejora en el bit de elisp? ¿O hay alguna otra forma que he pasado por alto?


32
2018-02-26 08:49


origen


Respuestas:


En base a sus comentarios a mi primera respuesta, ¿qué tal esto?

(defun my-isearch-word-at-point ()
  (interactive)
  (call-interactively 'isearch-forward-regexp))

(defun my-isearch-yank-word-hook ()
  (when (equal this-command 'my-isearch-word-at-point)
    (let ((string (concat "\\<"
                          (buffer-substring-no-properties
                           (progn (skip-syntax-backward "w_") (point))
                           (progn (skip-syntax-forward "w_") (point)))
                          "\\>")))
      (if (and isearch-case-fold-search
               (eq 'not-yanks search-upper-case))
          (setq string (downcase string)))
      (setq isearch-string string
            isearch-message
            (concat isearch-message
                    (mapconcat 'isearch-text-char-description
                               string ""))
            isearch-yank-flag t)
      (isearch-search-and-update))))

(add-hook 'isearch-mode-hook 'my-isearch-yank-word-hook)

15
2018-02-26 15:07



los símbolo de resaltado La extensión de emacs proporciona esta funcionalidad. En particular, la recomendación .emacsrc preparar:

(require 'highlight-symbol)

(global-set-key [(control f3)] 'highlight-symbol-at-point)
(global-set-key [f3] 'highlight-symbol-next)
(global-set-key [(shift f3)] 'highlight-symbol-prev)

Permite saltar al siguiente símbolo en el punto actual (F3), saltando al símbolo anterior (Shift + F3) o resaltando símbolos que coinciden con el que está debajo del cursor (Ctrl + F3). Los comandos continúan haciendo lo correcto si el cursor es de la mitad de la palabra.

A diferencia de la super estrella de vim, resaltar símbolos y saltar entre símbolos están vinculados a dos comandos diferentes. Personalmente, no me importa la separación, pero podrías unir los dos comandos con la misma pulsación de tecla si quisieras hacer coincidir exactamente el comportamiento de vim.


7
2018-06-11 05:55



Hay muchas formas de hacer esto:

http://www.emacswiki.org/emacs/SearchAtPoint


5
2018-02-26 12:41



La respuesta de scottfrazer funciona bien para mí, a excepción de las palabras que terminan en '_' (¿o tal vez otros caracteres que no son palabras?). Descubrí que el código para el modo símbolo de luz usaba una expresión regular diferente para el límite de palabras, según la versión de emacs, y eso me lo solucionó. Aquí está el código modificado:

(defconst my-isearch-rx-start
  (if (< emacs-major-version 22)
      "\\<"
    "\\_<")
  "Start-of-symbol regular expression marker.")

(defconst my-isearch-rx-end
  (if (< emacs-major-version 22)
      "\\>"
    "\\_>")
  "End-of-symbol regular expression marker.")

(defun my-isearch-word-at-point ()
  (interactive)
  (call-interactively 'isearch-forward-regexp))

(defun my-isearch-yank-word-hook ()
  (when (equal this-command 'my-isearch-word-at-point)
    (let ((string (concat my-isearch-rx-start
                          (buffer-substring-no-properties
                           (progn (skip-syntax-backward "w_") (point))
                           (progn (skip-syntax-forward "w_") (point)))
                          my-isearch-rx-end)))
      (if (and isearch-case-fold-search
               (eq 'not-yanks search-upper-case))
          (setq string (downcase string)))
      (setq isearch-string string
            isearch-message
            (concat isearch-message
                    (mapconcat 'isearch-text-char-description
                               string ""))
            isearch-yank-flag t)
      (isearch-search-and-update))))

(add-hook 'isearch-mode-hook 'my-isearch-yank-word-hook)

3
2017-09-02 19:19



¿Qué hay de los comandos integrados M-b C-s C-w (inicio de la palabra, búsqueda, búsqueda de palabras)


2
2018-05-11 18:49



Mickey de Dominando Emacs blog reintrodujo un genial "Escaneo inteligente"lib que da enlaces globales de M-n y M-p para navegar símbolos debajo del cursor en el buffer. No afecta el registro de búsqueda por lo que no es un * reemplazo tal cual, pero una alternativa inteligente y utilizable al problema de navegación.


2
2017-11-05 09:02



No lo he intentado, pero hay algún código aquí llamado Grep-O-Matic.


1
2018-02-26 09:14