From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: pjb@informatimago.com (Pascal J. Bourguignon) Newsgroups: gmane.emacs.help Subject: Re: check-lisp-parenthesis Date: Thu, 24 Dec 2009 17:19:52 +0100 Organization: Informatimago Message-ID: <877hscpcnr.fsf@hubble.informatimago.com> References: <87tyvg5t6d.fsf@Traian.DecebalComp> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1261672863 11984 80.91.229.12 (24 Dec 2009 16:41:03 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 24 Dec 2009 16:41:03 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Dec 24 17:40:56 2009 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1NNqkA-0002qk-Pf for geh-help-gnu-emacs@m.gmane.org; Thu, 24 Dec 2009 17:40:55 +0100 Original-Received: from localhost ([127.0.0.1]:35879 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NNqkA-0006lf-Mw for geh-help-gnu-emacs@m.gmane.org; Thu, 24 Dec 2009 11:40:54 -0500 Original-Path: news.stanford.edu!usenet.stanford.edu!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 130 Original-X-Trace: individual.net Hgw4rwRHZMhispB1h1YoWA+oYpvPt96RPj2CgvXW+gzO3LNXWe Cancel-Lock: sha1:ZDk5YWJjMGQ3ZTM4NGU1NGE2MmQ3ZWQ3N2YyNmM3OGFhODZhNGY0Yg== sha1:bMC2EFemPYBaCwQ75N0aujMb9L4= Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en X-Disabled: X-No-Archive: no User-Agent: Gnus/5.101 (Gnus v5.10.10) Emacs/22.3 (gnu/linux) Original-Xref: news.stanford.edu gnu.emacs.help:175770 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:70846 Archived-At: Cecil Westerhof writes: > I started with a function to check lisp parenthesis. What's wrong with check-parens? Your function does more than just checking parentheses. It reformats the code. You could call it beautify-parens. > Before a '(' I accept a space, a tab, a newline, a '(' and a ';'. When > there is another character the user is asked if for the '(' a space has > to be inserted. > > After a ')' I accept a space, a tab, a newline and a ')'. When there is > another character the user is asked if after the ')' a space has to be > appended. > > So far so good. > > But I also want to ask to remove white-space gaps. For example: > (message message) > )))) > should be changed -when the user wants it- to: > (message message))))) > > The gap is found, but when I say that I want to delete the gab, this is > not done. What am I doing wrong? > > The code: > (defun check-lisp-parenthesis () > (interactive) > (if (not (interactive-p)) > (message "check-lisp-parenthesis can only be called interactive") There's no reason to be so restrictive! The right way to use interactive-p is: (when (if (interactive-p) (y-or-n-p "Insert a space?") t) (insert " ")) > (save-excursion > (let ((found-gap-left 0) > (found-gap-right 0) > (found-left 0) > (found-right 0) > (inserted-gap-left 0) > (inserted-gap-right 0) > (inserted-left 0) > (inserted-right 0) > (message "")) > (goto-char (point-min)) > (while (re-search-forward "[^ \t\n(;](" nil t) > (setq found-left (1+ found-left)) > (goto-char (forward-point -1)) I would rather use: (goto-char (1+ (match-beginning 0) )) > (when (y-or-n-p "Insert a space? ") > (insert " ") > (setq inserted-left (1+ inserted-left)))) > (setq message (format "%sfound-left: %s, inserted-left: %s\n" > message > found-left inserted-left)) > (goto-char (point-min)) > (while (re-search-forward ")[^ \t\n)]" nil t) > (setq found-right (1+ found-right)) > (goto-char (forward-point -1)) > (when (y-or-n-p "Append a space? ") > (insert " ") > (setq inserted-right (1+ inserted-right)))) > (setq message (format "%sfound-right: %s, inserted-right: %s\n" > message > found-left inserted-left)) > (goto-char (point-min)) > (while (re-search-forward ")[ \t\n]+)" nil t) > (setq found-gap-right (1+ found-gap-right)) > (when (y-or-n-p (match-string 0)) ;"Delete gap? ") > (replace-match "))" nil nil nil 0) That replace-match is too far away from re-search-forward. y-or-n-p may use search and replace too. You should save the match-data with save-match-data: (while (re-search-forward ")[ \t\n]+)" nil t) (setq found-gap-right (1+ found-gap-right)) (when (save-match-data (y-or-n-p (format "Delete gap %S?" (match-string 0)))) (replace-match "))"))) And you don't need to pass the default values of optional parameters... > (setq inserted-gap-right (1+ inserted-gap-right))))) > (setq message (format "%sfound-gap-right: %s, inserted-gap-right: %s\n" > message > found-gap-right inserted-gap-right)) > (message message) > )))) It is faster to call several times message than to concatenate strings (even with format). In emacs, buffer operations are more optimized than string operations. For this reason, and also because your function doesn't take into account the rest of lisp syntax such as comments and strings, you should rewrite it using higher level buffer walking functions such as forward-sexp, looking-at, down-list, etc. However there are a lot of edge cases (eg. we wouldn't allow spaces between ' and the following sexp, or the dispatched macro character and the following sexp #2A (() ()) vs. #2A(() ()); notably, forward-sexp fails in the former case, it skips over #2A instead of skipping over #2A (() ()), but it works correctly over ' x. On the other hand, backward space fails in the ' x case, (but not for 'x)). The problem here is that the emacs lisp reader is quite different from the Common Lisp reader, and to deal correctly with Common Lisp, you would have to deal with reader macros too. -- __Pascal Bourguignon__ http://www.informatimago.com/ Litter box not here. You must have moved it again. I'll poop in the sink.