5

I've came across this comment in an evil-surround issue, which stated this code:

;; use non-spaced pairs when surrounding with an opening brace
(evil-add-to-alist
 'evil-surround-pairs-alist
 ?\( '("(" . ")")
 ?\[ '("[" . "]")
 ?\{ '("{" . "}")
 ?\) '("( " . " )")
 ?\] '("[ " . " ]")
 ?\} '("{ " . " }"))

And it actually works. but what are those strange ?\ symbols? What are they doing? What do they mean?

Drew
  • 75,699
  • 9
  • 109
  • 225
ninrod
  • 1,436
  • 2
  • 13
  • 28

1 Answers1

5

Emacs represents characters with the ?a syntax (or ?\X for special characters, where X is one of them).

(characterp "a")                        ; => nil
(characterp ?a)                         ; => t

They evaluate to integers:

(integerp ?a)                           ; => t

They are not single-character strings, so the following will throw an error:

(string-equal "a" ?a)                   ; => (throws an error)

You can convert them to strings using:

(char-to-string ?a)                     ; => "a", note: semi-obsolete

or just a plain old:

(string ?a)                             ; => "a"

So now you have:

(string-equal "a" (string ?a))          ; => t

And for your special characters like parentheses and braces:

(list (string-equal "(" (string ?\())
      (string-equal "[" (string ?\[))
      (string-equal "{" (string ?\{)))  ; => (t t t)
Dan
  • 32,584
  • 6
  • 98
  • 168
  • Dan, could the evil-surround author have chosen to implement the `evil-surround-pairs-alist` variable with string (e.g. `"("`) leads instead of integer (e.g. `?\(`) leads? Why didn't he just use the string format? – ninrod Feb 02 '17 at 17:06
  • @ninrod: in principle, yes: keys in an alist can be strings. But characters will be a faster lookup because you can test for equality with `eq` (so `(eq ?a ?a)` evaluates to `t`), whereas string equality is slower to evaluate. In effect, an alist with character keys can use `assq`, but one with string keys needs the slower `assoc`. Whether or not you'd ever *notice* the speed difference depends on a) the list length, and b) how often you run the function. It's also likely that he's querying the *characters* around point with `char-before` and `char-after`, and wants to skip conversion. – Dan Feb 02 '17 at 17:10
  • (minor) `?\ ` can be used for any character, not just special characters. So you *can* (but you need not) use `?\g` instead of `?g`. – Drew Feb 02 '17 at 18:20
  • 2
    @Drew: almost, but not quite, I think. For example, `?a` is the [character representation](https://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html#Basic-Char-Syntax) of lowercase "a" while `?\a` is the character representation of `C-g`, and `?t` represents lowercase "t" and `?\t` represents the `tab` character. So both `(eq ?a ?\a)` and `(eq ?t ?\t)` evaluate to `nil`. However, it does work for some other characters: `(eq ?z ?\z)` evaluates to `t`. – Dan Feb 02 '17 at 18:57
  • 1
    @Dan: Ah yes, right you are. It is true for characters for which there is not some other escape sequence defined. That is, as long as it is not one of the se: `\a`, `\b`, `\t`, `\n`, `\v`, `\r`, `\e`, `\s`, `\\ `, and `\d`. The relevant manual page is (elisp)[*Basic Char Syntax*](http://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html). – Drew Feb 02 '17 at 19:05