Skip to content

Commit

Permalink
Add --tmux option to replace fzf-tmux script
Browse files Browse the repository at this point in the history
  • Loading branch information
junegunn committed May 18, 2024
1 parent 01e7668 commit 83b6033
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 9 deletions.
6 changes: 4 additions & 2 deletions bin/fzf-tmux
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,10 @@ if [[ -z "$TMUX" ]]; then
exit $?
fi

# --height option is not allowed. CTRL-Z is also disabled.
args=("${args[@]}" "--no-height" "--bind=ctrl-z:ignore")
# * --height option is not allowed
# * CTRL-Z is also disabled
# * fzf-tmux script is not compatible with --tmux option in fzf 0.53.0 or later
args=("${args[@]}" "--no-height" "--bind=ctrl-z:ignore" "--no-tmux")

# Handle zoomed tmux pane without popup options by moving it to a temp window
if [[ ! "$opt" =~ "-E" ]] && tmux list-panes -F '#F' | grep -q Z; then
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func printScript(label string, content []byte) {
}

func exit(code int, err error) {
if err != nil {
if code == fzf.ExitError {
fmt.Fprintln(os.Stderr, err.Error())
}
os.Exit(code)
Expand Down
2 changes: 1 addition & 1 deletion man/man1/fzf-tmux.1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
..
.TH fzf-tmux 1 "May 2024" "fzf 0.52.1" "fzf-tmux - open fzf in tmux split pane"
.TH fzf-tmux 1 "May 2024" "fzf 0.53.0" "fzf-tmux - open fzf in tmux split pane"

.SH NAME
fzf-tmux - open fzf in tmux split pane
Expand Down
20 changes: 19 additions & 1 deletion man/man1/fzf.1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
..
.TH fzf 1 "May 2024" "fzf 0.52.1" "fzf - a command-line fuzzy finder"
.TH fzf 1 "May 2024" "fzf 0.53.0" "fzf - a command-line fuzzy finder"

.SH NAME
fzf - a command-line fuzzy finder
Expand Down Expand Up @@ -215,6 +215,24 @@ compatible with a negative height value.
.BI "--min-height=" "HEIGHT"
Minimum height when \fB--height\fR is given in percent (default: 10).
Ignored when \fB--height\fR is not specified.
.TP
.BI "--tmux=" "[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]"
Start fzf in a tmux popup. Requires tmux 3.3 or later. This option is ignored
if you are not running fzf inside tmux.

e.g.
\fB# Popup in the center with 80% width height
fzf --tmux 80%

# Popup on the left with 40% width and 100% height
fzf --tmux right,40%

# Popup on the bottom with 100% width and 30% height
fzf --tmux bottom,30%

# Popup on the top with 80% width and 40% height
fzf --tmux top,80%,40%\fR

.TP
.BI "--layout=" "LAYOUT"
Choose the layout (default: default)
Expand Down
4 changes: 2 additions & 2 deletions plugin/fzf.vim
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,10 @@ try
let use_term = 0
endif
if use_term
let optstr .= ' --no-height'
let optstr .= ' --no-height --no-tmux'
elseif use_height
let height = s:calc_size(&lines, dict.down, dict)
let optstr .= ' --height='.height
let optstr .= ' --no-tmux --height='.height
endif
" Respect --border option given in $FZF_DEFAULT_OPTS and 'options'
let optstr = join([s:border_opt(get(dict, 'window', 0)), s:extract_option($FZF_DEFAULT_OPTS, 'border'), optstr])
Expand Down
5 changes: 5 additions & 0 deletions src/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package fzf

import (
"os"
"sync"
"time"

Expand All @@ -19,6 +20,10 @@ Matcher -> EvtHeader -> Terminal (update header)

// Run starts fzf
func Run(opts *Options) (int, error) {
if opts.Tmux != nil && len(os.Getenv("TMUX")) > 0 {
return runTmux(os.Args[1:], opts)
}

if err := postProcessOptions(opts); err != nil {
return ExitError, err
}
Expand Down
2 changes: 1 addition & 1 deletion src/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

func writeTemporaryFile(data []string, printSep string) string {
f, err := os.CreateTemp("", "fzf-preview-*")
f, err := os.CreateTemp("", "fzf-temp-*")
if err != nil {
// Unable to create temporary file
// FIXME: Should we terminate the program?
Expand Down
103 changes: 103 additions & 0 deletions src/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ const Usage = `usage: fzf [options]
according to the input size.
--min-height=HEIGHT Minimum height when --height is given in percent
(default: 10)
--tmux=OPTS Start fzf in a tmux popup (requires tmux 3.3+)
[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
--border[=STYLE] Draw border around the finder
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical|
Expand Down Expand Up @@ -180,6 +182,13 @@ type sizeSpec struct {
percent bool
}

func (s sizeSpec) String() string {
if s.percent {
return fmt.Sprintf("%d%%", int(s.size))
}
return fmt.Sprintf("%d", int(s.size))
}

func defaultMargin() [4]sizeSpec {
return [4]sizeSpec{}
}
Expand All @@ -199,8 +208,15 @@ const (
posDown
posLeft
posRight
posCenter
)

type tmuxOptions struct {
width sizeSpec
height sizeSpec
position windowPosition
}

type layoutType int

const (
Expand Down Expand Up @@ -248,6 +264,74 @@ func (o *previewOpts) Toggle() {
o.hidden = !o.hidden
}

func parseTmuxOptions(arg string) (*tmuxOptions, error) {
var err error
opts := tmuxOptions{}
tokens := splitRegexp.Split(arg, -1)
if len(tokens) == 0 || len(tokens) > 3 {
return nil, errors.New("invalid tmux option: " + arg + " (expected: [center|top|bottom|left|right][,SIZE[%]][,SIZE[%]])")
}

// Defaults to 'center'
switch tokens[0] {
case "top", "up":
opts.position = posUp
opts.width = sizeSpec{100, true}
case "bottom", "down":
opts.position = posDown
opts.width = sizeSpec{100, true}
case "left":
opts.position = posLeft
opts.height = sizeSpec{100, true}
case "right":
opts.position = posRight
opts.height = sizeSpec{100, true}
case "center":
opts.position = posCenter
opts.width = sizeSpec{50, true}
opts.height = sizeSpec{50, true}
default:
opts.position = posCenter
opts.width = sizeSpec{50, true}
opts.height = sizeSpec{50, true}
tokens = append([]string{"center"}, tokens...)
}

// One size given
var size1 sizeSpec
if len(tokens) > 1 {
if size1, err = parseSize(tokens[1], 100, "size"); err != nil {
return nil, err
}
}

// Two sizes given
var size2 sizeSpec
if len(tokens) == 3 {
if size2, err = parseSize(tokens[2], 100, "size"); err != nil {
return nil, err
}
opts.width = size1
opts.height = size2
} else if len(tokens) == 2 {
switch tokens[0] {
case "top", "up":
opts.height = size1
case "bottom", "down":
opts.height = size1
case "left":
opts.width = size1
case "right":
opts.width = size1
case "center":
opts.width = size1
opts.height = size1
}
}

return &opts, nil
}

func parseLabelPosition(opts *labelOpts, arg string) error {
opts.column = 0
opts.bottom = false
Expand Down Expand Up @@ -296,6 +380,7 @@ type walkerOpts struct {
type Options struct {
Input chan string
Output chan string
Tmux *tmuxOptions
Bash bool
Zsh bool
Fish bool
Expand Down Expand Up @@ -1787,6 +1872,16 @@ func parseOptions(opts *Options, allArgs []string) error {
case "--version":
clearExitingOpts()
opts.Version = true
case "--tmux":
str, err := nextString(allArgs, &i, "tmux options required")
if err != nil {
return err
}
if opts.Tmux, err = parseTmuxOptions(str); err != nil {
return err
}
case "--no-tmux":
opts.Tmux = nil
case "-x", "--extended":
opts.Extended = true
case "-e", "--exact":
Expand Down Expand Up @@ -2264,6 +2359,10 @@ func parseOptions(opts *Options, allArgs []string) error {
if opts.FuzzyAlgo, err = parseAlgo(value); err != nil {
return err
}
} else if match, value := optString(arg, "--tmux="); match {
if opts.Tmux, err = parseTmuxOptions(value); err != nil {
return err
}
} else if match, value := optString(arg, "--scheme="); match {
opts.Scheme = strings.ToLower(value)
} else if match, value := optString(arg, "-q", "--query="); match {
Expand Down Expand Up @@ -2478,6 +2577,10 @@ func postProcessOptions(opts *Options) error {
uniseg.EastAsianAmbiguousWidth = 2
}

if opts.BorderShape == tui.BorderUndefined {
opts.BorderShape = tui.BorderNone
}

if err := validateSign(opts.Pointer, "pointer"); err != nil {
return err
}
Expand Down
Loading

0 comments on commit 83b6033

Please sign in to comment.