Сведения о вопросе

rjevskii

11:10, 4th August, 2020

Теги

regex   emacs   lisp    

Как привязать регулярное выражение к комбинации клавиш в emacs?

Просмотров: 433   Ответов: 4

Для контекста я что-то вроде Новичка emacs. Я не использовал его очень долго, но использую его все больше и больше (мне это очень нравится). Также мне комфортно с lisp, но не очень хорошо знаком с elisp.

То, что мне нужно сделать, это привязать регулярное выражение к комбинации клавиш, потому что я использую этот конкретный regex так часто.

То, что я делал:

M-C-s ^.*Table\(\(.*\n\)*?GO\)

Обратите внимание, что я использовал новую строку выше , но я обнаружил, что для isearch-forward-regexp вам действительно нужно заменить \n в регулярном выражении на результат C-q Q-j . Это вставляет литеральную новую строку (без завершения команды), позволяя мне поместить новую строку в выражение и сопоставить строки.

Как я могу привязать это к комбинации клавиш?

Я смутно понимаю, что мне нужно создать функцию elisp, которая выполняет isearch-forward-regexp с выражением, но я нечетко разбираюсь в деталях. Я поискал в гугле и нашел большинство документов, которые должны быть немного запутанным.

Как я могу привязать регулярное выражение к комбинации клавиш в emacs?


У Майка Стоуна был лучший ответ на данный момент-не совсем то, что я искал, но он работал для того, что мне нужно

Edit-этот вид работал, но после сохранения макроса, когда я вернулся, чтобы использовать его позже, я не мог использовать его с C-x e . (т. е., если я перезагружаю emacs, а затем набираю M-x macro-name, а затем C-x e , я получаю сообщение в минибуфере, например "нет последнего макроса kbd" или что-то подобное)


@Mike камень-Спасибо за информацию. Я попытался создать макрос вот так:

C-x( M-C-s ^.*Table\(\(.*C-q C-J\)*?GO\) C-x)

Это создало мой макрос, но когда я выполнил свой макрос, я не получил того же выделения, которое я обычно получаю, когда использую isearch-forward-regexp . Вместо этого он просто перескочил к концу следующего матча выражения. Так что это действительно не работает для того, что мне нужно. Есть идеи?

Edit: похоже, я могу использовать macros, чтобы делать то, что я хочу, мне просто нужно думать вне коробки isearch-forward-regexp . Я попробую то, что вы предложили.



  Сведения об ответе

screen

21:06, 1st October, 2020

Вы можете использовать macros, просто сделайте C-x ( , затем сделайте все для макроса, затем C-x ) , чтобы закончить макрос, затем C-x e выполнит последний определенный макрос. Затем вы можете назвать его с помощью M-x name-last-kbd-macro , что позволяет назначить ему имя , которое затем можно вызвать с помощью M-x TESTIT, затем сохранить определение с помощью M-x insert-kbd-macro , которое поместит макрос в ваш текущий буфер, а затем вы можете сохранить его в файле .emacs .

Пример:

C-x( abc *return* C-x)

Определит макрос для ввода "abc" и нажмите клавишу return.

C-xeee

Выполняет указанный выше макрос немедленно, 3 раза (сначала e выполняет его, затем следующие 2 e будут выполнять его еще дважды).

M-x name-last-kbd-macro testit

Имена макросов в "testit"

M-x testit

Выполняет только что названный макрос (печатает "abc", а затем возвращает).

M-x insert-kbd-macro

Помещает следующее в ваш текущий буфер:

(fset 'testit
   [?a ?b ?c return])

Который затем можно сохранить в файле .emacs , чтобы использовать именованный макрос снова и снова после перезапуска emacs.


  Сведения об ответе

PHPH

05:27, 17th August, 2020

Я начал с решения вашей проблемы буквально,

(defun search-maker (s)
  `(lambda ()
     (interactive)
     (let ((regexp-search-ring (cons ,s regexp-search-ring)) ;add regexp to history
           (isearch-mode-map (copy-keymap isearch-mode-map)))
       (define-key isearch-mode-map (vector last-command-event) 'isearch-repeat-forward) ;make last key repeat
       (isearch-forward-regexp)))) ;`

(global-set-key (kbd "C-. t") (search-maker "^.*Table\\(\\(.*\\n\\)*?GO\\)"))
(global-set-key (kbd "<f6>") (search-maker "HELLO WORLD"))

Последовательность клавиш из (kbd ...) запускает новый пустой поиск. Чтобы действительно найти нужную строку, вы нажимаете последнюю клавишу столько раз, сколько вам нужно. Так что C-. t t t или <f6> <f6> <f6> . Решение-это в основном хак, но я оставлю его здесь, Если вы хотите поэкспериментировать с ним.

Следующее, вероятно, ближе всего к тому, что вам нужно,

(defmacro define-isearch-yank (key string)
  `(define-key isearch-mode-map ,key 
     (lambda ()
       (interactive) 
       (isearch-yank-string ,string)))) ;`

(define-isearch-yank (kbd "C-. t") "^.*Table\\(\\(.*\\n\\)*?GO\\)")
(define-isearch-yank (kbd "<f6>") "HELLO WORLD")

Ключевые комбо теперь работают только в режиме isearch. Вы начинаете поиск в обычном режиме, а затем нажимаете комбинацию клавиш, чтобы вставить предопределенную строку.


  Сведения об ответе

lesha

05:59, 7th August, 2020

В общем случае, чтобы определить пользовательскую привязку ключей в Emacs, вы должны написать

(define-key global-map (kbd "C-c C-f") 'function-name)

define-key -это, что неудивительно, функция для определения нового ключа. global-map -это глобальная ключевая карта, в отличие от отдельных карт для каждого режима. (kbd "C-c C-f") возвращает строку, представляющую последовательность ключей C-c C-f . Есть и другие способы сделать это, включая прямой ввод строки, но обычно это самый простой способ, так как он принимает обычное письменное представление. 'function-name -это символ, который является именем функции.

Теперь, если ваша функция еще не определена, вы захотите определить ее, прежде чем использовать это. Чтобы сделать это, напишите

(defun function-name (args)
  (interactive)
  stuff
  ...)

defun определяет функцию-используйте C-h f defun для получения более конкретной информации. (interactive) на самом деле не является вызовом функции; он говорит компилятору, что это нормально для функции, вызываемой пользователем с помощью M-x function-name и через привязки клавиш.

Теперь, в частности, для интерактивного поиска это сложно; модуль isearch на самом деле не кажется настроенным для того, что вы пытаетесь сделать. Но вы можете использовать это, чтобы сделать что-то подобное.


  Сведения об ответе

baggs

01:38, 19th August, 2020

@Justin:

При выполнении макроса все немного по-другому... инкрементный поиск будет выполняться только один раз, и вам придется снова выполнить макрос, если вы хотите выполнить поиск снова. Однако вы можете выполнять более мощные и сложные действия, такие как поиск ключевого слова, переход к началу строки, отметка, переход к концу строки, M-w (копирование), затем переход к другому буферу, затем C-y (вставка), затем переход обратно к другому буферу и завершение макроса. Затем каждый раз при выполнении макроса вы будете копировать строку в следующий буфер.

Самое классное в emacs macros-это то, что он остановится, когда увидит колокол... что происходит, когда вы не можете соответствовать инкрементальному поиску (среди прочего). Таким образом, выше макрос, вы можете сделать C-u 1000 C-x e, который будет выполнять макрос 1000 раз... но так как вы сделали поиск, он будет копировать только 1000 строк, или пока поиск не завершится неудачей! Это означает, что если есть 100 совпадений, он будет выполнять макрос только 100 раз.

EDIT: Проверьте C-hf highlight-lines-matching-regexp, который покажет помощь команды, которая выделяет все, что соответствует regex... Хотя я не знаю, как отменить подсветку... в любом случае вы можете использовать сохраненный макрос, чтобы выделить все соответствующие regex, а затем другой макрос, чтобы найти следующий...?

Дальнейшее редактирование: M-x unhighlight-regexp отменит выделение, вы должны ввести последний regex, хотя (но по умолчанию используется regex, который вы использовали для выделения)


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться