From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Jean Louis Newsgroups: gmane.emacs.devel Subject: Re: A feature to go to last edit locations Date: Mon, 13 Feb 2023 22:24:02 +0300 Message-ID: References: <972bedcc-37c9-5180-ac41-90e25d854a63@yandex.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="24899"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mutt/2.2.9+54 (af2080d) (2022-11-21) Cc: Daniel =?utf-8?Q?Mart=C3=ADn?= , emacs-devel@gnu.org To: Dmitry Gutov Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Feb 13 20:26:51 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pReTT-0006Ie-F3 for ged-emacs-devel@m.gmane-mx.org; Mon, 13 Feb 2023 20:26:51 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pReSe-0005u8-6u; Mon, 13 Feb 2023 14:26:00 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pReSY-0005tn-9X for emacs-devel@gnu.org; Mon, 13 Feb 2023 14:25:55 -0500 Original-Received: from stw1.rcdrun.com ([217.170.207.13]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pReSW-0007La-AZ for emacs-devel@gnu.org; Mon, 13 Feb 2023 14:25:54 -0500 Original-Received: from localhost ([::ffff:197.239.6.48]) (AUTH: PLAIN admin, TLS: TLS1.3,256bits,ECDHE_RSA_AES_256_GCM_SHA384) by stw1.rcdrun.com with ESMTPSA id 0000000000103957.0000000063EA8EBD.000013D0; Mon, 13 Feb 2023 12:25:48 -0700 Mail-Followup-To: Dmitry Gutov , Daniel =?utf-8?Q?Mart=C3=ADn?= , emacs-devel@gnu.org Content-Disposition: inline In-Reply-To: <972bedcc-37c9-5180-ac41-90e25d854a63@yandex.ru> Received-SPF: pass client-ip=217.170.207.13; envelope-from=bugs@gnu.support; helo=stw1.rcdrun.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_SBL=0.141, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 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-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:303226 Archived-At: * Dmitry Gutov [2023-02-12 21:09]: > On 12/02/2023 19:41, Daniel Martín wrote: > > What do you think? Third-party packages like goto-last-change.el [2] or > > session.el [3] (see session-jump-to-last-change) implement this feature > > in a per-buffer basis, but I wonder if we could do better and implement > > something that works across buffers. > > I agree this kind of feature should work across buffers (and that's my main > criticism of the global/local marks feature already). I was reading, thanks, it inspired me. But Eli said something important, why go somewhere back randomly, but better going where user marked it to need it. Now I get it with single click: S-C- to record point and then S-C- and to go to previous or next one. It is using database, but it may serve for brainstorming. I also try to use database tables to switch to them, instead of buffers with files. Emacs has SQLite built-in, this way of work could be used in future, or package could easily be made. It would persist over sessions without problems. And I could make a switch that instead of moving over global points, and buffers, to move only in single buffer. (defvar rcd-db-emacs-point-id nil "Last Emacs point ID where user jumped to.") (defun rcd-db-emacs-point-next () "Go to next Emacs point." (interactive) (let ((next (rcd-db-emacs-point-to-go "next"))) next)) (defun rcd-db-emacs-point-previous () "Go to previous Emacs point." (interactive) (let ((previous (rcd-db-emacs-point-to-go "previous"))) previous)) (defun rcd-db-emacs-point-go-to (id) "Go to Emacs point ID." (let ((point (rcd-db-table-id-hash "emacspoints" id cf-db))) (when (hash-table-keys point) (let ((buffer-name (gethash "emacspoints_buffername" point)) (file-name (gethash "emacspoints_bufferfilename" point)) (table (gethash "emacspoints_table" point)) (column (gethash "emacspoints_column" point)) (table-id (gethash "emacspoints_tableid" point)) (point (gethash "emacspoints_point" point))) (cond ((and buffer-name (buffer-live-p (get-buffer buffer-name)) (not file-name) (not table)) (switch-to-buffer buffer-name) (goto-char point)) ((and buffer-name file-name (buffer-live-p (get-buffer buffer-name)) (not table)) (switch-to-buffer buffer-name) (goto-char point)) ((and buffer-name file-name (not (buffer-live-p (get-buffer buffer-name))) (not table)) (find-file file-name) (goto-char point)) ((and buffer-name table column table-id (buffer-live-p (get-buffer buffer-name))) (switch-to-buffer buffer-name) (goto-char point)) ((and buffer-name table column table-id (not (buffer-live-p (get-buffer buffer-name)))) (hyperscope-edit-with-mode table-id column) (switch-to-buffer buffer-name) (goto-char point)) (t (rcd-message "Point ID %s not found" id))))))) (keymap-global-set "M-s-" #'rcd-db-emacs-point-previous) (keymap-global-set "M-s-" #'rcd-db-emacs-point-next) (keymap-global-set "M-s-" #'rcd-db-emacs-point-record) (defun rcd-db-emacs-point-to-go (direction) "Return next Emacs point to go by using DIRECTION. DIRECTION is string that may be \"previous\" or \"next\"." (when (string-match "^next$\\|^previous$" direction) (let ((last (rcd-sql-first "SELECT emacspoints_id FROM emacspoints ORDER BY emacspoints_id DESC LIMIT 1" cf-db)) (first (rcd-sql-first "SELECT emacspoints_id FROM emacspoints ORDER BY emacspoints_id ASC LIMIT 1" cf-db)) (message (format "No %s point found" direction)) (next (when (integerp rcd-db-emacs-point-id) (rcd-sql-first "SELECT emacspoints_id FROM emacspoints WHERE emacspoints_id > $1 ORDER BY emacspoints_id ASC LIMIT 1" cf-db rcd-db-emacs-point-id))) (previous (when (integerp rcd-db-emacs-point-id) (rcd-sql-first "SELECT emacspoints_id FROM emacspoints WHERE emacspoints_id < $1 ORDER BY emacspoints_id DESC LIMIT 1" cf-db rcd-db-emacs-point-id)))) (cond ((and (string= direction "previous") rcd-db-emacs-point-id previous) (rcd-db-emacs-point-go-to (setq rcd-db-emacs-point-id previous))) ((and (string= direction "previous") rcd-db-emacs-point-id (null previous) last) (rcd-db-emacs-point-go-to (setq rcd-db-emacs-point-id last))) ((and (string= direction "previous") rcd-db-emacs-point-id (null previous) (null last)) (rcd-message message)) ((and (string= direction "next") rcd-db-emacs-point-id next) (rcd-db-emacs-point-go-to (setq rcd-db-emacs-point-id next))) ((and (string= direction "next") rcd-db-emacs-point-id (null next) first) (rcd-db-emacs-point-go-to (setq rcd-db-emacs-point-id first))) (t (rcd-message message)))))) (defun rcd-db-emacs-point-record () "Record Emacs point in the database." (interactive) (let* ((buffer-name (buffer-name)) (file-name (buffer-file-name)) (table rcd-db-current-table) (column rcd-db-current-column) (table-id rcd-db-current-table-id) (db-handle rcd-db-current-database-handle) (db-name (cond ((and db-handle (rcd-sql-first "SELECT current_database()" db-handle)) (t nil)))) (point (point)) (name (cond (current-prefix-arg (rcd-ask-get "Point name: ")) (table (format "DB: %s, table: %s, column: %s, ID: %s" db-name table column table-id)) ((not file-name) (format "Buffer: %s" buffer-name)) (t (format "File: %s" file-name)))) (description (cond (current-prefix-arg (sql-escape-string (rcd-ask "Point description: "))) (t "NULL"))) (table-uuid (when (and table-id (rcd-db-uuid-by-id table table-id cf-db)) (rcd-db-uuid-by-id table table-id cf-db)))) (rcd-sql-first (format "INSERT INTO emacspoints (emacspoints_name, emacspoints_description, emacspoints_buffername, emacspoints_bufferfilename, emacspoints_dbname, emacspoints_table, emacspoints_column, emacspoints_tableid, emacspoints_tableuuid, emacspoints_point) VALUES ($1, %s, $2, %s, %s, %s, %s, %s, %s, $3) ON CONFLICT DO NOTHING RETURNING emacspoints_id" description (sql-escape-string-or-null file-name) (sql-escape-string-or-null db-name) (sql-escape-string-or-null table) (sql-escape-string-or-null column) (or table-id "NULL") (sql-escape-string-or-null table-uuid)) cf-db name buffer-name point))) -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/