From: Bruno Barbier <brubar.cs@gmail.com>
To: Arthur Miller <arthur.miller@live.com>
Cc: emacs-orgmode@gnu.org
Subject: Re: Problem with let/cl-letf binding stuff with org-capture
Date: Sat, 11 Feb 2023 20:23:03 +0100 [thread overview]
Message-ID: <63e7eb19.050a0220.56539.6aa7@mx.google.com> (raw)
In-Reply-To: <AM9PR09MB4977306B77F9A5338764324596DF9@AM9PR09MB4977.eurprd09.prod.outlook.com>
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
next prev parent reply other threads:[~2023-02-11 19:23 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=63e7eb19.050a0220.56539.6aa7@mx.google.com \
--to=brubar.cs@gmail.com \
--cc=arthur.miller@live.com \
--cc=emacs-orgmode@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).