emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
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


  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).