all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Karl Fogel <kfogel@red-bean.com>
To: Drew Adams <drew.adams@oracle.com>
Cc: Stefan Monnier <monnier@iro.umontreal.ca>,
	 "emacs-devel@gnu.org" <emacs-devel@gnu.org>
Subject: Re: [External] : Re: [PATCH] Let bookmark handlers do everything, including display the destination
Date: Mon, 26 Sep 2022 14:47:49 -0500	[thread overview]
Message-ID: <87zgellxy2.fsf@red-bean.com> (raw)
In-Reply-To: <SJ0PR10MB5488FADAF5042C21C6D469E2F37E9@SJ0PR10MB5488.namprd10.prod.outlook.com> (Drew Adams's message of "Tue, 6 Sep 2022 00:07:04 +0000")

Drew, below you quite reasonably suggest that I show what I'm 
proposing by coding it up.  I didn't want to just let your message 
dangle without a reply, so this is just to say that I'm not sure 
if or when I'll have time to do that.  While I can volunteer to 
review code in a timely manner, I'm much more cautious about 
volunteering to write code these days.

I didn't want you to think my silence meant that I disagreed with 
your original idea or your followup -- I don't, it's just a matter 
of limited hacking time.

Best regards,
-Karl

On 06 Sep 2022, Drew Adams wrote:
>> >> There's some parallelism-unsafety going on here, obviously.
>> >> I'd love a way to wrap all this in a clean closure,
>> >> instead of setting a global variable which then retains
>> >> that setting until the next time we happen to set it.
>
>Retaining that setting till it's reset could
>be a feature, not a bug. ;-)
>
>I imagine I won't have a problem if you bind
>it lexically in `bookmark--jump-via', but I'm
>not sure.
>
>Bookmark+ is designed to work also with Emacs
>versions that don't have lexical binding.
>Maybe using `lexical-let' here'll suffice,
>maybe not.
>
>A `nil' value does matter - it's not the same
>as calling a function unconditionally, even
>when the function is `ignore'.
>
>E.g., my version of `bookmark-default-handler'
>has this code, which doesn't raise the frame if
>there's no display going on (a bookmark need
>not display anything):
>
>(when bmkp-jump-display-function
>  (save-current-buffer
>    (funcall bmkp-jump-display-function (current-buffer)))
>  (raise-frame))
>
>Sure, I could change (when XXXX ...) to
>(when (eq XXXX 'ignore) ...), but that wouldn't
>really improve anything, IMO.
>
>And I test the display function in some handlers,
>for conditional handling/dispatch.  E.g., my
>handler for Dired bookmarks:
>
>(defun bmkp-jump-dired (bookmark)
>  "..."
>  (let ((dir
>         (bookmark-prop-get bookmark 'dired-directory))
>        (mfiles
>         (bookmark-prop-get bookmark 'dired-marked))
>        (switches
>         (bookmark-prop-get bookmark 'dired-switches))
>        (subdirs
>         (bookmark-prop-get bookmark 'dired-subdirs))
>        (hidden-dirs
>         (bookmark-prop-get bookmark 'dired-hidden-dirs)))
>    (case bmkp-jump-display-function
>      ((nil bmkp--pop-to-buffer-same-window display-buffer)
>       (dired dir switches))
>      ((bmkp-select-buffer-other-window
>        pop-to-buffer
>        switch-to-buffer-other-window)
>       (dired-other-window dir switches))
>      (t (dired dir switches)))
>    (let ((inhibit-read-only  t))
>      (dired-insert-old-subdirs subdirs)
>      (dired-mark-remembered 
>       (mapcar (lexical-let ((dd  dir))
>                 (lambda (mf)
>                   (cons (expand-file-name mf dd) 42)))
>               mfiles))
>      (save-excursion
>        (dolist (dir  hidden-dirs)
>          (when (dired-goto-subdir dir) (dired-hide-subdir 1)))))
>    (let ((pos  (bookmark-get-position bookmark)))
>      (when pos (goto-char pos)))))
>
>Obviously testing for functional equality isn't
>possible.  But testing a function symbol lets a
>particular kind of bookmark jump differently
>depending on current context/settings.  
>
>> > Indeed :-(
>
>Not so obvious to me.  Fine as a general guideline.
>Not clear that it's a real win (no loss) here.
>
>> > Why can't `bookmark--jump-via` let-bind
>> > `bookmark-jump-display-function` around 
>> > the call to `bookmark-handle-bookmark`?
>> 
>> Of course -- obvious... 
>> Drew, does that sound good to you?
>
>See above.  And please show your proposed code.
>
>> > Regarding the patch, here are some comments:
>> >
>> >> +  To display the destination, HANDLER can call the function
>> >> that's the
>> >> +  value of variable `bookmark-jump-display-function', which 
>> >> is
>> >> set by
>> >> +  `bookmark-jump' to automatically accommodate other-window
>> >> etc.
>> >> +  displaying that depends on the jump command.  For 
>> >> example:
>> >> +
>> >> +   (funcall bookmark-jump-display-function 
>> >> (current-buffer))
>> >> +
>> >> +  Or HANDLER can directly call another display function. 
>> >> For
>> >> example:
>> >> +
>> >> +   (switch-to-buffer-other-tab BUFFER)
>> > ...
>> > the above goes significantly beyond what one usually
>> > expects from a docstring.  It would fit much better
>> > in a Texinfo manual instead.
>
>Feel free to write a TexInfo manual for bookmarking,
>including for writing bookmark handlers, etc.  What
>exists now, and is as old as `bookmark.el', is just
>some code comments and that doc string.
>
>That doc string documents the data structure for a
>bookmark - it's THE place where that's specified.
>
>The handler part of that is important for people
>who create a new bookmark type (always has been).
>It's the one bit of bookmark data that really needs
>explaining, as it's the one part that provides
>behavior (code).
>
>> >> +  Or HANDLER can invoke `bookmark-default-handler'.  That
>> >> displays the
>> >> +  destination.  It then moves to the recorded buffer 
>> >> position,
>> >> POS,
>> >> +  repositioning point, if necessary, to match the recorded
>> >> context
>> >> +  strings STR-BEFORE-POS and STR-AFTER-POS.  For instance, 
>> >> the
>> >> Info
>> >> +  handler, `Info-bookmark-jump', does this at its end:
>> >
>> > And this is (or should be) redundant with the docstring of
>> > `bookmark-default-handler` so better keep the link and the 
>> > the
>> > readers jump to it when they need/want to know what that 
>> > function does.
>
>How is saying that a custom handler can invoke the
>default handler, and summarizing what that does,
>redundant here?
>
>Sure, it could just say that your handler can invoke
>the default handler, and leave it at that.  But that
>just begs the question "Huh? Why?".  And then, when
>you go off to look at the doc of that function, all
>you find is this (unmodified):
>
> Default handler to jump to a particular bookmark location.
> BMK-RECORD is a bookmark record, not a bookmark name (i.e., not 
> a string).
> Changes current buffer and point and returns nil, or signals a 
> `file-error'.
>
> If BMK-RECORD has a property called `buffer', it should be a 
> live
> buffer object, and this buffer will be selected.
>
>(Why shouldn't it be able to be a bookmark name, BTW?)
>
>Does that doc string help you, if you're writing
>your own handler?  The code helps, but not that
>doc string.  It doesn't tell you what jumping
>_means/does_ in the default case.
>
>IMO there's little sense in saying only that your
>handler _can_ call the default handler.  And even
>less sense in saying neither that it can nor what
>calling it does, i.e., _why_ you might want your
>handler to invoke the default handler.
>
>But TexInfo manual - welcome.  Go for it, please.
>
>> Agreed.
>
>Please show your proposed code (e.g. doc string).
>
>It's a deficiency of the existing doc string
>that it doesn't really tell you anything useful
>about the HANDLER part, IMO.
>
>But as I said, feel free to put what you like in
>any of the doc strings.
>
>The patch doesn't _require_ any mention of the
>possibility or use case of calling the default
>handler from a nondefault handler.  I think it's
>good to mention that, but you needn't do so to
>make the code change.
>
>> >> +(defvar bookmark-jump-display-function nil
>> >> + "Function used currently to display a bookmark, or nil if 
>> >> no
>> >> function.")
>> >
>> > Please give it a function as default value (e.g. `ignore`).
>
>See above.  I don't think anything's really gained
>by doing that here.  As a general guideline, sure,
>no problem.  But let's hear a specific argument
>for doing that here, please.
>
>> I think I understand: by taking your advice, we don't have to
>> check the function's existence -- we can just call it
>> unconditionally, and if it happens to do nothing (i.e., is
>> `ignore'), that's fine.
>
>Not so fine, IMO.  And you might still need to test
>its existence - with `(eq 'ignore)' instead of just
>non-nil.  And then there's trying to test for
>functions "equivalent" to `ignore'...
>
>[FWIW, a somewhat related feature, which I didn't
>include in my patch (but which could be considered
>for another change), wraps most of the code of
>`bookmark--jump-via' in a `catch', to which a
>handler can `throw' to avoid doing anything else
>(e.g. after-jump hook, auto-showing annotations).]
>
>> A specific package may still override the
>> default handler and do whatever display magic is called for;
>> otherwise, bookmark.el's default handler will Do The Right 
>> Thing
>> for displaying.
>
>If "otherwise" means that if a handler doesn't
>use a display function then the display of the
>default handler is used, then that's wrong.  A
>handler needs to be able to not display anything.
>
>> But all this raises the question you raise below...
>
>What question below?  Do you mean the question
>"Why `save-current-buffer'?"
>
>> >> @@ -1350,6 +1391,9 @@
>> >>        ((and buf (get-buffer buf)))
>> >>        (t ;; If not, raise error.
>> >>         (signal 'bookmark-error-no-filename (list 'stringp
>> >>         file)))))
>> >> +    (when bookmark-jump-display-function
>> >> +      (save-current-buffer
>> >> +        (funcall bookmark-jump-display-function
>> >> +                 (current-buffer))))
>> >
>> > Why `save-current-buffer`?
>
>That's already in the code that the patch
>replaces.  It's in `bookmark--jump-via'.
>Displaying is now in the default handler (or
>another handler).  That's all.
>
>Take out that ` save-current-buffer', if you
>think you don't need it.  I'll likely leave it
>in my code.
>
>You can fiddle with the `bookmark--jump-via'
>code if you like, to ensure that the behavior
>change I described is the only one that's made.
>I think that's already the case, but feel free.
>
>The code right after `(save-current-buffer...)'
>expects the buffer that is current not to have
>changed.  In the unpatched code that right-after
>code is in `bookmark--jump-via'.  In the patched
>code it's in the default handler.
>
>> >>      (if place (goto-char place))
>> >>      ;; Go searching forward first.  Then, if forward-str
>> >>      exists and
>> >>      ;; was found in the file, we can search backward for
>> >>      behind-str.
>> >
>> > Hmm... `bookmark-default-handler` is also called via things 
>> > like
>> > `bookmark-insert`,
>
>Not in the code I patched or in the patched result,
>it isn't.
>
>`bookmark-insert' calls `bookmark-handle-bookmark'.
>That just invokes the default handler for _some_
>bookmarks.  In general it doesn't mean that any
>displaying occurs, and it doesn't say what
>"displaying" means for any given kind of bookmark.
>
>> > so I think `bookmark-insert` should explicitly bind
>> > `bookmark-jump-display-function` to `ignore`,
>
>But I don't have a problem if you want to do that.
>
>The problem you raise comes from `bookmark-insert'
>trying to use a handler to insert all of the text
>from the buffer that happens to be current after
>the bookmark is handled.  That assumes quite a lot.
>
>`bookmark-insert' is old (a vestige).  It seems to
>assume that you're just jumping to a file (see the
>doc string: "text of the file").  Or at least a
>text buffer.
>
>A more reasonable fix might be for `bookmark-insert'
>to do nothing or to raise an error if the bookmark
>type isn't a file bookmark.  (Or maybe a text file.
>Try it on a bookmark whose jumping displays an image
>file.)
>
>> > and of course that begs the question of what to do
>> > for handlers which don't obey 
>> > `bookmark-jump-display-function`.
>
>(Obey?  How about use?)  See above.  It's more than
>just a question of whether/how a bookmark displays
>something.  `bookmark-insert' apparently assumes a
>narrow (even if common) sort of bookmark.
>
>(BTW, do you notice `save-current-buffer' there?
>And that's before giving the handler any freedom
>to display.)
>
>> > I think it's good to provide more control to the bookmark's
>> > handler, but
>> > there seems to be a need for the caller to control the 
>> > display
>> > as well to some extent.
>
>What caller?  Caller of what - a bookmark handler?
>Do you see any other callers of handlers, besides
>`bookmark-insert' (which is already broken for
>bookmarks that don't go to a text buffer/file)?
>
>What kind of display control do you want a caller
>of a handler to have?  And why does that seem to
>you to be a need?  Can you elaborate on some
>handler-calling you have in mind?
>
>> ...which is that we now seem to have two possibly-redundant 
>> ways
>> to control displaying: write a custom handler, *or* bind
>> `bookmark-jump-display-function' to something?
>
>Redundant?  A handler's responsible for any
>displaying.  It can, but it need not, use the
>value of `bookmark-jump-display-function' to do
>that.  That's all.  
>
>What's the question?  By non-custom handler I
>guess you mean the default handler - it invokes
>`bookmark-jump-display-function'.
>
>BTW, with & without the patch there's this
>"redundancy": `bookmark-bmenu-switch-other-window'
>calls `bookmark--jump-via', passing a display
>function.  `bookmark-bmenu-other-frame' calls
>`bookmark-jump', passing a display function.
>
>The change the patch provides is to give handlers
>control over display - including choosing not to
>display anything.
> 
>> Or perhaps I'm misunderstanding something.  Drew, if you post 
>> the
>> next revision of the patch incorporating Stefan's points above, 
>> I
>> will review that in detail, when fully alert, and should be 
>> able
>> to distill any remaining questions -- I think we'd be pretty 
>> close
>> at that point.
>
>I posted a patch that I think does what I propose.
>It's very close to the code of Bookmark+, which
>has been used for quite a while now.  Feel free to
>not apply the patch or to apply it and change any
>doc strings.
>
>If you replace var `bookmark-jump-display-function'
>with binding a function in `bookmark--jump-via'
>then I'll try to adjust my code for that.  If I
>can't do so reasonably then the syncing of handler
>behavior between Bookmark+ and bookmark.el might
>not be so seamless.
>
>If you have an alternative patch to propose,
>please do so.  I'll try to take a look.



      reply	other threads:[~2022-09-26 19:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-13 20:59 [PATCH] Let bookmark handlers do everything, including display the destination Drew Adams
2022-08-18 18:14 ` Karl Fogel
2022-08-29 15:28   ` Stefan Monnier
2022-08-29 23:45     ` Karl Fogel
2022-09-06  0:07       ` [External] : " Drew Adams
2022-09-26 19:47         ` Karl Fogel [this message]

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

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87zgellxy2.fsf@red-bean.com \
    --to=kfogel@red-bean.com \
    --cc=drew.adams@oracle.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /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 external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.