I want to override some basic function, let's say save-buffer (even if it does not make sense, it's for the sake of clarity), and give it a new definition. But I want all the original behaviors to be callable by adding a C-u.
So,
C-x C-s become my new definition of save-buffer.
C-u C-x C-s would call the original C-x C-s (without argument)
C-u C-u C-x C-s would be same same as calling the original C-x C-s with one C-u
and so on: always "one less" C-u...
Right now, I test for the value of arg. If nil, I execute my new defintion; otherwise, I call-interactively save-buffer (for the example). But, then, save-buffer is called with one C-u argument. I don't see how to do the "-1" C-u part.
Here's one way to do it:
(defun foo (arg)
(interactive "p")
(message "foo %s" arg))
(defun bar (arg)
(interactive "p")
(message "bar %s" arg))
(defmacro wrap (fg f g)
`(defun ,fg (arg)
(interactive "p")
(message "%s" arg)
(if (= 1 arg)
(funcall ,g 1)
(funcall ,f (/ arg 4)))))
(wrap baz #'foo #'bar)
Now a plain baz will call bar. With C-u
it will call foo, dividing the given arg by 4.
Related
If I want to make my own function which among other thing calls wg-save (workgroups.el - save workgroups) then I do something like this:
(defun foo ()
(interactive)
...
(call-interactively 'wg-save)
)
(global-set-key (kbd "my binding") 'foo)
What about the following scenario (I will use eyebrowse.el as an example):
eyebrowse uses C-c C-w 'number' to move to different window configurations e.g. C-c C-w 1 to move to 1 or C-c C-w 2 to move to 2.
How can I write a similar function like the 'foo' since now I need to pass to 'call-interactively' a 'number' as parameter?
EDIT: C-c C-w 1 calls eyebrowse-switch-to-window-config-1.
So I need to make a 'foo' function like the above that will 'call-interactively'
'eyebrowse-switch-to-window-config-1' when the key binding is 'C-c C-w 1', 'eyebrowse-switch-to-window-config-2' when the key binding is 'C-c C-w 2' etc.
Something like the following (if it makes sense):
(defun foo ()
(interactive)
...
(call-interactively 'eyebrowse-switch-to-window-config-"number")
)
(global-set-key (kbd "C-c C-w 'number'") 'foo)
From the documentation, read with C-h f call-interactively RET:
Optional third arg KEYS, if given, specifies the sequence of events to
supply, as a vector, if the command inquires which events were used to
invoke it. If KEYS is omitted or nil, the return value of
`this-command-keys-vector' is used.
So to pass arguments to call-interactively, give it a vector with the arguments, like so
(call-interactively 'my-fn t (vector arg1 arg2))
That way you don't need to call eyebrowse-switch-to-config-window-nwhere n is a number, you call the function they rely on, eyebrowse-switch-to-window-config, and give it a number as argument.
You can get a number for argument like this: (see help of "interactive" )
(defun foo (arg)
(interactive "nWindow? ")
(call-interactively 'my-fn t (vector arg))
)
But did you read the source of eyebrowse ? It will give ideas.
(defun eyebrowse-switch-to-window-config-0 ()
"Switch to window configuration 0."
(interactive)
(eyebrowse-switch-to-window-config 0))
You can do something like this I believe:
(defun foo (NUM)
"Enter the NUM of the screen to go to.
If the key pressed is not a number go to screen 0."
(interactive
(list (read-key-sequence "Which window: ")))
((eyebrowse-switch-to-window-config 3) (string-to-number NUM)))
The key is the read-key-sequence function
To save time and space, you can use a loop to define all the keybindings you'll use.
For example, for eyebrowse instead of defining each keybinding you could do this instead:
(load-library "eyebrowse")
(dotimes (i 10)
(global-set-key
(kbd (concat "C-c C-w " (number-to-string i)))
`(lambda ()
(interactive)
(eyebrowse-switch-to-window-config ,i))))
I have the following code/text:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
In Emacs23 (23.4.1) I was able to press TAB in the last line ("second note line"; nomatter how this line was indented) and it was aligned correctly like this:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
I.e., it uses the previous line and indents the following line in the same way.
Now in Emacs24 (24.3.1) this does not work anymore and it is aligned like this:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
I.e. it aligns the multi-line string block, but does not depend on the previous line.
It affects only docstrings; code is indented as I want. I am using python-mode. How can I change this, so that pressing TAB aligns the block correctly?
Python mode has changed quite a bit between Emacs 23 and 24. There is no configuration that would allow you to do what you want.
But, Emacs is quite flexible and you can advise the (python-indent-context) function to make it return a different result that will lead to the behavior you want. The function (python-indent-context) returns a character at which the indentation is measured and used for indenting the current line. By default, when inside a string, it returns the point where the beginning of the string resides. Thus, your line will be indented to the indentation of the start of the string. We can easily modify it to return a point in the previous non-empty line instead, for instance like this:
(defun python-fake-indent-context (orig-fun &rest args)
(let ((res (apply orig-fun args))) ; Get the original result
(pcase res
(`(:inside-string . ,start) ; When inside a string
`(:inside-string . ,(save-excursion ; Find a point in previous non-empty line
(beginning-of-line)
(backward-sexp)
(point))))
(_ res)))) ; Otherwise, return the result as is
;; Add the advice
(advice-add 'python-indent-context :around #'python-fake-indent-context)
The same effect can be achieved using the old defadvice for older Emacs:
(defadvice python-indent-context (after python-fake-indent-context)
(pcase ad-return-value
(`(:inside-string . ,start) ; When inside a string
(setq ad-return-value ; Set return value
`(:inside-string . ,(save-excursion ; Find a point in previous non-empty line
(beginning-of-line)
(backward-sexp)
(point)))))))
(ad-activate 'python-indent-context)
What about editing the section de-stringified in a separate buffer? That would allow python-mode with all its facilities.
Here a first draft - original string will be stored in kill-ring:
(defun temp-edit-docstring ()
"Edit docstring in python-mode. "
(interactive "*")
(let ((orig (point))
(pps (parse-partial-sexp (point-min) (point))))
(when (nth 3 pps)
(let* (;; relative position in string
(relpos (- orig (+ 2 (nth 8 pps))))
(beg (progn (goto-char (nth 8 pps))
(skip-chars-forward (char-to-string (char-after)))(push-mark)(point)))
(end (progn (goto-char (nth 8 pps))
(forward-sexp)
(skip-chars-backward (char-to-string (char-before)))
(point)))
(docstring (buffer-substring beg end)))
(kill-region beg end)
(set-buffer (get-buffer-create "Edit docstring"))
(erase-buffer)
(switch-to-buffer (current-buffer))
(insert docstring)
(python-mode)
(goto-char relpos)))))
When ready, copy the contents back into original buffer.
Which remains to be implemented still.
I have buffers named *terminal<1>*, *terminal<2>*, *terminal<3>*, etc. Is there a way to bind a key combination that will take an argument for the number? That is, I want to bind C-c 1 to switch to *terminal<1>* and C-c 2 to switch to *terminal<2>*, and so on. If I can't do this directly, is it possible to do metaprogramming in Elisp that will define all the functions for me?
In this suggestion, the interactive switch-to-terminal will take either a prefix argument C-u 2 for example, or prompt the user.
The macro then makes setting up the key bindings a little easier.
Finally I bind C-c 1 to C-c 4 to switch to *terminal<1>* to *terminal<4>*.
(defun switch-to-terminal (buf-num)
(interactive "NNumber of buffer to visist: ")
(let* ((buf-name (format "*terminal<%d>*" buf-num))
(buf (get-buffer buf-name)))
(unless buf
(error "No buffer %s" buf-name))
(switch-to-buffer buf)))
(defmacro bind-switch-to-terminal (num)
`(global-set-key
,(kbd (format "C-c %d" num))
(lambda ()
(interactive)
(switch-to-terminal ,num))))
(bind-switch-to-terminal 1)
(bind-switch-to-terminal 2)
(bind-switch-to-terminal 3)
(bind-switch-to-terminal 4)
This change uses the same switch-to-terminal function, but replaces bind-switch-to-terminal with a function. The lexical-let* allows for the creation of a closure to create unique terminal switching functions, the dotimes loop then binds for C-c 1 to C-c 9.
(defun bind-switch-to-terminal (num)
(lexical-let* ((buf-num num)
(switch-func
(lambda ()
(interactive)
(switch-to-terminal buf-num))))
(global-set-key
(kbd (format "C-c %d" buf-num))
switch-func)))
(dotimes (num 9)
(bind-switch-to-terminal (1+ num)))
You can bind keys as usual:
(global-set-key (kbd "C-c 1") (lambda ()
(interactive)
(switch-to-buffer "*terminal<1>*")))
To create all the shortcuts from 1 to 9 we would use macros.
edit: This buggy version may put you on tracks. I give up :(
(defmacro gototerminal (count)
`(global-set-key (kbd ,(concat "C-c " (number-to-string count)))
;; with the comma I want to evaluate what is inside concat
(lambda () (interactive)
(switch-to-buffer (concat "*terminal<" ,count ">*"))))
)
(progn (setq count 1)
(while (< count 10)
(gototerminal count)
(setq count (1+ count))
))
ps: an elisp debugger is edebug. Set it with C-u C-M-x
I would write a function that calls interactive with an n argument which indicates that the function reads a number from the mini buffer:
(defun test (x)
(interactive "nNumber of buffer to visit: ")
(message (concat "received number: " (number-to-string x))))
Binding this to a key will let you enter a number in the mini buffer.
Another way is to use a numerical argument:
(defun test (x)
(interactive "P")
(message (concat "received number: " (number-to-string x))))
Say you bind this function to C-c c, you can then pass it the number 2 as an argument by pressing C-u 2 C-c c.
If you avoid the usage of an existing prefix key like C-c you can trigger a command with one keypress e.g. F9.
This command can have a single key as input.
Example:
(defun test (k)
(interactive "K")
(message "Pressed key: %d" (- (aref k 0) ?0)))
(local-set-key [f9] 'test)
Using query-replace, the minibuffer says this (having saved the previous arguments):
Query replace (default FROM -> TO)
is there a command to swap the args? To get this:
Query replace (default TO -> FROM)
AFAIK, nothing out of the box does that for you. But IMHO you don't need that.
All you need to do is use M-p. Use it once to get the last TO you used. Then repeat M-p a couple times to get the last FROM you used. Very quick.
After that, you can use C-x ESC ESC (or C-x M-: or C-x M-ESC), possibly followed by M-p, to repeat either combination (TO -> FROM or FROM -> TO).
(defun swap-query-replace-defaults ()
"Swap the initial expressions offered by `query-replace'. "
(interactive)
(let* ((erg query-replace-defaults)
(first (car erg))
(second (cdr erg)))
(setq query-replace-defaults (cons second first))
(when (interactive-p) (message "%s" query-replace-defaults))
query-replace-defaults))
Made a feature-request:
http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-10/msg00102.html
There's a shortcut to swap the args: M-p RET M-p M-p RET
I use this:
;; Redefine `query-replace-read-from' to add a custom keymap when
;; replacing strings. Now, C-u ENTER does the reverse suggested
;; replacement.
(defvar query-replace-keymap
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map [remap exit-minibuffer]
(lambda ()
(interactive)
(if (and current-prefix-arg query-replace-defaults)
(setq query-replace-defaults
(cons
(cdr query-replace-defaults)
(car query-replace-defaults))))
(exit-minibuffer)))
map))
(defun query-replace-read-from (prompt regexp-flag)
"Query and return the `from' argument of a query-replace operation.
The return value can also be a pair (FROM . TO) indicating that the user
wants to replace FROM with TO."
(if query-replace-interactive
(car (if regexp-flag regexp-search-ring search-ring))
(let* ((history-add-new-input nil)
(query-replace-defaults query-replace-defaults)
(prompt
(if query-replace-defaults
(format "%s (default %s -> %s): " prompt
(query-replace-descr (car query-replace-defaults))
(query-replace-descr (cdr query-replace-defaults)))
(format "%s: " prompt)))
(from
;; The save-excursion here is in case the user marks and copies
;; a region in order to specify the minibuffer input.
;; That should not clobber the region for the query-replace itself.
(save-excursion
(if regexp-flag
(read-regexp prompt nil query-replace-from-history-variable)
(read-from-minibuffer
prompt nil query-replace-keymap nil query-replace-from-history-variable
(car (if regexp-flag regexp-search-ring search-ring)) t)))))
(if (and (zerop (length from)) query-replace-defaults)
(cons (car query-replace-defaults)
(query-replace-compile-replacement
(cdr query-replace-defaults) regexp-flag))
(add-to-history query-replace-from-history-variable from nil t)
;; Warn if user types \n or \t, but don't reject the input.
(and regexp-flag
(string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\[nt]\\)" from)
(let ((match (match-string 3 from)))
(cond
((string= match "\\n")
(message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
((string= match "\\t")
(message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
(sit-for 2)))
from))))
How can I define a command in paredit mode that swaps parentheses and square brackets?
So the task is to turn this, for example:
(blah
(a (b)
c))
into this:
(blah
[a (b)
c])
With paredit mode, move to start of the expression (a ..) and then:
C-M-SPC [ <right> M-s
Without paredit, but still wanting to maintain balanced parens during transitions, move to a and then press C-M-SPC multiple times until error and then (assuming that CUA mode is on):
C-x <timeout> <right> <backspace> <backspace> [ ] <left> C-v
Well that is complex, so let's stick with paredit mode version, and try to make a command out of it. Keyboard Macro Editor tells you the names of commands being used, so you would be able to come up with at least the following code:
(defun my-switch-to-square ()
"Change (..) to [..]."
(interactive)
(mark-sexp --)
(paredit-open-square --)
(right-char --)
(paredit-splice-sexp --))
-- indicates part of code we have not yet decided. After you read documentation of each function in the code, you learn what arguments to pass, and that there is no need to call mark-sexp. After rewriting docstring and adding a call to left-char, the code you end up with would be:
(defun my-switch-to-square ()
"Change |(..) to |[..]. | is point position."
(interactive)
(paredit-open-square 1)
(right-char 1)
(paredit-splice-sexp)
(left-char 1))
The following code does what you request. You can bind swap-parens to whatever key binding you want.
(defvar swap-paren-pairs '("()" "[]"))
(defun swap-parens-at-points (b e)
(let ((open-char (buffer-substring b (+ b 1)))
(paren-pair-list (append swap-paren-pairs swap-paren-pairs)))
(while paren-pair-list
(if (eq (aref open-char 0) (aref (car paren-pair-list) 0))
(save-excursion
(setq to-replace (cadr paren-pair-list))
(goto-char b)
(delete-char 1)
(insert (aref to-replace 0))
(goto-char (- e 1))
(delete-char 1)
(insert (aref to-replace 1))
(setq paren-pair-list nil))
(setq paren-pair-list (cdr paren-pair-list))))))
(defun swap-parens ()
(interactive)
(cond ((looking-at "\\s(")
(swap-parens-at-points (point) (save-excursion (forward-sexp) (point))))
((and (> (point) 1) (save-excursion (forward-char -1) (looking-at "\\s)")))
(swap-parens-at-points (save-excursion (forward-sexp -1) (point)) (point)))
((message "Not at a paren"))))
I'm not sure what you mean by "define command"? You can do it like this:
|(foo bar)
"|" is point.
;; Keyboard Macro Editor. Press C-c C-c to finish; press C-x k RET to cancel.
;; Original keys: C-u [ C-f <M-up> C-b
Command: last-kbd-macro
Key: none
Macro:
C-u [ ;; paredit-open-square
C-f ;; forward-char
<M-up> ;; paredit-splice-sexp-killing-backward
C-b ;; backward-char
Although to be honest, this type of usage scenario is more common for VIM trickery. I've never actually used this IRL.
bzr branch lp:s-x-emacs-werkstatt
will deliver a library inspired by paredit, but delivering more detailed commands
M-x ar-bracket-parentized-atpt RET
puts brackets around parenteses at point
look inside thing-at-point-utils.el and the other files what else is provided