1
votes

Premises:

My Emacs has a small bug (cannot go up from inside of "") in one of its original defun (up-list). This defun is vital to one of my frequently used command (backward-up-list) which is bound to C-M-u.

Therefore, I wanted to achieve below objectives:

  1. Write a NEW defun named my-up-list which has the bug fix;
  2. RE-write the native defun backward-up-list to call the above new defun (instead of the native buggy up-list). (By RE-writing under the same defun name, I intend to preserve its original convenient key bindings.)

By following the Emacs Tutorial Here, I implemented it as below:

  1. I wrote a new defun my-up-list inside .emacs file; (see code in the end)
  2. I rewrote the defun backward-up-list under a the same name inside .emacs file; (see code in the end).

However, when wI tested it out by trying it in "|" (| is the cursor position), I encounter below error:

backward-up-list: Wrong number of arguments: (lambda nil (interactive) (let ((s (syntax-ppss))) (if (nth 3 s) (progn (goto-char (nth 8 s))))) (condition-case nil (progn (up-list)) (error nil))), 1 [2 times]

Question:

  • Is it the correct way to re-write a native defun just by putting the new implementation with the same name in .emacs file?
  • What may went wrong in my code?

Reference: (The my-up-list is from here)

;; I only changed "up-list" to "my-up-list" -modeller
(defun backward-up-list (&optional arg)
  "Move backward out of one level of parentheses.
With ARG, do this that many times.
A negative argument means move forward but still to a less deep spot.
This command assumes point is not in a string or comment."
  (interactive "^p")
  (my-up-list (- (or arg 1))))

;; copied from solution to another question - modeller
(defun my-up-list ()
  (interactive)
  (let ((s (syntax-ppss)))
    (when (nth 3 s)
      (goto-char (nth 8 s))))
  (ignore-errors (up-list)))
2
If the aim of redefining the function is to retain its keybindings, Emacs has you covered with command remapping. See C-h i g (elisp) Remapping Commands RET. Here you can use (global-set-key [remap backward-up-list] 'my-backward-up-list).phils
@phils thanks for the tips. It is great to learn an alternative way for doing the trick.modeller
It's not clear (to me at least) why you even want to do this. Vanilla up-list takes you out of the string, just past it. And invoking it again then takes you exactly where my-up-list takes you. So without my-up-list you just need to hit the up-list key twice to get the same effect. And as a bonus you can use up-list whenever you just want to get past the string. If you bind a command such as (my-)up-list to a key then you typically want it to be a simple, repeatable key anyway.Drew
@Drew, I got a "scan error: unbalanced parentheses" from the vanilla version up-list. I uses (self-compiled Emacs 23.4 64-bit). Please see code here: lpaste.net/109513modeller
Ah yes, there is an up-list bug in Emacs 23 and 24 (including the latest 24.4 pretest), and there is a different bug in Emacs 22 and prior. You could just pick up the definition from a recent Emacs 24.4 development snapshot, where the Emacs 23-24 bug has been fixed.Drew

2 Answers

1
votes

I guess your my-up-list function needs to accept the same arguments as the original up-list, and call up-list with them?

0
votes

The simplest way to do this is with the "advice" system. This provides some simple ways to wrap and extend existing functions. There's a whole section in the elisp manual explaining how to do it.