diff --git a/dired-collapse.el b/dired-collapse.el index c77ed20..1ee3e03 100644 --- a/dired-collapse.el +++ b/dired-collapse.el @@ -92,14 +92,17 @@ (defun dired-collapse--replace-file (file) "Replace file on the current line with FILE." - (delete-region (line-beginning-position) (1+ (line-end-position))) - (insert " ") - (insert-directory file dired-listing-switches nil nil) - (forward-line -1) - (dired-align-file (line-beginning-position) (1+ (line-end-position))) - (when (file-remote-p (dired-utils-get-filename)) - (while (search-forward (dired-current-directory) (line-end-position) t) - (replace-match "")))) + (let ((invis (get-text-property (save-excursion (dired-move-to-filename)) 'invisible))) + (delete-region (line-beginning-position) (1+ (line-end-position))) + (insert " ") + (insert-directory file dired-listing-switches nil nil) + (forward-line -1) + (dired-align-file (line-beginning-position) (1+ (line-end-position))) + (dired-insert-set-properties (line-beginning-position) (line-end-position)) + (dired-utils-fillin-invisible-property (line-beginning-position) (1+ (line-end-position)) invis) + (when (file-remote-p (dired-utils-get-filename)) + (while (search-forward (dired-current-directory) (line-end-position) t) + (replace-match ""))))) (defun dired-collapse--create-ov (&optional to-eol) "Create the shadow overlay which marks the collapsed path. @@ -145,7 +148,6 @@ filename (for example when the final directory is empty)." (when (string-match-p "/" path) (let ((default-directory (dired-current-directory))) (dired-collapse--replace-file path)) - (dired-insert-set-properties (line-beginning-position) (line-end-position)) (dired-collapse--create-ov (= 0 (length files))))))) (forward-line 1))))) diff --git a/dired-filter.el b/dired-filter.el index edc5d38..86cf1b7 100644 --- a/dired-filter.el +++ b/dired-filter.el @@ -656,11 +656,13 @@ The matched lines are returned as a string." map) "Keymap used when over a group header.") -(defun dired-filter-group--make-header (name &optional collapsed) - "Make group header named by NAME. +(defun dired-filter-group--make-header (name invis &optional collapsed) + "Make a group header named by NAME. -Optional argument COLLAPSED specifies if the header is collapsed -by default." +INVIS is the symbol that will be added/removed to the +`buffer-invisibility-spec' to collapse the header. Optional +argument COLLAPSED specifies if the header is collapsed by +default." (concat (propertize (concat " " @@ -668,9 +670,16 @@ by default." 'font-lock-face 'dired-filter-group-header)) 'keymap dired-filter-group-header-map 'dired-filter-group-collapsed collapsed - 'dired-filter-group-header name) + 'dired-filter-group-header name + 'dired-filter-group-invisible-property invis) "\n")) +(defun dired-filter-group--invisible-symbol (name id) + "Return a symbol for the invisible property of filter group named NAME. +ID is a unique identifier for the group to distinguish multiple +groups with the same NAME in the buffer." + (intern (format "%s-%s" name id))) + (defun dired-filter-group--apply (filter-group) "Apply FILTER-GROUP." (when (and dired-filter-group-mode @@ -699,13 +708,22 @@ by default." (when (/= (length group) 0) (push (cons name group) name-group-alist)))) (--each name-group-alist - (-let (((name . group) it)) - (insert (dired-filter-group--make-header name) group))) + (-let* (((name . group) it) + (invis (dired-filter-group--invisible-symbol name (point)))) + (insert (dired-filter-group--make-header name invis)) + (let ((beg (point))) + (insert group) + (dired-utils-fillin-invisible-property beg (point) invis)))) (when (and (text-property-any (save-excursion (dired-next-subdir 0)) (point-max) 'font-lock-face 'dired-filter-group-header) (save-excursion (backward-char 1) (dired-hacks-next-file))) - (insert (dired-filter-group--make-header "Default"))))) + (let ((invis (dired-filter-group--invisible-symbol "Default" (point)))) + (insert (dired-filter-group--make-header "Default" invis)) + (let ((beg (point))) + (while (dired-utils-get-filename) + (forward-line)) + (dired-utils-fillin-invisible-property beg (point) invis)))))) (setq next (ignore-errors (dired-next-subdir 1)))))) (when (featurep 'dired-details) (dired-details-delete-overlays) @@ -714,33 +732,17 @@ by default." (defun dired-filter-group-toggle-header () "Collapse or expand a filter group." (interactive) - (let ((inhibit-read-only t) - (name (save-excursion - (beginning-of-line) - (get-text-property (point) 'dired-filter-group-header))) - (collapsed (save-excursion - (beginning-of-line) - (get-text-property (point) 'dired-filter-group-collapsed))) - (beg (save-excursion - (forward-line 1) - (point))) - (end (save-excursion - (end-of-line) - (min (or (next-single-property-change (point) 'dired-filter-group-header) - (point-max)) - (dired-subdir-max))))) + (let* ((inhibit-read-only t) + (pos (line-beginning-position)) + (name (get-text-property pos 'dired-filter-group-header)) + (collapsed (get-text-property pos 'dired-filter-group-collapsed)) + (invis (get-text-property pos 'dired-filter-group-invisible-property))) (if collapsed - (alter-text-property - beg end 'invisible - (lambda (prop) - (delete 'dired-filter-group-toggle-header (-list prop)))) - (alter-text-property - beg end 'invisible - (lambda (prop) - (cons 'dired-filter-group-toggle-header (-list prop))))) + (remove-from-invisibility-spec invis) + (add-to-invisibility-spec invis)) (save-excursion (-let [(beg . end) (bounds-of-thing-at-point 'line)] (delete-region beg end)) - (insert (dired-filter-group--make-header name (not collapsed)))))) + (insert (dired-filter-group--make-header name invis (not collapsed)))))) (defun dired-filter-group-forward-drawer (&optional count) "Move point forward by COUNT drawers." diff --git a/dired-hacks-utils.el b/dired-hacks-utils.el index cbed262..3fe8e85 100644 --- a/dired-hacks-utils.el +++ b/dired-hacks-utils.el @@ -44,6 +44,43 @@ :group 'dired :prefix "dired-hacks-") +(defun dired-utils-fillin-invisible-property (beg end symbol) + "Put SYMBOL as the invisible text property for the region between BEG and END. + +Respect the current value of the invisible property for text in +the region." + (let ((next (next-single-property-change beg 'invisible nil end)) + (invis nil)) + (while (/= beg end) + (setq invis (get-text-property beg 'invisible)) + (cond + ((null invis) + (put-text-property beg next 'invisible symbol)) + ((and (symbolp invis) (not (eq invis symbol))) + (put-text-property beg next 'invisible (list invis symbol))) + ((and (listp invis) (not (memq symbol invis))) + (put-text-property beg next 'invisible (cons symbol invis)))) + (setq beg next + next (next-single-property-change beg 'invisible nil end))))) + +(defun dired-utils-remove-invisible-property (beg end symbol) + "Remove SYMBOL from the invisible property for the region between BEG and END. + +Respect the value of the invisible property for text in the +region." + (let ((next (next-single-property-change beg 'invisible nil end)) + (invis nil)) + (while (/= beg end) + (setq invis (get-text-property beg 'invisible)) + (cond + ((null invis)) + ((and (symbolp invis) (eq invis symbol)) + (put-text-property beg next 'invisible nil)) + ((listp invis) + (put-text-property beg next 'invisible (delq symbol invis)))) + (setq beg next + next (next-single-property-change beg 'invisible nil end))))) + (defun dired-utils-get-filename (&optional localp) "Like `dired-get-filename' but never signal an error. @@ -161,7 +198,7 @@ line." (--dotimes arg (forward-line) (while (and (or (not (dired-utils-is-file-p)) - (get-text-property (point) 'invisible)) + (invisible-p (point))) (= (forward-line) 0)))) (if (not (= (point) (point-max))) (dired-move-to-filename) @@ -181,7 +218,7 @@ line." (--dotimes arg (forward-line -1) (while (and (or (not (dired-utils-is-file-p)) - (get-text-property (point) 'invisible)) + (invisible-p (point))) (= (forward-line -1) 0)))) (if (not (= (point) (point-min))) (dired-move-to-filename) diff --git a/dired-narrow.el b/dired-narrow.el index 290650b..3bba4ce 100644 --- a/dired-narrow.el +++ b/dired-narrow.el @@ -161,10 +161,11 @@ when `dired-narrow-exit-when-one-left' and `dired-narrow-enable-blinking' are tr (if (funcall dired-narrow-filter-function filter) (progn (setq visible-files-cnt (1+ visible-files-cnt)) - (when (fboundp 'dired-insert-set-properties) - (dired-insert-set-properties (line-beginning-position) (1+ (line-end-position))))) + (dired-utils-remove-invisible-property + (line-beginning-position) (1+ (line-end-position)) :dired-narrow)) (put-text-property (line-beginning-position) (1+ (line-end-position)) :dired-narrow t) - (put-text-property (line-beginning-position) (1+ (line-end-position)) 'invisible :dired-narrow)))) + (dired-utils-fillin-invisible-property + (line-beginning-position) (1+ (line-end-position)) :dired-narrow)))) (unless (dired-hacks-next-file) (dired-hacks-previous-file)) (unless (dired-utils-get-filename) @@ -174,11 +175,8 @@ when `dired-narrow-exit-when-one-left' and `dired-narrow-enable-blinking' are tr (defun dired-narrow--restore () "Restore the invisible files of the current buffer." (let ((inhibit-read-only t)) - (remove-list-of-text-properties (point-min) (point-max) - '(invisible :dired-narrow)) - (when (fboundp 'dired-insert-set-properties) - (dired-insert-set-properties (point-min) (point-max))))) - + (dired-utils-remove-invisible-property + (point-min) (point-max) :dired-narrow))) (defun dired-narrow--blink-current-file () (let* ((beg (line-beginning-position)) diff --git a/dired-subtree.el b/dired-subtree.el index 75a1709..56a9dce 100644 --- a/dired-subtree.el +++ b/dired-subtree.el @@ -262,8 +262,13 @@ If no SUBTREES are specified, use `dired-subtree-overlays'." "After inserting the subtree, setup dired-details/dired-hide-details-mode." (if (fboundp 'dired-insert-set-properties) (let ((inhibit-read-only t) - (ov (dired-subtree--get-ov))) - (dired-insert-set-properties (overlay-start ov) (overlay-end ov))) + (ov (dired-subtree--get-ov)) + (invis (when (bound-and-true-p dired-filter-group-mode) + (save-excursion + (dired-filter-group-backward-drawer 1) + (get-text-property (point) 'dired-filter-group-invisible-property))))) + (dired-insert-set-properties (overlay-start ov) (overlay-end ov)) + (dired-utils-fillin-invisible-property (1- (overlay-start ov)) (overlay-end ov) invis)) (when (featurep 'dired-details) (dired-details-delete-overlays) (dired-details-activate))))