From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Bob Babcock Newsgroups: gmane.emacs.help Subject: Re: can I move back to the last edit position? Date: Sun, 12 Sep 2004 21:46:24 GMT Organization: EarthLink Inc. -- http://www.EarthLink.net Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Message-ID: References: NNTP-Posting-Host: deer.gmane.org X-Trace: sea.gmane.org 1095025794 30491 80.91.229.6 (12 Sep 2004 21:49:54 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sun, 12 Sep 2004 21:49:54 +0000 (UTC) Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Sun Sep 12 23:49:41 2004 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1C6cE7-0008LF-00 for ; Sun, 12 Sep 2004 23:49:40 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1C6cJa-0007tR-S6 for geh-help-gnu-emacs@m.gmane.org; Sun, 12 Sep 2004 17:55:18 -0400 Original-Path: shelby.stanford.edu!newsfeed.stanford.edu!cyclone.bc.net!news.glorb.com!border1.nntp.dca.giganews.com!nntp.giganews.com!peer01.cox.net!cox.net!elnk-pas-nf1!newsfeed.earthlink.net!stamper.news.pas.earthlink.net!stamper.news.atl.earthlink.net!newsread2.news.atl.earthlink.net.POSTED!0053d051!not-for-mail Original-Newsgroups: gnu.emacs.help User-Agent: Xnews/06.07.17 Original-Lines: 195 Original-NNTP-Posting-Host: 67.100.203.44 Original-X-Complaints-To: abuse@earthlink.net Original-X-Trace: newsread2.news.atl.earthlink.net 1095025584 67.100.203.44 (Sun, 12 Sep 2004 14:46:24 PDT) Original-NNTP-Posting-Date: Sun, 12 Sep 2004 14:46:24 PDT Original-Xref: shelby.stanford.edu gnu.emacs.help:125294 Original-To: help-gnu-emacs@gnu.org 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: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: main.gmane.org gmane.emacs.help:20649 X-Report-Spam: http://spam.gmane.org/gmane.emacs.help:20649 rokia wrote in news:ufz5oaxes.fsf@batbug.org: > hi, can you send the goto-chg.el to me? > I cant find it. :) thanks!! It's at http://groups.google.com/groups?q=goto-chg.el&hl=en&lr=&ie=UTF-8&selm=wun0uyustv.fsf%40symsoft.se&rnum=1 I think it's short enough to post in a text group, so here it is. I hope it doesn't get broken by any line wrapping: ;;; goto-chg.el --- goto last change ;;-------------------------------------------------------------------- ;; ;; Copyright (C) 2002, David Andersson ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2 of ;; the License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be ;; useful, but WITHOUT ANY WARRANTY; without even the implied ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. See the GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public ;; License along with this program; if not, write to the Free ;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, ;; MA 02111-1307 USA ;; ;;------------------------------------------------------------------- ;; ;; Author: David Andersson ;; Created: 16 May 2002 ;; Version: 1.0 ;; ;;; Commentary: ;; ;; Goto Last Change ;; ;; Goto the point of the most recent edit in the buffer. ;; Goto the second next edit, etc, when repeated. ;; Works by looking into buffer-undo-list to find points of change. ;; ;; You would probably like to bind it to a key, for example: ;; (global-set-key [kp-decimal] 'goto-last-change) ;; ;; Works with emacs-19.29, 19.31, 20.7 and XEmacs-20.4. ;; ;;-------------------------------------------------------------------- ;; ;;todo: rename file to "gotochange.el" or "goto-chgs" ? ;;todo: rename goto-last-change -> goto-last-edit ? ;;todo: rename adjective "-last-" -> "-latest-" or "-most-recent-" ? ;;todo: there are some new, maybe useful, funcs in simple.el in emacs 20, ;; for region undo. take a look. ;;todo: add functionality to visit changed point in text order, not only ;; in backward cronological order. (naa, highlight-changes-mode does that). ;;todo: invers indication that a change has been saved or not ;;todo: rename glc-wm-default to glc-wm or something ;;todo: merge glc-wm-default and glc-wm-current, 'let' can change it temporarly ;;todo: highlight the range of text involved in the last cange? ;; ;;-------------------------------------------------------------------- ;;; Code: (defvar glc-wm-default 8 "*goto-last-change don't visit the same point twice. glc-wm-default tells how far around a visited point not to visit again.") (defvar glc-wm-current 8 "Internal for goto-last-change.\nA copy of glc-wm-default or the ARG passed to goto-last-change.") (defvar glc-probe-depth 0 "Internal for goto-last-change.\nIt is non-zero between successive goto-last-change.") ;;todo: find begin and end of line, then use it somewhere ;(defun glc-get-surrounding (pos) ; (cons (- pos glc-wm-current) (+ pos glc-wm-current))) (defun glc-adjust-pos (pos e) "Given POS, a buffer position before the edit E, compute and return the \"same\" buffer position after E happend. Exception: return nil if POS is closer than `glc-wm-current' to the edit E. \nInsertion edits before POS returns a larger value. Deletion edits before POS returns a smaller value. \nThe edit E is an entry from the `buffer-undo-list'. See for details." (cond ((atom e) ; nil==cmd boundary, or, num==changed pos pos) ((numberp (car e)) ; (beg . end)==insertion (cond ((< pos (- (car e) glc-wm-current)) pos) ((> pos (+ (car e) glc-wm-current)) (+ pos (- (cdr e) (car e)))) (t nil))) ((stringp (car e)) ; (string . pos)==deletion (cond ((< pos (- (abs (cdr e)) glc-wm-current)) pos) ((> pos (+ (abs (cdr e)) (length (car e)) glc-wm-current)) (- pos (length (car e)))) (t nil))) ((null (car e)) ; (nil prop val beg . end)==prop change (cond ((< pos (- (nth 3 e) glc-wm-current)) pos) ((> pos (+ (nthcdr 4 e) glc-wm-current)) pos) (t nil))) (t ; (marker . dist)==marker moved pos))) ;; If recursive in stead of while-loopive, it tends to fill the call stack. ;; Isn't it tail optimized? (defun glc-adjust-list (r) "R is list of edit entries in chronological order. Pick the point of the first edit entry and update that point with the second, third, etc, edit entries. Return the final updated point, or nil if the point was closer than `glc-wm-current' to some edit in R. \nR is basically a reversed slice from the buffer-undo-list." (if r ;; Get pos (let ((pos (glc-get-pos (car r)))) (setq r (cdr r)) ;; Walk back in reverse list (while (and r pos) (setq pos (glc-adjust-pos pos (car r))) (setq r (cdr r))) pos) ;;else nil)) (defun glc-get-pos (e) "If E represents an edit, return a position value in E, the position where the edit took place. Return nil if E repesents no real change. \nE is a entry in the buffer-undo-list." (cond ((numberp e) e) ; num==changed position ((atom e) nil) ; nil==command boundary ((numberp (car e)) (cdr e)) ; (beg . end)==insertion ((stringp (car e)) (abs (cdr e))) ; (string . pos)==deletion ((null (car e)) (nthcdr 4 e)) ; (nil ...)==text property change ((atom (car e)) nil) ; (t ...)==file modification time (t nil))) ; (marker ...)==marker moved (defun glc-is-positionable (e) (and (not (numberp e)) (glc-get-pos e))) (defun glc-is-filetime (e) "Return t if E indicates a buffer became \"modified\", that is, it was previously saved or unchanged. Nil otherwise." (and (listp e) (eq (car e) t))) (defun goto-last-change (arg) "Go to the point where the last edit was made in the current buffer. Repeat the command to go to the second last edit, etc. \nIt does not go to the same point twice even if there has been many edits in the same place. You can set variable `glc-wm-default' to control how close is \"the same point\". Default is 8. If ARG is non-nil it is used instead. \nThis function uses undo information. If undo is disabled, so is this." (interactive "P") (cond ((not (eq this-command last-command)) (setq glc-probe-depth 0) (setq glc-wm-current glc-wm-default))) (cond ((null buffer-undo-list) (error "Buffer has not been changed")) ((eq buffer-undo-list 't) (error "No change info (undo is disabled)"))) (if (numberp arg) (setq glc-wm-current arg)) (let (rev pos (n 0) (l buffer-undo-list) (passed-save-entry (not (buffer-modified-p)))) ;; Walk back and forth in the buffer-undo-list, each time one step deeper, ;; until we can walk back the whole list with a 'pos' taht is not coming ;; close to another edit. (while (null pos) (setq glc-probe-depth (1+ glc-probe-depth)) (if (> n 150) (message "working...")) ;; Walk forward in buffer-undo-list, glc-probe-depth steps. ;; Build reverse list along the way (while (< n glc-probe-depth) (cond ((null l) (setq glc-probe-depth 0) (error "No further change info")) ((glc-is-positionable (car l)) (setq n (1+ n)) (setq rev (cons (car l) rev))) ((or passed-save-entry (glc-is-filetime (car l))) (setq passed-save-entry t))) (setq l (cdr l))) ;; Walk back in reverse list, from older to newer edits. ;; Adjusting pos along the way. (setq pos (glc-adjust-list rev))) ;; Found a place not previously visited, in 'pos'. (if (> n 150) (message "")) ; remove message "working..." (if passed-save-entry (message "(This change is saved)")) (goto-char pos))) (provide 'goto-chg) ;;; goto-chg.el ends here