From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Arthur Miller Newsgroups: gmane.emacs.devel Subject: Re: Partial wdired (edit just filename at the point) Date: Fri, 19 Mar 2021 12:15:57 +0100 Message-ID: References: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="3024"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Fri Mar 19 12:33:32 2021 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 1lNDNj-0000fO-4x for ged-emacs-devel@m.gmane-mx.org; Fri, 19 Mar 2021 12:33:31 +0100 Original-Received: from localhost ([::1]:52020 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lNDNi-0006IY-4d for ged-emacs-devel@m.gmane-mx.org; Fri, 19 Mar 2021 07:33:30 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:35878) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lNDLP-0004pt-S7 for emacs-devel@gnu.org; Fri, 19 Mar 2021 07:31:07 -0400 Original-Received: from mail-am7eur06olkn2067.outbound.protection.outlook.com ([40.92.16.67]:22758 helo=EUR06-AM7-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lNDLL-0004tA-BC for emacs-devel@gnu.org; Fri, 19 Mar 2021 07:31:07 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RMHNsGZZzvAi+XrhPtzeOJ8g3Vo2G5ISqlzO6JwomkabSRFGwGkd1IslCZKnw2aKX8JO9n8/AJuZYrND6IKiCb5z/F2hrL/Mde7FKXKcnx7s+kofjGtb3KqVILayysG+gIR/CQtne4vYAqqhyu/Kci9et1jJfGkAKolJRsuNP/W4b/SzQ/qb224XY958NtBcCKC4iqKXzppU5EYKrKGtVz9CjhTdlqINen+eUZrDXt/+E3OFiAAjDQW5BBjjNxPaLlIT6HJsnzjJ3t2LddA6iV7Ij/EJIOaqiJ4iXQ/r/f08xCxG4vDbvQ8rgFwpZbf9R/l1ABSPd/oTukpleZ3HEg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pQ4kjRKZY9K2xDJWC8z7nAu30axnTil5Kg07IecIiJk=; b=F3GSGIDDF/mncpGjdK2WPp4Bwh7S6xzo4Dqh1EwixRVOEMXc+F5dZLQ4CiclRp3aUBxU48JVijqnmJh869muOxwJKIXcFsJOeNVCboEvrhod7akHVfWn+E1T13/pfphq1yNFnKSGNGvACnQHiECKcaau0GvOpMxkvhnNUVVrgv/uGnsIe1JRoY4So7G8hV1P1WD0QED3wCicvsz8lnyibef7lRfHx+KDgX/xLT4eoNm+klpV4cXLpaD5mH+lokgN2buxTGl52tF0RZD82O/zZTTCNXc4uOazjB7wFm3vkj/xYU7gfLxBPMz3rBzsNDLpYSG7M8z9t4xfnpWPvNXLoA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pQ4kjRKZY9K2xDJWC8z7nAu30axnTil5Kg07IecIiJk=; b=YV+4GPCNBFOD8gPcLOpZPOkUhf9fLqhIQ/VoA6yeA86kNwLpecElSzZuH3GcGDVy1ynUrBiz2ubscfBlHCjda2CdlTHraDKAK5XzaXPTmnGDzSnMXk7p1uKnvbN7MnJ6lwGc2K9X81iuanSXpcIh9ly/sCWmqiUWx0KkBoQ2+kBUX8uckwte79FEBk9/EPo0Cs0S7os4OyCCG9905PVjMhzyS5cEhkcKKDYsCOQjkneLH33LHV11Os4fQqNZhvG3JemM458YkzORIY6ZCBvGDqp5/veVRwbEQZxrHDOD1apyXZlbU6tMoj8mk9brx3Wni8KFyb6nnshgcsYpeMMi9g== Original-Received: from VI1EUR06FT063.eop-eur06.prod.protection.outlook.com (2a01:111:e400:fc37::44) by VI1EUR06HT180.eop-eur06.prod.protection.outlook.com (2a01:111:e400:fc37::469) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3955.18; Fri, 19 Mar 2021 11:15:58 +0000 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com (2a01:111:e400:fc37::42) by VI1EUR06FT063.mail.protection.outlook.com (2a01:111:e400:fc37::260) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3955.18 via Frontend Transport; Fri, 19 Mar 2021 11:15:58 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:F0ACF72596CA8489A18983A6E3BF2571F332A1C8CD63B535CCF19C2F70869FBA; UpperCasedChecksum:A7DBFE75F77BDBADBFAA1CD1B86A40B7CD1422529F1B7CA90EE34FD09595617C; SizeAsReceived:8107; Count:46 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::2103:e705:bc0c:5a8b]) by AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::2103:e705:bc0c:5a8b%6]) with mapi id 15.20.3955.023; Fri, 19 Mar 2021 11:15:58 +0000 In-Reply-To: (Stefan Monnier's message of "Thu, 18 Mar 2021 10:21:23 -0400") X-TMN: [hfTSQDIMgTHF3/ig7iaJnjTNyqhDeeLZ] X-ClientProxiedBy: AM6P193CA0115.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::20) To AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) X-Microsoft-Original-Message-ID: <87zgyz5r82.fsf@live.com> X-MS-Exchange-MessageSentRepresentingType: 1 Original-Received: from pascal.homepc (90.230.29.56) by AM6P193CA0115.EURP193.PROD.OUTLOOK.COM (2603:10a6:209:85::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3955.18 via Frontend Transport; Fri, 19 Mar 2021 11:15:57 +0000 X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 46 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: 52c4e152-8d74-4528-22bd-08d8eac85eb7 X-MS-TrafficTypeDiagnostic: VI1EUR06HT180: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 2mHqzY0tEzF269zkWYf+Qn9bl9cAcK2MPiGqFzZAQ609iuCOzFcV/9SYYtvlFnF8Q5XrXQ64+TKHwDS3vT8+CU89oohW0cugrVm7LTXDZG/v+9u/Ik5OpqQPI5GKOivFsn7ilgo+L4p+9YdE/yPPX1GqNzOoHQ8NWy0nKFLDf5f4m8IWRjwhBKrJqdBATE8qmp4eYeJX/Sbfn0+tvi2uBqX7TEogWIoGkBaRu4mHPQevlnfnQTM9R42hdMC7zP2FxlsI3uz/uM2ol3nwRVxxmx+zwOnyrwMXr1MXsqALeNXjr+UUvib9yRyd+9rEDOyOfLrtgDuVfOs+tgshBHfC87lZeDsEamBL/hYbHd0PUh+BRtx/AKe+nOaZqgmjeMhsLj0GShVZ1STZ7Z8jaKzXWg== X-MS-Exchange-AntiSpam-MessageData: r2PG8uTEWgwI5UWqCaXC3v3bvxDL1IUjFaQkSd0skw81O0TtTB5zX4vwVbPgSNf15D3hDsnFg5n30X3PKkPW3tDsEuXorpbewdNckSxizRxxd9kyVVGnYImiTQy1LoH33ipKykTISofnbOKd09+eqQ== X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-Network-Message-Id: 52c4e152-8d74-4528-22bd-08d8eac85eb7 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Mar 2021 11:15:58.0267 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-AuthSource: VI1EUR06FT063.eop-eur06.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1EUR06HT180 Received-SPF: pass client-ip=40.92.16.67; envelope-from=arthur.miller@live.com; helo=EUR06-AM7-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, MSGID_FROM_MTA_HEADER=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 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" Xref: news.gmane.io gmane.emacs.devel:266595 Archived-At: --=-=-= Content-Type: text/plain Stefan Monnier writes: >>> As you can guess from the previous comment, we should loop over BEG...END >>> to process all the lines involved. >> Can you elaborate more on this please? > > Because that's how `before-change-functions` is defined. We can try and > argue that in the specific case of wdired buffer the multiline case will > never happen (presumably because of all the `read-only` annotations) or > that it will always be "on the same line as point", but I'm pretty sure > we'll end up finding corner cases where these are not true, so I find it > easier to slap a simple while loop around the code and stop worrying > about corner cases. Ok, thanks for the explanation. > [ As a general rule, I find it easier to write code if I just rely on > the few things which I know to be true, rather than having to think of > a set of unbounded possible cases. Here, what we know to be true is > that the upcoming changes will not affect anything outside BEG...END > (at least not until `before-change-functions` are called again). ] > >> This is what I got for each char I typed in: > > Try something like > > M-: (subst-char-in-region (point-min) (point-min) ?. ?-) RET Indeed, I was only concentrated on "interactive" editing, didn't thought so much of other elisp functions. Jere is a sketch with region, however, I am not able to get editing permissions correctly. I am not really sure what is going on. Maybe you or someone else see what is wrong there. Otherwise editing names and symlinks works fine. I hope the general "setup" to loop through the region is acceptable. I have attached my working file and as a patch so take a look at whichever is easier. --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=partial-wdired.el ;;; partial-wdired.el --- -*- lexical-binding: t; -*- ;; Copyright (C) 2020 Arthur Miller ;; Author: Arthur Miller ;; Keywords: ;; 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 3 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, see . ;;; Commentary: ;;; Enable editing of file name and properties only at the point. ;;; Code: (require 'wdired) ;;;###autoload (defun wdired-change-to-wdired-mode () "Put a Dired buffer in Writable Dired (WDired) mode. \\ In WDired mode, you can edit the names of the files in the buffer, the target of the links, and the permission bits of the files. After typing \\[wdired-finish-edit], Emacs modifies the files and directories to reflect your edits. See `wdired-mode'." (interactive) (unless (derived-mode-p 'dired-mode) (error "Not a Dired buffer")) (setq-local wdired-old-content (buffer-substring (point-min) (point-max))) (setq-local wdired-old-marks (dired-remember-marks (point-min) (point-max))) (setq-local wdired-old-point (point)) (setq-local query-replace-skip-read-only t) (add-function :after-while (local 'isearch-filter-predicate) #'wdired-isearch-filter-read-only) (use-local-map wdired-mode-map) (force-mode-line-update) (setq buffer-read-only nil) (dired-unadvertise default-directory) (add-hook 'kill-buffer-hook #'wdired-check-kill-buffer nil t) (add-hook 'before-change-functions #'wdired--before-change-fn nil t) (add-hook 'after-change-functions #'wdired--restore-properties nil t) (setq major-mode 'wdired-mode) (setq mode-name "Editable Dired") (setq revert-buffer-function 'wdired-revert) (set-buffer-modified-p nil) (setq buffer-undo-list nil) (run-mode-hooks 'wdired-mode-hook) (message "%s" (substitute-command-keys "Press \\[wdired-finish-edit] when finished \ or \\[wdired-abort-changes] to abort changes"))) (defun wdired--before-change-fn (beg end) (save-excursion ;; make sure to process at least entire line (goto-char beg) (setq beg (line-beginning-position)) (goto-char end) (setq end (line-end-position)) (while (< beg end) (unless (get-text-property beg 'front-sticky) (put-text-property beg (1+ beg) 'front-sticky t) (wdired--preprocess-files beg end) (when wdired-allow-to-change-permissions (wdired--preprocess-perms beg end)) (when (fboundp 'make-symbolic-link) (wdired--preprocess-symlinks beg end))) (forward-line) (setq beg (point))) ;; is this good enough? assumes no extra white lines from dired (put-text-property (1- (point-max)) (point-max) 'read-only t))) ;; Protect the buffer so only the filenames can be changed, and put ;; properties so filenames (old and new) can be easily found. (defun wdired--preprocess-files (beg end) (save-excursion (with-silent-modifications (goto-char beg) (let ((used-F (dired-check-switches dired-actual-switches "F" "classify")) filename) (setq filename (dired-get-filename nil t)) (when (and filename (not (member (file-name-nondirectory filename) '("." "..")))) (dired-move-to-filename) ;; The rear-nonsticky property below shall ensure that text preceding ;; the filename can't be modified. (add-text-properties (1- (point)) (point) `(old-name ,filename rear-nonsticky (read-only))) (put-text-property beg (point) 'read-only t) (dired-move-to-end-of-filename t) (put-text-property (point) (1+ (point)) 'end-name t)) (when (and used-F (looking-at "[*/@|=>]$")) (forward-char)) (when (save-excursion (and (re-search-backward dired-permission-flags-regexp nil t) (looking-at "l") (search-forward " -> " (line-end-position) t))) (goto-char (line-end-position))))))) ;; Put the needed properties to allow the user to change links' targets (defun wdired--preprocess-symlinks (beg end) (save-excursion (with-silent-modifications (goto-char beg) (when (looking-at dired-re-sym) (re-search-forward " -> \\(.*\\)$") (put-text-property (1- (match-beginning 1)) (match-beginning 1) 'old-link (match-string-no-properties 1)) (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t) (unless wdired-allow-to-redirect-links (put-text-property (match-beginning 0) (match-end 1) 'read-only t)))))) (defun wdired--preprocess-perms (beg end) (save-excursion (with-silent-modifications (setq-local wdired-col-perm nil) (goto-char beg) (when (and (not (looking-at dired-re-sym)) (wdired-get-filename) (re-search-forward dired-re-perms (line-end-position) 'eol)) (let ((begin (match-beginning 0)) (end (match-end 0))) (unless wdired-col-perm (setq wdired-col-perm (- (current-column) 9))) (if (eq wdired-allow-to-change-permissions 'advanced) (progn (put-text-property begin end 'read-only nil) ;; make first permission bit writable (put-text-property (1- begin) begin 'rear-nonsticky '(read-only))) ;; avoid that keymap applies to text following permissions (add-text-properties (1+ begin) end `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap)))) (put-text-property end (1+ end) 'end-perm t) (put-text-property begin (1+ begin) 'old-perm (match-string-no-properties 0))))))) (defun wdired-change-to-dired-mode () "Change the mode back to dired." (or (eq major-mode 'wdired-mode) (error "Not a Wdired buffer")) (let ((inhibit-read-only t)) (remove-text-properties (point-min) (point-max) '(front-sticky nil rear-nonsticky nil read-only nil keymap nil))) (remove-function (local 'isearch-filter-predicate) #'wdired-isearch-filter-read-only) (use-local-map dired-mode-map) (force-mode-line-update) (setq buffer-read-only t) (setq major-mode 'dired-mode) (setq mode-name "Dired") (dired-advertise) (remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t) (remove-hook 'before-change-functions 'wdired--before-change-fn t) (remove-hook 'after-change-functions 'wdired--restore-properties t) (setq-local revert-buffer-function 'dired-revert)) (defun wdired-abort-changes () "Abort changes and return to dired mode. " (interactive) (remove-hook 'before-change-functions 'wdired--before-change-fn t) (with-silent-modifications (erase-buffer) (insert wdired-old-content) (goto-char wdired-old-point)) (wdired-change-to-dired-mode) (set-buffer-modified-p nil) (setq buffer-undo-list nil) (message "Changes aborted")) (provide 'partial-wdired) --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Lazy-wdired-preprocessing.patch >From fe606faf0bd6dedadf5e8d90183d929e2bea60c4 Mon Sep 17 00:00:00 2001 From: Arthur Miller Date: Fri, 19 Mar 2021 11:50:06 +0100 Subject: [PATCH] Lazy wdired preprocessing. --- lisp/wdired.el | 174 ++++++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/lisp/wdired.el b/lisp/wdired.el index c495d8de34..88953d3bbd 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -249,21 +249,12 @@ wdired-change-to-wdired-mode (force-mode-line-update) (setq buffer-read-only nil) (dired-unadvertise default-directory) - (add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t) - (add-hook 'after-change-functions 'wdired--restore-properties nil t) + (add-hook 'kill-buffer-hook #'wdired-check-kill-buffer nil t) + (add-hook 'before-change-functions #'wdired--before-change-fn nil t) + (add-hook 'after-change-functions #'wdired--restore-properties nil t) (setq major-mode 'wdired-mode) (setq mode-name "Editable Dired") (setq revert-buffer-function 'wdired-revert) - ;; I temp disable undo for performance: since I'm going to clear the - ;; undo list, it can save more than a 9% of time with big - ;; directories because setting properties modify the undo-list. - (buffer-disable-undo) - (wdired-preprocess-files) - (if wdired-allow-to-change-permissions - (wdired-preprocess-perms)) - (if (fboundp 'make-symbolic-link) - (wdired-preprocess-symlinks)) - (buffer-enable-undo) ; Performance hack. See above. (set-buffer-modified-p nil) (setq buffer-undo-list nil) (run-mode-hooks 'wdired-mode-hook) @@ -271,6 +262,27 @@ wdired-change-to-wdired-mode "Press \\[wdired-finish-edit] when finished \ or \\[wdired-abort-changes] to abort changes"))) +(defun wdired--before-change-fn (beg end) + (save-excursion + ;; make sure to process at least entire line + (goto-char beg) + (setq beg (line-beginning-position)) + (goto-char end) + (setq end (line-end-position)) + + (while (< beg end) + (unless (get-text-property beg 'front-sticky) + (put-text-property beg (1+ beg) 'front-sticky t) + (wdired--preprocess-files beg end) + (when wdired-allow-to-change-permissions + (wdired--preprocess-perms beg end)) + (when (fboundp 'make-symbolic-link) + (wdired--preprocess-symlinks beg end))) + (forward-line) + (setq beg (point))) + ;; is this good enough? assumes no extra white lines from dired + (put-text-property (1- (point-max)) (point-max) 'read-only t))) + (defun wdired-isearch-filter-read-only (beg end) "Skip matches that have a read-only property." (not (text-property-not-all (min beg end) (max beg end) @@ -278,35 +290,33 @@ wdired-isearch-filter-read-only ;; Protect the buffer so only the filenames can be changed, and put ;; properties so filenames (old and new) can be easily found. -(defun wdired-preprocess-files () - (put-text-property (point-min) (1+ (point-min))'front-sticky t) +(defun wdired--preprocess-files (beg end) (save-excursion - (goto-char (point-min)) - (let ((b-protection (point)) - (used-F (dired-check-switches dired-actual-switches "F" "classify")) - filename) - (while (not (eobp)) + (with-silent-modifications + (goto-char beg) + (let ((used-F (dired-check-switches + dired-actual-switches "F" "classify")) + filename) (setq filename (dired-get-filename nil t)) (when (and filename - (not (member (file-name-nondirectory filename) '("." "..")))) + (not (member + (file-name-nondirectory filename) '("." "..")))) (dired-move-to-filename) - ;; The rear-nonsticky property below shall ensure that text preceding - ;; the filename can't be modified. + ;; The rear-nonsticky property below shall ensure that + ;; text preceding the filename can't be modified. (add-text-properties - (1- (point)) (point) `(old-name ,filename rear-nonsticky (read-only))) - (put-text-property b-protection (point) 'read-only t) + (1- (point)) (point) + `(old-name ,filename rear-nonsticky (read-only))) + (put-text-property beg (point) 'read-only t) (dired-move-to-end-of-filename t) (put-text-property (point) (1+ (point)) 'end-name t)) - (when (and used-F (looking-at "[*/@|=>]$")) (forward-char)) - (when (save-excursion - (and (re-search-backward - dired-permission-flags-regexp nil t) - (looking-at "l") - (search-forward " -> " (line-end-position) t))) - (goto-char (line-end-position))) - (setq b-protection (point)) - (forward-line)) - (put-text-property b-protection (point-max) 'read-only t)))) + (when (and used-F (looking-at "[*/@|=>]$")) (forward-char)) + (when (save-excursion + (and (re-search-backward + dired-permission-flags-regexp nil t) + (looking-at "l") + (search-forward " -> " (line-end-position) t))) + (goto-char (line-end-position))))))) ;; This code is a copy of some dired-get-filename lines. (defsubst wdired-normalize-filename (file unquotep) @@ -369,7 +379,6 @@ wdired-get-filename (and file (> (length file) 0) (concat (dired-current-directory) file)))))) - (defun wdired-change-to-dired-mode () "Change the mode back to dired." (or (eq major-mode 'wdired-mode) @@ -387,14 +396,15 @@ wdired-change-to-dired-mode (setq mode-name "Dired") (dired-advertise) (remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t) + (remove-hook 'before-change-functions 'wdired--before-change-fn t) (remove-hook 'after-change-functions 'wdired--restore-properties t) (setq-local revert-buffer-function 'dired-revert)) - (defun wdired-abort-changes () - "Abort changes and return to dired mode." + "Abort changes and return to dired mode. " (interactive) - (let ((inhibit-read-only t)) + (remove-hook 'before-change-functions 'wdired--before-change-fn t) + (with-silent-modifications (erase-buffer) (insert wdired-old-content) (goto-char wdired-old-point)) @@ -710,21 +720,19 @@ wdired-previous-line (dired-move-to-filename))) ;; Put the needed properties to allow the user to change links' targets -(defun wdired-preprocess-symlinks () - (let ((inhibit-read-only t)) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (when (looking-at dired-re-sym) - (re-search-forward " -> \\(.*\\)$") - (put-text-property (1- (match-beginning 1)) - (match-beginning 1) 'old-link - (match-string-no-properties 1)) - (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t) - (unless wdired-allow-to-redirect-links - (put-text-property (match-beginning 0) - (match-end 1) 'read-only t))) - (forward-line))))) +(defun wdired--preprocess-symlinks (beg end) + (save-excursion + (with-silent-modifications + (goto-char beg) + (when (looking-at dired-re-sym) + (re-search-forward " -> \\(.*\\)$") + (put-text-property (1- (match-beginning 1)) + (match-beginning 1) 'old-link + (match-string-no-properties 1)) + (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t) + (unless wdired-allow-to-redirect-links + (put-text-property (match-beginning 0) + (match-end 1) 'read-only t)))))) (defun wdired-get-previous-link (&optional old move) "Return the next symlink target. @@ -828,36 +836,36 @@ wdired-perm-mode-map (define-key map [down-mouse-1] 'wdired-mouse-toggle-bit) map)) -;; Put a keymap property to the permission bits of the files, and store the -;; original name and permissions as a property -(defun wdired-preprocess-perms () - (let ((inhibit-read-only t)) - (setq-local wdired-col-perm nil) - (save-excursion - (goto-char (point-min)) - (while (not (eobp)) - (when (and (not (looking-at dired-re-sym)) - (wdired-get-filename) - (re-search-forward dired-re-perms (line-end-position) 'eol)) - (let ((begin (match-beginning 0)) - (end (match-end 0))) - (unless wdired-col-perm - (setq wdired-col-perm (- (current-column) 9))) - (if (eq wdired-allow-to-change-permissions 'advanced) - (progn - (put-text-property begin end 'read-only nil) - ;; make first permission bit writable - (put-text-property - (1- begin) begin 'rear-nonsticky '(read-only))) - ;; avoid that keymap applies to text following permissions - (add-text-properties - (1+ begin) end - `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap)))) - (put-text-property end (1+ end) 'end-perm t) - (put-text-property - begin (1+ begin) 'old-perm (match-string-no-properties 0)))) - (forward-line) - (beginning-of-line))))) +;; Put a keymap property to the permission bits of the files, +;; and store the original name and permissions as a property +(defun wdired--preprocess-perms (beg end) + (save-excursion + (with-silent-modifications + (setq-local wdired-col-perm nil) + (goto-char beg) + (when (and (not (looking-at dired-re-sym)) + (wdired-get-filename) + (re-search-forward dired-re-perms + (line-end-position) 'eol)) + (let ((begin (match-beginning 0)) + (end (match-end 0))) + (unless wdired-col-perm + (setq wdired-col-perm (- (current-column) 9))) + (if (eq wdired-allow-to-change-permissions 'advanced) + (progn + (put-text-property begin end 'read-only nil) + ;; make first permission bit writable + (put-text-property + (1- begin) begin + 'rear-nonsticky '(read-only))) + ;; avoid that keymap applies to text following permissions + (add-text-properties + (1+ begin) end + `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap)))) + (put-text-property end (1+ end) 'end-perm t) + (put-text-property + begin (1+ begin) + 'old-perm (match-string-no-properties 0))))))) (defun wdired-perm-allowed-in-pos (char pos) (cond -- 2.31.0 --=-=-=--