From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Stefan Newsgroups: gmane.emacs.devel,gmane.comp.gnu.core-utils.bugs Subject: Re: dired-move-to-filename-regexp Date: Sat, 25 Sep 2004 15:08:04 -0400 Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Message-ID: References: <414D38E0.4080300@math.ku.dk> <7w8yb6wty1.fsf@sic.twinsun.com> <7wr7oxzgs4.fsf@sic.twinsun.com> <20040920050006.GA7888@fencepost> <876566decg.fsf@penguin.cs.ucla.edu> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1096139330 6422 80.91.229.6 (25 Sep 2004 19:08:50 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sat, 25 Sep 2004 19:08:50 +0000 (UTC) Cc: eggert@CS.UCLA.EDU, bug-coreutils@gnu.org, emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Sep 25 21:08:31 2004 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1CBHuJ-0000y7-00 for ; Sat, 25 Sep 2004 21:08:31 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1CBI0R-0000dx-UQ for ged-emacs-devel@m.gmane.org; Sat, 25 Sep 2004 15:14:51 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1CBI0K-0000dH-Os for emacs-devel@gnu.org; Sat, 25 Sep 2004 15:14:44 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1CBI0K-0000d1-39 for emacs-devel@gnu.org; Sat, 25 Sep 2004 15:14:44 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1CBI0G-0000cT-Tq; Sat, 25 Sep 2004 15:14:40 -0400 Original-Received: from [206.47.199.163] (helo=simmts5-srv.bellnexxia.net) by monty-python.gnu.org with esmtp (Exim 4.34) id 1CBHtu-0008Jp-0T; Sat, 25 Sep 2004 15:08:06 -0400 Original-Received: from empanada.home ([67.71.24.92]) by simmts5-srv.bellnexxia.net (InterMail vM.5.01.06.10 201-253-122-130-110-20040306) with ESMTP id <20040925190554.BDOB1635.simmts5-srv.bellnexxia.net@empanada.home>; Sat, 25 Sep 2004 15:05:54 -0400 Original-Received: by empanada.home (Postfix, from userid 502) id A1A413040F0; Sat, 25 Sep 2004 15:08:05 -0400 (EDT) Original-To: rms@gnu.org In-Reply-To: (Richard Stallman's message of "Sat, 25 Sep 2004 11:36:15 -0400") User-Agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3.50 (darwin) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:27567 gmane.comp.gnu.core-utils.bugs:2935 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:27567 >> That would be rather unreliable, since it would need to figure out the >> number of spaces between fields in both the new output and the old >> buffer. The gains that we got from --dired would be lost. >> I won't accept this approach. > Of course, the filename part would be determined just as it is now (using > the --dired data if available, for example). > Ok, you're right about that part. When using --dired, we would > still reliably find the filename. But finding where to insert extra > spaces would not be entirely reliable, just as finding the file name > was not entirely reliable in the past. See below a sample patch that "worked for me". Indeed, finding the places where to insert spaces is not entirely reliable, but adding spaces as is done below shouldn't make things worse. There are 2 cases I can think of where the code could pose problem: 1 - the dired-move-to-filename-regexp needs a specific number of spaces at some spot. This is a rare problem but can happen when we don't use --dired. Examples are the nunber of spaces between day and month, which is typically either one or 2 spaces, never more. 2 - If dired-move-to-filename initially gets it wrong (and goes too far), we may end up adding spaces in the actual file name. This is not as bad as it sounds: - It's extremely unlikely because we only add spaces "to align filenames" (once the filename is aligned to neighboring filenames, we don't add any spaces any more), so if dired-move-to-filename goes too far, it's very unlikely that we'll add spaces because it's most likely going to be already further than neighboring filenames. - It's a situation in which even without adding spaces, dired is all confused, so it's not clear we'll make things worse. Number 1 is actually solved in the code by being paranoid and checking each time we insert spaces that the outcome of dired-move-to-filename has not been affected (and reverting the change if it did). Number 2 could be reduced by trying to make sure that such misidentifications don't happen. This could be done e.g. by checking (file-exists-p (dired-get-filename)). The code below does not bother to do that, but it can be easily added. Stefan PS: I rarely use dired myself, so this is very lightly tested. --- orig/lisp/dired.el +++ mod/lisp/dired.el @@ -798,6 +798,98 @@ (dired-insert-directory dir dired-actual-switches file-list (not file-list) t))))) +(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 if 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 `dired-move-to-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 the there is indeed a file, and that there is anoter 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 (progn (goto-char beg) (forward-line -1) + (dired-move-to-filename)) + (progn (goto-char beg) (forward-line 1) + (dired-move-to-filename)))) + (setq other-col (current-column)) + ;; Make sure there is some work left to do. + (> other-col file-col)) + ;; Keep positions uptodate when we insert stuff. + (if (> other file) (setq other (copy-marker other))) + (setq file (copy-marker file)) + ;; Main loop. + (goto-char beg) + (while (and (> other-col file-col) + (skip-chars-forward "^ ") + ;; Skip the spaces, and make sure there's at least one. + (> (skip-chars-forward " ") 0) + ;; 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 "[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 highly + ;; 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 + (save-excursion + (goto-char other) + (move-to-column curcol) + (when (looking-at + (concat + (if (eq (char-before) ?\ ) " *" "[^ ]* *") + (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) + ;; Let's just make really sure we did not mess up. + (save-excursion + (unless (and (dired-move-to-filename) (= (point) file)) + ;; Damn! We messed up: let's revert the change. + (delete-char (- spaces))))))))))) + + (defun dired-insert-directory (dir switches &optional file-list wildcard hdr) "Insert a directory listing of DIR, Dired style. Use SWITCHES to make the listings. @@ -816,7 +909,10 @@ ;; with the new value of dired-move-to-filename-regexp. (if file-list (dolist (f file-list) - (insert-directory f switches nil nil)) + (let ((beg (point))) + (insert-directory f switches nil nil) + ;; Re-align fields, if necessary. + (dired-align-file beg (point)))) (insert-directory dir switches wildcard (not wildcard))) ;; Quote certain characters, unless ls quoted them for us. (if (not (string-match "b" dired-actual-switches))