Prevent Abbrev expansion after certain symbols in Emacs - 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.

Related

How to set a keybinding to create and jump to the next line in emacs?

I have the following code that attempts to create a new line and then jump to it. The idea is that move-end-of-line will jump to the end of the current line, and ["C-m"] would act as return/enter. Yet executing this command gives the error: "wrong number of arguments". How do I fix this?
(global-set-key (kbd "C-.") 'new-line)
(defun new-line ()
(interactive)
(move-end-of-line)
["C-m"]
)
I think you need to read the Emacs & elisp manuals: these questions are pretty easy to answer. Here's one way to do it.
(defun insert-line-after-line (&optional n)
(interactive "p")
(end-of-line 1) ;end of current line
(open-line n) ;open n new lines
(forward-line 1)) ;go to start of first of them
But seriously: Emacs has very extensive self-documentation, it is easy to find out how to do these things.
An option is to record a macro and use that.
M-x kmacro-start-macro
C-e
C-m
M-x kmacro-end-macro
If you don't care about the macro persisting, just run it:
C-x e
But if you want it to persist you would save it:
M-x name-last-kbd-macro new-line
M-x insert-kbd-macro new-line
and paste the output into your initialisation file (with your shortcut definition):
(global-set-key (kbd "C-.") 'new-line)
(fset 'new-line
[end return])
["C-m"] is like the way you specify a key for doing a key binding, but this is not the same as how you programmatically tell Emacs to insert a character into a document. You could use (insert-char ?\^M) (see ref here), but that would result in a literal ^M character (try it; another way to do the same thing interactively is Ctrl-Q followed by Ctrl-M). (insert "\n") seems to be what you're looking for.
Also, the reason you're getting the message "wrong number of arguments" is because (move-end-of-line) requires an argument when called out of interactive context. (move-end-of-line 1) works.
That said, possibly an easier way to achieve the result you're looking for is with the following setting:
(setq next-line-add-newlines t)
This will allow you to just do C-n at the end of the file and not worry about the distinction between moving and inserting.

Emacs: Insert word at point into replace string query

Is there an analogue to inserting the word after point into the isearch query by hitting C-w after C-s but for the replace string (and replace regexp) queries?
I also enjoy Sacha Chua's modification of C-x inserting whole word around point into isearch:
http://sachachua.com/blog/2008/07/emacs-keyboard-shortcuts-for-navigating-code/
This too would be really useful in some cases if it could be used in replace string.
I'd be very thankful for any tips!
Thank you!
This will do it, although it isn't as fancy as C-w in isearch because you can't keep hitting that key to extend the selection:
(defun my-minibuffer-insert-word-at-point ()
"Get word at point in original buffer and insert it to minibuffer."
(interactive)
(let (word beg)
(with-current-buffer (window-buffer (minibuffer-selected-window))
(save-excursion
(skip-syntax-backward "w_")
(setq beg (point))
(skip-syntax-forward "w_")
(setq word (buffer-substring-no-properties beg (point)))))
(when word
(insert word))))
(defun my-minibuffer-setup-hook ()
(local-set-key (kbd "C-w") 'my-minibuffer-insert-word-at-point))
(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)
EDIT:
Note that this is in the standard minibuffer, so you can use it use it anywhere you have a minibuffer prompt, for example in grep, occur, etc.
Two answers:
Replace+ automatically picks up text at point as the default value when you invoke replace commands.
More generally, Icicles does something similar to what scottfrazer's code (above) does, but it is more general. At any time, in any minibuffer, you can hit M-. (by default) to pick up text ("things") at point and insert it in the minibuffer. You can repeat this, to either (a) pick up successive things (e.g. words) of the same kind, accumulating them like C-w does for Isearch, or (b) pick up alternative, different things at point. More explanation here.
I think this exists in Emacs already - you just start replace with M-S-% and then press M-n (while the minibuffer is empty), this fills in the word under cursor, there are more useful things you can do with this, check http://endlessparentheses.com/predicting-the-future-with-the-m-n-key.html?source=rss#disqus_thread.

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

How to mark the text between the parentheses in Emacs?

Any such function or elisp script? I want the equivalent function as vi" sequence in vim.
Try the key sequence C-M-u C-M-SPC (i.e., while holding the Control and Meta keys, press u and Space in sequence), which executes the commands backward-up-sexp and mark-sexp.
Edit:
I made a mistake: backward-up-sexp doesn't exist in standard Emacs. I wrote it exactly because of the problem mentioned in lkahtz's comment, that the existing function backward-up-list won't work when point is between double quotes.
(defun backward-up-sexp (arg)
(interactive "p")
(let ((ppss (syntax-ppss)))
(cond ((elt ppss 3)
(goto-char (elt ppss 8))
(backward-up-sexp (1- arg)))
((backward-up-list arg)))))
(global-set-key [remap backward-up-list] 'backward-up-sexp)
expand-region (which is bound to C-=) works great.
Xah Lee has an emacs-lisp function which achieves this called xah-select-text-in-quote. It is available from his website:
Select text between the nearest left and right delimiters.
Delimiters here includes the following chars: \"<>(){}[]“”‘’‹›«»「」『』【】〖〗《》〈〉〔〕().
This command does not properly deal with nested brackets.

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.