Skip to content

Commit

Permalink
Enable focus events through configuration by using focus (option) and…
Browse files Browse the repository at this point in the history
… on-ui-enter/on-ui-exit events.
  • Loading branch information
laktak committed Sep 20, 2023
1 parent c816343 commit df36ad3
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 11 deletions.
18 changes: 15 additions & 3 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ func (app *app) loop() {
}()
}

onUiEnter(app)

for {
select {
case <-app.quitChan:
Expand All @@ -322,6 +324,7 @@ func (app *app) loop() {
cmd.eval(app, nil)
}

onUiExit(app)
app.quit()

app.nav.previewChan <- ""
Expand Down Expand Up @@ -461,12 +464,14 @@ func (app *app) loop() {
app.ui.draw(app.nav)
}
}

}

func (app *app) runCmdSync(cmd *exec.Cmd, pause_after bool) {
app.nav.previewChan <- ""
app.nav.dirPreviewChan <- nil

onUiExit(app)
if err := app.ui.suspend(); err != nil {
log.Printf("suspend: %s", err)
}
Expand All @@ -475,6 +480,7 @@ func (app *app) runCmdSync(cmd *exec.Cmd, pause_after bool) {
app.quit()
os.Exit(3)
}
onUiEnter(app)
}()

if err := cmd.Run(); err != nil {
Expand All @@ -495,6 +501,7 @@ func (app *app) runCmdSync(cmd *exec.Cmd, pause_after bool) {
// % No No Yes Yes Yes Statline for input/output
// ! Yes No Yes Yes Yes Pause and then resume
// & No Yes No No No Do nothing
// ^ No No Yes Yes Yes (internal for events)
func (app *app) runShell(s string, args []string, prefix string) {
app.nav.exportFiles()
app.ui.exportSizes()
Expand All @@ -513,12 +520,17 @@ func (app *app) runShell(s string, args []string, prefix string) {
var out io.Reader
var err error
switch prefix {
case "$", "!":
case "$", "!", "^":
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr

app.runCmdSync(cmd, prefix == "!")
if prefix != "^" {
app.runCmdSync(cmd, prefix == "!")
} else {
if err := cmd.Run(); err != nil {
app.ui.echoerrf("running ^shell: %s", err)
}
}
return
}

Expand Down
15 changes: 15 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ The following options can be used to customize the behavior of lf:
errorfmt string (default "\033[7;31;47m")
filesep string (default "\n")
findlen int (default 1)
focus bool (default true)
globsearch bool (default false)
hidden bool (default false)
hiddenfiles []string (default '.*')
Expand Down Expand Up @@ -208,6 +209,8 @@ The following special shell commands are used to customize the behavior of lf wh
pre-cd
on-cd
on-select
on-ui-enter
on-ui-exit
on-quit
The following commands/keybindings are provided by default:
Expand Down Expand Up @@ -743,6 +746,10 @@ File separator used in environment variables 'fs' and 'fx'.
Number of characters prompted for the find command.
When this value is set to 0, find command prompts until there is only a single match left.
focus bool (default on)
Focus displays the selection line inversed if enabled. It can be set from a terminal event to indicate if (or which) lf has focus.
globsearch bool (default false)
When this option is enabled, search command patterns are considered as globs, otherwise they are literals.
Expand Down Expand Up @@ -1110,6 +1117,14 @@ This shell command can be defined to be executed after changing a directory.
This shell command can be defined to be executed after the selection changes.
on-ui-enter
This shell command can be defined to be executed when the UI of lf becomes active. This will be triggered after lf starts and when foreground shell commands finish.
on-ui-exit
This shell command can be defined to be executed when the UI of lf becomes inactive. This will be triggered before lf exits and before starting foreground shell commands.
on-quit
This shell command can be defined to be executed before quit.
Expand Down
20 changes: 20 additions & 0 deletions docstring.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,18 @@ func (e *setExpr) eval(app *app, args []string) {
} else {
gOpts.tempmarks = "'"
}
case "focus":
gOpts.focus = true
app.ui.loadFile(app, true)
app.ui.loadFileInfo(app.nav)
case "nofocus":
gOpts.focus = false
app.ui.loadFile(app, true)
app.ui.loadFileInfo(app.nav)
case "focus!":
gOpts.focus = !gOpts.focus
app.ui.loadFile(app, true)
app.ui.loadFileInfo(app.nav)
case "timefmt":
gOpts.timefmt = e.val
case "truncatechar":
Expand Down Expand Up @@ -1157,6 +1169,22 @@ func onSelect(app *app) {
}
}

func onUiEnter(app *app) {
if cmd, ok := gOpts.cmds["on-ui-enter"]; ok {
ecmd := cmd.(*execExpr)
ecmd.prefix = "^"
ecmd.eval(app, nil)
}
}

func onUiExit(app *app) {
if cmd, ok := gOpts.cmds["on-ui-exit"]; ok {
ecmd := cmd.(*execExpr)
ecmd.prefix = "^"
ecmd.eval(app, nil)
}
}

func splitKeys(s string) (keys []string) {
for i := 0; i < len(s); {
r, w := utf8.DecodeRuneInString(s[i:])
Expand Down Expand Up @@ -2764,6 +2792,9 @@ func (e *execExpr) eval(app *app, args []string) {
case "&":
log.Printf("shell-async: %s -- %s", e, args)
app.runShell(e.value, args, e.prefix)
case "^":
log.Printf("shell-sync-evt: %s -- %s", e, args)
app.runShell(e.value, args, e.prefix)
default:
log.Printf("evaluating unknown execution prefix: %q", e.prefix)
}
Expand Down
21 changes: 21 additions & 0 deletions lf.1
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ The following options can be used to customize the behavior of lf:
errorfmt string (default "\e033[7;31;47m")
filesep string (default "\en")
findlen int (default 1)
focus bool (default true)
globsearch bool (default false)
hidden bool (default false)
hiddenfiles []string (default '.*')
Expand Down Expand Up @@ -231,6 +232,8 @@ The following special shell commands are used to customize the behavior of lf wh
pre-cd
on-cd
on-select
on-ui-enter
on-ui-exit
on-quit
.EE
.PP
Expand Down Expand Up @@ -905,6 +908,12 @@ File separator used in environment variables 'fs' and 'fx'.
.PP
Number of characters prompted for the find command. When this value is set to 0, find command prompts until there is only a single match left.
.PP
.EX
focus bool (default on)
.EE
.PP
Focus displays the selection line inversed if enabled. It can be set from a terminal event to indicate if (or which) lf has focus.
.PP
.EX
globsearch bool (default false)
.EE
Expand Down Expand Up @@ -1332,6 +1341,18 @@ This shell command can be defined to be executed after changing a directory.
.PP
This shell command can be defined to be executed after the selection changes.
.PP
.EX
on-ui-enter
.EE
.PP
This shell command can be defined to be executed when the UI of lf becomes active. This will be triggered after lf starts and when foreground shell commands finish.
.PP
.EX
on-ui-exit
.EE
.PP
This shell command can be defined to be executed when the UI of lf becomes inactive. This will be triggered before lf exits and before starting foreground shell commands.
.PP
.EX
on-quit
.EE
Expand Down
2 changes: 2 additions & 0 deletions opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ var gOpts struct {
tempmarks string
numberfmt string
tagfmt string
focus bool
}

var gLocalOpts struct {
Expand Down Expand Up @@ -241,6 +242,7 @@ func init() {
gOpts.tempmarks = "'"
gOpts.numberfmt = "\033[33m"
gOpts.tagfmt = "\033[31m"
gOpts.focus = true

gOpts.keys = make(map[string]expr)

Expand Down
31 changes: 23 additions & 8 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ func (win *win) printDir(screen tcell.Screen, dir *dir, context *dirContext, dir
}

ce := ""
if i == dir.pos {
if i == dir.pos && gOpts.focus {
switch dirStyle.role {
case Active:
ce = gOpts.cursoractivefmt
Expand All @@ -504,7 +504,7 @@ func (win *win) printDir(screen tcell.Screen, dir *dir, context *dirContext, dir

tag, ok := context.tags[path]
if ok {
if i == dir.pos {
if i == dir.pos && gOpts.focus {
win.print(screen, lnwidth+1, i, st, fmt.Sprintf(cursorescapefmt, tag))
} else {
win.print(screen, lnwidth+1, i, tcell.StyleDefault, fmt.Sprintf(optionToFmtstr(gOpts.tagfmt), tag))
Expand Down Expand Up @@ -1449,17 +1449,32 @@ func (ui *ui) readNormalEvent(ev tcell.Event, nav *nav) expr {
return nil
}

func readCmdEvent(ev tcell.Event) expr {
func (ui *ui) readCmdEvent(ev tcell.Event) expr {
switch tev := ev.(type) {
case *tcell.EventKey:
if tev.Key() == tcell.KeyRune {
if tev.Modifiers() == tcell.ModMask(tcell.ModAlt) {
val := string([]rune{'<', 'a', '-', tev.Rune(), '>'})
if expr, ok := gOpts.cmdkeys[val]; ok {
return expr
// support multi-key bindings but only for ESC[ at the moment
if tev.Rune() == '[' {
ui.keyAcc = append(ui.keyAcc, '<', 'a', '-', tev.Rune(), '>')
} else {
val := string([]rune{'<', 'a', '-', tev.Rune(), '>'})
if expr, ok := gOpts.cmdkeys[val]; ok {
return expr
}
}
} else {
return &callExpr{"cmd-insert", []string{string(tev.Rune())}, 1}
// multi-key bindings
if ui.keyAcc != nil {
ui.keyAcc = append(ui.keyAcc, tev.Rune())
val := string(ui.keyAcc)
ui.keyAcc = nil
if expr, ok := gOpts.cmdkeys[val]; ok {
return expr
}
} else {
return &callExpr{"cmd-insert", []string{string(tev.Rune())}, 1}
}
}
} else {
val := gKeyVal[tev.Key()]
Expand All @@ -1478,7 +1493,7 @@ func (ui *ui) readEvent(ev tcell.Event, nav *nav) expr {
}

if _, ok := ev.(*tcell.EventKey); ok && ui.cmdPrefix != "" {
return readCmdEvent(ev)
return ui.readCmdEvent(ev)
}

return ui.readNormalEvent(ev, nav)
Expand Down

0 comments on commit df36ad3

Please sign in to comment.