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: [PATCH] Lazy wdired preprocessing - BUG Date: Sat, 27 Mar 2021 19:20:04 +0100 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22006"; 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 Sat Mar 27 19:22:04 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 1lQDZT-0005a5-Hy for ged-emacs-devel@m.gmane-mx.org; Sat, 27 Mar 2021 19:22:03 +0100 Original-Received: from localhost ([::1]:37126 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lQDZS-0002VU-It for ged-emacs-devel@m.gmane-mx.org; Sat, 27 Mar 2021 14:22:02 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45306) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lQDXg-0001L0-Ga for emacs-devel@gnu.org; Sat, 27 Mar 2021 14:20:13 -0400 Original-Received: from mail-oln040092067091.outbound.protection.outlook.com ([40.92.67.91]:14561 helo=EUR02-AM5-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 1lQDXc-00061s-6U for emacs-devel@gnu.org; Sat, 27 Mar 2021 14:20:11 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JAtCyoDIcL4nyANq8GUTRmlQ2E8Jt85HUoMX44rJsGGhMl0pL4xCFkm+sxMvE3f7K0WYxSqX35gIuKiIf7/eq/L5if19dPLI4tmRApeDZc/TdpZzvMPhnfog/UwYzclzmNYC7/WR55HbqqPYlbB0I8j2XtoZWi7R5U2Mw5wA5KfENGdpaQFHosFnvInWUkuEAZIgn5sN5QJ7q8bWmiH35HoXOfuJEjp1oVZEL8VseU7BwHhZTB9kGsG4Ph3aCuLLe2KrRmPOd1pcIG/cuH4zDtSPMgpzFnSpeqEW0Rt4mdBfaWI/ixaM4dPyJL9uWV27M5YKxA0kh1rEedaxRHUZEw== 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=6CW9y4Z2hr6FAynFx4rVoYGFi8EDgx9ofRXvsJpu6Ls=; b=oaosdlcp4RxlUiT0CqBgi4U1O4cfxl0khbmvi0YQKRdGc5vIIiH6Uuhfwj+p6uIRfj6fmK8EJgLGVCv8x32Z5lahXn7XcFFFjYysSJNyXWkDy7v9J9QG1TWUWyW7TihTpotARP8JAt3MMXrWhuOgZYhXIAK4Wjf9JFvx4HYPBlsZgPmwnCbFXnWeEHSrMMLle3lu5RxCWVtWBe2c1rwiY/bM1kAwsP9YXnp1Dep9XQYn8LFIncAOtiIjOwoYbG8Av5BCLQ+WUYgXlW6OhNULgwGs6N/oCLw+5rsTWN19l1/v8E1LMIIjaBN+rXrz2cUXYkP9wVWgdiXOytgwJ3gIwA== 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=6CW9y4Z2hr6FAynFx4rVoYGFi8EDgx9ofRXvsJpu6Ls=; b=fpK7LubJsibcxbliI2k29sAklxyCwuhXntrApTL6vTqaUL2AQAVA2cKFBM246WtRkms/6U65p3D1UOBE+yv3o90b/aRkAqAlqAeieipQsyCQ2D4bP4zyjhauqxuCy7dMGrTSWFGJCKDzCggllZlAotl1rXhqN2kLlB5ErZtPbzqFDjcYhVmPudcvyLJyY+IUy9qDE9WPfuZACgCy84sWJ6GABpRV2049rROZCYMlE2n3m/NwAJ+ucNkYyl3sozq+ePb52rzoOb73gDCzZDD37i3e8p0x4Jjvf9G0MpQpn0ZrH8cYbyG/80Wo9vNSGZs90yfXnWCFuSmOBRkWY1pCXQ== Original-Received: from VE1EUR02FT056.eop-EUR02.prod.protection.outlook.com (2a01:111:e400:7e1e::41) by VE1EUR02HT071.eop-EUR02.prod.protection.outlook.com (2a01:111:e400:7e1e::351) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3977.29; Sat, 27 Mar 2021 18:20:05 +0000 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com (2a01:111:e400:7e1e::49) by VE1EUR02FT056.mail.protection.outlook.com (2a01:111:e400:7e1e::327) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3977.25 via Frontend Transport; Sat, 27 Mar 2021 18:20:05 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:234DB49F1302D90AF3B99DA886F20B1148E0B9FCC9F57F5D34AADED2B466B3A2; UpperCasedChecksum:50C1F3A39C2FA62F1022942ABD8C6FD68B67713D32E521864B86721E17ABD67D; SizeAsReceived:7611; 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.3977.032; Sat, 27 Mar 2021 18:20:05 +0000 In-Reply-To: (Stefan Monnier's message of "Sat, 27 Mar 2021 10:56:01 -0400") X-TMN: [MID80F19FFGqYjaqhl0rGjtrdYzsbQ1D] X-ClientProxiedBy: AM6P192CA0092.EURP192.PROD.OUTLOOK.COM (2603:10a6:209:8d::33) To AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) X-Microsoft-Original-Message-ID: <87a6qopigb.fsf_-_@live.com> X-MS-Exchange-MessageSentRepresentingType: 1 Original-Received: from pascal.homepc (90.230.29.56) by AM6P192CA0092.EURP192.PROD.OUTLOOK.COM (2603:10a6:209:8d::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3977.25 via Frontend Transport; Sat, 27 Mar 2021 18:20:04 +0000 X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 46 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: a8e3aa30-5985-4029-4d5a-08d8f14cf1bb X-MS-TrafficTypeDiagnostic: VE1EUR02HT071: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: CVrqnvQqR2WaebWJ6xKWgD9E3JjGJxdTsbhVYbkANYqQZkA32lKOnB6GJ+kYJRovQAWyhOHiHklz0QAfc5r3UjcyjA6GR2fTT2oSO7OV3hKIhufAZiuG/8Goyq52Gk8rCJ/y0ZAOowInqrWaiqU2niD/Xl9h94DKbml1PYxICqTj8MaAkqsQOT53kUn87Sok/35N3MsWcpziiQuJBguJIBjC4b5al98VszOFA4IIJWKdQQtZnNnWXNKfKGRsYKf1ayWLn6vNBIJtTE+o9YTRJTEsYnHfE4QIldjdM74AmNrB/WKAio+WpIWo97vo4uSEoxc8OsliKtKjpYZzPJNehh4UTD7QCRWnZ9RNeJ2bEWDidK/9aTcVaB/lwiWelfk/HyR+soKVajVcEs7+wQvKGw== X-MS-Exchange-AntiSpam-MessageData: wLkYKltzaTDhMJD0YIjjn4afWhrUiCsBjllSEFxXSIl1iOVG7gLFajYfbahRuVLxst7KtrjZ7JvulyxuPIkHmfHjmweNjvcnIwtVSVQ19ClGZRVtpvpZtosoUWqhYqQ1VWrxo1OsOcIigpRG8svG2A== X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-Network-Message-Id: a8e3aa30-5985-4029-4d5a-08d8f14cf1bb X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Mar 2021 18:20:05.1772 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-AuthSource: VE1EUR02FT056.eop-EUR02.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: VE1EUR02HT071 Received-SPF: pass client-ip=40.92.67.91; envelope-from=arthur.miller@live.com; helo=EUR02-AM5-obe.outbound.protection.outlook.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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_LOW=-0.7, 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:267112 Archived-At: Stefan Monnier writes: >>>> +(defvar wdired-perm-beg) ;; Column where the permission bits start >>>> +(defvar wdired-perm-end) ;; Column where the permission bits stop >>> I think this should use "--" in the names since they are internal variables. >> I just followed naming as already was in wdired. > > I know; fixing all the old code to use such conventions is hard, but > I try and make sure that new code at least follows those conventions ;-) > >>> `current-column` can be somewhat costly, so we should refrain from >>> calling it twice gratuitously. And here we can even take advantage of >>> the (rarely used and rarely applicable) multi-arg form of `<=` to fix >>> that "for free": >> Ok. Didn't know that (current-column) was expensive. I use now a good 'nuff >> implementation for this purpose (wdired--current-column). > > Oh, not *that* costly. Just in the sense that it's > better not to feel free to call it redundantly. > But, I think `wdired--current-column` looks fine: it completely > side-steps the question of what happens if some of the text is > currently invisible. > >> It's all yours now. I don't think I will have more time nor possibility >> to work on this, so if this one is not good enough, you will to finnish >> it on your own, or someone else could help. We are waiting a kid any >> day now, so no hobby programming for quite some time over for me :-). > > Would it be time to plug in Richard's endorsement of reproduction here? > > I pushed your change with the following additional patch on top, I have just rebuild with the new patch. I see a small bug: when entered wdired mode, and trying to do a very first change, it requires two keypresses. The first key press, I think, gets consumed in first call to wdired--self insert, so user is required to press again a key to do actual edit. I was struggling with that one so one of the reasons I pushed key event back onto the queue was that one. > + (let ((cmd (lookup-key map (this-command-keys)))) > + (call-interactively (or cmd 'self-insert-command))))))) I am not sure how that part works, so I am not attempting to suggest a change, not sure if it's that part, but I think the keypress is consumed in call to preprocess function. > > Stefan > > > commit ed6b9586d74795605debf614bd4328611e1f1c22 > Author: Stefan Monnier > Date: Sat Mar 27 10:54:10 2021 -0400 > > * lisp/wdired.el: Fix minor regressions and simplify a bit > > Use `wdired--current-column` more consistently to avoid mayhem when it > doesn't return the same result as `current-column`. > > (wdired--col-perm): Remove, redundant with `wdired--perm-beg`. > (wdired-change-to-wdired-mode): Don't error in empty directory. > (wdired--set-permission-bounds): Set `wdired--perm-beg` when we can't > find permissions. Move `wdired--perm-beg` 1 char further (like > `wdired--col-perm`). Use `wdired--current-column`. > (wdired--point-at-perms-p): Fix when `wdired--perm-beg` is nil. > (wdired--self-insert): Lookup the keymap to know command to call. > (wdired--before-change-fn): Just use `point` instead of `beg`. > Use `with-silent-modifications` here rather than in each of the > `wdired--preprocess-*` functions. > (wdired--preprocess-files): Presume we're at BOL and within > `with-silent-modifications`. Fix application of `read-only`. > (wdired-abort-changes): Don't use `with-silent-modifications` since > we're really modifying the buffer. > (wdired--preprocess-symlinks): Presume we're at BOL and within > `with-silent-modifications`. > (wdired--preprocess-perms): Presume we're at BOL and within > `with-silent-modifications`. > (wdired-set-bit): Add `char` argument. Use `wdired--current-column`. > Copy previous text properties rather than duplicating the code of > `wdired--preprocess-perms`. > (wdired-toggle-bit): Delegate to `wdired-set-bit`. > > diff --git a/lisp/wdired.el b/lisp/wdired.el > index 61272d947f..97861a4474 100644 > --- a/lisp/wdired.el > +++ b/lisp/wdired.el > @@ -189,7 +189,6 @@ wdired-mode-hook > "Hooks run when changing to WDired mode.") > > ;; Local variables (put here to avoid compilation gripes) > -(defvar wdired--col-perm) ;; Column where the permission bits start > (defvar wdired--perm-beg) ;; Column where the permission bits start > (defvar wdired--perm-end) ;; Column where the permission bits stop > (defvar wdired--old-content) > @@ -233,8 +232,6 @@ wdired-change-to-wdired-mode > (interactive) > (unless (derived-mode-p 'dired-mode) > (error "Not a Dired buffer")) > - (when (directory-empty-p (expand-file-name default-directory)) > - (error "No files to be renamed")) > (setq-local wdired--old-content > (buffer-substring (point-min) (point-max))) > (setq-local wdired--old-marks > @@ -264,49 +261,60 @@ wdired-change-to-wdired-mode > (defun wdired--set-permission-bounds () > (save-excursion > (goto-char (point-min)) > - (re-search-forward dired-re-perms nil t 1) > - (goto-char (match-beginning 0)) > - (setq-local wdired--perm-beg (current-column)) > - (goto-char (match-end 0)) > - (setq-local wdired--perm-end (current-column)))) > + (if (not (re-search-forward dired-re-perms nil t 1)) > + (progn > + (setq-local wdired--perm-beg nil) > + (setq-local wdired--perm-end nil)) > + (goto-char (match-beginning 0)) > + ;; Add 1 since the first char matched by `dired-re-perms' is the > + ;; one describing the nature of the entry (dir/symlink/...) rather > + ;; than its permissions. > + (setq-local wdired--perm-beg (1+ (wdired--current-column))) > + (goto-char (match-end 0)) > + (setq-local wdired--perm-end (wdired--current-column))))) > > (defun wdired--current-column () > (- (point) (line-beginning-position))) > > (defun wdired--point-at-perms-p () > - (<= wdired--perm-beg (wdired--current-column) wdired--perm-end)) > + (and wdired--perm-beg > + (<= wdired--perm-beg (wdired--current-column) wdired--perm-end))) > > (defun wdired--line-preprocessed-p () > (get-text-property (line-beginning-position) 'front-sticky)) > > (defun wdired--self-insert () > (interactive) > - (if (wdired--point-at-perms-p) > - (unless (wdired--line-preprocessed-p) > - (wdired--before-change-fn (line-beginning-position) (line-end-position)) > - (wdired-toggle-bit)) > - (call-interactively 'self-insert-command))) > + (if (wdired--line-preprocessed-p) > + (call-interactively 'self-insert-command) > + (wdired--before-change-fn (line-beginning-position) (line-end-position)) > + (let ((map (get-text-property (point) 'keymap))) > + (when map > + (let ((cmd (lookup-key map (this-command-keys)))) > + (call-interactively (or cmd 'self-insert-command))))))) > > (defun wdired--before-change-fn (beg end) > (save-excursion > - ;; make sure to process entire lines > - (goto-char beg) > - (setq beg (line-beginning-position)) > + ;; Make sure to process entire lines. > (goto-char end) > (setq end (line-end-position)) > + (goto-char beg) > + (forward-line 0) > > - (while (< beg end) > + (while (< (point) end) > (unless (wdired--line-preprocessed-p) > - (put-text-property beg (1+ beg) 'front-sticky t) > - (wdired--preprocess-files) > - (when wdired-allow-to-change-permissions > - (wdired--preprocess-perms)) > - (when (fboundp 'make-symbolic-link) > - (wdired--preprocess-symlinks))) > - (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))) > + (with-silent-modifications > + (put-text-property (point) (1+ (point)) 'front-sticky t) > + (wdired--preprocess-files) > + (when wdired-allow-to-change-permissions > + (wdired--preprocess-perms)) > + (when (fboundp 'make-symbolic-link) > + (wdired--preprocess-symlinks)))) > + (forward-line)) > + (when (eobp) > + (with-silent-modifications > + ;; 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." > @@ -317,28 +325,26 @@ wdired-isearch-filter-read-only > ;; properties so filenames (old and new) can be easily found. > (defun wdired--preprocess-files () > (save-excursion > - (with-silent-modifications > - (beginning-of-line) > - (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 (- (point) 1) (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))))))) > + (let ((used-F (dired-check-switches dired-actual-switches "F" "classify")) > + (beg (point)) > + (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)))))) > > ;; This code is a copy of some dired-get-filename lines. > (defsubst wdired-normalize-filename (file unquotep) > @@ -425,8 +431,8 @@ wdired-change-to-dired-mode > (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 > + (remove-hook 'before-change-functions #'wdired--before-change-fn t) > + (let ((inhibit-read-only t)) > (erase-buffer) > (insert wdired--old-content) > (goto-char wdired--old-point)) > @@ -451,7 +457,7 @@ wdired-finish-edit > (setq errors (cdr tmp-value)) > (setq changes (car tmp-value))) > (when (and wdired-allow-to-change-permissions > - (boundp 'wdired--col-perm)) ; could have been changed > + wdired--perm-beg) ; could have been changed > (setq tmp-value (wdired-do-perm-changes)) > (setq errors (+ errors (cdr tmp-value))) > (setq changes (or changes (car tmp-value)))) > @@ -744,17 +750,15 @@ wdired-previous-line > ;; Put the needed properties to allow the user to change links' targets > (defun wdired--preprocess-symlinks () > (save-excursion > - (with-silent-modifications > - (beginning-of-line) > - (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)))))) > + (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. > @@ -861,31 +865,26 @@ wdired-perm-mode-map > ;; original name and permissions as a property > (defun wdired--preprocess-perms () > (save-excursion > - (with-silent-modifications > - (setq-local wdired--col-perm nil) > - (beginning-of-line) > - (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))))))) > + (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))) > + (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 > @@ -897,39 +896,30 @@ wdired-perm-allowed-in-pos > ((memq char '(?t ?T)) (= pos 8)) > ((= char ?l) (= pos 5)))) > > -(defun wdired-set-bit () > +(defun wdired-set-bit (&optional char) > "Set a permission bit character." > - (interactive) > - (if (wdired-perm-allowed-in-pos last-command-event > - (- (current-column) wdired--col-perm)) > - (let ((new-bit (char-to-string last-command-event)) > + (interactive (list last-command-event)) > + (unless char (setq char last-command-event)) > + (if (wdired-perm-allowed-in-pos char > + (- (wdired--current-column) wdired--perm-beg)) > + (let ((new-bit (char-to-string char)) > (inhibit-read-only t) > - (pos-prop (- (point) (- (current-column) wdired--col-perm)))) > - (put-text-property 0 1 'keymap wdired-perm-mode-map new-bit) > - (put-text-property 0 1 'read-only t new-bit) > + (pos-prop (+ (line-beginning-position) wdired--perm-beg))) > + (set-text-properties 0 1 (text-properties-at (point)) new-bit) > (insert new-bit) > (delete-char 1) > - (put-text-property (1- pos-prop) pos-prop 'perm-changed t) > - (put-text-property (1- (point)) (point) 'rear-nonsticky '(keymap))) > + (put-text-property (1- pos-prop) pos-prop 'perm-changed t)) > (forward-char 1))) > > (defun wdired-toggle-bit () > "Toggle the permission bit at point." > (interactive) > - (let ((inhibit-read-only t) > - (new-bit "-") > - (pos-prop (- (point) (- (current-column) wdired--col-perm)))) > - (if (eq (char-after (point)) ?-) > - (setq new-bit > - (if (= (% (- (current-column) wdired--col-perm) 3) 0) "r" > - (if (= (% (- (current-column) wdired--col-perm) 3) 1) "w" > - "x")))) > - (put-text-property 0 1 'keymap wdired-perm-mode-map new-bit) > - (put-text-property 0 1 'read-only t new-bit) > - (insert new-bit) > - (delete-char 1) > - (put-text-property (1- pos-prop) pos-prop 'perm-changed t) > - (put-text-property (1- (point)) (point) 'rear-nonsticky '(keymap)))) > + (wdired-set-bit > + (cond > + ((not (eq (char-after (point)) ?-)) ?-) > + ((= (% (- (wdired--current-column) wdired--perm-beg) 3) 0) ?r) > + ((= (% (- (wdired--current-column) wdired--perm-beg) 3) 1) ?w) > + (t ?x)))) > > (defun wdired-mouse-toggle-bit (event) > "Toggle the permission bit that was left clicked."