Using C-M-% to do a query-replace-regexp in Emacs running in Mac terminal

8,431

Solution 1

Unlike GUI-based apps, terminal-based apps (like almost all of those that you run inside Terminal windows) are limited in which key combinations they can sense. Back when terminals were real hardware (not just emulated by programs like Terminal and xterm), terminals like DEC's VT-100 had a Control key, but it only worked in combination with certain other keys. Since most terminal emulation programs emulate a VT-100 (and its successors, including the VT-102 and the VT-220), there is no way to actually send a Control-Shift-5 (or whatever C-% is on your keyboard) to a terminal-based program.

You will probably have better luck mapping query-replace-regexp to a key (combination) that actually transmits something. The ‘F keys’ are (usually) mapped in a VT-220 style that the xterm-color termcap/terminfo entries know how to parse (F1-F4/F5 may be in a VT-100 style though!). If needed, you can configure Terminal to send whatever codes your termcap/terminfo is expecting (at least I can in the 10.4 Terminal). You can assign codes to a bare F-key or an F-key with a single modifier (Shift, Control, or Option). Any modifiers would not be passed (through the terminal) to Emacs as such, but you could map some of those combinations to the terminal key codes for higher function keys (F14-F20) (unless the combination is taken by a system shortcut—“Full Keyboard Access”, Expose, and Spaces(?)).

(global-set-key (kbd "<f13>") 'query-replace-regexp) ; I have a full-sized keyboard with an F13 on it.

Note that F1-F4 may not work properly, depending on the configuration of Terminal and emacs. For example, on my system (10.4), Terminal is configured with “ESCOP” (the VT-100 key code) for F1, but emacs expects “ESC[11~” (an ‘old’ xterm sequence). The keys work fine in emacs if I reconfigure either Terminal (⌘I; Keyboard) or emacs (see below).

; Expect VT-100 key codes for F1-F4
(define-key function-key-map "\eOP" [f1])
(define-key function-key-map "\eOQ" [f2])
(define-key function-key-map "\eOR" [f3])
(define-key function-key-map "\eOS" [f4])

Solution 2

I just found a solution (I'm running emacs in iterm2 on my macbook pro).

First, have a look at the current keybindings in emacs by running C-h b. Search for C-M-% (using the C-s command, e.g.) and you'll find that several escape sequences actually map to C-M-%. In iTerm2, you can map Control+Option+Shift+5 to one such escape sequence in Preferences > Profiles > Keys (picture). Emacs will then translate that escape sequence to C-M-%, which is bound to query-replace-regexp. Now pressing Control+Option+Shift+5 works how you want it to.

Remapping similar combinations that use both Control and Shift such as C-+ could be done in the same way. I'm not sure if this is possible in the default terminal.

See this question for more.

Solution 3

Poking around in function-key-map (C-h v function-key-map), I found that C-x @ c is bound to event-apply-control-modifier. This seems like it would work, but it interacts poorly with the way Terminal sends Meta keys with the “Use option as meta key” option (it sends an ESC character before the normal character).

When you type Control-x @ c Option-Shift-5, emacs sees C-x @ c ESC %. However, it binds the artificial Control modifier to the Escape key instead of translating the trailing ESC % to M-%. So it end up interpreting it as C-ESC %. Trying to stack these artificial Control and Meta modifiers also fails, because the first C-x in the second artificial modifier sequence absorbs the first artificial modifier.

But, it points to a possibility:

; cargo cult adaptation of event-apply-control-modifier
(defun event-apply-control-meta-modifiers (ignore-prompt)
  (vector
   (event-apply-modifier
    (event-apply-modifier (read-event)
                          'control 26 "C-")
    'meta 27 "M-")))
(define-key function-key-map (kbd "C-x @ %") 'event-apply-control-meta-modifiers)

Now, you can type Control-x @ Shift-5 Shift-5, emacs will see C-x @ % %, interpret it as C-M-%, and run finally query-replace-regexp.

Solution 4

For query-replace on MacBook Pro 2017 with OSX Sierra, running built-in emacs in Terminal, use

<esc> % 

in sequence. If required (depending on keyboard layout), use simultaneous < shift > key to access the % sign.

Solution 5

Have you tried <esc> C-%? It works for me.

The escape key is often mapped to meta (and alt (option on a mac) is not always mapped to meta). The only thing is that you don't hold it down like a shifting key, you just hit it.

BTW--If you are used to using alt as meta, the follow on question is "How do I map alt to meta in the mac terminal?" Which I believe has been asked on Stack Overflow long ago: Option or Command key as Meta key for LispBox on Macintosh suggests putting (setq mac-command-modifier 'meta) in your .emacs file.

Share:
8,431

Related videos on Youtube

Samvel
Author by

Samvel

SOreadytohelp

Updated on September 17, 2022

Comments

  • Samvel
    Samvel over 1 year

    I am trying to do a regular expression search-and-replace in Emacs, running in the Terminal program on my MacBook Pro, which is running OS X 10.6.2. As far as I know, this can be done by pressing C-M-% (I am assumimg this means Ctrl+Alt+Shift+5. Please correct me if I am wrong, since I am only starting to learn Emacs). However, when I do that, it doesn't work.

    I can do it by typing M-x query-replace-regexp, and when I do that, I see a reminder on the bottom of the screen saying I can also do it with C-M-%, but when I try C-M-%, nothing happens.

    EDIT: I would like to add that I have the "Use option as meta key" terminal option enabled, and it seems to work fine. For example, I can use alt-B and alt-F to go forward and back one word at a time in bash and Emacs.

    EDIT 2: I would also like to mention that I have my terminal set to declare the terminal type as "xterm" rather than the default of "xterm-color". I did that for reasons unrelated to this question (to prevent my colored prompt from looking funny after I cancel a reverse-i-search). However, I experimented in Emacs with "xterm" and "xterm-color", and either way I have the same problem with C-M-%.

    How can I make this work?

    • Admin
      Admin about 7 years
      In aquamacs, M-% works, which is Option+Shift+5. I kept hitting Option+5 and was wondering what the heck was going on, which landed me here. Even though you are not prompted with the following choices: space or "y" does the replacement, "n" skips the replacement, "q" quits searching.
    • Admin
      Admin over 3 years
      @7stud, are you sure that's not just query-replace you're seeing? I'm having some problem as OP and when I try your shortcut I don't get the regexp version.
  • Chris Johnsen
    Chris Johnsen over 14 years
    I am pretty sure that the linked SO question only refers to GUI Emacs, not tty Emacs.
  • Samvel
    Samvel over 14 years
    I am aware that escape can act as meta. It seems to work most of the time, but I tried <esc> C-% and that didn't work for me.
  • Samvel
    Samvel over 14 years
    Thank you for the suggestion. I may try that, but it looks kind of complicated. It seems like the quirks I am experiencing are coming from the terminal program I am using, so I may try a non-terminal version of Emacs.
  • Chris Johnsen
    Chris Johnsen over 14 years
    Yes, a GUI-based version of Emacs would work better for typing C-M-% in the normal way (Control-Option-Shift-5). I am fairly content with Aquamacs Emacs 1.9 (based on GNU Emacs 22.3.1). It has an option to make the Option key be Emacs's Meta modifier or to do the normal Mac OS X dead key/extended character.
  • Steven C. Howell
    Steven C. Howell almost 9 years
    What you describe is not at all the behavior in linux. On linux, when I run emacs inside a terminal the Alt key is interpreted by the terminal just fine (e.g. I can press Alt-Shift-5 to do a search and replace). Why would this be different on a Mac?
  • Michael Terry
    Michael Terry over 3 years
    The picture was a lifesaver. I'm not sure how one would know to leave off the M- or elide the spaces that C-h b shows.