How do you find the name of the current running funciton: current-function, this-function, current-defun, this-defun - elisp

I am trying to dynamically find the name of the current function (this-function) running i.e.
(defun my-func ()
(remove-hook 'some-hook this-function)
(do-something))

I haven't tested this, but why not write a macro to encapsulate what you want? Something like the following, maybe?
(defmacro one-shot-hook (name hook &rest body)
`(defun ,name ()
(remove-hook ',hook ',name)
,#body)
Then, for example
(macroexpand-all-1
'(one-shot-hook test c-mode-hook
(message "Yay!")))
gives
(defun test nil
(remove-hook (quote c-mode-hook) (quote test))
(message "Yay!"))
(when I've reformatted it).
This removes the problem of needing to know the name of the function you're in, which would need nasty macrology anyway (I'm not sure whether it's possible).
One more thing, I'd probably suggest just having a flag variable set to nil initially which your code tests to decide whether to run. Then you don't have to mess around adding and removing hooks all the time: the result will probably be much easier to customise and understand for anyone else using your code.

Related

Add extra action (recenter) to `org-forward-element`?

In org-mode, strike M-} which invoke org-forward-element is very handy to jump around.
However, the matching line always stay at the bottom. So I have to manually execute (recenter).
How could add the action (recenter) to org-forward-element?
I tried a decorator solution, but does not work.
(defun add-recenter(func)
(lambda ()
(func)
(recenter)))
(setq org-element-forward (add-recenter org-element-forward))
This seems to work:
(advice-add 'org-forward-element :after (lambda () (recenter)))
I first tried (advice-add 'org-forward-element :after 'recenter), but that didn't work, because if the advice function being added (in this case recenter) is interactive, its interactive spec overrides that of the old function (org-forward-element), which causes an error since recenter generates one argument while org-forward-element takes zero arguments.
The reason your code doesn't work is that in Emacs Lisp variables and functions are in separate namespaces, just like Common Lisp and unlike Scheme. This is sometimes described as "Lisp-2", as opposed to "Lisp-1". See e.g. this article: http://ergoemacs.org/emacs/lisp1_vs_lisp2.html
Basically every symbol has both a "value cell" and a "function cell". setq changes the symbol's value cell, and calling a symbol, like (foo), accesses its function cell. The corresponding Emacs Lisp code would be something like:
(defun add-recenter(func)
(lambda ()
(funcall func)
(recenter)))
(fset 'org-element-forward (add-recenter (symbol-function 'org-element-forward)))
That is essentially what the advice-add call above does.

Can't open links using org-link-open-from-string because (file-name-directory (buffer-file-name)) appears to return nil

I've had this problem for a very long time (which makes it a little hard to know what originally caused it), but it was mostly something I could ignore until now, however my workflow would be a lot simpler now if I could just solve this.
For a long time I noticed that if I called org-open-at-point (C-c C-o) on a headline in the agenda, after selecting to link I wished to open, it would fail due to wrong-type-argument, I recently discovered this wasn't an issue with the agenda as I had thought, but actually happens whenever I call this function on a headline even in the org-file directly.
However if I call the function directly on a link, even a link contained in the headline, it works as expected (although not when called directly on a link that is contained in the property drawer).
So far I've narrowed this down to the fact that when called on a headline, org-open-at-point calls org-link-open-from-string, which does not appear to be the case when called directly on a link. Presumably feeding the link I select from the prompt to this function as a string, while it doesn't need that rigmarole when called directly on a link itself. (Although I don't understand why this errors still when called directly on links in the properties drawer).
Here is the output of the emacs-lisp debugger cleaned up very slightly for minor readability improvement. The only thing I can think of is that something in the org-mode-hook is doing something weird?
(wrong-type-argument stringp nil)
file-name-directory(nil)
(string-match-p (concat (getenv "DATA_DIR") "/Notes") (file-name-directory (buffer-file-name)))
(if (string-match-p (concat (getenv "DATA_DIR") "/Notes") (file-name-directory (buffer-file-name))) (howm-mode))
(lambda nil (if (string-match-p (concat (getenv "DATA_DIR") "/Notes") (file-name-directory (buffer-file-name))) (howm-mode)))()
run-hooks(change-major-mode-after-body-hook text-mode-hook outline-mode-hook org-mode-hook)
apply(run-hooks (change-major-mode-after-body-hook text-mode-hook outline-mode-hook org-mode-hook))
run-mode-hooks(org-mode-hook)
org-mode()
org-link-open-from-string("[[pdftools:/data/Reading.bib]]")
eval((org-link-open-from-string "[[pdftools:/data/Reading.bib]]") t)
eval-expression((org-link-open-from-string "[[pdftools:/data/Reading.bib]]") nil nil 127)
funcall-interactively(eval-expression (org-link-open-from-string "[[pdftools:/data/Reading.bib]]") nil nil 127)
call-interactively(eval-expression nil nil)
command-execute(eval-expression)
I'm truly stumped here guys, spent a few hours on this, and also "Googling" occasionally over the last few months. Nobody else that I've found seems to have a comparable issue.
Please ignore the fact that I'm calling a pdftools link on something that isn't a PDF here, that has nothing to do with it, the issue is replicable regardless of the format of the link, and isn't exclusive to pdftools links or mismatched files to link type or anything like that.
What's causing this problem? I've spent tens of hours on this, to no avail. I'm still new to the debugger in Emacs to be honest.
UPDATE: Putting my thoughts down like this made me realise the offending call to (buffer-file-name) was being called due to this hook I'd added
(add-hook 'org-mode-hook '(lambda ()
(if (string-match-p (concat (getenv "DATA_DIR") "/Notes") (file-name-directory (buffer-file-name)))
(howm-mode))))
I've still no idea what the reason for buffer-file-name being nil is, but removing this piece of code, did indeed resolve the immediate issue.
Now I guess the question I still need answered, is why? Is it possible that this function is being called when the value is actually nil, i.e., there is no buffer? I had always thought there was always a buffer. This hook is also pretty important to my workflow.
ANOTHER UPDATE: Just realised that I can use a conditional to get around this issue:
(add-hook 'org-mode-hook '(lambda ()
(if
(string-match-p (concat (getenv "DATA_DIR") "/Notes") (if
(buffer-file-name) (file-name-directory (buffer-file-name)) (message "No buffer file name.")))
(howm-mode))))
(Yes I realise this is really inefficient and not very functional, I'll clean it up later ;).)
However if anybody has an explanation for exactly how buffer-file-name was nil, I'd love to know as I'm still learning Emacs' internals slowly slowly.
YET ANOTHER EDIT: It's obvious now that it's occurred to me but even if one IS always in a buffer as I suspect, it's also true that not all buffers have a file associated. Hence the nil value. Why I was ending up in a non-file buffer at precisely the moment org-hooks were called I'm not 100% sure.

Wrong type argument: sequencep, #<buffer *scratch*> when trying to evaluate a function in the scratch buffer

My emacs stops working when I try to evaluate a piece of lisp code in the scratch buffer (with eval-last-sexp) or the minibuffer, with the above error. I cannot recover from this, I have to kill the emacs process.
The function is:
(defun add-to-list (val list-of-numbers)
(mapcar #'(lambda (num) (+ val num))
list-of-numbers))
I have tried on a fresh spacemacs installation to exclude that there is something wrong with my configuration file but I get the same problem.
This seems like a well formed function and the function name displays in the minibuffer after evaluation, so it seems to be evaluated fine. But then the above error occurs.
Can somebody explain based on this information?
add-to-list is a Emacs build-in function. Maybe the redefinition is here the source of your problem?
What happens if you choose another function name?

Get variable value with a string in scheme

How can we get variable value with a string in scheme language as we can achieve this in Common Lisp:
> (defvar s 3)
> S
> (symbol-value (intern "S"))
> 3
I am accessing a parameter of parent function from the closure.
EDIT: I have found this solution, but I can't use eval because it evaluates at top level. Searching for alternatives.
(eval (string->symbol "s"))
EDIT 2: I have found that Common lisp code also try to find symbol in global space. So this question is basically for both Lisps(Common Lisp, Scheme).
Don't do that!
Variables are for when you know the variable at compile time. In that case it is never a string. You can still reason about strings in compile time but your code also needs to have a relation with the name for it to be interesting. When you use eval or other forms that evaluate structure and compile/run data in runtime you are probably not doing it right (but not always. I've in my 20 year career used eval intentionally in production code twice)
If you want to store values you use a data structure. An assoc would mimic a dynamic environment. You can also use a hash with a level indicator if the size is harmless.
You can't do what you want to do and in fact it is a confused thing to want to do.
Here's why what you are trying to do is confused. Consider how a Lisp system for which it was possible to do what you wanted would work. In particular consider something like this:
(define (foo a name)
(let ([b 10])
(display (get-value name))
(* a b)))
Where get-value is meant to be how you get the binding of whatever something is.
So, if I call (foo 10 "b") it should print 10 and return 100.
But wait: b is a compile-time constant in this code. Any compiler worth its salt is going to immediately turn this into
(define (foo a name)
(display (get-value name))
(* a 10))
And now there is no binding of b.
So there are two options here: what you want to work works and it is impossible to ever write a reasonable compiler for Scheme, or what you want to work doesn't work, and it is.

Change program code while running in Chicken Scheme

Is it possible to update the program code while it is being interpreted by csi, the Chicken Scheme Interpreter? If so, how?
So that I can interactively change part of the code and immediately see the effects of that changes.
For example, suppose I have written the following program:
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(assume (rest 1) has the effect of pausing the program for a second).
If I run this program, trough csi, it prints the string "Ciao" every second. If I change the string "Ciao" into something else, for example into "else", and I save the program code file, then csi continue interpreting the old program code, so I continuously see the string "Ciao". I'd like, in this case, that when I save the modified code with the string "Ciao" replaced by "else", csi continue its interpretation job by looking into the modified file, instead of the old file.
So that I obtain as output some "Ciao" followed by some "else": the "else" start to appear when I replace "Ciao" by "else" in the source code.
In general, the answer is "don't". The way you're supposed to use the REPL is by evaluating piecemeal changes against it, then evaluating a function or two to make sure everything went as expected. Part of this approach is structuring your program so that it can be easily tested in pieces, which implies not automatically starting any infinite loops. In the specific case you're asking about, you could instead write
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
You can now incrementally develop do-stuff, periodically evaluating new versions to your interpreter and calling them to make sure they work, then eventually calling start once you're confident that it's doing the right thing.
You may get mileage out of this similar question asked about Common Lisp.
As an aside, if you were using Common Lisp and SLIME, you could now do more or less what you proposed:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
Starting that up would start printing Ciao on separate lines in your SLIME REPL. If you changed do-stuff to
(defun do-stuff ()
(format t "else~%"))
then hit it with C-c C-c (the default binding for slime-compile-defun), you'd see your SLIME REPL start printing else lines in-flight.
CL-USER> (main-loop)
Ciao
Ciao
Ciao
; compiling (DEFUN DO-STUFF ...)else
else
else
else
else
else
; Evaluation aborted on NIL. User break.
CL-USER>
I'm not sure how to accomplish the same thing in Scheme, but I'm reasonably sure it's possible.
All that being said, you sometimes want to run a program part of which is an infinite loop. A real world example would be while testing a TCP server of some sort. If you're in such a situation, and your desired workflow is
Write file
Run csi my-file.scm
Edit file
Kill csi
Run csi my-file.scm
goto 3
and you basically just want to automate steps 4 through 6, you'll need an external tool to do it for you. Take a look at entr or hsandbox (the latter doesn't have Scheme support out of the box, but it doesn't look like it would be too hard to add).
There is no common way to make a running program check its source for changes but you there seems to be enough feratures available in Chicken to roll your own:
(use posix)
(use srfi-18)
(define (watch-reload! file)
(define (tsleep n)
(thread-sleep! (seconds->time (+ n (time->seconds (current-time))))))
(define (get-time)
(file-modification-time file))
(thread-start!
(lambda ()
(let loop ((filetime '()))
(let ((newtime (get-time)))
(when (not (equal? filetime newtime))
(load file))
(tsleep 10)
(loop newtime))))))
Now all you have to do is to use watch-reload! instead of load and it will check and reload every 10 seconds if the file has been modified.
If you save when the file is not valid scheme it stops working until you call watch-reload! on it again.
It may be that chicken programmers might have a better solution.

Resources