dirtyfiles: files that don't require cleaning before previewing them (#729)

* dirtyfiles

* wrong default on man page

* respect alphabetic order for options

* clean on shell commands

* formating if
This commit is contained in:
Lucas Mior 2021-12-25 14:49:30 -03:00 committed by GitHub
parent d879e8f8f8
commit 673dad9f07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 4 deletions

1
app.go
View File

@ -481,6 +481,7 @@ func (app *app) runShell(s string, args []string, prefix string) {
cmd.Stderr = os.Stderr
app.nav.previewChan <- ""
app.nav.previewChan <- "!"
if err := app.ui.suspend(); err != nil {
log.Printf("suspend: %s", err)
}

View File

@ -87,6 +87,7 @@ var (
"dironly",
"nodironly",
"dironly!",
"dirtyfiles",
"drawbox",
"nodrawbox",
"drawbox!",

9
doc.go
View File

@ -105,6 +105,7 @@ The following options can be used to customize the behavior of lf:
dircounts bool (default off)
dirfirst bool (default on)
dironly bool (default off)
dirtyfiles []string (default '!*')
drawbox bool (default off)
errorfmt string (default "\033[7;31;47m%s\033[0m")
filesep string (default "\n")
@ -534,6 +535,14 @@ Show directories first above regular files.
Show only directories.
dirtyfiles []string (default '!*')
List of dirty file glob patterns.
These files won't have 'cleaner' executed before previewing them.
Patterns can be given as relative or absolute paths.
Globbing supports the usual special characters, '*' to match any sequence, '?' to match any character, and '[...]' or '[^...] to match character sets or ranges.
In addition, if a pattern starts with '!', then its matches are excluded from dirty files.
drawbox bool (default off)
Draw boxes around panes with box drawing characters.

View File

@ -109,6 +109,7 @@ The following options can be used to customize the behavior of lf:
dircounts bool (default off)
dirfirst bool (default on)
dironly bool (default off)
dirtyfiles []string (default '!*')
drawbox bool (default off)
errorfmt string (default "\033[7;31;47m%s\033[0m")
filesep string (default "\n")
@ -565,6 +566,15 @@ Show directories first above regular files.
Show only directories.
dirtyfiles []string (default '!*')
List of dirty file glob patterns. These files won't have 'cleaner' called
before previewing them. Patterns can be given as relative or
absolute paths. Globbing supports the usual special characters, '*' to match
any sequence, '?' to match any character, and '[...]' or '[^...] to match
character sets or ranges. In addition, if a pattern starts with '!', then
its matches are excluded from dirty files.
drawbox bool (default off)
Draw boxes around panes with box drawing characters.

18
eval.go
View File

@ -68,6 +68,24 @@ func (e *setExpr) eval(app *app, args []string) {
gOpts.sortType.option ^= dirfirstSort
app.nav.sort()
app.ui.sort()
case "dirtyfiles":
toks := strings.Split(e.val, ":")
for _, s := range toks {
if s == "" {
app.ui.echoerr("dirtyfiles: glob should be non-empty")
return
}
_, err := filepath.Match(s, "a")
if err != nil {
app.ui.echoerrf("dirtyfiles: %s", err)
return
}
}
gOpts.dirtyfiles = toks
app.nav.sort()
app.nav.position()
app.ui.sort()
app.ui.loadFile(app.nav, true)
case "drawbox":
gOpts.drawbox = true
app.ui.renew()

7
lf.1
View File

@ -131,6 +131,7 @@ The following options can be used to customize the behavior of lf:
globsearch bool (default off)
hidden bool (default off)
hiddenfiles []string (default '.*')
dirtyfiles []string (default '!*')
icons bool (default off)
ifs string (default '')
ignorecase bool (default on)
@ -704,6 +705,12 @@ Show hidden files. On unix systems, hidden files are determined by the value of
.PP
List of hidden file glob patterns. Patterns can be given as relative or absolute paths. Globbing supports the usual special characters, '*' to match any sequence, '?' to match any character, and '[...]' or '[^...] to match character sets or ranges. In addition, if a pattern starts with '!', then its matches are excluded from hidden files.
.PP
.EX
dirtyfiles []string (default '!*')
.EE
.PP
List of dirty file glob patterns. Those files won't have 'cleaner' executed before previewing them. Patterns can be given as relative or absolute paths. Globbing supports the usual special characters, '*' to match any sequence, '?' to match any character, and '[...]' or '[^...] to match character sets or ranges. In addition, if a pattern starts with '!', then its matches are excluded from dirty files.
.PP
.EX
icons bool (default off)
.EE

16
nav.go
View File

@ -115,6 +115,7 @@ type dir struct {
sortType sortType // sort method and options from last sort
dironly bool // dironly value from last sort
hiddenfiles []string // hiddenfiles value from last sort
dirtyfiles []string // files that don't require cleaning
filter []string // last filter for this directory
ignorecase bool // ignorecase value from last sort
ignoredia bool // ignoredia value from last sort
@ -154,6 +155,7 @@ func (dir *dir) sort() {
dir.sortType = gOpts.sortType
dir.dironly = gOpts.dironly
dir.hiddenfiles = gOpts.hiddenfiles
dir.dirtyfiles = gOpts.dirtyfiles
dir.ignorecase = gOpts.ignorecase
dir.ignoredia = gOpts.ignoredia
@ -361,6 +363,7 @@ func (nav *nav) loadDirInternal(path string) *dir {
path: path,
sortType: gOpts.sortType,
hiddenfiles: gOpts.hiddenfiles,
dirtyfiles: gOpts.dirtyfiles,
ignorecase: gOpts.ignorecase,
ignoredia: gOpts.ignoredia,
}
@ -522,21 +525,26 @@ func (nav *nav) previewLoop(ui *ui) {
var prev string
for path := range nav.previewChan {
clear := len(path) == 0
forceClear := path == "!"
loop:
for {
select {
case path = <-nav.previewChan:
clear = clear || len(path) == 0
forceClear = forceClear || path == "!"
default:
break loop
}
}
dir := nav.currDir()
if clear && len(gOpts.previewer) != 0 && len(gOpts.cleaner) != 0 && nav.volatilePreview {
cmd := exec.Command(gOpts.cleaner, prev)
if err := cmd.Run(); err != nil {
log.Printf("cleaning preview: %s", err)
if forceClear || !isDirty(dir.files[dir.ind], dir.path, dir.dirtyfiles) {
cmd := exec.Command(gOpts.cleaner, prev)
if err := cmd.Run(); err != nil {
log.Printf("cleaning preview: %s", err)
}
nav.volatilePreview = false
}
nav.volatilePreview = false
}
if len(path) != 0 {
win := ui.wins[len(ui.wins)-1]

View File

@ -65,6 +65,7 @@ var gOpts struct {
truncatechar string
ratios []int
hiddenfiles []string
dirtyfiles []string
info []string
shellopts []string
keys map[string]expr
@ -111,6 +112,7 @@ func init() {
gOpts.truncatechar = "~"
gOpts.ratios = []int{1, 2, 3}
gOpts.hiddenfiles = []string{".*"}
gOpts.dirtyfiles = []string{"!*"}
gOpts.info = nil
gOpts.shellopts = nil
gOpts.sortType = sortType{naturalSort, dirfirstSort}

13
os.go
View File

@ -136,6 +136,19 @@ func isHidden(f os.FileInfo, path string, hiddenfiles []string) bool {
return hidden
}
func isDirty(f os.FileInfo, path string, dirtyfiles []string) bool {
dirty := false
for _, pattern := range dirtyfiles {
matched := matchPattern(strings.TrimPrefix(pattern, "!"), f.Name(), path)
if strings.HasPrefix(pattern, "!") && matched {
dirty = false
} else if matched {
dirty = true
}
}
return dirty
}
func userName(f os.FileInfo) string {
if stat, ok := f.Sys().(*syscall.Stat_t); ok {
if u, err := user.LookupId(fmt.Sprint(stat.Uid)); err == nil {