1

This defines the Helm-source for Emacs commands history.

(defvar helm-source-emacs-commands-history
    (helm-build-sync-source "Emacs commands history"
    :candidates (lambda ()
                    (let ((cmds))
                    (dolist (elem extended-command-history)
                        (push (intern elem) cmds))
                    cmds))
    :coerce #'intern-soft
    :action #'command-execute)
    "Emacs commands history")

From this source you get the latest commands that you called with M-x. I would have a function, that calls the latest command that I called with M-x earlier. I read the documentation about list elements.

Function: car cons-cell
This function returns the value referred to by the first slot of the cons cell cons-cell. In other words, it returns the CAR of cons-cell.

As a special case, if cons-cell is nil, this function returns nil. Therefore, any list is a valid argument. An error is signaled if the argument is not a cons cell or nil.

(car '(a b c))
    ⇒ a
(car '())
    ⇒ nil

So I assume I need to replace the push with car, and return the result.

(dolist (elem extended-command-history)
(car (intern elem))) 

But I got the error message

Debugger entered -- Lisp error (wrong-type-argument listp Info-next)
(Info-Next)

The Info-Next was indeed the latest command that I called with M-x. However, I don't understand the error. Another way to get the latest called function.

(defun foobar ()
    (interactive)
    (call-interactively (intern (car extended-command-history))))

After calling foobar, I get the following error:

funcall-interactively: Lisp nesting exceeds `max-lisp-eval-depth'

Any suggestion to get the latest command?

  • 1
    I, for one, don't understand the question. But I sense that there is a question here and that others will understand it. I hope you find an answer. – Drew Aug 10 '15 at 0:04
  • Why aren't you using the default binding of n to call Info-next ? – phils Aug 10 '15 at 1:33
  • 3
    I think you want (defun foobar () (call-interactively (intern (car extended-command-history))) but as things stand right now, the question is unclear. You're mixing your actual question with your personal research on the matter, and it ends up being difficult to understand. – YoungFrog Aug 10 '15 at 9:30
  • 3
    ReneFroger: Showing what you've tried is certainly to be encouraged, but in this instance there's a lot of confusion. I suspect that YoungFrog's comment has interpreted and answered your question correctly. It's great that you've been using the documentation, so you should (re-)read the details of each of the functions for the working version of the code, and hopefully you'll be able to understand why that does what you wanted (and why your original code did not). – phils Aug 10 '15 at 10:56
  • 3
    Please don't post the same question here and on StackOverflow. It's not forbidden, of course, but it just makes for more noise for everyone. (Just one opinion.) – Drew Aug 10 '15 at 13:51
2

Let's explain the different code bits of your question (I'm reusing some of what I said in my comments).

What we find in the helm source definition is:

(let ((cmds))
  (dolist (elem extended-command-history)
    (push (intern elem) cmds))
  cmds)

This builds a list of symbols. Each element of extended-command-history is a string which is transformed into a symbol via intern and pushed to the list cmds. Once done, cmds is returned. Btw, another, more concise but not more efficient, way of doing this is

(nreverse (mapcar 'intern extended-command-history))

Now what you want is to run the first element of extended-command-history and run it as a command. So a first naive approach would be:

(defun foobar ()
  (interactive)
  (call-interactively (intern (car extended-command-history))))

But if you do M-x foobar RET this will end up running foobar (because M-x pushes foobar to extended-command-history before calling it), hence the error you mentionned :

funcall-interactively: Lisp nesting exceeds `max-lisp-eval-depth'

To avoid this problem, one can run the first element of extended-command-history that is different from the current command. Here's some code to do this :

(defun foobar ()
  (interactive)
  (let ((history extended-command-history)
        cmd)
    ;; remove any occurence of this-command at the head of `history'.
    (while (string= this-command (setq cmd (pop history))))
    (message "Running cmd: %s" cmd)
    (call-interactively (intern cmd))))

As you mentionned, we could also run the cadr of extended-command-history, but it would be off by one in the case foobar is not ran via M-x but via some key binding (because in this case, it won't get added to the head of extended-command-history).

  • I'd like to add that I think you're solving your problem with the wrong tools. If you want to use a given command repeatedly, just bind it to a key (and maybe check that it is not bound already, using C-h w -- in the case of Info-next it is bound to n.) – YoungFrog Aug 10 '15 at 15:15
  • YoungFrog, thanks for your helpful explaination. Now I understand better where I went wrong, and new ways to do it right, including checking if keys are bound. It's really appreciated, YoungFrog. Thanks! – ReneFroger Aug 10 '15 at 23:35
0

After some asking and research, the error funcall-interactively: Lisp nesting exceeds max-lisp-eval-depth is quite reasonable. The last command will be foobar since it is interactive. Use use cadr instead of car in foobar.

  • Please note that this will fail if you decided to bind foobar to a key. – YoungFrog Aug 10 '15 at 14:07
  • You're sharp and right. Indeed, I already noticed it after bounding it to a key. See my reply above on your solution. – ReneFroger Aug 11 '15 at 0:02

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.