all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* How to return to the position from where I did tags-query-replace?
@ 2007-09-05 18:33 Yevgeniy Makarov
  2007-09-05 21:41 ` Eric Hanchrow
       [not found] ` <mailman.388.1189029337.18990.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 16+ messages in thread
From: Yevgeniy Makarov @ 2007-09-05 18:33 UTC (permalink / raw)
  To: help-gnu-emacs

Hello,

If I do tags-query-replace across several files, I may end up in a
different buffer from the one where I started the search. How do I go
back to the original place? M-* says "No previous location for find-
tag invocation", and this is correct, because I did not invoke M-.
(find-tag). The same question goes for tags-search command.

Thank you,
Yevgeniy

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2007-09-05 18:33 How to return to the position from where I did tags-query-replace? Yevgeniy Makarov
@ 2007-09-05 21:41 ` Eric Hanchrow
       [not found] ` <mailman.388.1189029337.18990.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 16+ messages in thread
From: Eric Hanchrow @ 2007-09-05 21:41 UTC (permalink / raw)
  To: help-gnu-emacs

I suspect that if you hit C-x C-@ (`pop-global-mark') a few times,
you'll wind up where you started.
-- 
Keaton, Chaplin, Garbo - let them now make room for Gromit.
        A. O. Scott, in The New York Times

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
       [not found] ` <mailman.388.1189029337.18990.help-gnu-emacs@gnu.org>
@ 2018-02-03 22:27   ` Ambrose Laing
  2018-02-04  3:28     ` Emanuel Berg
  0 siblings, 1 reply; 16+ messages in thread
From: Ambrose Laing @ 2018-02-03 22:27 UTC (permalink / raw)
  To: help-gnu-emacs

I would like the same outcome as the original poster: I would like for tags-query-replace to always return to the position of the point when the command was invoked, except that I want it to happen programmatically.  Here are two approaches I tried, neither of which works.  In each case, if I run the commands manually, it does what I want, but if I put the commands into the function, it doesn't work.

(defun my-tags-query-replace ()
  (interactive)
  (point-to-register "a")
  (command-execute 'tags-query-replace)
  (jump-to-register "a"))

(defun my-tags-query-replace ()
  (interactive)
  (bc-set)
  (command-execute 'tags-query-replace)
  (bc-goto-current)
  (setq *bc-bookmarks* (cdr *bc-bookmarks*)))

Any ideas how to do this correctly?
Thanks you,
Ambrose


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-03 22:27   ` Ambrose Laing
@ 2018-02-04  3:28     ` Emanuel Berg
  2018-02-04  4:30       ` Emanuel Berg
  0 siblings, 1 reply; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04  3:28 UTC (permalink / raw)
  To: help-gnu-emacs

Ambrose Laing wrote:

> I would like the same outcome as the original
> poster: I would like for tags-query-replace
> to always return to the position of the point
> when the command was invoked, except that
> I want it to happen programmatically.
> Here are two approaches I tried, neither of
> which works.

In general, I would do it like this.
Perhaps you can modify it so that instead of
applying `apply' to the args, put
`tags-query-replace' there and give the whole
thing the same interface as that function (also
change the name, of course).

This means you also have to change shortcuts to
invoke it instead of the original function.

With advice it can be set up completely
transparent if you care to read up on those...

(defun do-whatever-return (fun &rest args)
  (let ((point  (point))
        (buffer (current-buffer)) )
    (apply fun args)
    (when (bufferp buffer)
      (switch-to-buffer buffer)
      (goto-char (point) ))))
;; (do-whatever-return #'switch-to-buffer "*Help*")

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04  3:28     ` Emanuel Berg
@ 2018-02-04  4:30       ` Emanuel Berg
  2018-02-04  4:34         ` Emanuel Berg
  2018-02-04  4:46         ` Emanuel Berg
  0 siblings, 2 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04  4:30 UTC (permalink / raw)
  To: help-gnu-emacs

Boy, advices are sure difficult to use, even
for people who do not know how to use them!

But this seems to work (?). The original
function I wrote, actually didn't require any
modification, just the extra advice call to
glue it together.

I wrote a couple of pretty meaningless random
functions, no pun intended, just for testing.
Those are the ones one should replace with the
real thing, if one would like to do this
for real.

(defun do-whatever-return (fun &rest args)
  (let ((point  (point))
        (buffer (current-buffer)) )
    (apply fun args)
    (when (bufferp buffer)
      (switch-to-buffer buffer)
      (goto-char (point) ))))
;; (do-whatever-return #'switch-to-buffer "*Help*")

(defun switch-buffer-random ()
  (let*((buffers      (buffer-list))
        (num-bufs     (length buffers))
        (rand-buf-num (random (1- num-bufs)))
        (buf          (nth rand-buf-num buffers)) )
    (when (bufferp buf) (switch-to-buffer buf)) ))
;; (switch-buffer-random)

(defun move-point-random ()
  (let*((min (point-min))
        (max (point-max))
        (random-char (+ min (random (- max min))))
        (new-char (goto-char random-char)) )
    (message "New point in %s is %d" (current-buffer) (point))
    ))
;; (move-point-random)

(defun switch-buffer-move-point-random ()
  (switch-buffer-random)
  (move-point-random) )
;; (switch-buffer-move-point-random)

;; (advice-add 'switch-buffer-move-point-random :around #'do-whatever-return)
;; (switch-buffer-move-point-random)

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04  4:30       ` Emanuel Berg
@ 2018-02-04  4:34         ` Emanuel Berg
  2018-02-04  4:46         ` Emanuel Berg
  1 sibling, 0 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04  4:34 UTC (permalink / raw)
  To: help-gnu-emacs

Here is the file:

    http://user.it.uu.se/~embe8573/emacs-init/my-random.el

I added this so one can try it easily with and
without the advice in play:

;; (advice-add    'switch-buffer-move-point-random :around #'do-whatever-return)
;; (switch-buffer-move-point-random)

;; (advice-remove 'switch-buffer-move-point-random         #'do-whatever-return)
;; (switch-buffer-move-point-random)

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04  4:30       ` Emanuel Berg
  2018-02-04  4:34         ` Emanuel Berg
@ 2018-02-04  4:46         ` Emanuel Berg
  2018-02-04 20:14           ` aklaing
  1 sibling, 1 reply; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04  4:46 UTC (permalink / raw)
  To: help-gnu-emacs

Emanuel Berg wrote:

> (goto-char (point))

He he, good one! That should be

    (goto-char point)

Any further edits will be in the source
file [1] only. Modern society does not allow
this inefficiency.

[1] http://user.it.uu.se/~embe8573/emacs-init/my-random.el

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04  4:46         ` Emanuel Berg
@ 2018-02-04 20:14           ` aklaing
  2018-02-04 20:25             ` Emanuel Berg
  2018-02-04 20:29             ` aklaing
  0 siblings, 2 replies; 16+ messages in thread
From: aklaing @ 2018-02-04 20:14 UTC (permalink / raw)
  To: help-gnu-emacs

Thanks Emanuel for taking a look at this.  Your solution works correctly for your test case (moving to a random buffer and location) but not as-written for tags-query-replace, which has some peculiarities (I just realized).

Looking at the code, the tags-query-replace function uses a function called
user-error for flow control.  Deep in the logic, if it realizes that it has finished the job normally, it calls user-error, which is somewhat similar to throwing an exception deep in the call stack.  Because this unwinds the stack and discards it, the part of the code following (apply fun args) never gets evaluated.  This probably also explains why my two initial attempts do not work.

One hacky solution (based on your approach) is to do something similar to putting a try/catch around the call to (apply fun args), as follows:

(defun do-tags-query-replace-return (fun &rest args)
  (let ((tmp-point  (point)) 
        (tmp-buffer (current-buffer)))
    (message "DWR Before: %d %s %s" tmp-point tmp-buffer args)
    (condition-case tmp-err
	(apply fun args)
      (user-error
       (let ((err-message (cadr tmp-err)))
	 (if (string= err-message "All files processed")
	     (message "DWR Trapped: %s" err-message)
	   (signal (car tmp-err) (cdr tmp-err))))))
    (message "DWR After: %d %s %s" tmp-point tmp-buffer args)
    (when (bufferp tmp-buffer)
      (switch-to-buffer tmp-buffer)
      (goto-char tmp-point)
      nil)))

Notes: this is similar to putting a try/catch around the
(apply fun args).  I say it is (only) similar because elisp has a notion of try/catch which is different from its own notion of error-handling, though
there are similarities.

I like your approach better than my first two attempts because it does not require an external package like breadcrumb.  Though (I believe) registers are native in emacs, it is better to avoid using persistent state for something that should really be on the execution stack.

It should be noted that this solution only works for tags-query-replace, because it only traps one very specific type of error, which is the one tags-query-replace "throws" when it completes normally.  If tags-query-replace exits for any other real error, this will fail -- in the sense that it will not return to where it was before it started.  And I think that is a good thing.

One thing that is still not good about this solution is that if etags.el changes the string that it uses to indicate completion ("All files processed"), this solution will stop working.  That is too fragile.

In the long term, it would probably be better for etags.el to not use user-error to indicate normal completion, but that is more elisp than I want to do right now.  It requires changes in more than one place.  If the/an author of etags.el reads this and you have some time, maybe you can please take a look?

If anyone wants to use the hacky solution above, you might as well remove the DWR message calls.

Thanks again for your help, it pushed me to spend more time on it and learn a bit more elisp than I already knew.

Thanks,

On Saturday, February 3, 2018 at 11:46:13 PM UTC-5, Emanuel Berg wrote:
> Emanuel Berg wrote:
> 
> > (goto-char (point))
> 
> He he, good one! That should be
> 
>     (goto-char point)
> 
> Any further edits will be in the source
> file [1] only. Modern society does not allow
> this inefficiency.
> 
> [1] http://user.it.uu.se/~embe8573/emacs-init/my-random.el
> 
> -- 
> underground experts united
> http://user.it.uu.se/~embe8573



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:14           ` aklaing
@ 2018-02-04 20:25             ` Emanuel Berg
  2018-02-04 20:36               ` Emanuel Berg
  2018-02-04 20:37               ` aklaing
  2018-02-04 20:29             ` aklaing
  1 sibling, 2 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04 20:25 UTC (permalink / raw)
  To: help-gnu-emacs

aklaing wrote:

> Thanks Emanuel for taking a look at this.
> [...]

NP, but are you saying, your function throws an
error when it *does* work, and this make the
advice not work?

If so, IMO it'll just be too confusion to try
to write a framework around that.

The docstring for `error' doesn't say anything
about aborting normal execution, but maybe it
does, I don't know:

    (error STRING &rest ARGS)

    Signal an error, making error message by
    passing all args to `format'. In Emacs, the
    convention is that error messages start
    with a capital letter but *do not* end with
    a period. Please follow this convention for
    the sake of consistency.

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:14           ` aklaing
  2018-02-04 20:25             ` Emanuel Berg
@ 2018-02-04 20:29             ` aklaing
  2018-02-04 20:38               ` Emanuel Berg
  1 sibling, 1 reply; 16+ messages in thread
From: aklaing @ 2018-02-04 20:29 UTC (permalink / raw)
  To: help-gnu-emacs

Another minor note if anyone wants to use this: as suggested by Emanuel, you will need to use these to put it in place (or remove it):

(advice-add 'tags-query-replace :around #'do-tags-query-replace-return)
;; (advice-remove 'tags-query-replace #'do-tags-query-replace-return)

On Sunday, February 4, 2018 at 3:14:39 PM UTC-5, akl...@gmail.com wrote:
> Thanks Emanuel for taking a look at this.  Your solution works correctly for your test case (moving to a random buffer and location) but not as-written for tags-query-replace, which has some peculiarities (I just realized).
> 
> Looking at the code, the tags-query-replace function uses a function called
> user-error for flow control.  Deep in the logic, if it realizes that it has finished the job normally, it calls user-error, which is somewhat similar to throwing an exception deep in the call stack.  Because this unwinds the stack and discards it, the part of the code following (apply fun args) never gets evaluated.  This probably also explains why my two initial attempts do not work.
> 
> One hacky solution (based on your approach) is to do something similar to putting a try/catch around the call to (apply fun args), as follows:
> 
> (defun do-tags-query-replace-return (fun &rest args)
>   (let ((tmp-point  (point)) 
>         (tmp-buffer (current-buffer)))
>     (message "DWR Before: %d %s %s" tmp-point tmp-buffer args)
>     (condition-case tmp-err
> 	(apply fun args)
>       (user-error
>        (let ((err-message (cadr tmp-err)))
> 	 (if (string= err-message "All files processed")
> 	     (message "DWR Trapped: %s" err-message)
> 	   (signal (car tmp-err) (cdr tmp-err))))))
>     (message "DWR After: %d %s %s" tmp-point tmp-buffer args)
>     (when (bufferp tmp-buffer)
>       (switch-to-buffer tmp-buffer)
>       (goto-char tmp-point)
>       nil)))
> 
> Notes: this is similar to putting a try/catch around the
> (apply fun args).  I say it is (only) similar because elisp has a notion of try/catch which is different from its own notion of error-handling, though
> there are similarities.
> 
> I like your approach better than my first two attempts because it does not require an external package like breadcrumb.  Though (I believe) registers are native in emacs, it is better to avoid using persistent state for something that should really be on the execution stack.
> 
> It should be noted that this solution only works for tags-query-replace, because it only traps one very specific type of error, which is the one tags-query-replace "throws" when it completes normally.  If tags-query-replace exits for any other real error, this will fail -- in the sense that it will not return to where it was before it started.  And I think that is a good thing.
> 
> One thing that is still not good about this solution is that if etags.el changes the string that it uses to indicate completion ("All files processed"), this solution will stop working.  That is too fragile.
> 
> In the long term, it would probably be better for etags.el to not use user-error to indicate normal completion, but that is more elisp than I want to do right now.  It requires changes in more than one place.  If the/an author of etags.el reads this and you have some time, maybe you can please take a look?
> 
> If anyone wants to use the hacky solution above, you might as well remove the DWR message calls.
> 
> Thanks again for your help, it pushed me to spend more time on it and learn a bit more elisp than I already knew.
> 
> Thanks,
> 
> On Saturday, February 3, 2018 at 11:46:13 PM UTC-5, Emanuel Berg wrote:
> > Emanuel Berg wrote:
> > 
> > > (goto-char (point))
> > 
> > He he, good one! That should be
> > 
> >     (goto-char point)
> > 
> > Any further edits will be in the source
> > file [1] only. Modern society does not allow
> > this inefficiency.
> > 
> > [1] http://user.it.uu.se/~embe8573/emacs-init/my-random.el
> > 
> > -- 
> > underground experts united
> > http://user.it.uu.se/~embe8573



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:25             ` Emanuel Berg
@ 2018-02-04 20:36               ` Emanuel Berg
  2018-02-04 20:37               ` aklaing
  1 sibling, 0 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04 20:36 UTC (permalink / raw)
  To: help-gnu-emacs

> The docstring for `error' doesn't say
> anything about aborting normal execution, but
> maybe it does, I don't know

OK, so it does

(progn
  (error "This error is for display purposes only.")
  1) ; not 1

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:25             ` Emanuel Berg
  2018-02-04 20:36               ` Emanuel Berg
@ 2018-02-04 20:37               ` aklaing
  2018-02-04 20:41                 ` Emanuel Berg
  1 sibling, 1 reply; 16+ messages in thread
From: aklaing @ 2018-02-04 20:37 UTC (permalink / raw)
  To: help-gnu-emacs

Yes.  It (tags-query-replace) throws exceptions whether it completes successfully or not.  It does not work because the (apply fun args) is in the middle of other code.  So the part of the calling code which follows the (apply fun args) does not execute unless you catch the exception.

There is more detailed doc at:
https://www.gnu.org/software/emacs/manual/html_node/elisp/Signaling-Errors.html (first paragraph).  Further down the page it talks about user-error.

On Sunday, February 4, 2018 at 3:25:36 PM UTC-5, Emanuel Berg wrote:
> aklaing wrote:
> 
> > Thanks Emanuel for taking a look at this.
> > [...]
> 
> NP, but are you saying, your function throws an
> error when it *does* work, and this make the
> advice not work?
> 
> If so, IMO it'll just be too confusion to try
> to write a framework around that.
> 
> The docstring for `error' doesn't say anything
> about aborting normal execution, but maybe it
> does, I don't know:
> 
>     (error STRING &rest ARGS)
> 
>     Signal an error, making error message by
>     passing all args to `format'. In Emacs, the
>     convention is that error messages start
>     with a capital letter but *do not* end with
>     a period. Please follow this convention for
>     the sake of consistency.
> 
> -- 
> underground experts united
> http://user.it.uu.se/~embe8573



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:29             ` aklaing
@ 2018-02-04 20:38               ` Emanuel Berg
  0 siblings, 0 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04 20:38 UTC (permalink / raw)
  To: help-gnu-emacs

To have an `error' (or `user-error') when there
isn't an error, does that come across as
counter-intuitive to any of you guys? :)

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:37               ` aklaing
@ 2018-02-04 20:41                 ` Emanuel Berg
  2018-02-04 20:52                   ` aklaing
  0 siblings, 1 reply; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04 20:41 UTC (permalink / raw)
  To: help-gnu-emacs

aklaing wrote:

> It (tags-query-replace) throws exceptions
> whether it completes successfully or not.
> It does not work because the (apply fun args)
> is in the middle of other code.

Well yes, only the words "it does not work"
should be in the beginning of the _first_
sentence, not the second.

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:41                 ` Emanuel Berg
@ 2018-02-04 20:52                   ` aklaing
  2018-02-04 21:02                     ` Emanuel Berg
  0 siblings, 1 reply; 16+ messages in thread
From: aklaing @ 2018-02-04 20:52 UTC (permalink / raw)
  To: help-gnu-emacs

It is not ideal to use exceptions the way it does, but it is free software and I love using the function so much that I'm not going to complain :-).

I suppose one could argue that the only difference it makes to anyone is that after running the function they need to change buffer back to their original buffer, manually, and it is really not a big deal, and that is why this issue has survived so long (I'm assuming etags.el was pretty  much the same in 2007 in regard to this issue).

But yes you're right, code that runs normally should not end with an exception.

On Sunday, February 4, 2018 at 3:41:36 PM UTC-5, Emanuel Berg wrote:
> aklaing wrote:
> 
> > It (tags-query-replace) throws exceptions
> > whether it completes successfully or not.
> > It does not work because the (apply fun args)
> > is in the middle of other code.
> 
> Well yes, only the words "it does not work"
> should be in the beginning of the _first_
> sentence, not the second.
> 
> -- 
> underground experts united
> http://user.it.uu.se/~embe8573



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: How to return to the position from where I did tags-query-replace?
  2018-02-04 20:52                   ` aklaing
@ 2018-02-04 21:02                     ` Emanuel Berg
  0 siblings, 0 replies; 16+ messages in thread
From: Emanuel Berg @ 2018-02-04 21:02 UTC (permalink / raw)
  To: help-gnu-emacs

aklaing wrote:

> I suppose one could argue that the only
> difference it makes to anyone is that after
> running the function they need to change
> buffer back to their original buffer,
> manually, and it is really not a big deal,
> and that is why this issue has survived so
> long (I'm assuming etags.el was pretty much
> the same in 2007 in regard to this issue).

Yeah but that is only in this case. If people
did that all the time then the whole advice
business would go down :)

-- 
underground experts united
http://user.it.uu.se/~embe8573


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-02-04 21:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-05 18:33 How to return to the position from where I did tags-query-replace? Yevgeniy Makarov
2007-09-05 21:41 ` Eric Hanchrow
     [not found] ` <mailman.388.1189029337.18990.help-gnu-emacs@gnu.org>
2018-02-03 22:27   ` Ambrose Laing
2018-02-04  3:28     ` Emanuel Berg
2018-02-04  4:30       ` Emanuel Berg
2018-02-04  4:34         ` Emanuel Berg
2018-02-04  4:46         ` Emanuel Berg
2018-02-04 20:14           ` aklaing
2018-02-04 20:25             ` Emanuel Berg
2018-02-04 20:36               ` Emanuel Berg
2018-02-04 20:37               ` aklaing
2018-02-04 20:41                 ` Emanuel Berg
2018-02-04 20:52                   ` aklaing
2018-02-04 21:02                     ` Emanuel Berg
2018-02-04 20:29             ` aklaing
2018-02-04 20:38               ` Emanuel Berg

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.