5

I am not able to figure out what is wrong in this elisp form:

(define-key ggtags-mode-map (kbd "M-.")
  (lambda ()
    (interactive)
    (ggtags-find-tag-dwim)
    (recenter)))

I keep getting this message:

Wrong number of arguments: (1 . 2), 0

The debugger message:

Debugger entered--Lisp error: (wrong-number-of-arguments (1 . 2) 0)
  ggtags-find-tag-dwim()
  (lambda nil (interactive) (ggtags-find-tag-dwim) (recenter))()
  funcall-interactively((lambda nil (interactive) (ggtags-find-tag-dwim) (recenter)))
  call-interactively((lambda nil (interactive) (ggtags-find-tag-dwim) (recenter)) nil nil)
  command-execute((lambda nil (interactive) (ggtags-find-tag-dwim) (recenter)))
  • 2
    Doing M-x toggle-debug-on-error should give you more info when that happens. – npostavs Oct 10 '17 at 19:17
  • I get this error but I still dont get it. updated in the post. – SFbay007 Oct 10 '17 at 19:36
  • 3
    The function ggtags-find-tag-dwim takes a mandatory argument NAME and a second, optional WHAT. You are calling it without any arguments. Refer to its documentation with M-x describe-function RET ggtags-find-tag-dwim RET or C-h f ggtags-find-tag-dwim RET. – Basil Oct 10 '17 at 19:37
  • Basil, thanks. Then why this works with no arguments needed? (define-key ggtags-mode-map (kbd "M-.") 'ggtags-find-tag-dwim) – SFbay007 Oct 10 '17 at 21:08
  • @SFbay007 Because invoking a function from a key binding calls it interactively, and ggtags-find-tag-dwim provides an interactive form for generating its two arguments when called as a command, rather than as a function. – Basil Oct 10 '17 at 22:00
6

“Wrong number of arguments: (1 . 2), 0” means that a function expects at least 1 and at most 2 arguments (i.e. 1 mandatory and 1 optional argument), but it was called with 0 arguments.

As npostavs explained in a comment, you can run M-x toggle-debug-on-error and repeat the action again to get more information. When the error occurs, you'll see a backtrace, which lists the active function calls, from innermost to outermost. The first line is the function that was just called, that's the one which isn't receiving the correct number of arguments. When you've finished reading the backtrace, press ESC ESC ESC or C-] to exit the debugging mode.

The help for the function ggtags-find-tag-dwim (C-h f ggtags-find-tag-dwim RET) tells you that its call syntax is

(ggtags-find-tag-dwim NAME &optional WHAT)

I.e. it's called with two parameters called name and what (the names are capitalized in the help), and the second parameter is optional.

When the function is called interactively, i.e. when it's directly bound to a key (or mouse or other event), Emacs passes it parameters based on the function's interactive specification. Some common examples of automatic parameter passing include the numerical prefix argument, the point or region (point and mark), something typed by the user (arbitrary string, file name, buffer name, etc.), etc. Parameters can also be generated by Lisp code given in the function definition.

You need to pull up the source code to see the interactive specification. The source code will be linked from the function help if it's available. The interactive specification looks like a call to a function called interactive just below the function's documentation string.

(defun ggtags-find-tag-dwim (name &optional what)
  "Find NAME by context.
…"
  (interactive
   (let ((include (and (not current-prefix-arg) (ggtags-include-file))))
     (ggtags-ensure-project)
     (if include (list include 'include)
       (list (ggtags-read-tag 'definition current-prefix-arg)
             (and current-prefix-arg 'definition)))))
…

You can copy this interactive specification into your own wrapper. But since it's complicated and your wrapper is simple, you should instead tell Emacs to call the function interactively, i.e. to pass parameters automatically as if the function had been directly invoked by pressing a key.

(define-key ggtags-mode-map (kbd "M-.")
  (lambda ()
    (interactive)
    (call-interactively 'ggtags-find-tag-dwim)
    (recenter)))

For this specific case, since it seems that you always want to run recenter after ggtags-find-tag-dwim, there's a simpler way: the Ggtags package has a customization for this. In the Customize interface, navigate to the Ggtags group (“GNU Global source code tagging system”), and change “Hook run immediately after finding a tag.” to recenter. Alternatively, put the following line in your init file:

(setq ggtags-find-tag-hook 'recenter)
  • Thank you for the write up. That worked. However, the (recenter) function is still not executing or maybe executing too early. Is there a way to make ti recenter correctly after finding the tag? – SFbay007 Oct 11 '17 at 0:20
  • @SFbay007 I've tried to reproduce this and I find that the target line is centered unless it was already visible in the buffer in which case the buffer isn't scrolled. I think this has to do with the delicate interactions between window point and buffer point, which I've come across before 1 2 3 but I haven't figured out what's going on here. This would warrant a new question. Please explain precisely what is going wrong for you, because most of the time, it does work. – Gilles Oct 11 '17 at 23:20
  • Thanks for the follow up Gilles. I have posted the full issue here:emacs.stackexchange.com/questions/36094/… – SFbay007 Oct 11 '17 at 23:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.