Emacs can't reset Ctrl-d key behaviour - emacs

I wanted to change the behaviour of Ctrl-d key. So it will delete a word backward. I created a function:
(defun backward-delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
(interactive "p")
(delete-region (point) (progn (backward-word arg) (point))))
Then inserted this into emacs.d:
(global-set-key (kbd "\C-d") 'backward-delete-word)
It works in fundamental-mode, but in php-mode it just removes the next character. When I click
Ctrl-h k Ctrl-d
Emacs gives this:
C-d runs the command c-electric-delete-forward, which is an
interactive compiled Lisp function in `cc-cmds.el'.
It is bound to C-d.
(c-electric-delete-forward ARG)
Somehow, it was reset to another function. How to find out, where it was reset and make it work with my function instead?

I don't have php-mode so I can't say for sure, but the binding is likely overriden in php-mode-map (which, as a major mode map, has higher precedence than the global map).
You can check by using C-h b to list all available key bindings and look for C-d or c-electric-delete-forward in the output buffer to see in which keymap the binding is defined.
Assuming php-mode-map overrides the C-d binding, you can disable it using
(define-key php-mode-map (kbd "C-d") nil)

Related

Emacs global-set-key in find-file

In my init.el file I have this:
(global-set-key "\M-n" (lambda () (interactive) (insert "~")))
This allows me to use Alt-n on my Mac to produce the ~ character. It works fine in buffers etc. but when I try to use it in find-file I get
"End of history no default available".
C-h k reveals that M-n actually calls:
(lambda nil (interactive) (insert "~"))
Why doesn't this work with find-file?
Global key bindings are overridden by local (i.e., major-mode) key bindings, which are overridden by minor-mode bindings, which are overridden by... IOW, there are lots of levels of key binding.
In this case, your global binding is overridden by a minibuffer keymap binding.
In the minibuffer completion keymaps, which are local maps, M-n is bound to next-history-element. If you want M-n in such a map to be bound to something else, then you need to bind it. For example:
(define-key minibuffer-local-completion-map "\M-n" 'your-command)
There are several minibuffer completion keymaps, depending on your Emacs version. The two main ones are minibuffer-local-completion-map and minibuffer-local-must-match-map.

how to emulate a specific key press in Emacs Lisp

Context: I want to make a minor mode where pressing f twice fast results in whatever the pressing of ( should do at that time. This doesn't always mean just insertion of (. For example, in buffers where paredit mode or autopair mode is enabled, pressing of ( usually results in insertion of (). In a paredit mode buffer, that sometimes results in wrapping the selected text: for example, if I select a b and press (, that should result in replacing the selection with (a b).
For detection of f being pressed twice, I just need to take the logic in the short code in http://www.emacswiki.org/emacs/electric-dot-and-dash.el
So the only missing piece is a Lisp code snippet that tells Emacs "Trigger pressing of ( now!"
The first thing that came to my mind was that the snippet should do
find the command bound to the key (
and then call call-interactively on that command.
but that breaks down if the auto pairing package (autopair or paredit or other similar package) binds ( to a command that has a logic that looks up what key was used to call the command, or if the package simply relies on post-self-insert-hook or post-command-hook instead of binding (.
update
I've looked up Key Chord documentation and it turns out what I am trying to do with answers to this question has a simpler solution:
(require 'key-chord)
(key-chord-mode 1)
(defvar my-easy-open-paren-mode-map
(let ((map (make-sparse-keymap)))
(key-chord-define map ",." (kbd "("))
map))
(define-minor-mode my-easy-open-paren-mode
"In this mode, pressing . and , together is another way of pressing the open paren.")
(defvar my-easy-semicolon-mode-map
(let ((map (make-sparse-keymap)))
(key-chord-define map ";;" (kbd "C-e ;"))
map))
(define-minor-mode my-easy-semicolon-mode
"In this mode, pressing semicolon twice fast is another way of pressing C-e and semicolon.")
(add-hook 'prog-mode-hook 'my-easy-open-paren-mode)
(add-hook 'c-mode-common-hook 'my-easy-semicolon-mode)
Triggering key press may still be useful in other contexts though.
You might appreciate the Key Chord library for binding functions to a double key-press. (I wouldn't recommend using f if you'll be writing in English, mind you; but YMMV.)
post-self-insert-hook would still run if the binding was self-insert-command. post-command-hook will run in any case, but if you're worried about it seeing an incorrect function and/or input event, you can manipulate those...
After looking up the binding, your function can set this-command to the function you're about to call-interactively, and last-command-event to the required key. e.g.:
(defun my-fake-paren ()
(interactive)
(let ((command (key-binding "(")))
(setq last-command-event ?\()
(setq this-command command)
(call-interactively command)))
I use Key Chord for this sort of thing, although the page you link appears to do the same thing. The trick is getting the call to call-interactively to work correctly. I wrapped it in a let that reset the variable last-command-event, such that call-interactively thinks it was a "(". This works for me in paredit and fundamental modes.
(require 'key-chord)
(key-chord-mode 1)
(defun my-paren-call ()
(interactive)
(let ((last-command-event ?\())
(call-interactively (key-binding "("))))
(key-chord-define-global "ff" 'my-paren-call)

Why doesn't my keymap for C-c C-c work in C++?

I'm new to emacs and using emacs 24 and trying to bind C-c C-c to a function to comment out a single line. I have the following in my init.el file but it doesn't seem to work in c++.
(defun toggle-comment-on-line ()
"comment or uncomment current line"
(interactive)
(comment-or-uncomment-region (line-beginning-position) (line-end-position))
(next-line))
(global-set-key (kbd "C-c C-c") 'toggle-comment-on-line)
When I'm playing around in the scratch page it works fine and when I check with C-h k C-c C-cit displays the right function but when I'm in C++ the same command displays the text:
C-c C-c runs the command comment-region, which is an interactive
compiled Lisp function in `newcomment.el'.
It is bound to C-c C-c, <menu-bar> <C++> <Comment Out Region>.
(comment-region BEG END &optional ARG)
Comment or uncomment each line in the region.
With just C-u prefix arg, uncomment each line in region BEG .. END.
Numeric prefix ARG means use ARG comment characters.
If ARG is negative, delete that many comment characters instead.
The strings used as comment starts are built from `comment-start'
and `comment-padding'; the strings used as comment ends are built
from `comment-end' and `comment-padding'.
By default, the `comment-start' markers are inserted at the
current indentation of the region, and comments are terminated on
each line (even for syntaxes in which newline does not end the
comment and blank lines do not get comments). This can be
changed with `comment-style'.
I assume something else is overriding C++ keybindings but I don't know what or how to fix it? Does anyone have any ideas?
Yes, c++ mode has its own keymap, which overrides the global map. Use the following instead:
(define-key c++-mode-map (kbd "C-c C-c") 'toggle-comment-on-line)
I've improved your code a bit, and below there's also the
code to bind the key without an error
(it happens because you're trying to define a key in
c++-mode-map before it was defined)
(defun toggle-comment-on-line ()
"comment or uncomment current line"
(interactive)
(let ((beg (if (region-active-p)
(region-beginning)
(line-beginning-position)))
(end (if (region-active-p)
(region-end)
(line-end-position))))
(comment-or-uncomment-region beg end)
(next-line)))
(add-hook 'c++-mode-hook
(lambda()
(define-key c++-mode-map (kbd "C-c C-c") 'moo-complete)))
As a side note, I strongly recommend against binding C-c C-c,
as this is a very popular mode specific binding that's different in every mode,
but means generally confirm:
in org-mode it evaluates a babel block of code
in message-mode it sends the email
in python-mode it sends the buffer to the process
in wdired it confirms your edits to the file names
So you'll really have a headache if you bind it, unless you're
using Emacs just for c++-mode.
I've been using Emacs for 3 years now and I have comment-dwim
on C-.. I'm quite happy with it so far.
If you're willing to use a different key binding, you can use the following code:
;; Nothing to see here.
after which you can do C-a C-SPC C-n M-;.

Running emacs keyboard macros in batch mode

I want to be able to save a keyboard macro in emacs and apply it to a file repeatedly in batch mode. To give a simple example, I made the following file paren-delete.el which is supposed to delete all parentheses and their contents. When I run emacs --batch target.txt --load paren-delete.el, nothing seems to have changed. It appears that only the first kbd function does what it's supposed to, so clearly I don't understand how that command works.
I know that it would be preferable to avoid keyboard macros and write my functions in proper elisp, but I'd prefer a quick-and-dirty solution, and I feel like I'm close.
(kbd "M-x load-library kmacro")
(fset 'delete-paren
(lambda (&optional arg) "Keyboard macro." (interactive "p")
(kmacro-exec-ring-item (quote ("^S(^M^B^#^[^N^W" 0 "%d")) arg)))
(start-kbd-macro nil)
(kbd "M-x delete-paren")
(end-kbd-macro)
(kbd "C-u 0 C-x e")
(save-buffer)
One answer:
Define a function that runs the macro: Write this in an Emacs-Lisp buffer leaving the cursor at the end::
(defun foo ()
M-x insert-kbd-macro RET
Now you have this text, but with the definition of your keyboard macro in place of XXXXX:
(defun foo () (setq last-kbd-macro XXXXX)
Replace setq last-kbd-macro by execute-kbd-macro, and add a final ):
(defun foo () (execute-kbd-macro XXXXX)
Then use C-x C-e after the definition or C-M-x anywhere inside it.
That defines function foo, which does just what your keyboard macro did (in the same context, e.g., same mode, so same key bindings).
Save the definition to your init file. You can use it with Emacs in batch mode. You can also add (interactive) after () to make it a command, so you can use it with M-x.
Another answer:
With Bookmark+, use C-u M-x bmkp-make-function-bookmark to create a bookmark from the last keyboard macro. You are prompted for the bookmark name.
Bookmarks are persistent. To use a bookmark in batch mode, call it as an argument of bookmark-jump, like so: (bookmark-jump THE-BOOKMARK-NAME).

emacs - set shortcut key only in major mode?

I would like to override C-l and use it to do M-x erase-buffer followed by simulating hitting RET, only when I am in m-shell-mode. C-l should be its default, recenter-top-bottom, otherwise. How do I do so?
Not sure what m-shell-mode is, but if it's a well-defined major mode, then the following should do the trick:
(require 'm-shell-mode)
(define-key m-shell-mode-map (kbd "C-l") 'erase-buffer)
Might I suggest an alternative binding, which has the same visual effect, but keeps the buffer contents around (which can be handy).
(defun shell-clear-command (&optional a)
"\"clear\" the screen"
(interactive "P")
(recenter (or a 0)))
(define-key m-shell-mode-map (kbd "C-l") 'shell-clear-command)
If m-shell-mode is based on comint-mode, which is true of many modes that provide a shell to interact with another process, then you can pass the return keypress to matlab with the function comint-send-input. In that case the following code should do what you want:
(defun clear-and-return ()
"Erases the buffer, and then passes a return to the buffer process.
Assumes the buffer is attached to a comint process."
(interactive)
(erase-buffer)
(comint-send-input))
(defun my-m-shell-mode-hook ()
(local-set-key (kbd "C-l") 'clear-and-return))
(add-hook 'm-shell-mode-hook 'my-m-shell-mode-hook)
The first defun makes a function that does what you want. The second is a hook function that will bind C-l to that function for the buffer that is active when the function is called. The add-hook tells emacs to run the second function whenever you start m-shell-mode. You can add further m-shell-mode customizations inside the body of my-m-shell-mode, and Emacs will run all of them each time you start the mode.
If m-shell-mode is not based on comint-mode, you need to find out what happens when you press return. From a buffer that is running the mode, type C-h k RET to find the function bound to the return key. Use that function instead of comint-send-input in the code above.
You can add to your m-shell-mode hook the following code:
(local-set-key (kbd "C-l") 'erase-buffer)