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)))))