Skip to content
20 changes: 11 additions & 9 deletions dired-collapse.el
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)))))

Expand Down
66 changes: 34 additions & 32 deletions dired-filter.el
Original file line number Diff line number Diff line change
Expand Up @@ -656,21 +656,30 @@ 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
" "
(propertize (format "[ %s%s ]" name (if collapsed " ..." ""))
'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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that you got rid of this!

(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."
Expand Down
41 changes: 39 additions & 2 deletions dired-hacks-utils.el
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,43 @@
:group 'dired
:prefix "dired-hacks-")

(defun dired-utils-fillin-invisible-property (beg end symbol)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two functions look generic enough (if we also pass the property name as arg) to be included in some other package (s.el?). We can leave them here for now but I know I've written similar code before.

They would be quite useful in Emacs itself as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I got the idea from font-lock-fillin-text-property.

"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.

Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
14 changes: 6 additions & 8 deletions dired-narrow.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))
Expand Down
9 changes: 7 additions & 2 deletions dired-subtree.el
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
Expand Down