Emacs global-abbrev-table with bracketed definition - emacs

See the following abbrev-table for emacs:
(define-abbrev-table 'global-abbrev-table '(
("8in" "∈")
("(x)" "⊗")
))
(setq-default abbrev-mode t)
If I evaluate the region above and then type in "8in", this string is abbreviated to ∈ in my emacs buffer. Great. However, if I type in "(x)", this is not abbreviated to anything. I was hoping for an abbreviation to ⊗. What have I got wrong in my global-abbrev-table definition? I have also tried with \(x\) and \\(x\\), but neither result in an abbreviation of "(x)".

(let ((syntab (copy-syntax-table)))
(modify-syntax-entry ?\( "w" syntab)
(modify-syntax-entry ?\) "w" syntab)
(set-syntax-table syntab))
(define-abbrev-table 'global-abbrev-table '(("(x)" "⊗")))
Of course, you might not want ( and ) to have word-constituent syntax in general...

Seems Emacs currently only accepts word syntax for characters composing an abbreviation.
BTW can't see a reason for that.

Related

Make Emacs prettify-symbols-mode work on non-whitespace separated words.

The new prettify-symbols-mode in Emacs works beautifully for translating:
lambda something -> λ something
I'd also like to make:
lambda.something -> λsomething
Sadly, prettify-symbols-mode only recognizes spaces as word/symbol separators by default.
Any ideas on how to use '.' as a token separator?
The code that does the actual substitution is prettify-symbols--compose-symbol in prog-mode.el. It excludes matches if the character before or after the word has the character type word or symbol. In many mode, for example emacs-lisp-mode the . character has symbol type.
You could either change the syntax code for . in the major mode, you could tell font-lock to use a different character code when highlighting (see the variable font-lock-defaults for details), or you could do ju-jutsu on the prettify-symbols--compose-symbol mode like modifying it using defadvice or simply replace it with your own.
Thanks to Lindydancer, I ended up doing this:
(add-hook 'python-mode-hook
(lambda ()
(push '("self" . ?◎) prettify-symbols-alist)
(modify-syntax-entry ?. ".")))
which results in a reasonable compromise output of:
◎.method

Arbitrary characters for forward-word/backward-word in Emacs

How to add an arbitrary character (hyphen, for example) to forward/backward-word functionality, so Emacs would handle words like "k-vector" as a single word. The same question about double-click on the word.
Syntax tables define which character is considered a word constituent. You can read about it here.
Emacs's notion of "word" is rather fixed and doesn't quite match what you want. You can mess with the syntax-table, but it might break functionality of the major-mode.
AFAICT what you want is to handle what Emacs calls "symbols" rather than "words". E.g. use forward-symbol and backward-symbol commands.
The easiest way to use those other commands might be to enable superword-mode.
Add following to your .emacs file to make hyphen included in words for every major mode:
(add-hook 'after-change-major-mode-hook
(lambda ()
(modify-syntax-entry ?- "w")))
You can use this code it use regular expression it use space or parents as word separator
(defun backward-word-with-dash ()
(interactive)
(search-backward-regexp "[ ()][A-Za-z\-]+ *")
(forward-char))
(defun forward-word-with-dash ()
(interactive)
(search-forward-regexp " *[A-Za-z\-]+[ ()]")
(backward-char))
(global-set-key "\M-b" 'backward-word-with-dash)
(global-set-key "\M-f" 'forward-word-with-dash)
if you want other characters just add it to the regex

Prevent Abbrev expansion after certain symbols in Emacs

Is there a way to prevent automatic expansion of an abbreviation in the built-in abbrev-mode after certain symbols? E.g. I want my abbrev to expand after whitespace, newline, comma etc., but not after a dash or underscore.
I know I can hit C-q before typing the (say) underscore, but an automatic solution would be much nicer since this occurs for me very often.
There are some abbrev hooks in the manual, but since I am a total beginner with Elisp I don't see an obvious solution...
Thank you very much!
Make underscore be a word-constituent character for the current mode. From the Emacs manual, node Expanding Abbrevs:
[A]ny character that is not a word constituent expands an abbrev, and any word-constituent character can be part of an abbrev.
Use function modify-syntax-entry to modify the syntax class of _, to make it a word constituent:
(modify-syntax-entry ?_ "w")
This solution is useful only if it is not otherwise bothersome for _ to be a word-constituent character. Do you want _ to act as if it is a part of a word or not? That's the first question.
OK, so a hint of the solution was already in the question itself. This is what works for me:
(defun protect-underscore ()
(interactive)
(insert "_"))
(defun protect-dash ()
(interactive)
(insert "-"))
(defun protect-equal ()
(interactive)
(insert "="))
(global-set-key (kbd "_") 'protect-underscore)
(global-set-key (kbd "-") 'protect-dash)
(global-set-key (kbd "=") 'protect-equal)
I am sure there has to be a more elegant solution... thanks goes to Magnar.

Making M-( the default behavior in Emacs when "(" is typed

How does one make M-( the default behavior for typing an opening "(" character? I want Emacs to automatically insert the closing ")" after the cursor when I type a "(" character regardless of whether it's part of an M-key combination. Additionaly, I want to extend this behavior to quotes, subquotes, brackets and braces. Typing M-( is a pain, and there don't appear to be any comparable forms for those other characters.
I don't write much elisp myself, but this is something I cribbed off somebody. The code goes into your .emacs.
(setq skeleton-pair t)
(setq skeleton-pair-on-word t) ; apply skeleton trick even in front of a word.
(global-set-key "[" 'skeleton-pair-insert-maybe)
(global-set-key "{" 'skeleton-pair-insert-maybe)
(global-set-key "(" 'skeleton-pair-insert-maybe)
(global-set-key "\"" 'skeleton-pair-insert-maybe)
Check out paredit.el which keeps parens/braces/quotes balanced as you wish, and also does offers many other features to assist with s-exp manipulation. If you're going to be writing Lisp code (as your name implies) you will probably want to use this library eventually.
"(" is bound to self-insert-command while M-'(' is insert-parenthesis. You can reverse that simply by using global-set-key or define-key to bind "(" to insert-parenthesis.

replace-char in Emacs Lisp ?

Emacs Lisp has replace-string but has no replace-char. I want to replace "typographic" curly quotes (Emacs code for this character is hexadecimal 53979) with regular ASCII quotes, and I can do so with:
(replace-string (make-string 1 ?\x53979) "'")
I think it would be better with replace-char.
What is the best way to do this?
This is the way I replace characters in elisp:
(subst-char-in-string ?' ?’ "John's")
gives:
"John’s"
Note that this function doesn't accept characters as string. The first and second argument must be a literal character (either using the ? notation or string-to-char).
Also note that this function can be destructive if the optional inplace argument is non-nil.
Why not just use
(replace-string "\x53979" "'")
or
(while (search-forward "\x53979" nil t)
(replace-match "'" nil t))
as recommended in the documentation for replace-string?
which would certainly be better with replace-char. Any way to improve my code?
Is it actually slow to the point where it matters? My elisp is usually ridiculously inefficient and I never notice. (I only use it for editor tools though, YMMV if you're building the next MS live search with it.)
Also, reading the docs:
This function is usually the wrong thing to use in a Lisp program.
What you probably want is a loop like this:
(while (search-forward "’" nil t)
(replace-match "'" nil t))
This answer is probably GPL licensed now.
What about this
(defun my-replace-smart-quotes (beg end)
"replaces ’ (the curly typographical quote, unicode hexa 2019) to ' (ordinary ascii quote)."
(interactive "r")
(save-excursion
(format-replace-strings '(("\x2019" . "'")) nil beg end)))
Once you have that in your dotemacs, you can paste elisp example codes (from blogs and etc) to your scratch buffer and then immediately press C-M-\ (to indent it properly) and then M-x my-replace-smart-quotes (to fix smart quotes) and finally C-x C-e (to run it).
I find that the curly quote is always hexa 2019, are you sure it's 53979 in your case? You can check characters in buffer with C-u C-x =.
I think you can write "’" in place of "\x2019" in the definition of my-replace-smart-quotes and be fine. It's just to be on the safe side.