* complex query replace using perform-replace with replace-re-search-function
@ 2012-06-15 13:49 jack-mac
2012-06-15 14:42 ` Barry Margolin
0 siblings, 1 reply; 2+ messages in thread
From: jack-mac @ 2012-06-15 13:49 UTC (permalink / raw)
To: help-gnu-emacs
Hello!
I'm using GNU Emacs 23.1.1 (i686-pc-linux-gnu, GTK+ Version 2.22.0) of
2011-03-04 on roseapple, modified by Debian
[1] I need some help for my function `jd-sh-format-pipes' which is
described below.
It works *almost* correctly!
The query process just asks for the correct occurrences (the one
recognized by my function `jd-sh-re-search-pipe'), but *all* the
occurrences of the regexp are semi-highlighted (including what I call
exceptions to the regexp). Nevertheless, the perform-replace process
skips these exceptions and full-highlights only the correct ones.
Is this a bug?
If it's normal, how is it possible to have *only* the 'correct'
occurrences semi-highlighted?
BTW, is there any place where I could find any examples of how to use
`perform-replace' with a customized `replace-re-search-function'
and/or `replacements' being a cons cell with a function?
================================================================
[2] Also, when reading the code of `perform-replace', I found
something strange (NOT related to my problem, I think, since I don't
use the `delimited-flag').
It changes twice the `search-function' variable:
Once is ok for me (since it takes into account the value of the
variable `replace-re-search-function'):
(let* ([snip]
(search-function
(if regexp-flag
replace-re-search-function
replace-search-function))
[snip])
but the second one (when `delimited-flag' is t) seems to erase the
previous value of `search-function' and does NOT take into account the
value of the variable `replace-re-search-function'):
(if delimited-flag
(setq search-function 're-search-forward
search-string (concat "\\b"
(if regexp-flag from-string
(regexp-quote from-string))
"\\b")))
Is this correct?
================================================================
Here is the description of my function `jd-sh-format-pipes'
with a sample file to reformat.
Thanks in advance
)jack(
;;; [jack] 120610 I want each pipe in my ksh files to be surrounded by
exactly one space,
;;; i.e. basically replace "<cm1> *| *<cmd2>" by "<cm1> | <cmd2>"
;;; but there are some exceptions:
;;; - `good_pipe'
;;; <cm1> | <cmd2>
;;; when the pipe is already surrounded by exactly one space, leave
it
;;; - `comment'
;;; # r1238 | vtgk1446 (Jacques) | 2012-01-31 10:26:23
;;; Don't change a comment
;;; - `string'
;;; sed -e 's|x|y|g' -e "s|$x|$y|g"
;;; Don't change a string
;;; - `double_pipe'
;;; <cmd1> || <cmd2>
;;; Don't separate a double pipe: don't change it into "<cmd1> | |
<cmd2>"
;;; Don't squeeze the spaces: don't change it into "<cmd1> ||
<cmd2>"
;;; - `case_clause'
;;; case <x> in
;;; <val>|<val>)
;;; Don't change a case clause: don't change it into "<val> |
<val>)"
;;; - `pipe_at_beginning-of-line'
;;; <cmd1> \
;;; | <cmd2>
;;; Don't squeeze the leading spaces, squeeze only the trailing ones
;;;
;;; As regexps don't like exceptions, it's probably nearly impossible
;;; to use `query-replace-regexp' with a regexp.
;;; So, I'll use a customized `replace-re-search-function'.
(defvar jd-sh-format-pipes-any-pipe-re "[ \t]*| *")
(defvar jd-sh-format-pipes-good-pipe-re " | ")
(defun jd-re-paren (&rest args)
(apply 'concat (cons "\\(" (append args (list "\\)")))))
(defun jd-sh-format-pipes ()
(interactive)
(let ((replace-re-search-function 'jd-sh-re-search-pipe)
(any-pipe jd-sh-format-pipes-any-pipe-re)
(good-pipe jd-sh-format-pipes-good-pipe-re))
(query-replace-regexp any-pipe good-pipe)))
(defun jd-sh-re-search-pipe (regexp &optional bound noerror count)
(let ((good-pipe jd-sh-format-pipes-good-pipe-re)
(pipe-at-bol (concat "^[ \t]*" (jd-re-paren "|") " *"))
(good-pipe-at-bol "| ")
(double-pipe "[ \t]*||[ \t]*")
bop bopo eop ppss
(found (not 'true)))
(while (and (not found)
(re-search-forward regexp bound noerror))
(setq bop (match-beginning 0) bopo bop eop (match-end 0))
(setq ppss (syntax-ppss)) ; Thanks to Stefan!
(when (not 'debug)
(message "%s %s"
(save-excursion
(beginning-of-line)
(buffer-substring (point) (+ (point) 9)))
ppss))
(cond
((nth 3 ppss)) ; Inside a string
((nth 4 ppss)) ; Inside a comment
((equal (buffer-substring bop eop) good-pipe)) ; Already ok
((save-excursion
(goto-char bop)
(save-match-data
(looking-at double-pipe))) ; E.g. <cmd1> || <cmd2>
(forward-char)) ; Just skip the second pipe
((save-excursion
;; E.g.: <cmd1> \
;; | <cmd2>
(beginning-of-line)
(save-match-data
(when (and (looking-at pipe-at-bol)
(= eop (match-end 0)))
(cond
((equal (buffer-substring (match-beginning 1) eop)
good-pipe-at-bol)
t) ; Already ok
(t (setq bop (1- (match-beginning 1)))
nil)))))) ; Process it in another clause
;; E.g.: case <x> in
;; <val>|<val>)
((save-excursion
(beginning-of-line)
(save-match-data
(and (looking-at "^[^()\n]*[)]")
(<= eop (match-end 0)))))) ; Skip it
(t (setq found t)
;; Restore match data with a possibly different bop
(goto-char bop)
(if (looking-at regexp)
(goto-char (match-end 0))
(error "Something went wrong between %s and %s at %s"
bopo eop bop)))))
found))
The following file should be opened with sh-mode to get correct
comment
and string syntax.
Then M-x jd-sh-format-pipes RET
$ cat jd-sh-format-pipes-example.ksh
#!/bin/ksh
normal |command|with | some| pipes || Some should | not | be
changed
# normal |comment|with | some| pipes || None should | be changed
# r1238 | vtgk1446 (Jacques) | 2012-01-31 10:26:23
normal |string|with | pipes | sed -e 's|x|y|g' -e "s|$x|$y|g" dont
change
normal |command|with | pipes \
|some| be || changed \
| some| should | not be || changed \
| some| should | not be || changed
case $clause in
dont|change) ;;
esac
# File "jd-sh-format-pipes-example.ksh" ends here
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: complex query replace using perform-replace with replace-re-search-function
2012-06-15 13:49 complex query replace using perform-replace with replace-re-search-function jack-mac
@ 2012-06-15 14:42 ` Barry Margolin
0 siblings, 0 replies; 2+ messages in thread
From: Barry Margolin @ 2012-06-15 14:42 UTC (permalink / raw)
To: help-gnu-emacs
In article
<51b588c0-c619-4466-926e-91b26a2c7ad6@d17g2000vbv.googlegroups.com>,
jack-mac <duthen.mac@gmail.com> wrote:
> [2] Also, when reading the code of `perform-replace', I found
> something strange (NOT related to my problem, I think, since I don't
> use the `delimited-flag').
>
> It changes twice the `search-function' variable:
>
> Once is ok for me (since it takes into account the value of the
> variable `replace-re-search-function'):
>
> (let* ([snip]
> (search-function
> (if regexp-flag
> replace-re-search-function
> replace-search-function))
> [snip])
>
> but the second one (when `delimited-flag' is t) seems to erase the
> previous value of `search-function' and does NOT take into account the
> value of the variable `replace-re-search-function'):
>
> (if delimited-flag
> (setq search-function 're-search-forward
> search-string (concat "\\b"
> (if regexp-flag from-string
> (regexp-quote from-string))
> "\\b")))
>
> Is this correct?
Yes. Notice that the second one calls regexp-quote if regexp-flag was
not set. This escapes all the special regexp characters in the search
string. This allows it to use an RE search, but it will only find
literal matches.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-06-15 14:42 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-15 13:49 complex query replace using perform-replace with replace-re-search-function jack-mac
2012-06-15 14:42 ` Barry Margolin
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).