From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: [Request for Mentor] subst-char-in-region Date: Mon, 15 Dec 2014 09:29:07 -0500 Message-ID: References: <87r3w5jdow.fsf@newcastle.ac.uk> <87bnn8j4c9.fsf@newcastle.ac.uk> <87a92pyur5.fsf@newcastle.ac.uk> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1418653787 14977 80.91.229.3 (15 Dec 2014 14:29:47 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 15 Dec 2014 14:29:47 +0000 (UTC) Cc: emacs-devel@gnu.org To: phillip.lord@newcastle.ac.uk (Phillip Lord) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Dec 15 15:29:38 2014 Return-path: Envelope-to: ged-emacs-devel@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 1Y0WeW-0007zw-LZ for ged-emacs-devel@m.gmane.org; Mon, 15 Dec 2014 15:29:36 +0100 Original-Received: from localhost ([::1]:39999 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0WeW-0006I6-5v for ged-emacs-devel@m.gmane.org; Mon, 15 Dec 2014 09:29:36 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:56409) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0WeB-0006Gd-W2 for emacs-devel@gnu.org; Mon, 15 Dec 2014 09:29:23 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y0We4-0003Kt-Fe for emacs-devel@gnu.org; Mon, 15 Dec 2014 09:29:15 -0500 Original-Received: from ironport2-out.teksavvy.com ([206.248.154.181]:56239) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0We4-0003Kb-CL for emacs-devel@gnu.org; Mon, 15 Dec 2014 09:29:08 -0500 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjsPAOwQflTO+ILA/2dsb2JhbABbDoJ5g2CFWsUdBAICgSQXAQEBAQEBfIQDAQEDAVYjBQsLNBIUGA2IbgnWWQEBAQEGAQEBAR6QbweESAWLAaQugXiCAiCBGV4hgncBAQE X-IPAS-Result: AjsPAOwQflTO+ILA/2dsb2JhbABbDoJ5g2CFWsUdBAICgSQXAQEBAQEBfIQDAQEDAVYjBQsLNBIUGA2IbgnWWQEBAQEGAQEBAR6QbweESAWLAaQugXiCAiCBGV4hgncBAQE X-IronPort-AV: E=Sophos;i="5.07,502,1413259200"; d="scan'208";a="102527894" Original-Received: from 206-248-130-192.dsl.teksavvy.com (HELO ceviche.home) ([206.248.130.192]) by ironport2-out.teksavvy.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 15 Dec 2014 09:29:07 -0500 Original-Received: by ceviche.home (Postfix, from userid 20848) id 6B8D5660D3; Mon, 15 Dec 2014 09:29:07 -0500 (EST) In-Reply-To: <87a92pyur5.fsf@newcastle.ac.uk> (Phillip Lord's message of "Mon, 15 Dec 2014 12:15:10 +0000") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 206.248.154.181 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:180152 Archived-At: > Initially, because I wasn't sure that the a-c-f gave me all the > information that I needed. I thought it might do, but I was confused by > the third argument which is "length in bytes of the pre-change text". Is > "length in bytes" the same as "char position". I presumed note. Ha, nicely spotted, that's a bug in the docstring. It passes (or should anyway) the length in characters. > The difficulty is that in some cases the conversion function uses the > contents of this buffer to work out the equivalent location in that > buffer. When the b-c-f is called the two buffers are in sync, so this > conversion works. But when the a-c-f is called, the two buffers are not > in sync because we haven't percolated the change yet. So, rather than the length of the previous text, you'd need to actually know the previous text? Of course, you can use b-c-f to stash the "previous text", but indeed it won't necessarily always be exactly right, in the sense that the previous text stashed in b-c-f may not have the exact same boundaries, so you'll need to massage it a bit. The way I see it, you'll need to do something like (defvar-local my-before-change-text nil) (defun my-bcf (beg end) (setq my-before-change-text (if (null my-before-change-text) (cons beg (buffer-substring beg end)) (let* ((oldbeg (car my-before-change-text)) (oldtext (cdr my-before-change-text)) (oldend (+ oldbeg (length oldtext))) (newbeg (min beg oldbeg)) (newend (max end oldend))) (cl-assert (equal oldtext (buffer-substring oldbeg oldend))) (if (or (< newbeg oldbeg) (> newend oldend)) (cons newbeg (buffer-substring newbeg newend)) my-before-change-text))))) (add-hook 'before-change-functions #'my-bcf) And then in after-change-functions, you'll need something like (defun my-acf (beg end oldlen) (let ((oldtext (substring (cdr my-before-change-text) (- beg (car my-before-change-text)) (+ oldlen (- beg (car my-before-change-text)))))) (setq my-before-change-text nil) ...)) -- Stefan