Function: dired-align-file
dired-align-file is a byte-compiled function defined in dired.el.gz.
Signature
(dired-align-file BEG END)
Documentation
Align the fields of a file to the ones of surrounding lines.
BEG..END is the line where the file info is located.
Source Code
;; Defined in /usr/src/emacs/lisp/dired.el.gz
(defun dired-align-file (beg end)
"Align the fields of a file to the ones of surrounding lines.
BEG..END is the line where the file info is located."
;; Some versions of ls try to adjust the size of each field so as to just
;; hold the largest element ("largest" in the current invocation, of
;; course). So when a single line is output, the size of each field is
;; just big enough for that one output. Thus when dired refreshes one
;; line, the alignment of this line w.r.t the rest is messed up because
;; the fields of that one line will generally be smaller.
;;
;; To work around this problem, we here add spaces to try and
;; re-align the fields as needed. Since this is purely aesthetic,
;; it is of utmost importance that it doesn't mess up anything like
;; `dired-move-to-filename'. To this end, we limit ourselves to
;; adding spaces only, and to only add them at places where there
;; was already at least one space. This way, as long as
;; `directory-listing-before-filename-regexp' always matches spaces
;; with "*" or "+", we know we haven't made anything worse. There
;; is one spot where the exact number of spaces is important, which
;; is just before the actual filename, so we refrain from adding
;; spaces there (and within the filename as well, of course).
(save-excursion
(let (file file-col other other-col)
;; Check that there is indeed a file, and that there is another adjacent
;; file with which to align, and that additional spaces are needed to
;; align the filenames.
(when (and (setq file (progn (goto-char beg)
(dired-move-to-filename nil end)))
(setq file-col (current-column))
(setq other
(or (and (goto-char beg)
(zerop (forward-line -1))
(dired-move-to-filename))
(and (goto-char beg)
(zerop (forward-line 1))
(dired-move-to-filename))))
(setq other-col (current-column))
(/= file other)
;; Make sure there is some work left to do.
(> other-col file-col))
;; If we've only looked at the line above, check to see if the line
;; below exists as well and if so, align with the shorter one.
(when (and (< other file)
(goto-char beg)
(zerop (forward-line 1))
(dired-move-to-filename))
(let ((alt-col (current-column)))
(when (< alt-col other-col)
(setq other-col alt-col)
(setq other (point)))))
;; Keep positions up-to-date when we insert stuff.
(if (> other file) (setq other (copy-marker other)))
(setq file (copy-marker file))
;; Main loop.
(goto-char beg)
(skip-chars-forward " ") ;Skip to the first field.
(while (and (> other-col file-col)
;; Don't touch anything just before (and after) the
;; beginning of the filename.
(> file (point)))
;; We're now just in front of a field, with a space behind us.
(let* ((curcol (current-column))
;; Nums are right-aligned.
(num-align (looking-at-p "[0-9]"))
;; Let's look at the other line, in the same column: we
;; should be either near the end of the previous field, or
;; in the space between that field and the next.
;; [ Of course, it's also possible that we're already within
;; the next field or even past it, but that's unlikely since
;; other-col > file-col. ]
;; Let's find the distance to the alignment-point (either
;; the beginning or the end of the next field, depending on
;; whether this field is left or right aligned).
(align-pt-offset
;; It is never TRT to realign the first column of
;; file's data. But the code below does attempt to
;; realign the first column if there's no whitespace
;; before it, so we force it to let the first column
;; alone.
(if (zerop curcol)
0
(save-excursion
(goto-char other)
(move-to-column curcol)
(when (looking-at
(concat
(if (eq (char-before) ?\s) " *" "[^ ]* *")
(if num-align "[0-9][^ ]*")))
(- (match-end 0) (match-beginning 0))))))
;; Now, the number of spaces to insert is align-pt-offset
;; minus the distance to the equivalent point on the
;; current line.
(spaces
(if (not num-align)
align-pt-offset
(and align-pt-offset
(save-excursion
(skip-chars-forward "^ ")
(- align-pt-offset (- (current-column) curcol)))))))
(when (and spaces (> spaces 0))
(setq file-col (+ spaces file-col))
(if (> file-col other-col)
(setq spaces (- spaces (- file-col other-col))))
(insert-char ?\s spaces 'inherit)
;; Let's just make really sure we did not mess up.
(unless (save-excursion
(eq (dired-move-to-filename) (marker-position file)))
;; Damn! We messed up: let's revert the change.
(delete-char (- spaces)))))
;; Now skip to next field.
(skip-chars-forward "^ ") (skip-chars-forward " "))
(set-marker file nil)))))