Вопрос или проблема
Как заменить текущее слово под курсором в Emacs?
Я знаю, что могу использовать query-replace или replace-string, но каждый раз мне приходится вводить всю строку, которую нужно заменить, это просто раздражает.
В Vi есть аналогичная команда cword, и я могу использовать сочетание клавиш для подстановки слова под курсором:
nmap <leader>z :%s#\<<C-r>=expand("<cword>")<CR>\>#
Кто-нибудь знает, как сделать это в Emacs?
Инкрементальный поиск имеет эту функцию, но функции замены — нет. К счастью, инкрементальный поиск имеет способ переключения в режим замены, когда вы выбрали поисковый термин. Итак:
- Нажмите C-s, чтобы перейти в режим инкрементального поиска
- Нажмите C-w, чтобы добавить текущее слово в буфер поиска. Вы можете продолжать нажимать, чтобы добавлять несколько слов, а также можете использовать C-M-y для добавления отдельных символов и C-y для добавления целых строк
- Нажмите M-%, чтобы переключиться в режим замены, используя уже созданный вами буфер поиска
Как вы, вероятно, знаете, используя M-% обычно, это режим запроса на замену, где программа спрашивает вас, что делать с каждым совпадением. Если вы просто хотите заменить их все, нажмите ! при первом совпадении.
;; query-replace current word
(defun qrc (replace-str)
(interactive "sDo query-replace current word with: ")
(forward-word)
(let ((end (point)))
(backward-word)
(kill-ring-save (point) end)
(query-replace (current-kill 0) replace-str) ))
Я долго мучился и хотел того же самого с момента перехода с Vim на Emacs.
После некоторых исследований и экспериментов, я придумал функцию ниже, которая позволяет сделать то же самое с установленным пакетом Evil или используя spacemacs.
Она также работает с активным регионом (или визуальным выделением в стиле vim), что может быть очень полезно для замены слова типа abc-def-hij:
; заменяет текущее слово или выделение в стиле vim для Evil-режима
(defun evil-replace-word-selection()
(interactive)
(if (use-region-p)
(let (
(selection (buffer-substring-no-properties (region-beginning) (region-end))))
(if (= (length selection) 0)
(message "empty string")
(evil-ex (concat "'<,'>s/" selection "https://unix.stackexchange.com/"))
))
(evil-ex (concat "%s/" (thing-at-point 'word) "https://unix.stackexchange.com/"))))
Затем в вашем init.el определите то же самое сочетание клавиш:
(global-set-key (kbd "\C-co") 'evil-replace-word-selection)
Сочетание клавиш немного отличается от vim, которое “space z”, но я еще не разобрался, как сопоставить это в Emacs, когда существует Evil-режим. Продолжает жаловаться, что это не префикс и т.д., и я относительно новичок в Emacs. Но все же это не так плохо, и меня устраивает это решение в данный момент.
Используйте копирование и вставку: M-d C-_ M-x replace-string RET C-y
(kill-word
, undo
, replace-string
, yank
). Если вы уже начали замену, вы можете вернуться к исходному буферу, чтобы сделать копирование и вставку с помощью обычных команд переключения окна или буфера: M-x replace-string RET … C-x o M-d C-_ C-x o C-y
. Вы можете использовать префиксный аргумент на M-d
(например, ESC 4 2 M-d
), чтобы заменить несколько слов.
Если вы планируете заменить одно или несколько слов под курсором, вы можете начать с инкрементального поиска (C-s
), использовать C-w
, чтобы начать поиск слова под курсором, затем нажмите M-%
, чтобы переключиться на replace-string
.
Если вы переходите в поиск и замену с M-S-%
, то просто нажатие M-n
заполняет слово под курсором, снова нажатие обертывает его в “символьный разделитель”.
Я абсолютно новичок в Emacs, но могу предложить следующее:
M-b чтобы переместиться назад через слово
M-d чтобы удалить до конца слова
Теперь вы можете написать новое слово. Это работает практически как cw
в Vim
- Поместите курсор на слово, которое вы хотите заменить.
- Выполните
- интерактивную функцию
query-replace
, используя M-x query-replace RET или M-%. Или, альтернативно, - интерактивную функцию
query-replace-regexp
, используя M-x query-replace-regexp RET или C-M-%.
- интерактивную функцию
- Нажмите стрелку вниз ↓, чтобы слово появилось в запросе.
На это уже был дан ответ, и я не могу комментировать, потому что у меня недостаточно репутации.
Но то, что вы ищете, это ciw
в Vim.
В Emacs самое близкое, что я нашел, это это сочетание:
M-b M-d
Это перемещает к началу слова, которое находится под курсором, и затем удаляет это слово.
Этот фрагмент расширяет ответ Эмануэля Берга, чтобы:
- отобразить выбранную строку для замены;
- использовать символ вместо слов, что дает мне лучшие результаты в коде на Python (или вообще в
superword-mode
).
(defun query-replace-at-point (old new)
"Вызвать `query-replace`, присвоив OLD символу под курсором, заменив его на введенный NEW."
(interactive
(let* ((old-symbol (symbol-name (symbol-at-point)))
(new-symbol (read-string (format "Переименовать %s в: " old-symbol) old-symbol)))
(list old-symbol new-symbol)))
(query-replace old new))
Этот подход аналогичен описанному Майклом Мрозеком, но начинается с isearch-forward-symbol-at-point
, который добавляет слово в точке в поисковую строку.
- Нажмите M-s ., чтобы перейти в режим инкрементального поиска.
- Нажмите M-%, чтобы переключиться в режим замены.
- Опционально нажмите M-n, чтобы предварительно заполнить строку замены поисковой строкой.
С этим подходом, курсор может находиться в любой части слова. Тестировалось, чтобы правильно работать со словами, содержащими дефисы.
.
Ответ или решение
Как заменить текущее слово под курсором в Emacs
Замена слова под курсором в Emacs может быть более эффективной, чем через стандартные команды вроде replace-string
или query-replace
, особенно если вы ищете функциональность, аналогичную cword
в Vim. Ниже рассмотрены несколько способов, как можно осуществить замену слова под курсором в Emacs, а также предложены функции, которые позволяют облегчить этот процесс.
Использование Incremental Search и Replace
-
Включение инкрементального поиска:
- Нажмите
C-s
для перехода в режим инкрементального поиска. - Используйте
C-w
, чтобы вставить текущее слово под курсором в строку поиска. Можно повторно нажиматьC-w
для добавления нескольких слов,C-M-y
для отдельных символов иC-y
для целых строк.
- Нажмите
-
Переход в режим замены:
- Нажмите
M-%
для перехода в режим замены, используя уже собранную строку поиска. - Для замены всех совпадений нажмите
!
.
- Нажмите
Создание пользовательской функции для замены слова
Используйте следующую функцию, чтобы автоматически заменить текущее слово:
(defun replace-current-word (replace-str)
"Заменяет текущее слово под курсором на вводимую строку."
(interactive "sЗаменить текущее слово на: ")
(forward-word)
(let ((end (point)))
(backward-word)
(kill-ring-save (point) end)
(query-replace (current-kill 0) replace-str)))
Вы можете привязать эту функцию к определенной клавише:
(global-set-key (kbd "C-c r") 'replace-current-word)
Использование Evil Mode
Если вы используете пакеты Evil
или Spacemacs
, вы можете применять аналогичный стиль команд, как в Vim:
(defun evil-replace-word-selection()
(interactive)
(if (use-region-p)
(let ((selection (buffer-substring-no-properties (region-beginning) (region-end))))
(unless (= (length selection) 0)
(evil-ex (concat "'<,'>s/" selection "/РЕЗУЛЬТАТ/"))))
(evil-ex (concat "%s/" (thing-at-point 'word) "/РЕЗУЛЬТАТ/"))))
Для активации функции:
(global-set-key (kbd "C-c o") 'evil-replace-word-selection)
Другие методы
-
Непосредственное редактирование:
- Используйте
M-b
для перемещения в начало слова. - Примените
M-d
для удаления текущего слова. - Введите новое слово вручную.
- Используйте
-
Замена символов:
- Используйте режим
isearch-forward-symbol-at-point
, нажимаяM-s .
, чтобы добавить слово под курсором в строку поиска. - Нажмите
M-%
для замены. Это подход особенно удобен для слов с дефисами.
- Используйте режим
Заключение
Хотя Emacs предоставляет разнообразие способов замены текста, использование пользовательских функций и навигации делает процесс более интуитивным и быстродействующим. Эти методы позволяют избежать необходимости повторного ввода искомого слова, улучшая эффективность работы с текстом.