Date: Sun, 21 Jun 1998 16:07:59 -0500 (CDT) From: Joel Ray Holveck <detlev!joelh@mail.camalott.com> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: bin/7011: Improvements to ls to help Emacs users; patch included Message-ID: <199806212107.QAA25952@detlev.UUCP>
next in thread | raw e-mail | index | archive | help
>Number: 7011
>Category: bin
>Synopsis: Improvements to ls to help Emacs users; patch included
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Sun Jun 21 14:10:01 PDT 1998
>Last-Modified:
>Originator: Joel Ray Holveck
>Organization:
None
>Release: FreeBSD 3.0-CURRENT i386
>Environment:
FreeBSD-current, cvsup'd late 20Jun98. GNU Emacs 20.2.2.
>Description:
Emacs's editing mode, dired, will ls individual files when it creates
changes. However, our current implementation of ls may use different
column widths for different sets of files being ls'd. This means that
if a single dired directory listing includes data from multiple
invocations of ls, the columns may not align properly.
This problem should also exist under any other directory utility which
directly displays the output of ls, and will display data obtained
from multiple invocations with different filesets at the same time.
>How-To-Repeat:
Launch Emacs. Press: C-x C-f ~ RET
Dired will launch and displays a directory listing of the home
directory. A portion of a sample follows:
-rwxr-xr-x 1 joelh joelh 3863 May 11 23:20 .bashrc
-rw-r--r-- 1 joelh joelh 32126 Jun 21 14:10 .emacs
-rw-r--r-- 1 joelh joelh 209 Jan 8 12:34 .emacs.bmk
-rw-r--r-- 1 joelh joelh 0 Mar 4 02:45 .emacs_args
-rw------- 1 joelh joelh 4217 Jun 17 00:24 .fetchmailrc
Using C-n and C-p, navigate to an item that uses less than the maximum
width of any column (eg, has a size an order of magnitude smaller than
another). (I am using .emacs.bmk as an example.) Press M
(dired-do-chmod). Press u+r (which is probably a nop in chmod, but
will cause the file selected to refresh by itself). The directory
will now have skewed columns:
-rwxr-xr-x 1 joelh joelh 3863 May 11 23:20 .bashrc
-rw-r--r-- 1 joelh joelh 32126 Jun 21 14:10 .emacs
-rw-r--r-- 1 joelh joelh 209 Jan 8 12:34 .emacs.bmk
-rw-r--r-- 1 joelh joelh 0 Mar 4 02:45 .emacs_args
-rw------- 1 joelh joelh 4217 Jun 17 00:24 .fetchmailrc
>Fix:
I propose a change to ls which will allow minimum column widths to be
set in the environment. A runtime environment variable, LS_COLWIDTHS
is added. This is a colon-delimited list of minimum column widths for
each variable-width column, in order of display by 'ls -lois'. For
example, by default, 'ls -l' may display:
total 321
-rw-r--r-- 1 joelh bin 7435 Jun 21 13:45 cmp.o
-rwxr-xr-x 1 joelh bin 238385 Jun 21 14:42 ls
-rw-r--r-- 1 joelh bin 4352 Jun 21 14:42 ls.1.gz
-rw-r--r-- 1 joelh bin 21182 Jun 21 14:42 ls.o
-rw-r--r-- 1 joelh bin 16457 Jun 21 13:45 print.o
-rw-r--r-- 1 joelh bin 9814 Jun 21 13:45 stat_flags.o
-rw-r--r-- 1 joelh bin 11508 Jun 21 13:45 util.o
However, with LS_COLWIDTHS set to 6:4:2:8:8:1:7:0 (the affected fields
for a simple -l listing are block count, user, group, and size),
'ls -l' in the same directory will display:
total 321
-rw-r--r-- 1 joelh bin 7435 Jun 21 13:45 cmp.o
-rwxr-xr-x 1 joelh bin 238385 Jun 21 14:42 ls
-rw-r--r-- 1 joelh bin 4352 Jun 21 14:42 ls.1.gz
-rw-r--r-- 1 joelh bin 21182 Jun 21 14:42 ls.o
-rw-r--r-- 1 joelh bin 16457 Jun 21 13:45 print.o
-rw-r--r-- 1 joelh bin 9814 Jun 21 13:45 stat_flags.o
-rw-r--r-- 1 joelh bin 11508 Jun 21 13:45 util.o
By setting LS_COLWIDTHS to a reasonable value, all invocations of ls
will use the same column widths, thereby effectively allowing a
repeatable output format under normal conditions. (The problem will
still manifest as before if the column widths specified in
LS_COLWIDTHS are insufficient to display the requested listing, since
the columns output will still expand to meet the needs of the
listing.)
If additional output columns are added in the future, it is
recommended to append column width specifiers to LS_COLWIDTHS rather
than adding them in display order, to maintain backward compatibility.
Attached are the diffs to ls.c and ls.1 to implement the recommended
change.
Happy hacking,
joelh
*** ls.c-orig Sun Jun 21 13:54:31 1998
--- ls.c Sun Jun 21 14:42:40 1998
***************
*** 69,74 ****
--- 69,75 ----
static void display __P((FTSENT *, FTSENT *));
static int mastercmp __P((const FTSENT **, const FTSENT **));
static void traverse __P((int, char **, int));
+ static u_quad_t makenines __P((u_long));
static void (*printfcn) __P((DISPLAY *));
static int (*sortfcn) __P((const FTSENT *, const FTSENT *));
***************
*** 396,401 ****
--- 397,403 ----
u_quad_t maxsize;
u_long btotal, maxblock, maxinode, maxlen, maxnlink;
int bcfile, flen, glen, ulen, maxflags, maxgroup, maxuser;
+ char* initmax;
int entries, needstats;
char *user, *group, *flags, buf[20]; /* 32 bits == 10 digits */
***************
*** 411,421 ****
needstats = f_inode || f_longform || f_size;
flen = 0;
! btotal = maxblock = maxinode = maxlen = maxnlink = 0;
bcfile = 0;
- maxuser = maxgroup = maxflags = 0;
flags = NULL;
- maxsize = 0;
for (cur = list, entries = 0; cur; cur = cur->fts_link) {
if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
warnx("%s: %s",
--- 413,441 ----
needstats = f_inode || f_longform || f_size;
flen = 0;
! btotal = 0;
! initmax = getenv("LS_COLWIDTHS");
! /* This sscanf matches the order of ls -lios. */
! if (initmax != NULL) {
! if (sscanf(initmax,
! " %lu : %lu : %lu : %i : %i : %i : %qu : %lu ",
! &maxinode, &maxblock, &maxnlink, &maxuser,
! &maxgroup, &maxflags, &maxsize, &maxlen)
! == 8) {
! maxinode = makenines(maxinode);
! maxblock = makenines(maxblock);
! maxnlink = makenines(maxnlink);
! maxsize = makenines(maxsize);
! } else {
! fputs("ls: bad LS_COLWIDTHS\n", stderr);
! initmax = NULL;
! }
! }
! if (initmax == NULL)
! maxblock = maxinode = maxlen = maxnlink =
! maxuser = maxgroup = maxflags = maxsize = 0;
bcfile = 0;
flags = NULL;
for (cur = list, entries = 0; cur; cur = cur->fts_link) {
if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
warnx("%s: %s",
***************
*** 560,563 ****
--- 580,603 ----
return (-1);
}
return (sortfcn(*a, *b));
+ }
+
+ /*
+ * Makenines() returns (10**n)-1. This is useful for converting a width
+ * into a number that wide in decimal.
+ */
+ static u_quad_t
+ makenines(n)
+ u_long n;
+ {
+ u_long i;
+ u_quad_t reg;
+
+ reg = 1;
+ /* Use a loop instead of pow(), since all values of n are small. */
+ for (i = 0; i < n; i++)
+ reg *= 10;
+ reg--;
+
+ return reg;
}
*** ls.1-orig Sun Jun 21 14:35:08 1998
--- ls.1 Sun Jun 21 14:41:42 1998
***************
*** 373,378 ****
--- 373,385 ----
See
.Xr environ 7
for more information.
+ .It Ev LS_COLWIDTHS
+ If this variable is set, it is considered to be a
+ colon-delimited list of minimum column widths (possibly
+ zero). The columns are, in order: inode, block count,
+ number of links, user name, group name, flags, file size,
+ file name. (This corresponds to the order of the relevant
+ columns in output.)
.El
.Sh COMPATIBILITY
The group field is now automatically included in the long listing for
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199806212107.QAA25952>
