* Problem with let/cl-letf binding stuff with org-capture @ 2023-02-10 15:05 Arthur Miller 2023-02-10 15:38 ` Ruijie Yu via General discussions about Org-mode. ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Arthur Miller @ 2023-02-10 15:05 UTC (permalink / raw) To: emacs-orgmode Based on a Reddit thread: https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3 I did a small experiment to see if I can re-use org-capture, to just capture a string from a buffer, without actually writing to any file. My plan was to just let-bind org-capture-finalize with cl-letf: #+begin_src emacs-lisp (defun my-read-string () (cl-letf (((symbol-function 'org-capture-finalize) ;; C-c C-c (lambda (&optional _) (interactive "P") (buffer-string))) ((symbol-function 'org-kill-note-or-show-branches) #'kill-buffer)) ;; C-c C-k (let ((org-capture-templates '(("s" "string" plain (function ignore))))) (org-capture nil "s")))) #+end_src Unfortunately, that does not work. Regardless of binding, and if I used cl-letf or cl-flet or cl-labels, or old let, or something brewed on the internet, the binding org-capture see for org-capture-finalize, is the original one from org-capture.el. My second experiment was to abstract the finalize function into a funcallable fariable in org-capture.el (I have patched org-capture.el with this): #+begin_src emacs-lisp (defvar org-capture-finalizer #'org-capture--default-finalize) (defun org-capture-finalize (&optional stay-with-capture) "Finalize the capture process. With prefix argument STAY-WITH-CAPTURE, jump to the location of the captured item after finalizing." (interactive "P") (funcall org-capture-finalizer stay-with-capture)) (defun org-capture--default-finalize (&optional stay-with-capture) "Default implementation for org-capture finalizer function." ;; this is the original org-capture-finalize just renamed to "default-finalize" ) #+end_src So I could then have something like this (never mind C-c C-k function being removed): #+begin_src emacs-lisp (defun my-read-string () (let ((org-capture-templates '(("s" "string" plain (function ignore)))) (org-capture-finalizer (lambda (&optional _) (interactive "P") (buffer-string)))) (org-capture nil "s"))) #+end_src However I see that the binding for the org-capture-finalizer, in capture buffer, is still the default 'org-capture--default-finalize' and not my lambda. I am really not an expert on emacs lisp; and I do understand that this is somewhat "creative" use of org-capture (to put it nicely :-)), but I would like to understand what is going on here. I don't understand why let-binding here does not work? If I take (symbol-functon 'org-capture) I see it is a closure. I am not sure if it has something with the problem to do? I have tested to disable lexical binding, re-eval things, but the let-binding seems rock stable :). Nothing makes org-capture to reconsider using my local let-binding. I would really like to understand this, so please if someone can explain it, I will appreciate to hear. Thanks in advance /arthur ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-10 15:05 Problem with let/cl-letf binding stuff with org-capture Arthur Miller @ 2023-02-10 15:38 ` Ruijie Yu via General discussions about Org-mode. 2023-02-10 16:29 ` Arthur Miller 2023-02-10 19:00 ` Bruno Barbier 2023-02-11 16:49 ` Ihor Radchenko 2 siblings, 1 reply; 19+ messages in thread From: Ruijie Yu via General discussions about Org-mode. @ 2023-02-10 15:38 UTC (permalink / raw) To: Arthur Miller; +Cc: emacs-orgmode Hi Arthur, Please excuse my brevity and semi-random line of thought, as I’m replying on mobile right now. See below. > On Feb 10, 2023, at 23:11, Arthur Miller <arthur.miller@live.com> wrote: > > > Based on a Reddit thread: > > https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3 > > I did a small experiment to see if I can re-use org-capture, to just capture a > string from a buffer, without actually writing to any file. > > My plan was to just let-bind org-capture-finalize with cl-letf: > > #+begin_src emacs-lisp > (defun my-read-string () > (cl-letf (((symbol-function 'org-capture-finalize) ;; C-c C-c > (lambda (&optional _) (interactive "P") (buffer-string))) > ((symbol-function 'org-kill-note-or-show-branches) #'kill-buffer)) ;; C-c C-k > (let ((org-capture-templates '(("s" "string" plain (function ignore))))) > (org-capture nil "s")))) > #+end_src Based on my somewhat-limited experience with CL (and elisp), I have never seen this particular type of letf structure. What I am used to seeing and writing is the following: (cl-letf ((f (x) (1+ x)) (1+ (f 2))) ; => 4 In particular, IIUC, I don’t think you would need symbol-function here. Maybe you can learn more from the docstring of cl-letf than me trying to drain my memory on this topic without reference. Also, in the code snippet you provided, what *should* org-capture-finalize be? A function that can be called like this: (org-capture-finalize arg1 arg2) ? Or a variable containing a function (reference) that can be called like this: (funcall org-capture-finalize arg1 arg2) ? In the former case you might be able to use cl-letf, and in the latter case you should use let with a lambda value. > Unfortunately, that does not work. Regardless of binding, and if I used cl-letf > or cl-flet or cl-labels, or old let, or something brewed on the internet, the > binding org-capture see for org-capture-finalize, is the original one from > org-capture.el. > > My second experiment was to abstract the finalize function into a funcallable > fariable in org-capture.el (I have patched org-capture.el with this): > > #+begin_src emacs-lisp > (defvar org-capture-finalizer #'org-capture--default-finalize) > > (defun org-capture-finalize (&optional stay-with-capture) > "Finalize the capture process. > With prefix argument STAY-WITH-CAPTURE, jump to the location of the > captured item after finalizing." > (interactive "P") > (funcall org-capture-finalizer stay-with-capture)) > > > (defun org-capture--default-finalize (&optional stay-with-capture) > "Default implementation for org-capture finalizer function." > > ;; this is the original org-capture-finalize just renamed to "default-finalize" > ) > #+end_src > > So I could then have something like this (never mind C-c C-k function being > removed): > > #+begin_src emacs-lisp > (defun my-read-string () > (let ((org-capture-templates '(("s" "string" plain (function ignore)))) > (org-capture-finalizer > (lambda (&optional _) (interactive "P") (buffer-string)))) > (org-capture nil "s"))) > #+end_src > > However I see that the binding for the org-capture-finalizer, in capture buffer, > is still the default 'org-capture--default-finalize' and not my lambda. I guess this answers part of my question in my previous paragraph. Is org-capture-finalizer defined via defvar? If so, does it help if you put an empty defvar before the let binding? If not, maybe someone actually using Emacs right now can be of more help here. > I am really not an expert on emacs lisp; and I do understand that this is > somewhat "creative" use of org-capture (to put it nicely :-)), but I would like > to understand what is going on here. > > I don't understand why let-binding here does not work? If I take (symbol-functon > 'org-capture) I see it is a closure. I am not sure if it has something with the > problem to do? I have tested to disable lexical binding, re-eval things, but > the let-binding seems rock stable :). Nothing makes org-capture to reconsider > using my local let-binding. > > I would really like to understand this, so please if someone can explain it, I > will appreciate to hear. > > Thanks in advance > /arthur Best, RY ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-10 15:38 ` Ruijie Yu via General discussions about Org-mode. @ 2023-02-10 16:29 ` Arthur Miller 0 siblings, 0 replies; 19+ messages in thread From: Arthur Miller @ 2023-02-10 16:29 UTC (permalink / raw) To: Ruijie Yu; +Cc: emacs-orgmode Ruijie Yu <ruijie@netyu.xyz> writes: > Hi Arthur, > > Please excuse my brevity and semi-random line of thought, as I’m replying on mobile right now. See below. > >> On Feb 10, 2023, at 23:11, Arthur Miller <arthur.miller@live.com> wrote: >> >> >> Based on a Reddit thread: >> >> https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3 >> >> I did a small experiment to see if I can re-use org-capture, to just capture a >> string from a buffer, without actually writing to any file. >> >> My plan was to just let-bind org-capture-finalize with cl-letf: >> >> #+begin_src emacs-lisp >> (defun my-read-string () >> (cl-letf (((symbol-function 'org-capture-finalize) ;; C-c C-c >> (lambda (&optional _) (interactive "P") (buffer-string))) >> ((symbol-function 'org-kill-note-or-show-branches) #'kill-buffer)) ;; C-c C-k >> (let ((org-capture-templates '(("s" "string" plain (function ignore))))) >> (org-capture nil "s")))) >> #+end_src > > Based on my somewhat-limited experience with CL (and elisp), I have never seen > this particular type of letf structure. What I am used to seeing and writing is > the following: It uses "place" or "field" to set the symbol binding, as in setf or incf. You can read more on SX: https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf > (cl-letf ((f (x) (1+ x)) > (1+ (f 2))) > ; => 4 > > In particular, IIUC, I don’t think you would need symbol-function here. Maybe > you can learn more from the docstring of cl-letf than me trying to drain my > memory on this topic without reference. > > Also, in the code snippet you provided, what *should* org-capture-finalize be? A function that can be called like this: > > (org-capture-finalize arg1 arg2) > > ? Or a variable containing a function (reference) that can be called like this: > > (funcall org-capture-finalize arg1 arg2) > > ? In the former case you might be able to use cl-letf, and in the latter case you should use let with a lambda value. > >> Unfortunately, that does not work. Regardless of binding, and if I used cl-letf >> or cl-flet or cl-labels, or old let, or something brewed on the internet, the >> binding org-capture see for org-capture-finalize, is the original one from >> org-capture.el. >> >> My second experiment was to abstract the finalize function into a funcallable >> fariable in org-capture.el (I have patched org-capture.el with this): >> >> #+begin_src emacs-lisp >> (defvar org-capture-finalizer #'org-capture--default-finalize) >> >> (defun org-capture-finalize (&optional stay-with-capture) >> "Finalize the capture process. >> With prefix argument STAY-WITH-CAPTURE, jump to the location of the >> captured item after finalizing." >> (interactive "P") >> (funcall org-capture-finalizer stay-with-capture)) >> >> >> (defun org-capture--default-finalize (&optional stay-with-capture) >> "Default implementation for org-capture finalizer function." >> >> ;; this is the original org-capture-finalize just renamed to "default-finalize" >> ) >> #+end_src >> >> So I could then have something like this (never mind C-c C-k function being >> removed): >> >> #+begin_src emacs-lisp >> (defun my-read-string () >> (let ((org-capture-templates '(("s" "string" plain (function ignore)))) >> (org-capture-finalizer >> (lambda (&optional _) (interactive "P") (buffer-string)))) >> (org-capture nil "s"))) >> #+end_src >> >> However I see that the binding for the org-capture-finalizer, in capture buffer, >> is still the default 'org-capture--default-finalize' and not my lambda. > > I guess this answers part of my question in my previous paragraph. Is > org-capture-finalizer defined via defvar? If so, does it help if you put an > empty defvar before the let binding? If not, maybe someone actually using Emacs > right now can be of more help here. These were two different examples; one that let-binds the function 'org-caputre-finalize', via cl-letf and the latter one that was completely different in which I have defvared a symbol so I can let-bind it as a variable. > If not, maybe someone actually using Emacs > right now can be of more help here. Don't worry; thanks for the help anyway! /a ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-10 15:05 Problem with let/cl-letf binding stuff with org-capture Arthur Miller 2023-02-10 15:38 ` Ruijie Yu via General discussions about Org-mode. @ 2023-02-10 19:00 ` Bruno Barbier 2023-02-11 6:33 ` Arthur Miller 2023-02-11 16:49 ` Ihor Radchenko 2 siblings, 1 reply; 19+ messages in thread From: Bruno Barbier @ 2023-02-10 19:00 UTC (permalink / raw) To: Arthur Miller, emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: > However I see that the binding for the org-capture-finalizer, in capture buffer, > is still the default 'org-capture--default-finalize' and not my lambda. > > I am really not an expert on emacs lisp; and I do understand that this is > somewhat "creative" use of org-capture (to put it nicely :-)), but I would like > to understand what is going on here. > > I don't understand why let-binding here does not work? Your bindings probably work. But, as the function `org-capture' just *starts* the capture process, they are removed when exiting the 'let', before you even begin editing your capture. I'm not sure I understand your use case: if you have a piece of org text, you can put it anywhere (possibly using refiling). If you really want to just get the piece of text, you might be able to use the hook `org-capture-mode-hook' to replace the key binding to 'C-c C-c' in the capture buffer, so that it calls your own function that will take the string and call `org-capture-kill'. Note that they are safer way to modify Emacs behavior than overwriting the functions. You can usually use hooks (like `org-capture-mode-hook'): (info "(elisp) Hooks") or, if it's not possible, you can advise the functions: (info "(elisp) Advising Functions") Bruno ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-10 19:00 ` Bruno Barbier @ 2023-02-11 6:33 ` Arthur Miller 2023-02-11 7:58 ` Bruno Barbier 0 siblings, 1 reply; 19+ messages in thread From: Arthur Miller @ 2023-02-11 6:33 UTC (permalink / raw) To: Bruno Barbier; +Cc: emacs-orgmode Bruno Barbier <brubar.cs@gmail.com> writes: > Arthur Miller <arthur.miller@live.com> writes: > >> However I see that the binding for the org-capture-finalizer, in capture buffer, >> is still the default 'org-capture--default-finalize' and not my lambda. >> >> I am really not an expert on emacs lisp; and I do understand that this is >> somewhat "creative" use of org-capture (to put it nicely :-)), but I would like >> to understand what is going on here. >> >> I don't understand why let-binding here does not work? > > Your bindings probably work. But, as the function `org-capture' > just *starts* the capture process, they are removed when exiting the > 'let', before you even begin editing your capture. Yes of course :) I am quite aware that org-capture just setups the buffer, and that org-capture-finalize finnishes by writing stuff to files etc, and yet I have tottally forgott it when writing this. This for opening my eyes. > I'm not sure I understand your use case: if you have a piece > of org text, you can put it anywhere (possibly using refiling). it is just a fun test. I wouldn't do that myself normally and I have no idea why the blog author needs it either. If I wanted to input multiline text into some dokument I would open dokument itself. But this was just a thought I am testing; you can read in the link I posted in the first mail. > If you really want to just get the piece of text, you might be able to > use the hook `org-capture-mode-hook' to replace the key binding to > 'C-c C-c' in the capture buffer, so that it calls your own function that > will take the string and call `org-capture-kill'. In this case you wouldn't like to replace the key binding, it would affect all org-capture buffers; the point is just to replace it when called in certain context (my-read-line). Let-binding the function in this context achieves exactly the same effect of C-c C-c beng bound to my function but without affecting all org-capture-buffers. > You can usually use hooks (like `org-capture-mode-hook'): > (info "(elisp) Hooks") > > or, if it's not possible, you can advise the functions: > > (info "(elisp) Advising Functions") Yes, I am aware of both hooks and advising; but again, with those I would affect all uses of the function, and that would lead to checking some global state or variable to switch on, which is not optimal either. With let-binding we can have different behaviour only in a certain context. Anyway, thanks, I needed the reminder above. cheers /arthur ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-11 6:33 ` Arthur Miller @ 2023-02-11 7:58 ` Bruno Barbier 2023-02-11 16:14 ` Arthur Miller 0 siblings, 1 reply; 19+ messages in thread From: Bruno Barbier @ 2023-02-11 7:58 UTC (permalink / raw) To: Arthur Miller; +Cc: emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: >> Bruno Barbier <brubar.cs@gmail.com> writes: >> If you really want to just get the piece of text, you might be able to >> use the hook `org-capture-mode-hook' to replace the key binding to >> 'C-c C-c' in the capture buffer, so that it calls your own function that >> will take the string and call `org-capture-kill'. > > In this case you wouldn't like to replace the key binding, it would affect all > org-capture buffers; the point is just to replace it when called in certain > context (my-read-line). Let-binding the function in this context achieves > exactly the same effect of C-c C-c beng bound to my function but without > affecting all org-capture-buffers. The hook `org-capture-mode-hook' will be run in your special capture buffer. You can override the "C-c C-c" binding only there. > > Yes, I am aware of both hooks and advising; but again, with those I would affect > all uses of the function, and that would lead to checking some global state or > variable to switch on, which is not optimal either. With let-binding we can have > different behaviour only in a certain context. Even if I could let bind the function at the right time, I would avoid that solution, as I can't garantuee that this global hack will not break other parts of Emacs (other captures, output filters, threads, timers, etc.). > > Anyway, thanks, I needed the reminder above. You're welcome. Bruno ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-11 7:58 ` Bruno Barbier @ 2023-02-11 16:14 ` Arthur Miller 2023-02-11 19:23 ` Bruno Barbier 0 siblings, 1 reply; 19+ messages in thread From: Arthur Miller @ 2023-02-11 16:14 UTC (permalink / raw) To: Bruno Barbier; +Cc: emacs-orgmode Bruno Barbier <brubar.cs@gmail.com> writes: > Arthur Miller <arthur.miller@live.com> writes: > >>> Bruno Barbier <brubar.cs@gmail.com> writes: >>> If you really want to just get the piece of text, you might be able to >>> use the hook `org-capture-mode-hook' to replace the key binding to >>> 'C-c C-c' in the capture buffer, so that it calls your own function that >>> will take the string and call `org-capture-kill'. >> >> In this case you wouldn't like to replace the key binding, it would affect all >> org-capture buffers; the point is just to replace it when called in certain >> context (my-read-line). Let-binding the function in this context achieves >> exactly the same effect of C-c C-c beng bound to my function but without >> affecting all org-capture-buffers. > > The hook `org-capture-mode-hook' will be run in your special > capture buffer. You can override the "C-c C-c" binding only there. Yes and in every other capture buffer, so I would either have to test on some variable, make another mode, or mode-map or something similar. Just to customize on the key, instead of the value bound to that key. >> >> Yes, I am aware of both hooks and advising; but again, with those I would affect >> all uses of the function, and that would lead to checking some global state or >> variable to switch on, which is not optimal either. With let-binding we can have >> different behaviour only in a certain context. > > Even if I could let bind the function at the right time, I would avoid > that solution, as I can't garantuee that this global hack will not break > other parts of Emacs (other captures, output filters, threads, timers, > etc.). Why do you think it will break other parts? This is not a global hack, on contrary it exactly tries to prevent to be "global" in entire Emacs, by let-binding a name to a local lambda, which becomes "global" only in that buffer. If that explains. Here is another version on the same theme, where I don't think you could modify the local environment without let-binding at all: #+begin_src emacs-lisp (defun my-read-string (prompt) (let ((delta 20 ) (minibuffer-mode-map org-mode-map)) (window-resize (minibuffer-window) delta) (cl-letf (((symbol-function 'org-ctrl-c-ctrl-c) (lambda () (interactive) (let ((s (buffer-string))) (exit-minibuffer) s))) ((symbol-function 'minibuffer-mode) #'org-mode) ((symbol-function 'minibuffer-complete-and-exit) #'org-return) ((symbol-function 'org-kill-note-or-show-branches) #'keyboard-escape-quit)) (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " prompt "\n\n"))))) #+end_src read-string is written in C and creates its own minibuffer, which is deleted by the time read-string exits. I don't know of any other way to cutomize exactly *that* minibuffer, without installing a hook or advising some functions, which I think is way less clean and much more "global" than just running the function in a local environment. As I understand, let binding for this purpose is a normal technique in lisps, but I am not an expert as said; I am actually experimenting with this for the purpose of learning and seeing what is possible. Of course, we can always write our own read-string function and re-implement the function from scratch, which author of that blog actually did. The experiment was to test if I can modify the existing functionality to re-use, rather than to re-invent something. Since read-string functions does not let us specify buffer, mode, etc, let binding is one way of doing it locally. Considering how org-capture works, the same technique of just modifying the local environment is not really applicable; now when you reminded me that capture buffer lives longer then let-binding, I understand what happens. I can access the buffer after org-capture exits, in my-read-string: (with-current-buffer (try-completion "CAPTURE" (mapcar #'buffer-name (buffer-list))) ( .... do the thng .... ) but I am not sure if I can do anything here without introducing at-least an extra keymap, to not install into the org-capture-mode-map, so I can as well create a minor mode, but at this point it is not much different than re-invinting the read-string, so I'll terminate my experiment here :). But I wouldn't speak in some generic terms like "use hooks" or "advise" instead of let-binding. Let binding is a powerful and legitimate technique to modify local environment of functions. I am not really sure where it stands in abstraction, if it is sort-of template, or interface programming, since I am not that familiar with lisp (yet), but I do understand it has very good and powerful uses. Consider this (you can actually eval an run from gnus, or in scartch): #+begin_src emacs-lisp ;;;; Project folder - org-capture related code (defvar org-project-root-dir nil) (defvar org-project-templates nil) (defvar org-project-finalize-hooks nil) (setq org-project-templates `(("W" "Web Projects") ("Wb" "Bootstrap Project" plain (function org-project-new) "A Bootstrap Project") ("Wh" "Web project" plain (function org-project-new) "Simple HTML Project") ("C" "C/C++ Projects") ("Cc" "C Console Project" plain (function org-project-new) "A Command Line Project with C") ("CC" "C++ Console Project" plain (function org-project-new) "A Command Line Project with C++") ("CG" "C++ GLUT Project" plain (function org-project-new) "Simple GLUT Project") ("CQ" "C++ Qt Project" plain (function org-project-new) "Qt Project") ("CK" "C++ Qt Quick Project" plain (function org-project-new) "Qt Quick Project"))) (defun org-project-new-project () (interactive) (let ((org-capture-templates org-project-templates)) (org-capture))) (define-key global-map (kbd "C-S-n") #'org-project-new-project) (defun org-project-new () "Interactively create new directory for a project. Directory should not exist prior to call to this function." (let ((project-path (read-file-name "Project name: " org-project-root-dir nil nil nil))) (cond ((not (file-directory-p project-path)) (make-directory project-path) (let ((file-name (concat (file-name-nondirectory project-path) ".org"))) (find-file (expand-file-name file-name project-path)) (goto-char (point-min)))) (t (message "Directory %s already exists." project-path)))) (if org-project-finalize-hooks (run-hooks org-project-finalize-hooks))) #+end_src The only extra work I did, was to actually create an interactive function to specify a path, and I can re-use both org-capture template language and interactive functionality already built into the org-capture. I get an entire framework for free :). The real action is happening in hooks, where I init git, copy some templates, license and some other boiler-plate stuff. I don't know what would be the alternative, but let-binding on org-capture-templates, let me clearly re-use the functionality without polluting the global org-capture-templates variable and without re-implementing pretty much anything. As I understand, let binding is useful in lisp, and as legitimate technique as hooks, or advices. As said, I am not an expert, but I think, it is probably preferrable to advising, where possible, since advising is global to all function instances, while let-binding affects only local function instances, if I can borrow some of OOP terms here. I am very interested to hear more on the topic, since I would definitely like to learn more about different techniques. Hope that explains a bit more on the background of the experiment :). best regards /a ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-11 16:14 ` Arthur Miller @ 2023-02-11 19:23 ` Bruno Barbier 2023-02-12 7:21 ` Arthur Miller 0 siblings, 1 reply; 19+ messages in thread From: Bruno Barbier @ 2023-02-11 19:23 UTC (permalink / raw) To: Arthur Miller; +Cc: emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: > Bruno Barbier <brubar.cs@gmail.com> writes: > >> Arthur Miller <arthur.miller@live.com> writes: >> >> The hook `org-capture-mode-hook' will be run in your special >> capture buffer. You can override the "C-c C-c" binding only there. > > Yes and in every other capture buffer No. If you modify the hook only during your call to 'org-capture', it will be called only once in your buffer. >> Even if I could let bind the function at the right time, I would avoid >> that solution, as I can't garantuee that this global hack will not break >> other parts of Emacs (other captures, output filters, threads, timers, >> etc.). > > Why do you think it will break other parts? This is not a global hack, on contrary it > exactly tries to prevent to be "global" in entire Emacs, by let-binding a name > to a local lambda, which becomes "global" only in that buffer. If that > explains. You are assigning a local value to the global binding. Everything in Emacs will use your functions until you exit the cl-letf. It's like if you were using 'fset'. Here is an example that uses cl-letf. Note that the call to async-shell-command is outside the "local" binding, yet, the cl-letf breaks it. You should try this in an other Emacs, just in case. (defun oops () (let ((v (async-shell-command "date" "!sh async"))) (cl-letf (((symbol-function 'comint-output-filter) (lambda (proc string) (message "async-shell-command is using my binding: %s" string) (read-string "What's the password?")))) (read-string "what: ") ))) (oops) > > Here is another version on the same theme, where I don't think you could modify the local > environment without let-binding at all: > > #+begin_src emacs-lisp > (defun my-read-string (prompt) > (let ((delta 20 ) > (minibuffer-mode-map org-mode-map)) > (window-resize (minibuffer-window) delta) > (cl-letf (((symbol-function 'org-ctrl-c-ctrl-c) > (lambda () > (interactive) > (let ((s (buffer-string))) > (exit-minibuffer) s))) > ((symbol-function 'minibuffer-mode) #'org-mode) > ((symbol-function 'minibuffer-complete-and-exit) #'org-return) > ((symbol-function 'org-kill-note-or-show-branches) #'keyboard-escape-quit)) > (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " prompt "\n\n"))))) > #+end_src I hope I've convinced you to not do that. I definitely will not try it, as Emacs needs a working minibuffer for plenty of things: debugging, saving, quitting, etc. > read-string is written in C and creates its own minibuffer, which is deleted by > the time read-string exits. I don't know of any other way to cutomize exactly > *that* minibuffer, without installing a hook or advising some functions, which I > think is way less clean and much more "global" than just running the function in > a local environment. As I understand, let binding for this purpose is a normal > technique in lisps, but I am not an expert as said; I am actually experimenting > with this for the purpose of learning and seeing what is possible. Yes, let binding is fundamental. But I think it's the first time I see 'cl-letf' with the 'symbol-function' place. > ... > but I am not sure if I can do anything here without introducing at-least an > extra keymap, to not install into the org-capture-mode-map, so I can as well > create a minor mode, but at this point it is not much different than > re-invinting the read-string, so I'll terminate my experiment here :). You can replace the buffer keymap with a keymap that only contain your custom keys, and inherits everything else from org-capture-mode-map. > > But I wouldn't speak in some generic terms like "use hooks" or "advise" instead > of let-binding. I didn't mean to say to not use let bindings. I'm trying to say that using 'fset' (i.e. cl-letf + the symbol-function place) looks like a really bad idea to me. And, in this case, hooks and adivces are what is usually used. > (defun org-project-new-project () > (interactive) > (let ((org-capture-templates org-project-templates)) > (org-capture))) > > ... > I don't know what would be the alternative, but let-binding on > org-capture-templates, let me clearly re-use the functionality without polluting > the global org-capture-templates variable and without re-implementing pretty > much anything. That looks to me like a perfect use of a let binding. You bind a dynamic *variable* using *let*, and, that variable is rebound, and used, during, and only during 'org-capture'. > I am very interested to hear more on the topic, since I would definitely like to > learn more about different techniques. Variables are designed to be overriden (let bounds). Functions are not (as there is only one binding at any given time). > Hope that explains a bit more on the background of the experiment :). I'm still confused about the idea of making 'read-string' behave like 'org-capture', but, we use Emacs because we can experiment! No need for justification ;-) And, experimenting with the minibuffer, which is one of the fundamental component to control Emacs, that's definitely courageous :-) best, Bruno ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-11 19:23 ` Bruno Barbier @ 2023-02-12 7:21 ` Arthur Miller 2023-02-12 9:22 ` Bruno Barbier 0 siblings, 1 reply; 19+ messages in thread From: Arthur Miller @ 2023-02-12 7:21 UTC (permalink / raw) To: Bruno Barbier; +Cc: emacs-orgmode Bruno Barbier <brubar.cs@gmail.com> writes: > Arthur Miller <arthur.miller@live.com> writes: > >> Bruno Barbier <brubar.cs@gmail.com> writes: >> >>> Arthur Miller <arthur.miller@live.com> writes: >>> >>> The hook `org-capture-mode-hook' will be run in your special >>> capture buffer. You can override the "C-c C-c" binding only there. >> >> Yes and in every other capture buffer > > No. If you modify the hook only during your call to 'org-capture', it > will be called only once in your buffer. > >>> Even if I could let bind the function at the right time, I would avoid >>> that solution, as I can't garantuee that this global hack will not break >>> other parts of Emacs (other captures, output filters, threads, timers, >>> etc.). >> >> Why do you think it will break other parts? This is not a global hack, on contrary it >> exactly tries to prevent to be "global" in entire Emacs, by let-binding a name >> to a local lambda, which becomes "global" only in that buffer. If that >> explains. > > You are assigning a local value to the global binding. Everything in > Emacs will use your functions until you exit the cl-letf. It's like if > you were using 'fset'. Yes, you are totally correct; unfortunately binding with cl-flet or cl-labels, does not work, so binding the global is the only one that works. > Here is an example that uses cl-letf. Note that the call to > async-shell-command is outside the "local" binding, yet, the cl-letf > breaks it. You should try this in an other Emacs, just in case. > > (defun oops () > (let ((v (async-shell-command "date" "!sh async"))) > (cl-letf > (((symbol-function 'comint-output-filter) > (lambda (proc string) > (message "async-shell-command is using my binding: %s" string) > (read-string "What's the password?")))) > (read-string "what: ") > ))) > (oops) Yes, I definitely agree with you about the concerns, which are certainly valid, but you would get same effect with advice, it is not different at all. The difference is that let-binding is automatically removed and installed, and only active during the cl-letf, while advice is manually installed and active until manually removed. It is not about the tool, but what you do with the tool. >> Here is another version on the same theme, where I don't think you could modify the local >> environment without let-binding at all: >> >> #+begin_src emacs-lisp >> (defun my-read-string (prompt) >> (let ((delta 20 ) >> (minibuffer-mode-map org-mode-map)) >> (window-resize (minibuffer-window) delta) >> (cl-letf (((symbol-function 'org-ctrl-c-ctrl-c) >> (lambda () >> (interactive) >> (let ((s (buffer-string))) >> (exit-minibuffer) s))) >> ((symbol-function 'minibuffer-mode) #'org-mode) >> ((symbol-function 'minibuffer-complete-and-exit) #'org-return) >> ((symbol-function 'org-kill-note-or-show-branches) #'keyboard-escape-quit)) >> (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " prompt "\n\n"))))) >> #+end_src > > I hope I've convinced you to not do that. I definitely will not try it, > as Emacs needs a working minibuffer for plenty of things: debugging, > saving, quitting, etc. Your minibuffer will continue to work during and after that function. If you don't use recursive minibuffer, that will only affect the internal buffer created by read-string. If recursive minibuffer is enabled, yes they will also be affected. Of course, there is no reason for you to try that, that was just an example, but I feel a bit of passive aggressivity here, for no good reason tbh. >> read-string is written in C and creates its own minibuffer, which is deleted by >> the time read-string exits. I don't know of any other way to cutomize exactly >> *that* minibuffer, without installing a hook or advising some functions, which I >> think is way less clean and much more "global" than just running the function in >> a local environment. As I understand, let binding for this purpose is a normal >> technique in lisps, but I am not an expert as said; I am actually experimenting >> with this for the purpose of learning and seeing what is possible. > > Yes, let binding is fundamental. But I think it's the first time I see > 'cl-letf' with the 'symbol-function' place. https://nullprogram.com/blog/2017/10/27/ https://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf >> but I am not sure if I can do anything here without introducing at-least an >> extra keymap, to not install into the org-capture-mode-map, so I can as well >> create a minor mode, but at this point it is not much different than >> re-invinting the read-string, so I'll terminate my experiment here :). > > You can replace the buffer keymap with a keymap that only contain your custom > keys, and inherits everything else from org-capture-mode-map. Isn't that what I wrote: introducing an extra keymap? Of course I can solve the problem differently, but that was not what question was about :). >> But I wouldn't speak in some generic terms like "use hooks" or "advise" instead >> of let-binding. > > I didn't mean to say to not use let bindings. I'm trying to say that > using 'fset' (i.e. cl-letf + the symbol-function place) looks like a > really bad idea to me. Well, I definitely understand you, and agree that overwriting function for everyone and everything is not the best idea, but unfortunately bindings work as they do in Emacs. I would prefer to have a local binding, with cl-flet, but this does not work in Emacs: (defun my-read-string (prompt) (let ((delta 20 ) (minibuffer-mode-map org-mode-map)) (window-resize (minibuffer-window) delta) (cl-flet ((org-ctrl-c-ctrl-c () (interactive) (let ((s (buffer-string))) (exit-minibuffer) s)) (minibuffer-mode () #'org-mode) (minibuffer-complete-and-exit () #'org-return) (org-kill-note-or-show-branches () #'keyboard-escape-quit)) (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " prompt "\n\n"))))) > And, in this case, hooks and adivces are what is > usually used. Hooks serve a different purpose. Advice can serve same purpose with exactly same side effect, and some other limitations. With some care, let-binding is still more "local" then advice. With other words, I agree with you about the problems, but not with dogmatic approach that it should never be done, and that hooks and advices are the replacement. >> (defun org-project-new-project () >> (interactive) >> (let ((org-capture-templates org-project-templates)) >> (org-capture))) >> >> ... > >> I don't know what would be the alternative, but let-binding on >> org-capture-templates, let me clearly re-use the functionality without polluting >> the global org-capture-templates variable and without re-implementing pretty >> much anything. > > That looks to me like a perfect use of a let binding. You bind a dynamic > *variable* using *let*, and, that variable is rebound, and used, during, and > only during 'org-capture'. > > > >> I am very interested to hear more on the topic, since I would definitely like to >> learn more about different techniques. > > Variables are designed to be overriden (let bounds). Functions are not I have never heard before that functions are not designed to be overriden. I think of them as two slots in a symbol structure; let creates bindings for value slot, and flet for function slot. Functions are just objects or data as any other value in lisp. > (as there is only one binding at any given time). Yes, unfortunately, in Emacs it is so; but I don't think it should be :). There is an interesting package by Nick Ferrier https://github.com/nicferrier/emacs-noflet but it does not seem to work, at least not for me. regards /a ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-12 7:21 ` Arthur Miller @ 2023-02-12 9:22 ` Bruno Barbier 2023-02-12 16:12 ` Arthur Miller 0 siblings, 1 reply; 19+ messages in thread From: Bruno Barbier @ 2023-02-12 9:22 UTC (permalink / raw) To: Arthur Miller; +Cc: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 4014 bytes --] Hi Arthur, Arthur Miller <arthur.miller@live.com> writes: > Bruno Barbier <brubar.cs@gmail.com> writes: > > ... but I feel a > bit of passive aggressivity here, for no good reason tbh. I'm just trying to help, giving some valid or invalid advices. I'm sorry that what I wrote, and how I wrote it, made you feel that way. >> >> Yes, let binding is fundamental. But I think it's the first time I see >> 'cl-letf' with the 'symbol-function' place. > > https://nullprogram.com/blog/2017/10/27/ > https://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html > https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf > Thanks for these links. I like cl-flet and cl-labels :-) >>> but I am not sure if I can do anything here without introducing at-least an >>> extra keymap, to not install into the org-capture-mode-map, so I can as well >>> create a minor mode, but at this point it is not much different than >>> re-invinting the read-string, so I'll terminate my experiment here :). >> >> You can replace the buffer keymap with a keymap that only contain your custom >> keys, and inherits everything else from org-capture-mode-map. > > Isn't that what I wrote: introducing an extra keymap? > Of course I can solve the problem differently, but that was not what question > was about :). Right. Even when inheriting from the old keymap, it's still building a new keymap. Sorry :-) > Well, I definitely understand you, and agree that overwriting function for > everyone and everything is not the best idea, but unfortunately bindings work as > they do in Emacs. I would prefer to have a local binding, with cl-flet, but this > does not work in Emacs: > > (defun my-read-string (prompt) > (let ((delta 20 ) > (minibuffer-mode-map org-mode-map)) > (window-resize (minibuffer-window) delta) > (cl-flet ((org-ctrl-c-ctrl-c () > (interactive) > (let ((s (buffer-string))) > (exit-minibuffer) s)) > (minibuffer-mode () #'org-mode) > (minibuffer-complete-and-exit () #'org-return) > (org-kill-note-or-show-branches () #'keyboard-escape-quit)) > (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " > prompt "\n\n"))))) Yes. cl-flet looks safe to me :-) > > Hooks serve a different purpose. Advice can serve same purpose with exactly > same side effect, and some other limitations. With some care, let-binding is > still more "local" then advice. With other words, I agree with you about the > problems, but not with dogmatic approach that it should never be done, and > that hooks and advices are the replacement. Sorry if my words sounding dogmatic. Else, I agree too :-) >> >>> I am very interested to hear more on the topic, since I would definitely like to >>> learn more about different techniques. >> >> Variables are designed to be overriden (let bounds). Functions are not > > I have never heard before that functions are not designed to be overriden. I > think of them as two slots in a symbol structure; let creates bindings for value > slot, and flet for function slot. Functions are just objects or data as any > other value in lisp. > >> (as there is only one binding at any given time). > > Yes, unfortunately, in Emacs it is so; ok. We do really agree then :-) > but I don't think it should be > :). ... oh no ! ;-) > > There is an interesting package by Nick Ferrier > > https://github.com/nicferrier/emacs-noflet > but it does not seem to work, at least not for me. It's almost like a temporary advice ;-) About your use case, if what you need is asynchronous editing, maybe the with-editor package will be of interest to you: https://github.com/magit/with-editor/blob/main/lisp/with-editor.el It allows sub-processes to call Emacs for editing tasks. It's used by magit. It's easy enough to reuse. I've attached my attempt at it if you're interested. best, Bruno [-- Attachment #2: my-edit-async draft --] [-- Type: text/plain, Size: 1563 bytes --] (cl-defun my-edit-async (finish &key mode buffer-name setup cancel) "Open a buffer, let the user edit its content. Return the editing buffer. Call FINISH in the editing buffer if the user validates his edit (C-c C-c). When CANCEL is non-nil, call CANCEL in the editing buffer if the user cancels his edit (C-c C-k). When done, delete the buffer and its content. When MODE is non-nil, use it as the major-mode. When BUFFER-NAME is non-nil, use it to generate a new unique name of the editing buffer. When SETUP is non-nil, call it in the edit buffer to setup the buffer before starting the edit." (unless buffer-name (setq buffer-name "@Async edit")) (let ((buf (generate-new-buffer buffer-name))) (with-current-buffer buf (when mode (funcall mode)) (when setup (funcall setup)) (with-editor-mode 1) (setq with-editor-previous-winconf (current-window-configuration)) (add-hook 'with-editor-pre-finish-hook (lambda () (funcall finish) (set-buffer-modified-p nil)) nil :local) (add-hook 'with-editor-pre-cancel-hook (lambda () (when cancel (funcall cancel)) (set-buffer-modified-p nil)) nil :local) (switch-to-buffer buf)) buf)) (my-edit-async (lambda () (message "My edit:\n%S" (buffer-string))) :cancel (lambda () (message "Canceled (discarded: %s)" (buffer-string))) :setup (lambda () (insert "initial content") (goto-char (point-min)))) [-- Attachment #3: Type: text/plain, Size: 22 bytes --] > regards > /a ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-12 9:22 ` Bruno Barbier @ 2023-02-12 16:12 ` Arthur Miller 2023-02-12 16:22 ` Ihor Radchenko 2023-02-13 18:37 ` Bruno Barbier 0 siblings, 2 replies; 19+ messages in thread From: Arthur Miller @ 2023-02-12 16:12 UTC (permalink / raw) To: Bruno Barbier; +Cc: emacs-orgmode Bruno Barbier <brubar.cs@gmail.com> writes: > Hi Arthur, > > Arthur Miller <arthur.miller@live.com> writes: > >> Bruno Barbier <brubar.cs@gmail.com> writes: >> >> ... but I feel a >> bit of passive aggressivity here, for no good reason tbh. > > I'm just trying to help, giving some valid or invalid advices. I'm > sorry that what I wrote, and how I wrote it, made you feel that way. It is ok, I just don't want us to go into social media discussion style where there is more important to assert own ego then to come into some insight. >>> >>> Yes, let binding is fundamental. But I think it's the first time I see >>> 'cl-letf' with the 'symbol-function' place. >> >> https://nullprogram.com/blog/2017/10/27/ >> https://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html >> https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf >> > > Thanks for these links. I like cl-flet and cl-labels :-) They are good for introducing *new* bindings, not so for overriding locally. >>>> but I am not sure if I can do anything here without introducing at-least an >>>> extra keymap, to not install into the org-capture-mode-map, so I can as well >>>> create a minor mode, but at this point it is not much different than >>>> re-invinting the read-string, so I'll terminate my experiment here :). >>> >>> You can replace the buffer keymap with a keymap that only contain your custom >>> keys, and inherits everything else from org-capture-mode-map. >> >> Isn't that what I wrote: introducing an extra keymap? >> Of course I can solve the problem differently, but that was not what question >> was about :). > > Right. Even when inheriting from the old keymap, it's still building a > new keymap. Sorry :-) > > >> Well, I definitely understand you, and agree that overwriting function for >> everyone and everything is not the best idea, but unfortunately bindings work as >> they do in Emacs. I would prefer to have a local binding, with cl-flet, but this >> does not work in Emacs: >> >> (defun my-read-string (prompt) >> (let ((delta 20 ) >> (minibuffer-mode-map org-mode-map)) >> (window-resize (minibuffer-window) delta) >> (cl-flet ((org-ctrl-c-ctrl-c () >> (interactive) >> (let ((s (buffer-string))) >> (exit-minibuffer) s)) >> (minibuffer-mode () #'org-mode) >> (minibuffer-complete-and-exit () #'org-return) >> (org-kill-note-or-show-branches () #'keyboard-escape-quit)) >> (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " >> prompt "\n\n"))))) > > Yes. cl-flet looks safe to me :-) > >> >> Hooks serve a different purpose. Advice can serve same purpose with exactly >> same side effect, and some other limitations. With some care, let-binding is >> still more "local" then advice. With other words, I agree with you about the >> problems, but not with dogmatic approach that it should never be done, and >> that hooks and advices are the replacement. > > Sorry if my words sounding dogmatic. > Else, I agree too :-) > > >>> >>>> I am very interested to hear more on the topic, since I would definitely like to >>>> learn more about different techniques. >>> >>> Variables are designed to be overriden (let bounds). Functions are not >> >> I have never heard before that functions are not designed to be overriden. I >> think of them as two slots in a symbol structure; let creates bindings for value >> slot, and flet for function slot. Functions are just objects or data as any >> other value in lisp. >> >>> (as there is only one binding at any given time). >> >> Yes, unfortunately, in Emacs it is so; > > ok. We do really agree then :-) > > >> but I don't think it should be > :). > > ... oh no ! ;-) > > >> >> There is an interesting package by Nick Ferrier >> >> https://github.com/nicferrier/emacs-noflet > >> but it does not seem to work, at least not for me. > > It's almost like a temporary advice ;-) > > > About your use case, if what you need is asynchronous editing, maybe the > with-editor package will be of interest to you: > https://github.com/magit/with-editor/blob/main/lisp/with-editor.el > > It allows sub-processes to call Emacs for editing tasks. It's used by > magit. It's easy enough to reuse. I've attached my attempt at it if > you're interested. > > best, > > Bruno > > (cl-defun my-edit-async (finish &key mode buffer-name setup cancel) > "Open a buffer, let the user edit its content. > Return the editing buffer. Call FINISH in the editing buffer if > the user validates his edit (C-c C-c). When CANCEL is non-nil, > call CANCEL in the editing buffer if the user cancels his > edit (C-c C-k). When done, delete the buffer and its content. > > When MODE is non-nil, use it as the major-mode. When BUFFER-NAME > is non-nil, use it to generate a new unique name of the editing buffer. > When SETUP is non-nil, call it in the edit buffer to setup the > buffer before starting the edit." > (unless buffer-name (setq buffer-name "@Async edit")) > (let ((buf (generate-new-buffer buffer-name))) > (with-current-buffer buf > (when mode (funcall mode)) > (when setup > (funcall setup)) > (with-editor-mode 1) > (setq with-editor-previous-winconf > (current-window-configuration)) > (add-hook 'with-editor-pre-finish-hook > (lambda () > (funcall finish) > (set-buffer-modified-p nil)) > nil :local) > (add-hook 'with-editor-pre-cancel-hook > (lambda () > (when cancel (funcall cancel)) > (set-buffer-modified-p nil)) > nil :local) > (switch-to-buffer buf)) > buf)) > > (my-edit-async > (lambda () (message "My edit:\n%S" (buffer-string))) > :cancel (lambda () (message "Canceled (discarded: %s)" (buffer-string))) > :setup (lambda () (insert "initial content") (goto-char (point-min)))) > That looks very nice indeed. I am not aware of that package, I will definitely use it somewhere, sometime. But with that we are getting now into 1K extra sloc solution. With this experiment, I was mostly interesting to see how I can re-use what already is in Emacs. Lisps are great for prototyping and writing new software. Legend says that Steele was cranking out 10 intepreters a week at his time :). I don't know how true it is, just read it in some blog, but the point is that we are rather typing fast new pieces instead of learning how to re-use stuff, which in the long run I believe is a bad habit, since we are debugging bits that does the same what someone else already debugged. Don't get me wrong, I have nothing against using someones package, certainly not with-editor, seems like a good package; I am just talking about programming in general. This was also me trying to get better in Emacs Lisp, but I have to admit I am a bit dissapointed we can't just override function bindings with cl-flet. Function slot is just another slot :). I am using cl-labels and cl-flet myself to introduce "local" functions, to not pollute global namespace (symbol table), which they are good for, and to keep code local where it is used, and I think they are also slightly more clear then lambdas. They are good for that, unfortunately it is a bit of dissapoitment that we can't locally bind functions slots other then actually overriding them globally. And for the last time: I am not using this version of read-string, I don't need it myself; it was just me thinking how to implement something after reading a blog post. Anyway, thanks for the input, it was valuable to me. regards /a ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-12 16:12 ` Arthur Miller @ 2023-02-12 16:22 ` Ihor Radchenko 2023-02-13 18:40 ` Bruno Barbier 2023-02-13 18:37 ` Bruno Barbier 1 sibling, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2023-02-12 16:22 UTC (permalink / raw) To: Arthur Miller; +Cc: Bruno Barbier, emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: > And for the last time: I am not using this version of read-string, I don't need > it myself; it was just me thinking how to implement something after reading a > blog post. Anyway, thanks for the input, it was valuable to me. Note that Emacs 29 has `read-string-from-buffer'. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-12 16:22 ` Ihor Radchenko @ 2023-02-13 18:40 ` Bruno Barbier 2023-02-15 11:45 ` Arthur Miller 0 siblings, 1 reply; 19+ messages in thread From: Bruno Barbier @ 2023-02-13 18:40 UTC (permalink / raw) To: Ihor Radchenko, Arthur Miller; +Cc: emacs-orgmode Ihor Radchenko <yantar92@posteo.net> writes: > Note that Emacs 29 has `read-string-from-buffer'. I completely missed the fact that it was already in Emacs. I'll definitely use the string-edit version (the version with callbacks). Thanks Ihor. Bruno ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-13 18:40 ` Bruno Barbier @ 2023-02-15 11:45 ` Arthur Miller 2023-02-15 13:18 ` Bruno Barbier 0 siblings, 1 reply; 19+ messages in thread From: Arthur Miller @ 2023-02-15 11:45 UTC (permalink / raw) To: Bruno Barbier; +Cc: Ihor Radchenko, emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 576 bytes --] Bruno Barbier <brubar.cs@gmail.com> writes: > Ihor Radchenko <yantar92@posteo.net> writes: > >> Note that Emacs 29 has `read-string-from-buffer'. > > I completely missed the fact that it was already in Emacs. > > I'll definitely use the string-edit version (the version > with callbacks). > > Thanks Ihor. Same here, very much thanks Ihor! I postponed answering unitll i have testedit. Cool. Now I have to say are you f-n kidding me :). Anyway, a follow question: Where is the source code?! Normally the help window says "... is a Lisp function in <some-source-file>." [-- Attachment #2: no-source-link.png --] [-- Type: image/png, Size: 152244 bytes --] ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-15 11:45 ` Arthur Miller @ 2023-02-15 13:18 ` Bruno Barbier 2023-02-15 17:36 ` arthur miller 0 siblings, 1 reply; 19+ messages in thread From: Bruno Barbier @ 2023-02-15 13:18 UTC (permalink / raw) To: Arthur Miller; +Cc: Ihor Radchenko, emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: > > Anyway, a follow question: Where is the source code?! lisp/textmodes/string-edit.el > Normally the help window says "... is a Lisp function in <some-source-file>." > My Emacs tells me it's an autoloaded function with the usual link. Bruno ^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: Problem with let/cl-letf binding stuff with org-capture 2023-02-15 13:18 ` Bruno Barbier @ 2023-02-15 17:36 ` arthur miller 0 siblings, 0 replies; 19+ messages in thread From: arthur miller @ 2023-02-15 17:36 UTC (permalink / raw) To: Bruno Barbier; +Cc: Ihor Radchenko, emacs-orgmode@gnu.org [-- Attachment #1: Type: text/plain, Size: 752 bytes --] Hemma.... thanks, for some reason, my Emacs does not display the link but it does for other functions. Strange. Thanks for the help! -------- Originalmeddelande -------- Från: Bruno Barbier <brubar.cs@gmail.com> Datum: 2023-02-15 14:18 (GMT+01:00) Till: Arthur Miller <arthur.miller@live.com> Kopia: Ihor Radchenko <yantar92@posteo.net>, emacs-orgmode@gnu.org Ämne: Re: Problem with let/cl-letf binding stuff with org-capture Arthur Miller <arthur.miller@live.com> writes: > > Anyway, a follow question: Where is the source code?! lisp/textmodes/string-edit.el > Normally the help window says "... is a Lisp function in <some-source-file>." > My Emacs tells me it's an autoloaded function with the usual link. Bruno [-- Attachment #2: Type: text/html, Size: 1474 bytes --] ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-12 16:12 ` Arthur Miller 2023-02-12 16:22 ` Ihor Radchenko @ 2023-02-13 18:37 ` Bruno Barbier 1 sibling, 0 replies; 19+ messages in thread From: Bruno Barbier @ 2023-02-13 18:37 UTC (permalink / raw) To: Arthur Miller; +Cc: emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: > Bruno Barbier <brubar.cs@gmail.com> writes: > >> > > That looks very nice indeed. I am not aware of that package, I will definitely > use it somewhere, sometime. But with that we are getting now into 1K extra sloc > solution. With this experiment, I was mostly interesting to see how I can re-use > what already is in Emacs. Lisps are great for prototyping and writing new > software. Legend says that Steele was cranking out 10 intepreters a week at his > time :). I don't know how true it is, just read it in some blog, but the > point is that we are rather typing fast new pieces instead of learning how > to re-use stuff, which in the long run I believe is a bad habit, since we are > debugging bits that does the same what someone else already debugged. Don't get > me wrong, I have nothing against using someones package, certainly not > with-editor, seems like a good package; I am just talking about programming in > general. ... And the piece of code, that I just wrote and sent, was already available in Emacs (see Ihor's email). I've definitely failed to do my research before coding ... I definitely get your point! :-) > This was also me trying to get better in Emacs Lisp, but I have to admit I am a > bit dissapointed we can't just override function bindings with cl-flet. Function > slot is just another slot :). > > I am using cl-labels and cl-flet myself to introduce "local" functions, to not > pollute global namespace (symbol table), which they are good for, and to keep > code local where it is used, and I think they are also slightly more clear then > lambdas. They are good for that, unfortunately it is a bit of dissapoitment that > we can't locally bind functions slots other then actually overriding them globally. Since I've learned that cl-flet and cl-labels are local lexically, I'm using them more and more: that removes lot of noisy funcalls, compare to lambdas. > And for the last time: I am not using this version of read-string, I don't need > it myself; it was just me thinking how to implement something after reading a > blog post. Anyway, thanks for the input, it was valuable to me. Got it. Thanks for your patience and your valuable inputs too. And I'm definitely going to use the version that is in Emacs. Thanks for this too. best, Bruno ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-10 15:05 Problem with let/cl-letf binding stuff with org-capture Arthur Miller 2023-02-10 15:38 ` Ruijie Yu via General discussions about Org-mode. 2023-02-10 19:00 ` Bruno Barbier @ 2023-02-11 16:49 ` Ihor Radchenko 2023-02-15 13:06 ` Arthur Miller 2 siblings, 1 reply; 19+ messages in thread From: Ihor Radchenko @ 2023-02-11 16:49 UTC (permalink / raw) To: Arthur Miller; +Cc: emacs-orgmode Arthur Miller <arthur.miller@live.com> writes: > Based on a Reddit thread: > > https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3 > > I did a small experiment to see if I can re-use org-capture, to just capture a > string from a buffer, without actually writing to any file. You can use a template target set to function pointing to temporary buffer. + org-capture-before-finalize-hook -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problem with let/cl-letf binding stuff with org-capture 2023-02-11 16:49 ` Ihor Radchenko @ 2023-02-15 13:06 ` Arthur Miller 0 siblings, 0 replies; 19+ messages in thread From: Arthur Miller @ 2023-02-15 13:06 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode Ihor Radchenko <yantar92@posteo.net> writes: > Arthur Miller <arthur.miller@live.com> writes: > >> Based on a Reddit thread: >> >> https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3 >> >> I did a small experiment to see if I can re-use org-capture, to just capture a >> string from a buffer, without actually writing to any file. > > You can use a template target set to function pointing to temporary > buffer. + org-capture-before-finalize-hook I did try something this: #+begin_src emacs-lisp (defun my-func () (with-current-buffer (get-buffer-create "my-capture-buffer"))) (defun my-hook () (with-current-buffer (try-completion "CAPTURE" (mapcar #'buffer-name (buffer-list))) (let ((content (buffer-string))) (kill-buffer) content))) (defun my-read-string () (let ((org-capture-templates `(("s" "string" plain (function my-func)))) (org-capture-before-finalize-hook #'my-hook)) (org-capture nil "s"))) #+end_src But that does not work well, because capture will put buffer it is called from as original buffer and write to that one. To prevent that I can call capture from a temporary buffer: #+begin_src emacs-lisp (defun my-read-string () (with-current-buffer (get-buffer-create "my-capture-buffer") (let ((org-capture-templates `(("s" "string" plain (function ignore)))) (org-capture-before-finalize-hook #'my-hook)) (org-capture nil "s")))) #+end_src but than capture complains about the buffer not being a file buffer, despite the before finalize hook. I could point it to some temp file like /tmp/my-capture, by manipulating capture plist myself, but it seems to be too expensive to create a temp file just for a hack to read a string form a buffer. There is probably some other way, but I give up here, especially since you point our read-string-from-buffer :) Anyway, thanks for the input and help. /a ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2023-02-15 17:37 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-02-10 15:05 Problem with let/cl-letf binding stuff with org-capture Arthur Miller 2023-02-10 15:38 ` Ruijie Yu via General discussions about Org-mode. 2023-02-10 16:29 ` Arthur Miller 2023-02-10 19:00 ` Bruno Barbier 2023-02-11 6:33 ` Arthur Miller 2023-02-11 7:58 ` Bruno Barbier 2023-02-11 16:14 ` Arthur Miller 2023-02-11 19:23 ` Bruno Barbier 2023-02-12 7:21 ` Arthur Miller 2023-02-12 9:22 ` Bruno Barbier 2023-02-12 16:12 ` Arthur Miller 2023-02-12 16:22 ` Ihor Radchenko 2023-02-13 18:40 ` Bruno Barbier 2023-02-15 11:45 ` Arthur Miller 2023-02-15 13:18 ` Bruno Barbier 2023-02-15 17:36 ` arthur miller 2023-02-13 18:37 ` Bruno Barbier 2023-02-11 16:49 ` Ihor Radchenko 2023-02-15 13:06 ` Arthur Miller
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).