diff options
author | Junegunn Choi <junegunn.c@gmail.com> | 2022-12-18 00:22:15 +0900 |
---|---|---|
committer | Junegunn Choi <junegunn.c@gmail.com> | 2022-12-21 01:35:08 +0900 |
commit | 1ba7484d606bf3797b3936651051bb4113dbcad2 (patch) | |
tree | e4452678c4991f113d6178d8f4f215dbecbe52af /src/terminal.go | |
parent | 51c518da1e981dddda18e55272be482e972d6861 (diff) |
Add --listen=HTTP_PORT option to receive actions
Supersedes #2019
See also:
* #1728
* https://github.com/junegunn/fzf.vim/pull/1044
Diffstat (limited to 'src/terminal.go')
-rw-r--r-- | src/terminal.go | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/src/terminal.go b/src/terminal.go index e0ff5b2b..47cc34cf 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -3,8 +3,10 @@ package fzf import ( "bufio" "fmt" + "io" "io/ioutil" "math" + "net/http" "os" "os/signal" "regexp" @@ -167,6 +169,7 @@ type Terminal struct { padding [4]sizeSpec strong tui.Attr unicode bool + listenPort int borderShape tui.BorderShape cleanExit bool paused bool @@ -200,6 +203,7 @@ type Terminal struct { sigstop bool startChan chan fitpad killChan chan int + serverChan chan []*action slab *util.Slab theme *tui.ColorTheme tui tui.Renderer @@ -481,7 +485,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { } var previewBox *util.EventBox showPreviewWindow := len(opts.Preview.command) > 0 && !opts.Preview.hidden - if len(opts.Preview.command) > 0 || hasPreviewAction(opts) { + // We need to start previewer if HTTP server is enabled even when --preview option is not specified + if len(opts.Preview.command) > 0 || hasPreviewAction(opts) || opts.ListenPort > 0 { previewBox = util.NewEventBox() } strongAttr := tui.Bold @@ -556,6 +561,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { margin: opts.Margin, padding: opts.Padding, unicode: opts.Unicode, + listenPort: opts.ListenPort, borderShape: opts.BorderShape, borderLabel: nil, borderLabelOpts: opts.BorderLabel, @@ -595,6 +601,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { theme: opts.Theme, startChan: make(chan fitpad, 1), killChan: make(chan int), + serverChan: make(chan []*action), tui: renderer, initFunc: func() { renderer.Init() }, executing: util.NewAtomicBool(false)} @@ -619,6 +626,39 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { return &t } +func (t *Terminal) startServer() { + if t.listenPort == 0 { + return + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + w.WriteHeader(http.StatusBadRequest) + return + } + body, err := io.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + response := "" + actions := parseSingleActionList(string(body), func(message string) { + response = message + }) + + if len(response) > 0 { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintln(w, response) + return + } + t.serverChan <- actions + }) + go func() { + http.ListenAndServe(fmt.Sprintf(":%d", t.listenPort), nil) + }() +} + func borderLines(shape tui.BorderShape) int { switch shape { case tui.BorderHorizontal, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderDouble: @@ -2256,6 +2296,9 @@ func (t *Terminal) Loop() { env = append(env, "FZF_PREVIEW_"+lines) env = append(env, columns) env = append(env, "FZF_PREVIEW_"+columns) + if t.listenPort > 0 { + env = append(env, fmt.Sprintf("FZF_LISTEN_PORT=%d", t.listenPort)) + } cmd.Env = env } @@ -2492,6 +2535,16 @@ func (t *Terminal) Loop() { looping := true _, startEvent := t.keymap[tui.Start.AsEvent()] + t.startServer() + eventChan := make(chan tui.Event) + needBarrier := true + barrier := make(chan bool) + go func() { + for { + <-barrier + eventChan <- t.tui.GetChar() + } + }() for looping { var newCommand *string changed := false @@ -2499,11 +2552,21 @@ func (t *Terminal) Loop() { queryChanged := false var event tui.Event + actions := []*action{} if startEvent { event = tui.Start.AsEvent() startEvent = false } else { - event = t.tui.GetChar() + if needBarrier { + barrier <- true + } + select { + case event = <-eventChan: + needBarrier = true + case actions = <-t.serverChan: + event = tui.Invalid.AsEvent() + needBarrier = false + } } t.mutex.Lock() @@ -3043,7 +3106,9 @@ func (t *Terminal) Loop() { } if t.jumping == jumpDisabled { - actions := t.keymap[event.Comparable()] + if len(actions) == 0 { + actions = t.keymap[event.Comparable()] + } if len(actions) == 0 && event.Type == tui.Rune { doAction(&action{t: actRune}) } else if !doActions(actions) { |