mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2024-12-01 09:13:55 +00:00
Make GET endpoint available from 'execute' and 'transform' actions
This commit is contained in:
parent
9dc3ed638a
commit
b2ecb6352c
@ -4,6 +4,15 @@ CHANGELOG
|
|||||||
0.53.1
|
0.53.1
|
||||||
------
|
------
|
||||||
- Bug fixes and minor improvements
|
- Bug fixes and minor improvements
|
||||||
|
- Better cache management and improved rendering for `--tail`
|
||||||
|
- Fixed crash when using `--tiebreak=end` with very long items
|
||||||
|
- Fixed mouse support on Windows
|
||||||
|
- zsh 5.0 compatibility (thanks to @LangLangBart)
|
||||||
|
- Fixed `--walker-skip` to also skip symlinks to directories
|
||||||
|
- GET endpoint is now available from `execute` and `transform` actions (it used to timeout due to lock conflict)
|
||||||
|
```sh
|
||||||
|
fzf --listen --bind 'focus:transform-header:curl -s localhost:$FZF_PORT?limit=0 | jq .'
|
||||||
|
```
|
||||||
|
|
||||||
0.53.0
|
0.53.0
|
||||||
------
|
------
|
||||||
|
@ -117,14 +117,13 @@ func _() {
|
|||||||
_ = x[actUnbind-106]
|
_ = x[actUnbind-106]
|
||||||
_ = x[actRebind-107]
|
_ = x[actRebind-107]
|
||||||
_ = x[actBecome-108]
|
_ = x[actBecome-108]
|
||||||
_ = x[actResponse-109]
|
_ = x[actShowHeader-109]
|
||||||
_ = x[actShowHeader-110]
|
_ = x[actHideHeader-110]
|
||||||
_ = x[actHideHeader-111]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeHeaderactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformHeaderactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactResponseactShowHeaderactHideHeader"
|
const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeHeaderactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformHeaderactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeader"
|
||||||
|
|
||||||
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 242, 256, 277, 292, 306, 320, 333, 350, 358, 371, 387, 399, 407, 421, 435, 446, 457, 475, 492, 499, 518, 530, 544, 553, 568, 580, 593, 604, 615, 627, 641, 662, 677, 692, 709, 716, 721, 730, 741, 752, 765, 780, 791, 804, 811, 824, 837, 854, 869, 882, 896, 910, 926, 946, 958, 981, 999, 1023, 1041, 1058, 1068, 1084, 1106, 1119, 1135, 1147, 1161, 1177, 1195, 1215, 1237, 1251, 1266, 1274, 1280, 1294, 1309, 1319, 1335, 1350, 1360, 1368, 1375, 1384, 1397, 1413, 1428, 1437, 1448, 1457, 1466, 1475, 1486, 1499, 1512}
|
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 242, 256, 277, 292, 306, 320, 333, 350, 358, 371, 387, 399, 407, 421, 435, 446, 457, 475, 492, 499, 518, 530, 544, 553, 568, 580, 593, 604, 615, 627, 641, 662, 677, 692, 709, 716, 721, 730, 741, 752, 765, 780, 791, 804, 811, 824, 837, 854, 869, 882, 896, 910, 926, 946, 958, 981, 999, 1023, 1041, 1058, 1068, 1084, 1106, 1119, 1135, 1147, 1161, 1177, 1195, 1215, 1237, 1251, 1266, 1274, 1280, 1294, 1309, 1319, 1335, 1350, 1360, 1368, 1375, 1384, 1397, 1413, 1428, 1437, 1448, 1457, 1466, 1475, 1488, 1501}
|
||||||
|
|
||||||
func (i actionType) String() string {
|
func (i actionType) String() string {
|
||||||
if i < 0 || i >= actionType(len(_actionType_index)-1) {
|
if i < 0 || i >= actionType(len(_actionType_index)-1) {
|
||||||
|
@ -38,9 +38,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type httpServer struct {
|
type httpServer struct {
|
||||||
apiKey []byte
|
apiKey []byte
|
||||||
actionChannel chan []*action
|
actionChannel chan []*action
|
||||||
responseChannel chan string
|
getHandler func(getParams) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type listenAddress struct {
|
type listenAddress struct {
|
||||||
@ -73,7 +73,7 @@ func parseListenAddress(address string) (listenAddress, error) {
|
|||||||
return listenAddress{parts[0], port}, nil
|
return listenAddress{parts[0], port}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startHttpServer(address listenAddress, actionChannel chan []*action, responseChannel chan string) (net.Listener, int, error) {
|
func startHttpServer(address listenAddress, actionChannel chan []*action, getHandler func(getParams) string) (net.Listener, int, error) {
|
||||||
host := address.host
|
host := address.host
|
||||||
port := address.port
|
port := address.port
|
||||||
apiKey := os.Getenv("FZF_API_KEY")
|
apiKey := os.Getenv("FZF_API_KEY")
|
||||||
@ -99,9 +99,9 @@ func startHttpServer(address listenAddress, actionChannel chan []*action, respon
|
|||||||
}
|
}
|
||||||
|
|
||||||
server := httpServer{
|
server := httpServer{
|
||||||
apiKey: []byte(apiKey),
|
apiKey: []byte(apiKey),
|
||||||
actionChannel: actionChannel,
|
actionChannel: actionChannel,
|
||||||
responseChannel: responseChannel,
|
getHandler: getHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -165,17 +165,11 @@ func (server *httpServer) handleHttpRequest(conn net.Conn) string {
|
|||||||
case 0:
|
case 0:
|
||||||
getMatch := getRegex.FindStringSubmatch(text)
|
getMatch := getRegex.FindStringSubmatch(text)
|
||||||
if len(getMatch) > 0 {
|
if len(getMatch) > 0 {
|
||||||
server.actionChannel <- []*action{{t: actResponse, a: getMatch[1]}}
|
response := server.getHandler(parseGetParams(getMatch[1]))
|
||||||
select {
|
if len(response) > 0 {
|
||||||
case response := <-server.responseChannel:
|
|
||||||
return good(response)
|
return good(response)
|
||||||
case <-time.After(channelTimeout):
|
|
||||||
go func() {
|
|
||||||
// Drain the channel
|
|
||||||
<-server.responseChannel
|
|
||||||
}()
|
|
||||||
return answer(httpUnavailable+jsonContentType, `{"error":"timeout"}`)
|
|
||||||
}
|
}
|
||||||
|
return answer(httpUnavailable+jsonContentType, `{"error":"timeout"}`)
|
||||||
} else if !strings.HasPrefix(text, "POST / HTTP") {
|
} else if !strings.HasPrefix(text, "POST / HTTP") {
|
||||||
return bad("invalid request method")
|
return bad("invalid request method")
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,6 @@ type Terminal struct {
|
|||||||
startChan chan fitpad
|
startChan chan fitpad
|
||||||
killChan chan bool
|
killChan chan bool
|
||||||
serverInputChan chan []*action
|
serverInputChan chan []*action
|
||||||
serverOutputChan chan string
|
|
||||||
eventChan chan tui.Event
|
eventChan chan tui.Event
|
||||||
slab *util.Slab
|
slab *util.Slab
|
||||||
theme *tui.ColorTheme
|
theme *tui.ColorTheme
|
||||||
@ -497,7 +496,6 @@ const (
|
|||||||
actUnbind
|
actUnbind
|
||||||
actRebind
|
actRebind
|
||||||
actBecome
|
actBecome
|
||||||
actResponse
|
|
||||||
actShowHeader
|
actShowHeader
|
||||||
actHideHeader
|
actHideHeader
|
||||||
)
|
)
|
||||||
@ -839,7 +837,6 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
startChan: make(chan fitpad, 1),
|
startChan: make(chan fitpad, 1),
|
||||||
killChan: make(chan bool),
|
killChan: make(chan bool),
|
||||||
serverInputChan: make(chan []*action, 100),
|
serverInputChan: make(chan []*action, 100),
|
||||||
serverOutputChan: make(chan string),
|
|
||||||
eventChan: make(chan tui.Event, 6), // (load + result + zero|one) | (focus) | (resize) | (GetChar)
|
eventChan: make(chan tui.Event, 6), // (load + result + zero|one) | (focus) | (resize) | (GetChar)
|
||||||
tui: renderer,
|
tui: renderer,
|
||||||
ttyin: ttyin,
|
ttyin: ttyin,
|
||||||
@ -893,7 +890,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
|
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
|
||||||
|
|
||||||
if t.listenAddr != nil {
|
if t.listenAddr != nil {
|
||||||
listener, port, err := startHttpServer(*t.listenAddr, t.serverInputChan, t.serverOutputChan)
|
listener, port, err := startHttpServer(*t.listenAddr, t.serverInputChan, t.dumpStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -2996,11 +2993,14 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.tui.Pause(true)
|
t.tui.Pause(true)
|
||||||
|
t.mutex.Unlock()
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
|
t.mutex.Lock()
|
||||||
t.tui.Resume(true, false)
|
t.tui.Resume(true, false)
|
||||||
t.redraw()
|
t.redraw()
|
||||||
t.refresh()
|
t.refresh()
|
||||||
} else {
|
} else {
|
||||||
|
t.mutex.Unlock()
|
||||||
if capture {
|
if capture {
|
||||||
out, _ := cmd.StdoutPipe()
|
out, _ := cmd.StdoutPipe()
|
||||||
reader := bufio.NewReader(out)
|
reader := bufio.NewReader(out)
|
||||||
@ -3016,6 +3016,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
} else {
|
} else {
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
}
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
}
|
}
|
||||||
t.executing.Set(false)
|
t.executing.Set(false)
|
||||||
removeFiles(tempFiles)
|
removeFiles(tempFiles)
|
||||||
@ -3719,8 +3720,6 @@ func (t *Terminal) Loop() error {
|
|||||||
doAction = func(a *action) bool {
|
doAction = func(a *action) bool {
|
||||||
switch a.t {
|
switch a.t {
|
||||||
case actIgnore, actStart, actClick:
|
case actIgnore, actStart, actClick:
|
||||||
case actResponse:
|
|
||||||
t.serverOutputChan <- t.dumpStatus(parseGetParams(a.a))
|
|
||||||
case actBecome:
|
case actBecome:
|
||||||
valid, list := t.buildPlusList(a.a, false)
|
valid, list := t.buildPlusList(a.a, false)
|
||||||
if valid {
|
if valid {
|
||||||
@ -4708,7 +4707,29 @@ func (t *Terminal) dumpItem(i *Item) StatusItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) tryLock(timeout time.Duration) bool {
|
||||||
|
sleepDuration := 10 * time.Millisecond
|
||||||
|
|
||||||
|
for {
|
||||||
|
if t.mutex.TryLock() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout -= sleepDuration
|
||||||
|
if timeout <= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(sleepDuration)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Terminal) dumpStatus(params getParams) string {
|
func (t *Terminal) dumpStatus(params getParams) string {
|
||||||
|
if !t.tryLock(channelTimeout) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer t.mutex.Unlock()
|
||||||
|
|
||||||
selectedItems := t.sortSelected()
|
selectedItems := t.sortSelected()
|
||||||
selected := make([]StatusItem, util.Max(0, util.Min(params.limit, len(selectedItems)-params.offset)))
|
selected := make([]StatusItem, util.Max(0, util.Min(params.limit, len(selectedItems)-params.offset)))
|
||||||
for i := range selected {
|
for i := range selected {
|
||||||
|
Loading…
Reference in New Issue
Block a user