unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Custom query-replace.
@ 2015-07-12 20:47 R. Clayton
  2015-07-13  7:19 ` Yuri Khan
  0 siblings, 1 reply; 4+ messages in thread
From: R. Clayton @ 2015-07-12 20:47 UTC (permalink / raw)
  To: help-gnu-emacs

I'm trying to write a query-replace command to deal with hyphens in text.  For
each match, I want to perform one of three changes:

  delete hyphen; go from "for- got" to "forgot"
  unspace hyphen; go from "red- headed" to "red-headed"
  space hyphen; go from "stop- it" to "stop - it"

as well as the usual query-replace options (quit, skip, and so on).  For
example, typing 'D' at the query-replace prompt would delete the hyphen.

I had a hazy idea I could do this by flogging some keymap.  However, once I got
this far

  (defun rehyphenate ()

    (interactive)

    (let (f r)

      (fset 'r (lambda (data count)
                 (concat (match-string 1) "-" (match-string 2))))

      (fset 'f (lambda ()
                 (perform-replace
                   "\\([a-z]\\)- +\\([a-z]\\)"    ; from-string
                   (cons 'r "")                   ; replacements
                   t                              ; query-flag
                   t                              ; regexp-flag
                   nil                            ; delimited-flag
                   nil                            ; repeat-count
                   nil                            ; keymap
                   (point-min)                    ; start
                   (point-max)                    ; end
                   )))
      (while (f)
        )))

I realized my hazy idea was hazier than I though.  It seems to me I have two
paths I can follow:

  Continue to flog the keymap by including commands in the keymap that in turn
  flog the replacement text, or otherwise communicate the change choice to the
  replacement function.

  Move the query from the match to the replacement function, which would forego
  standard query-replace behavior, such as quitting and skipping, which is an
  ok trade-off.

Both of these paths seem unattractive to me.  What alternatives are there
available for me to do what I want?  Is there some similarly-behaving code
around I can steal from?




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

* Re: Custom query-replace.
  2015-07-12 20:47 Custom query-replace R. Clayton
@ 2015-07-13  7:19 ` Yuri Khan
  2015-07-13 10:55   ` Marcin Borkowski
  2015-07-14 17:32   ` R. Clayton
  0 siblings, 2 replies; 4+ messages in thread
From: Yuri Khan @ 2015-07-13  7:19 UTC (permalink / raw)
  To: R. Clayton; +Cc: help-gnu-emacs@gnu.org

On Mon, Jul 13, 2015 at 2:47 AM, R. Clayton <rvclayton@acm.org> wrote:
> I'm trying to write a query-replace command to deal with hyphens in text.  For
> each match, I want to perform one of three changes:
>
>   delete hyphen; go from "for- got" to "forgot"
>   unspace hyphen; go from "red- headed" to "red-headed"
>   space hyphen; go from "stop- it" to "stop - it"
>
> as well as the usual query-replace options (quit, skip, and so on).  For
> example, typing 'D' at the query-replace prompt would delete the hyphen.

So you want to search for a pattern and interactively optionally
replace each occurrence with one of several possible replacements. I
don’t know of a ready-made solution for that. Here’s what I would do
instead.


Record and save four macros that:

0. all assume the starting position where the point is immediately
after the hyphen and its following whitespace if any;

1a. one (“delete-hyphen-and-find-next”) deletes the preceding
whitespace and the hyphen;
1b. another (“unspace-hyphen-and-find-next”) deletes the preceding whitespace;
1c. yet another (“space-hyphen-and-find-next”) does a backwards
isearch for the hyphen, inserts a single space before it and pops the
mark saved by the isearch;
1d. the fourth (“find-next-hyphen”) does nothing at this point;

2. after which all four macros skip (using regexp isearch) to the next
occurrence of the search pattern, preparing for the next replacement.

Bind them to sufficiently easy keys.

Go to the start of buffer (M-<); if it is not an occurrence of the
search pattern, prime the loop by invoking “find-next-hyphen”.

Repeatedly invoke one of the four macros, until the buffer ends.

In case of mistake, undo. To return to the place of last occurrence in
case of doubt, pop the mark (C-u C-SPC).

Between the replacements, you can make any other edits, provided that
you leave the point at a position suitable for the next replacement.
(“find-next-hyphen” can be used at any position.)


Possible improvement: Rewrite the macros as elisp functions. Check
preconditions. Instead of isearch, use non-interactive elisp search
facilities. (This way, you protect against document corruption when
running macros at unsuitable positions, and stop clobbering the last
isearch pattern.)


Possible further improvement: If you encounter this task frequently
and the need for other edits is low, you might want to make it a minor
mode that (1) primes the loop on entry; (2) binds super-easy
(basically, single-character) keys; (3) binds another super-easy key
(such as “q”) to disable the mode.



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

* Re: Custom query-replace.
  2015-07-13  7:19 ` Yuri Khan
@ 2015-07-13 10:55   ` Marcin Borkowski
  2015-07-14 17:32   ` R. Clayton
  1 sibling, 0 replies; 4+ messages in thread
From: Marcin Borkowski @ 2015-07-13 10:55 UTC (permalink / raw)
  To: R. Clayton, help-gnu-emacs@gnu.org


On 2015-07-13, at 09:19, Yuri Khan <yuri.v.khan@gmail.com> wrote:

> Possible further improvement: If you encounter this task frequently
> and the need for other edits is low, you might want to make it a minor
> mode that (1) primes the loop on entry; (2) binds super-easy
> (basically, single-character) keys; (3) binds another super-easy key
> (such as “q”) to disable the mode.

I sent a PM to the OP with (more or less) this, which I made for my own
use some time ago.  (I did not want to send that code to the list -- it
is not really polished at all.)  If there is any interest, I might try
to improve and/or rewrite and publish it.

Basically, it is a mode and a function (modeled on Isearch) which, given
a list whose elements are lists with a regex as the car and a list of
possible replacements as the cdr, walk through the buffer, finding
subsequent matches for any of these regexen and allowing to cycle
through the given possible replacements with TAB.  It's not very well
written - I wrote it several years ago, when my Elisp-fu was weaker -
but works.

Best,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University



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

* Re: Custom query-replace.
  2015-07-13  7:19 ` Yuri Khan
  2015-07-13 10:55   ` Marcin Borkowski
@ 2015-07-14 17:32   ` R. Clayton
  1 sibling, 0 replies; 4+ messages in thread
From: R. Clayton @ 2015-07-14 17:32 UTC (permalink / raw)
  To: Yuri Khan; +Cc: help-gnu-emacs

Thanks for your reply to my message.

  Possible further improvement: If you encounter this task frequently and the
  need for other edits is low, you might want to make it a minor mode that (1)
  primes the loop on entry; (2) binds super-easy (basically, single-character)
  keys; (3) binds another super-easy key (such as “q”) to disable the mode.

A good idea; minor modes hadn't occured to me.



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

end of thread, other threads:[~2015-07-14 17:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-12 20:47 Custom query-replace R. Clayton
2015-07-13  7:19 ` Yuri Khan
2015-07-13 10:55   ` Marcin Borkowski
2015-07-14 17:32   ` R. Clayton

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