mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2024-11-08 14:50:55 +00:00
Add --tmux option to replace fzf-tmux script
This commit is contained in:
parent
01e7668915
commit
83b6033906
@ -132,8 +132,10 @@ if [[ -z "$TMUX" ]]; then
|
|||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --height option is not allowed. CTRL-Z is also disabled.
|
# * --height option is not allowed
|
||||||
args=("${args[@]}" "--no-height" "--bind=ctrl-z:ignore")
|
# * 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
|
# 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
|
if [[ ! "$opt" =~ "-E" ]] && tmux list-panes -F '#F' | grep -q Z; then
|
||||||
|
2
main.go
2
main.go
@ -35,7 +35,7 @@ func printScript(label string, content []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func exit(code int, err error) {
|
func exit(code int, err error) {
|
||||||
if err != nil {
|
if code == fzf.ExitError {
|
||||||
fmt.Fprintln(os.Stderr, err.Error())
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
}
|
}
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
|
@ -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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
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
|
.SH NAME
|
||||||
fzf-tmux - open fzf in tmux split pane
|
fzf-tmux - open fzf in tmux split pane
|
||||||
|
@ -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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
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
|
.SH NAME
|
||||||
fzf - a command-line fuzzy finder
|
fzf - a command-line fuzzy finder
|
||||||
@ -215,6 +215,24 @@ compatible with a negative height value.
|
|||||||
.BI "--min-height=" "HEIGHT"
|
.BI "--min-height=" "HEIGHT"
|
||||||
Minimum height when \fB--height\fR is given in percent (default: 10).
|
Minimum height when \fB--height\fR is given in percent (default: 10).
|
||||||
Ignored when \fB--height\fR is not specified.
|
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
|
.TP
|
||||||
.BI "--layout=" "LAYOUT"
|
.BI "--layout=" "LAYOUT"
|
||||||
Choose the layout (default: default)
|
Choose the layout (default: default)
|
||||||
|
@ -537,10 +537,10 @@ try
|
|||||||
let use_term = 0
|
let use_term = 0
|
||||||
endif
|
endif
|
||||||
if use_term
|
if use_term
|
||||||
let optstr .= ' --no-height'
|
let optstr .= ' --no-height --no-tmux'
|
||||||
elseif use_height
|
elseif use_height
|
||||||
let height = s:calc_size(&lines, dict.down, dict)
|
let height = s:calc_size(&lines, dict.down, dict)
|
||||||
let optstr .= ' --height='.height
|
let optstr .= ' --no-tmux --height='.height
|
||||||
endif
|
endif
|
||||||
" Respect --border option given in $FZF_DEFAULT_OPTS and 'options'
|
" 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])
|
let optstr = join([s:border_opt(get(dict, 'window', 0)), s:extract_option($FZF_DEFAULT_OPTS, 'border'), optstr])
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package fzf
|
package fzf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -19,6 +20,10 @@ Matcher -> EvtHeader -> Terminal (update header)
|
|||||||
|
|
||||||
// Run starts fzf
|
// Run starts fzf
|
||||||
func Run(opts *Options) (int, error) {
|
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 {
|
if err := postProcessOptions(opts); err != nil {
|
||||||
return ExitError, err
|
return ExitError, err
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func writeTemporaryFile(data []string, printSep string) string {
|
func writeTemporaryFile(data []string, printSep string) string {
|
||||||
f, err := os.CreateTemp("", "fzf-preview-*")
|
f, err := os.CreateTemp("", "fzf-temp-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Unable to create temporary file
|
// Unable to create temporary file
|
||||||
// FIXME: Should we terminate the program?
|
// FIXME: Should we terminate the program?
|
||||||
|
103
src/options.go
103
src/options.go
@ -63,6 +63,8 @@ const Usage = `usage: fzf [options]
|
|||||||
according to the input size.
|
according to the input size.
|
||||||
--min-height=HEIGHT Minimum height when --height is given in percent
|
--min-height=HEIGHT Minimum height when --height is given in percent
|
||||||
(default: 10)
|
(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]
|
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
||||||
--border[=STYLE] Draw border around the finder
|
--border[=STYLE] Draw border around the finder
|
||||||
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical|
|
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical|
|
||||||
@ -180,6 +182,13 @@ type sizeSpec struct {
|
|||||||
percent bool
|
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 {
|
func defaultMargin() [4]sizeSpec {
|
||||||
return [4]sizeSpec{}
|
return [4]sizeSpec{}
|
||||||
}
|
}
|
||||||
@ -199,8 +208,15 @@ const (
|
|||||||
posDown
|
posDown
|
||||||
posLeft
|
posLeft
|
||||||
posRight
|
posRight
|
||||||
|
posCenter
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type tmuxOptions struct {
|
||||||
|
width sizeSpec
|
||||||
|
height sizeSpec
|
||||||
|
position windowPosition
|
||||||
|
}
|
||||||
|
|
||||||
type layoutType int
|
type layoutType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -248,6 +264,74 @@ func (o *previewOpts) Toggle() {
|
|||||||
o.hidden = !o.hidden
|
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 {
|
func parseLabelPosition(opts *labelOpts, arg string) error {
|
||||||
opts.column = 0
|
opts.column = 0
|
||||||
opts.bottom = false
|
opts.bottom = false
|
||||||
@ -296,6 +380,7 @@ type walkerOpts struct {
|
|||||||
type Options struct {
|
type Options struct {
|
||||||
Input chan string
|
Input chan string
|
||||||
Output chan string
|
Output chan string
|
||||||
|
Tmux *tmuxOptions
|
||||||
Bash bool
|
Bash bool
|
||||||
Zsh bool
|
Zsh bool
|
||||||
Fish bool
|
Fish bool
|
||||||
@ -1787,6 +1872,16 @@ func parseOptions(opts *Options, allArgs []string) error {
|
|||||||
case "--version":
|
case "--version":
|
||||||
clearExitingOpts()
|
clearExitingOpts()
|
||||||
opts.Version = true
|
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":
|
case "-x", "--extended":
|
||||||
opts.Extended = true
|
opts.Extended = true
|
||||||
case "-e", "--exact":
|
case "-e", "--exact":
|
||||||
@ -2264,6 +2359,10 @@ func parseOptions(opts *Options, allArgs []string) error {
|
|||||||
if opts.FuzzyAlgo, err = parseAlgo(value); err != nil {
|
if opts.FuzzyAlgo, err = parseAlgo(value); err != nil {
|
||||||
return err
|
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 {
|
} else if match, value := optString(arg, "--scheme="); match {
|
||||||
opts.Scheme = strings.ToLower(value)
|
opts.Scheme = strings.ToLower(value)
|
||||||
} else if match, value := optString(arg, "-q", "--query="); match {
|
} else if match, value := optString(arg, "-q", "--query="); match {
|
||||||
@ -2478,6 +2577,10 @@ func postProcessOptions(opts *Options) error {
|
|||||||
uniseg.EastAsianAmbiguousWidth = 2
|
uniseg.EastAsianAmbiguousWidth = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.BorderShape == tui.BorderUndefined {
|
||||||
|
opts.BorderShape = tui.BorderNone
|
||||||
|
}
|
||||||
|
|
||||||
if err := validateSign(opts.Pointer, "pointer"); err != nil {
|
if err := validateSign(opts.Pointer, "pointer"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
149
src/tmux.go
Normal file
149
src/tmux.go
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package fzf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/junegunn/fzf/src/tui"
|
||||||
|
"github.com/junegunn/fzf/src/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func escapeSingleQuote(str string) string {
|
||||||
|
return "'" + strings.ReplaceAll(str, "'", "'\\''") + "'"
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTmux(args []string, opts *Options) (int, error) {
|
||||||
|
ns := time.Now().UnixNano()
|
||||||
|
|
||||||
|
output := filepath.Join(os.TempDir(), fmt.Sprintf("fzf-tmux-output-%d", ns))
|
||||||
|
if err := mkfifo(output, 0666); err != nil {
|
||||||
|
return ExitError, err
|
||||||
|
}
|
||||||
|
defer os.Remove(output)
|
||||||
|
|
||||||
|
// Find fzf executable
|
||||||
|
fzf := "fzf"
|
||||||
|
if found, err := os.Executable(); err == nil {
|
||||||
|
fzf = found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare arguments
|
||||||
|
args = append([]string{"--bind=ctrl-z:ignore"}, args...)
|
||||||
|
if opts.BorderShape == tui.BorderUndefined {
|
||||||
|
args = append(args, "--border")
|
||||||
|
}
|
||||||
|
args = append(args, "--no-height")
|
||||||
|
args = append(args, "--no-tmux")
|
||||||
|
argStr := ""
|
||||||
|
for _, arg := range args {
|
||||||
|
// %q formatting escapes $'foo\nbar' to "foo\nbar"
|
||||||
|
argStr += " " + escapeSingleQuote(arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build command
|
||||||
|
var command string
|
||||||
|
if opts.Input == nil && util.IsTty() {
|
||||||
|
command = fmt.Sprintf(`%q%s > %q`, fzf, argStr, output)
|
||||||
|
} else {
|
||||||
|
input := filepath.Join(os.TempDir(), fmt.Sprintf("fzf-tmux-input-%d", ns))
|
||||||
|
if err := mkfifo(input, 0644); err != nil {
|
||||||
|
return ExitError, err
|
||||||
|
}
|
||||||
|
defer os.Remove(input)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
inputFile, err := os.OpenFile(input, os.O_WRONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if opts.Input == nil {
|
||||||
|
io.Copy(inputFile, os.Stdin)
|
||||||
|
} else {
|
||||||
|
for item := range opts.Input {
|
||||||
|
fmt.Fprint(inputFile, item+opts.PrintSep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputFile.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
command = fmt.Sprintf(`%q%s < %q > %q`, fzf, argStr, input, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current directory
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
dir = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set tmux options for popup placement
|
||||||
|
// C Both The centre of the terminal
|
||||||
|
// R -x The right side of the terminal
|
||||||
|
// P Both The bottom left of the pane
|
||||||
|
// M Both The mouse position
|
||||||
|
// W Both The window position on the status line
|
||||||
|
// S -y The line above or below the status line
|
||||||
|
tmuxArgs := []string{"display-popup", "-E", "-B", "-d", dir}
|
||||||
|
switch opts.Tmux.position {
|
||||||
|
case posUp:
|
||||||
|
tmuxArgs = append(tmuxArgs, "-xC", "-y0")
|
||||||
|
case posDown:
|
||||||
|
tmuxArgs = append(tmuxArgs, "-xC", "-yS")
|
||||||
|
case posLeft:
|
||||||
|
tmuxArgs = append(tmuxArgs, "-x0", "-yC")
|
||||||
|
case posRight:
|
||||||
|
tmuxArgs = append(tmuxArgs, "-xR", "-yC")
|
||||||
|
case posCenter:
|
||||||
|
tmuxArgs = append(tmuxArgs, "-xC", "-yC")
|
||||||
|
}
|
||||||
|
tmuxArgs = append(tmuxArgs, "-w"+opts.Tmux.width.String())
|
||||||
|
tmuxArgs = append(tmuxArgs, "-h"+opts.Tmux.height.String())
|
||||||
|
|
||||||
|
// To ensure that the options are processed by a POSIX-compliant shell,
|
||||||
|
// we need to write the command to a temporary file and execute it with sh.
|
||||||
|
exports := os.Environ()
|
||||||
|
for idx, pairStr := range exports {
|
||||||
|
pair := strings.SplitN(pairStr, "=", 2)
|
||||||
|
exports[idx] = fmt.Sprintf("export %s=%s", pair[0], escapeSingleQuote(pair[1]))
|
||||||
|
}
|
||||||
|
temp := writeTemporaryFile(append(exports, command), "\n")
|
||||||
|
defer os.Remove(temp)
|
||||||
|
tmuxArgs = append(tmuxArgs, "sh", temp)
|
||||||
|
|
||||||
|
// Take the output
|
||||||
|
go func() {
|
||||||
|
outputFile, err := os.OpenFile(output, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if opts.Output == nil {
|
||||||
|
io.Copy(os.Stdout, outputFile)
|
||||||
|
} else {
|
||||||
|
reader := bufio.NewReader(outputFile)
|
||||||
|
sep := opts.PrintSep[0]
|
||||||
|
for {
|
||||||
|
item, err := reader.ReadString(sep)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
opts.Output <- item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFile.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmd := exec.Command("tmux", tmuxArgs...)
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
if exitError, ok := err.(*exec.ExitError); ok {
|
||||||
|
return exitError.ExitCode(), err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExitOk, nil
|
||||||
|
}
|
9
src/tmux_unix.go
Normal file
9
src/tmux_unix.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package fzf
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
func mkfifo(path string, mode uint32) error {
|
||||||
|
return unix.Mkfifo(path, mode)
|
||||||
|
}
|
17
src/tmux_windows.go
Normal file
17
src/tmux_windows.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package fzf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mkfifo(path string, mode uint32) error {
|
||||||
|
m := strconv.FormatUint(uint64(mode), 8)
|
||||||
|
cmd := exec.Command("mkfifo", "-m", m, path)
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -356,7 +356,8 @@ type MouseEvent struct {
|
|||||||
type BorderShape int
|
type BorderShape int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BorderNone BorderShape = iota
|
BorderUndefined BorderShape = iota
|
||||||
|
BorderNone
|
||||||
BorderRounded
|
BorderRounded
|
||||||
BorderSharp
|
BorderSharp
|
||||||
BorderBold
|
BorderBold
|
||||||
|
Loading…
Reference in New Issue
Block a user