Emacs -- Timing execution of function calls in Emacs lisp - emacs

I'm looking for some assistance, please, to measure the time of a function call when using a while loop -- i.e., the clock should stop when the function throws done. I found the following timer on the mailing list: http://lists.gnu.org/archive/html/help-gnu-emacs/2008-06/msg00087.html
(defmacro measure-time (&rest body)
"Measure the time it takes to evaluate BODY."
`(let ((time (current-time)))
,#body
(message "%.06f" (float-time (time-since time)))))
It's used like this:
(measure-time
(dotimes (i 100000)
(1+ 1)))
An example of how to use the timer macro with a while loop would be greatly appreciated. I'm looking for the total time beginning from before the while loop commenced to the end when done is thrown.
(defun test ()
(measure-time)
(catch 'done
(while t
[*** do a bunch of stuff]
(when (condition-satisfied-p)
[*** STOP THE CLOCK AND PRINT TOTAL DURATION ***]
(throw 'done nil) ))))

Exactly as per the example you've quoted. You literally wrap (measure-time ... ) around the thing you're timing. The entirety of the catch expression, in your case.
Did you not try that?

BTW, this macro is called benchmark-elapse in Emacs, but it is not autoloaded, so you need to (require 'benchmark) before using it.

Related

Infinite loop when byte compile

I'm author of evil-commentary, the full source less than 200 lines can be found in the repo.
Basically I have something like this.
(evil-define-operator evil-commentary (beg end type)
"Comment or uncomment region that {motion} moves over."
:move-point nil
(interactive "<R>")
(let ((comment-function
(cdr (assoc major-mode
evil-commentary-comment-function-for-mode-alist))))
(if comment-function (funcall comment-function beg end)
(comment-or-uncomment-region beg end))))
(defun evil-commentary-comment-for-org (beg end)
"Comment function for `org-mode'."
(interactive "r")
(if (and (fboundp 'org-in-src-block-p)
(org-in-src-block-p))
(evil-commentary-do-in-org-src-block beg end
(call-interactively 'evil-commentary))
(comment-or-uncomment-region beg end)))
The idea is that evil-commentary will call evil-commentary-comment-for-org in an org file, and if we're in a src block, evil-commentary-comment-for-org will call evil-commentary again in the src-edit buffer (which now has different major-mode)
The setup works just fine, however when I compile the code, I get an infinite loop evil-commentary -> evil-commentary-comment-for-org -> evil-commentary... with Variable binding depth exceeds max-specpdl-size error...
I found that it will work if I compile the code after org is loaded, but that not I wanted because evil-commentary will stop working if an user compile with an old version of org then upgrade it. (A flaw of package.el)
Thank you!
The problem is in this line, which expands to:
(org-babel-do-in-edit-buffer
(call-interactively 'evil-commentary))
If you haven't loaded org, the byte compiler doesn't know org-babel-do-in-edit-buffer is a macro, and can't expand it. So it simply compiles a call to an (as of yet unknown) function called org-babel-do-in-edit-buffer.
When execution reaches that line, the function arguments are evaluated first (as in any other function call) and there you have your infinite loop.
Try requiring org inside an eval-when-compile block.

Elisp: any way to stop edebug besides top-level?

I'm working on a function to break out of edebug while keeping
the arguments of current function bound.
(defun stop-edebug ()
"Stop edebugging"
(interactive)
(if (not edebug-mode)
(error "edebug isn't running!")
(save-excursion
(beginning-of-defun)
(if (looking-at "(defun\\s-+\\_<[^ ]+\\_>\\s-+(")
(progn
(goto-char (match-end 0))
(backward-char 1)
(forward-sexp 1)
(let ((sexps (mapcar
(lambda(x!) (cons x! (symbol-value x!)))
(preceding-sexp))))
(edebug-mode -1)
(mapc (lambda(x) (set (car x) (cdr x))) sexps)))))))
This way i can eval the function body at my own pace after edebug has bound
the function arguments for me.
The problem is that (edebug-mode -1) isn't really the way to exit
edebug. It leads edebug marker lingering in the buffer and maybe other
side-effects that I'm not aware of.
Normally, exiting is done with q that's bound to top-level.
But I don't how to call anything after top-level since
it's a jump straight to the main command loop.
So I'm asking either for a way to call something after top-level
or for a better way to exit edebug than (edebug-mode -1).
To run code after calling top-level you can schedule that code for later execution in a timer. E.g.
...
(run-with-timer 0 nil
(lambda ()
(do the thing (here))))
(top-level))

AUCTeX: Run Compile Command n-times

I'd like to have a function that asks for a number n and executes the default compile command n-times afterwards. That is to say unlike C-c C-c (i.e. TeX-command-master) I don't want to be asked which command to run, it should select the default compile command based on the AUCTeX settings. Naturally if any error occurs the execution should stop.
I know about TeX-texify, however, this doesn't statisfy my needs because sometimes I just want emacs to run pdflatex five times indepent of what the AUCTeX parser thinks is adequate.
Any help is much appreciated!
Edit: I have looked into this a little further and using code from the above reference I have started writing a function that does this. However, it has one major flaw. Let me first give you the code:
(defcustom TeX-MultiTeX-Command "LaTeX" "Default MultiTeX command" :type 'string :group 'TeX-command)
(defun TeX-MultiTeX (n)
"Run TeX-command n-times"
(interactive "nRun TeX/LaTeX how many times: ")
(while (> n 0)
(TeX-command TeX-MultiTeX-Command 'TeX-master-file)
(setq n (- n 1))))
As you can see, I have implemented a config variable for selecting the correct compilation command. Now let me present the problem:
The compilation of the LaTeX document takes some time, however, my function instantly calls the second (and following) executions of the compile command. Maybe someone can provide help in finding a solution that checks whether compilation has finished successfully prior to executing (TeX-command TeX-MultiTeX-Command 'TeX-master-file), then executes said function or prints some error message if compilation finished with an error.
With the help of the code of the TeX-texify function I have developed a function that does what I want, the code is given below.
I'd like to thank user4815162342; although this solution is not based on his suggestion, I think his solution might be of use for a different problem. Also I'd like to thank TN, the author of TeX-texify, I shamelessly took and adapted his code for my problem. ;)
(defcustom TeX-MultiTeX-Command "LaTeX"
"Default MultiTeX command"
:type 'string :group 'TeX-command)
(defun TeX-MultiTeX-sentinel (&optional proc sentinel)
"Non-interactive! Call the standard-sentinel of the current LaTeX-process.
If there is still something left do do start the next latex-command."
(set-buffer (process-buffer proc))
(funcall TeX-MultiTeX-sentinel proc sentinel)
(let ((case-fold-search nil))
(when (string-match "\\(finished\\|exited\\)" sentinel)
(set-buffer TeX-command-buffer)
(unless (plist-get TeX-error-report-switches (intern (TeX-master-file)))
(TeX-MultiTeX TeX-MultiTeX-num-left)))))
(defun TeX-MultiTeX (n)
"Run TeX-command n-times"
(interactive "nRun TeX/LaTeX how many times: ")
(when (or (called-interactively-p 'any)
(null (boundp 'TeX-MultiTeX-num-left)))
(setq TeX-MultiTeX-num-left n))
(if (>= TeX-MultiTeX-num-left 1)
(progn
(TeX-command TeX-MultiTeX-Command 'TeX-master-file)
(setq TeX-MultiTeX-num-left (- TeX-MultiTeX-num-left 1))
(setq proc (get-buffer-process (current-buffer)))
(setq TeX-MultiTeX-sentinel (process-sentinel proc))
(set-process-sentinel proc 'TeX-MultiTeX-sentinel))))
It seems that you need a synchronous way to run TeX-command. I haven't word with TeX-command, but if it uses the compilation API, it can be made to wait for the compilation to finish, although it's not exactly obvious how to do that. Here is an example that uses compilation-finish-functions to achieve the desired effect:
(require 'cl) ; for lexical-let
(defun compile-and-wait (compilefun)
(interactive)
(lexical-let ((done nil) finish-callback)
(setq finish-callback
;; when the compilation is done, remove the callback from
;; compilation-finish-functions and interrupt the wait
(lambda (buf msg)
(setq compilation-finish-functions
(delq finish-callback compilation-finish-functions))
(setq done t)))
(push finish-callback compilation-finish-functions)
(funcall compilefun)
(while (not done)
(sleep-for .1))))
EDIT
AUC TeX is not using compilation mode to spawn TeX, so the above cannot work. Since it's still useful for other compilation buffers, I'm leaving it in the answer. Another way to implement TeX-MultiTeX is by binding TeX-process-asynchronous to nil, which should ensure that AUC TeX waits for the command to finish.

Can an elisp piece of code "yield" so emacs doesn't block?

Is there any way to write something like this without taking over emacs?
(defun dumb-wait (seconds)
(let ((done (+ (second (current-time)) seconds)))
(while (< (second (current-time)) done)
(message "waiting"))))
(dump-wait 5) will block emacs from 5 seconds. Is there anyway to write this so it doesn't block? I just want to be in a loop and check some condition from time to time, and still be able to use emacs.
Thanks!
(run-at-time time repeat function &rest args) should do it. nil as time means now.
(setq my-timer
(run-at-time nil 5 (lambda () (message "waiting")))) ; returns timer object
;; or
(setq my-timer
(run-at-time nil 5 'message "waiting"))
(cancel-timer my-timer) ; use timer object from above
Edit:
The parameter repeat expects a number as seconds, however there's a function timer-duration, which you can use instead of the number. It returns the number of seconds as provided with a string parameter. This is somewhat easier to read for big intervals.
(timer-duration "3 hours 2 seconds 1 millisec") ; => 10802.001
Possible word you can use are defined in the variable timer-duration-words.
On a related note, there's no general way to write Emacs Lisp code that doesn't block because the language doesn't have features like coroutines, continuations and threading (yet). Instead, you've got to look for asynchronous inbuilts that do something closest to what you want. Example: url-retrieve and async-shell-command. Some applications like SLIME have managed to work around this issue and have implemented a sort of threading on their own, while others like gnus are waiting for Emacs Lisp to improve.

Help with an interactive Emacs Lisp function for replacing text

I've been using Emacs for a couple months now, and I want to get started in elisp programming. Specifically, I'd like to write my own interactive function. However, I'm more than a bit lost. (interactive ...) has tons of options and I'm not sure which one I want. Then, I don't really know the names of the functions I need. If someone could kindly help me turn my pseudocode into real code, I would be mighty appreciative! (And as always, any links to informative places would be good. Right now I've just been reading this.)
Here is pseudocode for what I'd like to do:
(defun my-func (buffer) ; I think I need the buffer as an arg?
"does some replacements"
(interactive ???) ; ?
(let (replacements (list
'("a-regexp-string" . "a-replacement-string-with-backreferences")
...)) ; more of the above
(while replacements
(let (current (car replacements)) ; get a regexp-replacement pair
(some-regexp-replace-func buffer (car current) (cdr current)) ; do the replacement
(setq replacements (cdr replacements))))))
First, from the looks of your function you would probably be doing it in the current buffer, so no, you don't need to have a 'buffer' argument. If that's a bad assumption, I can change the code. Next, in a 'let' if you are assigning to variables you need another set of parens around each pair of var/value. Finally, when looping through a list I prefer to use functional-programming-like functions (mapcar, mapc, etc.). I'll try to inline some comments here:
(defun my-func ()
"Do some replacements"
(interactive)
(let ((replacements (list '("foo" . "bar")
'("baz" . "quux"))))
(save-excursion ; So point isn't moved after this function
(mapc (lambda (x) ; Go through the list, with this 'inline' function
; being called with each element as the variable 'x'
(goto-char (point-min)) ; Start at the beginning of the buffer
(while (re-search-forward (car x) nil t) ; Search for the car of the replacement
(replace-match (cdr x)))) ; And replace it with the cdr
replacements)))) ; The list we're mapc'ing through
As for what to read, I'd suggest the Elisp manual that comes with Emacs.