mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-12 13:23:48 -05:00
18
CHANGELOG.md
18
CHANGELOG.md
@@ -124,6 +124,24 @@ This version includes a few minor updates to fzf's classic visual style:
|
|||||||
- Markers no longer use background colors.
|
- Markers no longer use background colors.
|
||||||
- The `--color base16` theme (alias: `16`) has been updated for better compatibility with both dark and light themes.
|
- The `--color base16` theme (alias: `16`) has been updated for better compatibility with both dark and light themes.
|
||||||
|
|
||||||
|
### `--listen` now supports Unix domain sockets
|
||||||
|
|
||||||
|
If an argument to `--listen` ends with `.sock`, fzf will listen on a Unix
|
||||||
|
domain socket at the specified path.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
fzf --listen /tmp/fzf.sock --no-tmux
|
||||||
|
|
||||||
|
# GET
|
||||||
|
curl --unix-socket /tmp/fzf.sock http
|
||||||
|
|
||||||
|
# POST
|
||||||
|
curl --unix-socket /tmp/fzf.sock http -d up
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that any existing file at the given path will be removed before creating
|
||||||
|
the socket, so avoid using an important file path.
|
||||||
|
|
||||||
### Added options
|
### Added options
|
||||||
|
|
||||||
#### `--gutter CHAR`
|
#### `--gutter CHAR`
|
||||||
|
|||||||
@@ -1133,19 +1133,25 @@ On Windows, the default value is \fBcmd /s/c\fR when \fB$SHELL\fR is not
|
|||||||
set.
|
set.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-listen[=[ADDR:]PORT]" "\-\-listen\-unsafe[=[ADDR:]PORT]"
|
.B "\-\-listen[=SOCKET_PATH|[ADDR:]PORT]" "\-\-listen\-unsafe[=[ADDR:]PORT]"
|
||||||
Start HTTP server and listen on the given address. It allows external processes
|
Start HTTP server and listen on the given address or Unix socket. It allows
|
||||||
to send actions to perform via POST method.
|
external processes to send actions to perform via POST method and query the
|
||||||
|
program state via GET method. For the argument to be recognized as a socket
|
||||||
|
path, it must have \fB.sock\fR extension.
|
||||||
|
|
||||||
- If the port number is omitted or given as 0, fzf will automatically choose
|
- If the port number is omitted or given as 0, fzf will automatically choose
|
||||||
a port and export it as \fBFZF_PORT\fR environment variable to the child processes
|
a port and export it as \fBFZF_PORT\fR environment variable to the child processes.
|
||||||
|
|
||||||
|
- If a Unix socket path is given, fzf will create a Unix domain socket at the
|
||||||
|
given path. The existing file will be removed. The path to the socket file
|
||||||
|
is exported as \fBFZF_SOCK\fR environment variable.
|
||||||
|
|
||||||
- If \fBFZF_API_KEY\fR environment variable is set, the server would require
|
- If \fBFZF_API_KEY\fR environment variable is set, the server would require
|
||||||
sending an API key with the same value in the \fBx\-api\-key\fR HTTP header
|
sending an API key with the same value in the \fBx\-api\-key\fR HTTP header.
|
||||||
|
|
||||||
- \fBFZF_API_KEY\fR is required for a non-localhost listen address
|
- \fBFZF_API_KEY\fR is required for a non-localhost listen address.
|
||||||
|
|
||||||
- To allow remote process execution, use \fB\-\-listen\-unsafe\fR
|
- To allow remote process execution, use \fB\-\-listen\-unsafe\fR.
|
||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
\fB# Start HTTP server on port 6266
|
\fB# Start HTTP server on port 6266
|
||||||
@@ -1184,6 +1190,18 @@ e.g.
|
|||||||
'
|
'
|
||||||
\fR
|
\fR
|
||||||
|
|
||||||
|
Here is an example script that uses a Unix socket instead of a TCP port.
|
||||||
|
|
||||||
|
\fB
|
||||||
|
fzf --listen=/tmp/fzf.sock
|
||||||
|
|
||||||
|
# GET
|
||||||
|
curl --unix-socket /tmp/fzf.sock http
|
||||||
|
|
||||||
|
# POST
|
||||||
|
curl --unix-socket /tmp/fzf.sock http -d up
|
||||||
|
\fR
|
||||||
|
|
||||||
.SS DIRECTORY TRAVERSAL
|
.SS DIRECTORY TRAVERSAL
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-walker=[file][,dir][,follow][,hidden]"
|
.B "\-\-walker=[file][,dir][,follow][,hidden]"
|
||||||
@@ -1373,6 +1391,8 @@ fzf exports the following environment variables to its child processes.
|
|||||||
.br
|
.br
|
||||||
.BR FZF_PORT " Port number when \-\-listen option is used"
|
.BR FZF_PORT " Port number when \-\-listen option is used"
|
||||||
.br
|
.br
|
||||||
|
.BR FZF_SOCK " Unix socket path when \-\-listen option is used"
|
||||||
|
.br
|
||||||
.BR FZF_PREVIEW_TOP " Top position of the preview window"
|
.BR FZF_PREVIEW_TOP " Top position of the preview window"
|
||||||
.br
|
.br
|
||||||
.BR FZF_PREVIEW_LEFT " Left position of the preview window"
|
.BR FZF_PREVIEW_LEFT " Left position of the preview window"
|
||||||
|
|||||||
@@ -206,7 +206,9 @@ Usage: fzf [options]
|
|||||||
|
|
||||||
ADVANCED
|
ADVANCED
|
||||||
--with-shell=STR Shell command and flags to start child processes with
|
--with-shell=STR Shell command and flags to start child processes with
|
||||||
--listen[=[ADDR:]PORT] Start HTTP server to receive actions (POST /)
|
--listen[=SOCKET_PATH] Start HTTP server to receive actions via Unix domain socket
|
||||||
|
(Path should end with .sock)
|
||||||
|
--listen[=[ADDR:]PORT] Start HTTP server to receive actions via TCP
|
||||||
(To allow remote process execution, use --listen-unsafe)
|
(To allow remote process execution, use --listen-unsafe)
|
||||||
|
|
||||||
DIRECTORY TRAVERSAL (Only used when $FZF_DEFAULT_COMMAND is not set)
|
DIRECTORY TRAVERSAL (Only used when $FZF_DEFAULT_COMMAND is not set)
|
||||||
|
|||||||
@@ -46,15 +46,20 @@ type httpServer struct {
|
|||||||
type listenAddress struct {
|
type listenAddress struct {
|
||||||
host string
|
host string
|
||||||
port int
|
port int
|
||||||
|
sock string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (addr listenAddress) IsLocal() bool {
|
func (addr listenAddress) IsLocal() bool {
|
||||||
return addr.host == "localhost" || addr.host == "127.0.0.1"
|
return addr.host == "localhost" || addr.host == "127.0.0.1" || len(addr.sock) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultListenAddr = listenAddress{"localhost", 0}
|
var defaultListenAddr = listenAddress{"localhost", 0, ""}
|
||||||
|
|
||||||
func parseListenAddress(address string) (listenAddress, error) {
|
func parseListenAddress(address string) (listenAddress, error) {
|
||||||
|
if strings.HasSuffix(address, ".sock") {
|
||||||
|
return listenAddress{"", 0, address}, nil
|
||||||
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(address, ":", 3)
|
parts := strings.SplitN(address, ":", 3)
|
||||||
if len(parts) == 1 {
|
if len(parts) == 1 {
|
||||||
parts = []string{"localhost", parts[0]}
|
parts = []string{"localhost", parts[0]}
|
||||||
@@ -70,7 +75,7 @@ func parseListenAddress(address string) (listenAddress, error) {
|
|||||||
if len(parts[0]) == 0 {
|
if len(parts[0]) == 0 {
|
||||||
parts[0] = "localhost"
|
parts[0] = "localhost"
|
||||||
}
|
}
|
||||||
return listenAddress{parts[0], port}, nil
|
return listenAddress{parts[0], port, ""}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startHttpServer(address listenAddress, actionChannel chan []*action, getHandler func(getParams) string) (net.Listener, int, error) {
|
func startHttpServer(address listenAddress, actionChannel chan []*action, getHandler func(getParams) string) (net.Listener, int, error) {
|
||||||
@@ -80,8 +85,18 @@ func startHttpServer(address listenAddress, actionChannel chan []*action, getHan
|
|||||||
if !address.IsLocal() && len(apiKey) == 0 {
|
if !address.IsLocal() && len(apiKey) == 0 {
|
||||||
return nil, port, errors.New("FZF_API_KEY is required to allow remote access")
|
return nil, port, errors.New("FZF_API_KEY is required to allow remote access")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var listener net.Listener
|
||||||
|
var err error
|
||||||
|
if len(address.sock) > 0 {
|
||||||
|
os.Remove(address.sock)
|
||||||
|
listener, err = net.Listen("unix", address.sock)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("failed to listen on %s", address.sock)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
addrStr := fmt.Sprintf("%s:%d", host, port)
|
addrStr := fmt.Sprintf("%s:%d", host, port)
|
||||||
listener, err := net.Listen("tcp", addrStr)
|
listener, err = net.Listen("tcp", addrStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, port, fmt.Errorf("failed to listen on %s", addrStr)
|
return nil, port, fmt.Errorf("failed to listen on %s", addrStr)
|
||||||
}
|
}
|
||||||
@@ -97,6 +112,7 @@ func startHttpServer(address listenAddress, actionChannel chan []*action, getHan
|
|||||||
return nil, port, err
|
return nil, port, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
server := httpServer{
|
server := httpServer{
|
||||||
apiKey: []byte(apiKey),
|
apiKey: []byte(apiKey),
|
||||||
|
|||||||
@@ -1268,8 +1268,10 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
t.listener = listener
|
t.listener = listener
|
||||||
|
if port > 0 {
|
||||||
t.listenPort = &port
|
t.listenPort = &port
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if t.hasStartActions {
|
if t.hasStartActions {
|
||||||
t.eventChan <- tui.Start.AsEvent()
|
t.eventChan <- tui.Start.AsEvent()
|
||||||
@@ -1292,6 +1294,9 @@ func (t *Terminal) environForPreview() []string {
|
|||||||
|
|
||||||
func (t *Terminal) environImpl(forPreview bool) []string {
|
func (t *Terminal) environImpl(forPreview bool) []string {
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
|
if t.listenAddr != nil && len(t.listenAddr.sock) > 0 {
|
||||||
|
env = append(env, "FZF_SOCK="+t.listenAddr.sock)
|
||||||
|
}
|
||||||
if t.listenPort != nil {
|
if t.listenPort != nil {
|
||||||
env = append(env, fmt.Sprintf("FZF_PORT=%d", *t.listenPort))
|
env = append(env, fmt.Sprintf("FZF_PORT=%d", *t.listenPort))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user