* patch for `dired-hide-details-mode'
@ 2013-07-20 21:53 Drew Adams
0 siblings, 0 replies; only message in thread
From: Drew Adams @ 2013-07-20 21:53 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 8655 bytes --]
`dired-hide-details-mode' is essentially a reimplementation of
dired-details (by Rob Giardina). The Emacs 24 implementation of
hiding details is better (more efficient) that that of dired-details,
which is a good thing.
But the behavior is not as good for users as that available with
dired-details+. Attached is a patch that rectifies this. It gives
users more control.
These are the enhancements:
1. Users can decide whether the initial hide/show state of new Dired
buffers reflects the last chosen state for a Dired buffer. This is
decided by option `dired-hide-details-propagate'. Non-nil means
propagate the last chosen state as the initial state of a new Dired
buffer.
2. If `dired-hide-details-propagate' is nil, or if the user has not
yet explicitly changed any Dired hide/show state, then option
`dired-hide-details-initially' defines the initial state of a new
Dired buffer. IOW, it specifies what the "last" state defaults to.
In the patch the default value of each option is t, but this is open
for discussion. In my experience with dired-details+ most users
prefer to hide details by default and to let the last chosen state
update the default state.
But if we wanted to keep the traditional behavior by default then we
would just set both options to nil by default. The main point is to
give users a choice.
Note that regardless of the option values, once a user has chosen a
state for a given Dired buffer it remains in effect until s?he hits
`(' to choose a different state for _that buffer_. IOW, the options
affect only new Dired buffers, that is, buffers where the user has not
yet used `('. A user display choice for a given buffer is never
overridden.
Initialization behavior applies also to `C-x C-v RET', that is,
accepting the same directory as the alternate one to visit. This is
in keeping with `find-alternate-file' resetting other Dired settings
(markings, omissions, display order, switches, etc.). Reverting using
`g', however, keeps the user's chosen display state; i.e., unlike `C-x
C-v RET', the state is not reinitialized with `g'.
Here is an argument for having non-nil default values for both
options:
a. `dired-hide-details-propagate': Hide details by default.
Simpler, screen-space conservative. Show details on demand: `('.
b. `dired-hide-details-propagate': Propagate last view by default.
This essentially tells Emacs, "Don't do anything I haven't told you
to do. Just keep doing what I last told you to do until I tell you
otherwise."
The rest of this mail defends (b) in more detail, as it might not be
obvious why propagating the last hide/show state is the right default
behavior.
It is a simple behavior. No second-guessing by Emacs of which view
(hiding or showing details) you want for a given Dired buffer. Easy
to understand, predictable.
Q. But, you might say, why should the last chosen state for Dired
buffer FOO determine the initial state of new Dired buffer BAR, which
might be for a distant directory, one not necessarily related to FOO
in any way?
A. I know of no _better_ heuristic. Yes, there is not necessarily any
structural relationship between directories FOO and BAR -- they may be
distant or even in different file systems. And the last time you used
`(' might have been long ago, so that there might not be any
user-activity relationship between FOO and BAR either.
But in practice it is often the case that you do use FOO and BAR in
the same way wrt Dired details. And this is so whether or not they
are related structurally.
If for your current activity you interact with multiple Dired buffers
then you often want to do so in similar ways -- the particular
activity is one thing the buffers likely have in common at the moment.
More than half the time, on average. That's the bet we make if we
turn propagation on by default.
E.g., if you want to see last modification times in the current Dired
buffer and you're comparing with another one, then you likely want to
see mod times there also.
And if in some given context it is not the case that you will use BAR
and other new Dired buffers in the same way as you used FOO, then you
just hit `(' to get the right state from then on. You need hit `('
only once to get in the right state for whatever it is you are about
to do, no matter how many new buffers are involved in that activity.
Contrast that with the design choice of having the same initial state
always be imposed regardless of the context -- propagation turned off
by default. In that case you end up needing to hit `(' quite often -
once for each Dired buffer where you want a different state from the
default one.
Without propagation the default state is static, unrelated to what you
have been doing. That too is simple behavior, but not as useful, IMO.
Assume for a moment that propagation by default is good. Now try as a
user to get that effect with propagation turned off. That is, try to
get the next new Dired buffer to have the same state as the last one
you set explicitly. Not so easy.
You end up hitting `(' all over the place in that scenario because
Emacs eagerly imposes the same static default state, over and over.
You should need to hit `(' only when you really want to change the way
you look at Dired listings.
Of course, if the state you want for each buffer happens to be the
static default one, no problem. But if the state you want for the
next six Dired buffers is the opposite of that default state, then you
will hit `(' six times.
Now consider the opposite: propagation is turned on, but you instead
want each new Dired buffer to open with the same (static) default
display. How to get by?
With propagation turned on, whether the desired state for new buffers
is hiding or showing details is unimportant, and so is the value of
option `dired-hide-details-initially'. Why? Because it is trivial to
set the state the way you want it once and for all, before opening any
new Dired buffers. A single press of `(' is all you need.
IOW, with propagation turned on, if you in fact want the
static-default behavior at any time, and if the current display is not
what you want, then you hit `(' -- just once. Never again after that.
And of course you can customize the options to give you the static
default you want from the outset. The two hypothetical
opposite-design-from-what-you-want scenarios are just to show that
turning propagation on by default provides more flexibility for users
and more useful behavior generally.
The last-used hide/show state is the one most likely to be what you
want at any time. It is the one you have been using most recently
while interacting with Dired. This is what makes it likely to be
relevant to future Dired buffers.
The last-used state is typically your most-used state, and it is
probably also your preferred default state. There is no guarantee
that it is what you want for any given new Dired buffer, but it has a
better chance of being appropriate.
And if it is wrong at any time, just toggle.
My own preferred state hides details. But if for some Dired activity
I want to see details, then I hit `(' once for the duration -
regardless of how many new directories I'm interested in, as long as
the activity applies to them. And when I'm done needing to see
details I hit `(' once and I'm back to being spared the extra noise
for new buffers. Trivial, and not confusing or annoying.
The point is that you can easily change the current state that gets
propagated by hitting `('. And most of the time you need not hit it
at all. By definition -- because you would have already hit `(' if
you were not yet in the right state.
Worst-case scenario for propagated-state behavior is visiting multiple
new Dired buffers in an order that exactly alternates hidden/shown.
There is no special reason anyone would do that. I have never done
that or seen anyone do that.
But even if you did manifest that worst-case behavior, it is no worse
than the current vanilla Emacs behavior, which always starts from the
same (static default) state, which shows details. There, you have
definitely got a good chance that that starting state is not the one
you want at any given time. It is equivalent to the rigid worst-case
behavior for propagation.
Not propagating the last state gives us built-in worst-case behavior.
Some users might prefer it, and they can easily obtain it. But it
is not a good default behavior.
[-- Attachment #2: dired-2013-07-20.patch --]
[-- Type: application/octet-stream, Size: 4142 bytes --]
diff -cw dired.el dired-patched-2013-07-20.el
*** dired.el Sat Jul 20 12:10:57 2013
--- dired-patched-2013-07-20.el Sat Jul 20 12:18:28 2013
***************
*** 249,254 ****
--- 249,266 ----
:version "24.4"
:group 'dired)
+ (defcustom dired-hide-details-initially t
+ "Non-nil means hide details in Dired from the outset."
+ :type 'boolean :version "24.4" :group 'dired)
+
+ (defcustom dired-hide-details-propagate t
+ "Non-nil means display the next Dired buffer the same way as the last.
+ The last `dired-hide-details-mode' value set is used by the next Dired
+ buffer created."
+ :type 'boolean :version "24.4" :group 'dired)
+
+
+
;; Internal variables
(defvar dired-marker-char ?* ; the answer is 42
***************
*** 297,302 ****
--- 309,322 ----
(put 'dired-actual-switches 'safe-local-variable 'dired-safe-switches-p)
+ (defvar dired-hide-details-last-state dired-hide-details-initially
+ "Last `dired-hide-details-mode' value.
+ Initialized to the value of option `dired-hide-details-initially'.")
+
+ (defvar dired-hide-details-toggled nil
+ "Non-nil means you have already toggled hiding details in this buffer.")
+ (make-variable-buffer-local 'dired-hide-details-toggled)
+
(defvar dired-re-inode-size "[0-9 \t]*"
"Regexp for optional initial inode and file size as made by `ls -i -s'.")
***************
*** 2265,2286 ****
(substring file (match-end 0))
file))
\f
! ;;; Minor mode for hiding details
;;;###autoload
(define-minor-mode dired-hide-details-mode
"Hide details in Dired mode."
:group 'dired
! (unless (derived-mode-p 'dired-mode)
! (error "Not a Dired buffer"))
(dired-hide-details-update-invisibility-spec)
(if dired-hide-details-mode
! (add-hook 'wdired-mode-hook
! 'dired-hide-details-update-invisibility-spec
! nil
! t)
! (remove-hook 'wdired-mode-hook
! 'dired-hide-details-update-invisibility-spec
! t)))
(defun dired-hide-details-update-invisibility-spec ()
(funcall (if dired-hide-details-mode
--- 2285,2309 ----
(substring file (match-end 0))
file))
\f
! ;;; Minor modes for hiding details
!
! ;;;###autoload
! (define-globalized-minor-mode global-dired-hide-details-mode dired-hide-details-mode
! dired-hide-details-if-dired)
!
;;;###autoload
(define-minor-mode dired-hide-details-mode
"Hide details in Dired mode."
+ (and dired-hide-details-propagate dired-hide-details-last-state)
:group 'dired
! (unless (derived-mode-p 'dired-mode) (error "Not a Dired buffer"))
(dired-hide-details-update-invisibility-spec)
+ (setq dired-hide-details-toggled t)
+ (when dired-hide-details-propagate
+ (setq dired-hide-details-last-state dired-hide-details-mode))
(if dired-hide-details-mode
! (add-hook 'wdired-mode-hook 'dired-hide-details-update-invisibility-spec nil t)
! (remove-hook 'wdired-mode-hook 'dired-hide-details-update-invisibility-spec t)))
(defun dired-hide-details-update-invisibility-spec ()
(funcall (if dired-hide-details-mode
***************
*** 2299,2304 ****
--- 2322,2342 ----
'remove-from-invisibility-spec)
'dired-hide-details-link))
+ (defun dired-hide/show-details ()
+ "Hide/show details according to user options.
+ If `dired-hide-details-propagate' is non-nil and details have
+ never been hidden in the buffer, then hide/show according to your last
+ hide/show choice in any other Dired buffer or, if no last choice,
+ according to option `dired-hide-details-initially'."
+ (unless (or dired-hide-details-toggled ; No op if hide/show already set.
+ (buffer-narrowed-p)) ; No-op when showing just newly copied file etc.
+ (cond (dired-hide-details-propagate
+ (dired-hide-details-mode (if dired-hide-details-last-state 1 -1)))
+ (dired-hide-details-initially
+ (dired-hide-details-mode 1)))))
+
+ (add-hook 'dired-after-readin-hook #'dired-hide/show-details)
+ \f
;;; Functions for finding the file name in a dired buffer line.
(defvar dired-permission-flags-regexp
Diff finished. Sat Jul 20 12:20:35 2013
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2013-07-20 21:53 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-20 21:53 patch for `dired-hide-details-mode' Drew Adams
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).