From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: jack-mac Newsgroups: gmane.emacs.help Subject: complex query replace using perform-replace with replace-re-search-function Date: Fri, 15 Jun 2012 06:49:05 -0700 (PDT) Organization: http://groups.google.com Message-ID: <51b588c0-c619-4466-926e-91b26a2c7ad6@d17g2000vbv.googlegroups.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 X-Trace: dough.gmane.org 1339768533 16567 80.91.229.3 (15 Jun 2012 13:55:33 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Fri, 15 Jun 2012 13:55:33 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Fri Jun 15 15:55:32 2012 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1SfWzq-0004uY-I4 for geh-help-gnu-emacs@m.gmane.org; Fri, 15 Jun 2012 15:55:30 +0200 Original-Received: from localhost ([::1]:47290 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SfWzq-00005i-Dt for geh-help-gnu-emacs@m.gmane.org; Fri, 15 Jun 2012 09:55:30 -0400 Original-Path: usenet.stanford.edu!postnews.google.com!d17g2000vbv.googlegroups.com!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 192 Original-NNTP-Posting-Host: 193.49.124.107 Original-X-Trace: posting.google.com 1339768249 810 127.0.0.1 (15 Jun 2012 13:50:49 GMT) Original-X-Complaints-To: groups-abuse@google.com Original-NNTP-Posting-Date: Fri, 15 Jun 2012 13:50:49 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: d17g2000vbv.googlegroups.com; posting-host=193.49.124.107; posting-account=OWLhBgoAAAD1H7ELDXVfr3-5BJaMOe1v User-Agent: G2/1.0 X-HTTP-Via: 1.1 miaouuuuuuu:3131 (squid/2.7.STABLE4) X-HTTP-UserAgent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0,gzip(gfe) Original-Xref: usenet.stanford.edu gnu.emacs.help:192849 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:85250 Archived-At: 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 " *| *" by " | " ;;; but there are some exceptions: ;;; - `good_pipe' ;;; | ;;; 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' ;;; || ;;; Don't separate a double pipe: don't change it into " | | " ;;; Don't squeeze the spaces: don't change it into " || " ;;; - `case_clause' ;;; case in ;;; |) ;;; Don't change a case clause: don't change it into " | )" ;;; - `pipe_at_beginning-of-line' ;;; \ ;;; | ;;; 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. || (forward-char)) ; Just skip the second pipe ((save-excursion ;; E.g.: \ ;; | (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 in ;; |) ((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