summaryrefslogtreecommitdiffstats
path: root/src/terminal.go
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2022-12-18 00:22:15 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2022-12-21 01:35:08 +0900
commit1ba7484d606bf3797b3936651051bb4113dbcad2 (patch)
treee4452678c4991f113d6178d8f4f215dbecbe52af /src/terminal.go
parent51c518da1e981dddda18e55272be482e972d6861 (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.go71
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) {