diff --git a/doc.md b/doc.md index 0adf63ed..3e2fe0b8 100644 --- a/doc.md +++ b/doc.md @@ -811,7 +811,7 @@ Apply filter pattern after each keystroke during filtering. ## info ([]string) (default ``) A list of information that is shown for directory items at the right side of the pane. -Currently supported information types are `size`, `time`, `atime`, and `ctime`. +Currently supported information types are `size`, `time`, `atime`, `ctime`, `perm`, `user` and `group`. Information is only shown when the pane width is more than twice the width of information. ## infotimefmtnew (string) (default `Jan _2 15:04`) diff --git a/doc.txt b/doc.txt index f9a8b966..399ae5ce 100644 --- a/doc.txt +++ b/doc.txt @@ -864,8 +864,8 @@ info ([]string) (default ``) A list of information that is shown for directory items at the right side of the pane. Currently supported information types are size, time, -atime, and ctime. Information is only shown when the pane width is more -than twice the width of information. +atime, ctime, perm, user and group. Information is only shown when the +pane width is more than twice the width of information. infotimefmtnew (string) (default Jan _2 15:04) diff --git a/eval.go b/eval.go index 23a6be5e..bd553a85 100644 --- a/eval.go +++ b/eval.go @@ -260,9 +260,9 @@ func (e *setExpr) eval(app *app, args []string) { toks := strings.Split(e.val, ":") for _, s := range toks { switch s { - case "size", "time", "atime", "ctime": + case "size", "time", "atime", "ctime", "perm", "user", "group": default: - app.ui.echoerr("info: should consist of 'size', 'time', 'atime' or 'ctime' separated with colon") + app.ui.echoerr("info: should consist of 'size', 'time', 'atime', 'ctime', 'perm', 'user' or 'group' separated with colon") return } } @@ -482,9 +482,9 @@ func (e *setLocalExpr) eval(app *app, args []string) { toks := strings.Split(e.val, ":") for _, s := range toks { switch s { - case "size", "time", "atime", "ctime": + case "size", "time", "atime", "ctime", "perm", "user", "group": default: - app.ui.echoerr("info: should consist of 'size', 'time', 'atime' or 'ctime' separated with colon") + app.ui.echoerr("info: should consist of 'size', 'time', 'atime', 'ctime', 'perm', 'user' or 'group' separated with colon") return } } diff --git a/lf.1 b/lf.1 index c3484a83..9d63563d 100644 --- a/lf.1 +++ b/lf.1 @@ -1,6 +1,6 @@ .\" Automatically generated by Pandoc 2.11.4 .\" -.TH "LF" "1" "2024-07-01" "" "DOCUMENTATION" +.TH "LF" "1" "2024-09-13" "" "DOCUMENTATION" .hy .SH NAME .PP @@ -882,7 +882,8 @@ Apply filter pattern after each keystroke during filtering. A list of information that is shown for directory items at the right side of the pane. Currently supported information types are \f[C]size\f[R], -\f[C]time\f[R], \f[C]atime\f[R], and \f[C]ctime\f[R]. +\f[C]time\f[R], \f[C]atime\f[R], \f[C]ctime\f[R], \f[C]perm\f[R], +\f[C]user\f[R] and \f[C]group\f[R]. Information is only shown when the pane width is more than twice the width of information. .SS infotimefmtnew (string) (default \f[C]Jan _2 15:04\f[R]) diff --git a/ui.go b/ui.go index 5d6e22ca..c06b7264 100644 --- a/ui.go +++ b/ui.go @@ -287,7 +287,7 @@ func infotimefmt(t time.Time) string { return t.Format(gOpts.infotimefmtold) } -func fileInfo(f *file, d *dir) string { +func fileInfo(f *file, d *dir, userWidth int, groupWidth int) string { var info string for _, s := range getInfo(d.path) { @@ -320,6 +320,12 @@ func fileInfo(f *file, d *dir) string { info = fmt.Sprintf("%s %*s", info, max(len(gOpts.infotimefmtnew), len(gOpts.infotimefmtold)), infotimefmt(f.accessTime)) case "ctime": info = fmt.Sprintf("%s %*s", info, max(len(gOpts.infotimefmtnew), len(gOpts.infotimefmtold)), infotimefmt(f.changeTime)) + case "perm": + info = fmt.Sprintf("%s %s", info, f.FileInfo.Mode().String()) + case "user": + info = fmt.Sprintf("%s %-*s", info, userWidth, userName(f.FileInfo)) + case "group": + info = fmt.Sprintf("%s %-*s", info, groupWidth, groupName(f.FileInfo)) default: log.Printf("unknown info type: %s", s) } @@ -402,6 +408,23 @@ func (win *win) printDir(ui *ui, dir *dir, context *dirContext, dirStyle *dirSty } } + var userWidth int + var groupWidth int + + // Only fetch user/group widths if configured to display them + for _, s := range getInfo(dir.path) { + switch s { + case "user": + userWidth = getUserWidth(dir, beg, end) + case "group": + groupWidth = getGroupWidth(dir, beg, end) + } + + if userWidth > 0 && groupWidth > 0 { + break + } + } + for i, f := range dir.files[beg:end] { st := dirStyle.colors.get(f) @@ -461,7 +484,7 @@ func (win *win) printDir(ui *ui, dir *dir, context *dirContext, dirStyle *dirSty // subtract space for tag and icon maxFilenameWidth := maxWidth - 1 - runeSliceWidth(icon) - info := fileInfo(f, dir) + info := fileInfo(f, dir, userWidth, groupWidth) showInfo := len(info) > 0 && 2*len(info) < maxWidth if showInfo { maxFilenameWidth -= len(info) @@ -519,6 +542,26 @@ func (win *win) printDir(ui *ui, dir *dir, context *dirContext, dirStyle *dirSty } } +func getUserWidth(dir *dir, beg int, end int) int { + maxw := 0 + + for _, f := range dir.files[beg:end] { + maxw = max(len(userName(f.FileInfo)), maxw) + } + + return maxw +} + +func getGroupWidth(dir *dir, beg int, end int) int { + maxw := 0 + + for _, f := range dir.files[beg:end] { + maxw = max(len(groupName(f.FileInfo)), maxw) + } + + return maxw +} + func getWidths(wtot int) []int { rsum := 0 for _, r := range gOpts.ratios {