Подтвердить что ты не робот

Как я могу эмулировать поиск Vim * в GNU Emacs?

В Vim клавиша * в обычном режиме выполняет поиск слова под курсором. В GNU Emacs ближайшим родным эквивалентом будет:

C-s C-w

Но это не совсем то же самое. Он открывает мини-буфер инкрементного поиска и копирует курсор в текущем буфере до конца слова. В Vim вы искали бы все слово, даже если вы находитесь посреди слова, когда вы нажимаете *.

Я приготовил немного elisp, чтобы сделать что-то подобное:

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

Это отходит назад до начала слова перед тем, как начать поиск. Я привязал его к С++, который легко набирать на клавиатуре и похож на *, поэтому, когда я набираю C-+ C-w, он копирует с начала слова в мини-буфер поиска.

Однако это все еще не идеально. В идеале он будет искать regexp для "\<" word "\>", чтобы не показывать частичные совпадения (поиск слова "bar" не должен соответствовать "foobar", просто "bar" сам по себе). Я попытался использовать search-forward-regexp и concat'ing\< > но это не обернуто в файл, не выделяет совпадения и, как правило, довольно хромым. Функция isearch- * кажется лучшим выбором, но при написании сценариев они плохо себя ведут.

Любые идеи? Может ли кто-нибудь предложить какие-либо улучшения в бит elisp? Или есть другой способ, который я забыл?

4b9b3361

Ответ 1

Основываясь на ваших отзывах на мой первый ответ, как насчет этого:

(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)

Ответ 2

выделить символ Расширение emacs обеспечивает эту функциональность. В частности, рекомендуется установить .emacsrc:

(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)

Позволяет перейти к следующему символу в текущей точке (F3), перепрыгивая на предыдущий символ (Shift + F3) или выделяя символы, соответствующие одному под курсором (Ctrl + F3). Команды продолжают делать правильные вещи, если ваш курсор находится в середине слова.

В отличие от суперзвезды vim, выделение символов и переключение между символами связаны с двумя разными командами. Я лично не против разделения, но вы можете связать две команды под тем же нажатием клавиши, если хотите точно совместить поведение vim.

Ответ 4

Ответ scottfrazer хорошо работает для меня, за исключением слов, которые заканчиваются на "_" (или, возможно, на других неглавных символах?). Я обнаружил, что код для режима с символами света использует другое регулярное выражение для границы слова в зависимости от версии emacs и исправил его для меня. Вот модифицированный код:

(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)

Ответ 5

Как насчет встроенных команд M-b C-s C-w (начало слова, поиск, поиск слов)

Ответ 6

Микки из Освоение Emacs в блоге вновь появилось классное " Smart Scan "lib, которая дает глобальные привязки M-n и M-p для навигации по символам под курсором в буфере. Не влияет на регистр поиска, поэтому он не заменяет * как есть, а умную и полезную альтернативу проблеме навигации.

Ответ 7

Я не пробовал, но есть код здесь под названием Grep-O-Matic.

Ответ 8

С этим вы должны иметь возможность выполнять C- * в режиме поиска.

(define-key isearch-mode-map [?\C-*] 'kmk-isearch-yank-thing)

(defun kmk-isearch-yank-thing ()
  "Pull next thing from buffer into search string."
  (interactive)
  (let ((string (regexp-quote (thing-at-point 'word))))
    (setq isearch-string 
      (concat isearch-string "\\")
      isearch-message
      (concat isearch-message
          (mapconcat 'isearch-text-char-description
                 string ""))
      ;; Don't move cursor in reverse search.
      isearch-yank-flag t))
  (setq isearch-regexp t isearch-word nil isearch-success t isearch-adjusted t)
  (isearch-search-and-update))

Ответ 9

;Here is my version: Emulates Visual Studio/Windows key bindings 
; C-F3 - Start searching the word at the point
; F3 searches forward and Shift F3 goes reverse

(setq my-search-wrap nil)

(defun my-search-func (dir)
  (interactive)
  (let* ((text (car search-ring)) newpoint)
        (when my-search-wrap  
             (goto-char (if (= dir 1) (point-min) (point-max)))
             (setq my-search-wrap nil))
        (setq newpoint (search-forward text nil t dir))
        (if newpoint
          (set-mark (if (= dir 1) (- newpoint (length text))
                         (+ newpoint (length text))))
          (message "Search Failed: %s" text) (ding)
          (setq my-search-wrap text))))

(defun my-search-fwd () (interactive) (my-search-func 1))
(defun my-search-bwd () (interactive) (my-search-func -1))

(defun yank-thing-into-search ()
   (interactive)
   (let ((text (if mark-active
          (buffer-substring-no-properties (region-beginning)(region-end))
                 (or (current-word) ""))))
     (when (> (length text) 0) (isearch-update-ring text) (setq my-search-wrap nil)
            (my-search-fwd))))
(global-set-key (kbd "")    'my-search-fwd)            ; Visual Studio like search keys
(global-set-key (kbd "")  'my-search-bwd)
(global-set-key (kbd "")  'yank-thing-into-search)