From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: phillip.lord@newcastle.ac.uk (Phillip Lord) Newsgroups: gmane.emacs.devel Subject: Re: [Request for Mentor] subst-char-in-region Date: Tue, 16 Dec 2014 11:30:15 +0000 Message-ID: <87tx0vg7co.fsf@newcastle.ac.uk> 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 1418729445 22076 80.91.229.3 (16 Dec 2014 11:30:45 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 16 Dec 2014 11:30:45 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Dec 16 12:30:36 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 1Y0qKo-0004r6-7E for ged-emacs-devel@m.gmane.org; Tue, 16 Dec 2014 12:30:34 +0100 Original-Received: from localhost ([::1]:44166 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0qKn-0005VT-N8 for ged-emacs-devel@m.gmane.org; Tue, 16 Dec 2014 06:30:33 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:59893) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0qKd-0005ST-3A for emacs-devel@gnu.org; Tue, 16 Dec 2014 06:30:27 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y0qKY-0008PY-4U for emacs-devel@gnu.org; Tue, 16 Dec 2014 06:30:23 -0500 Original-Received: from cheviot22.ncl.ac.uk ([128.240.234.22]:53706) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y0qKX-0008PD-Sk for emacs-devel@gnu.org; Tue, 16 Dec 2014 06:30:18 -0500 Original-Received: from smtpauth-vm.ncl.ac.uk ([10.8.233.129] helo=smtpauth.ncl.ac.uk) by cheviot22.ncl.ac.uk with esmtp (Exim 4.63) (envelope-from ) id 1Y0qKW-0003wk-D0; Tue, 16 Dec 2014 11:30:16 +0000 Original-Received: from jangai.ncl.ac.uk ([10.66.67.223] helo=localhost) by smtpauth.ncl.ac.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.63) (envelope-from ) id 1Y0qKV-00059x-Hw; Tue, 16 Dec 2014 11:30:15 +0000 In-Reply-To: (Stefan Monnier's message of "Mon, 15 Dec 2014 09:29:07 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 128.240.234.22 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:180195 Archived-At: Stefan Monnier writes: >> 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. Ah, okay. Can I fix it? This started of as a RFM thread, and this would give me my first commit to Emacs core, even if it is just documentation. > >> 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? Potentially, yes. For example, imagine I have a buffer like this ==== Here is some documentation ==== which maps to another buffer where the documentation is commented out ==== ;; Here is some documentation ==== How to map between "equivalent" positions in the two? I do this by counting backward from the end of the line in both buffers; this works because the two lines differ only at the beginning. With this technique, to calculate the equivalent position for the end of a change, I need to know whether there are any new lines in changed region. > 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) > ...)) That's possible, I guess, but it's still messy. The problem is I now need to analyse both the buffer and the text which has been removed. I also use the same function (to convert locations in the two buffers) outside of changes (on the post-command-hook) where there is no changed text. It adds considerable complexity the function. Still I will give it a try. For the moment, though, I have a workable solution (which is only make incremental changes after white-listing commands); I have this working with diff-mode now (nice example, incidentally, cause I found another, unrelated, bug in my code). Would you accept a commit to subst-char-in-region, though, which signals the correct values on b-c-f? As I outlined in my previous email, it can be done with no increase in computational complexity. Then I could white-list fill-paragraph (at least when emacs 25 comes out!). Phil