Skip to content
Draft

wip #4645

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#/bin/sh
export CGO_ENABLED=1
rm -rf /tmp/go-link-*
rm -rf /tmp/go-build*
go clean -r -cache -testcache -modcache
go build -a -buildvcs=false -ldflags="-linkmode=internal" .
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module github.com/junegunn/fzf

require (
github.com/gdamore/tcell/v2 v2.5.4
github.com/mattn/go-isatty v0.0.17
github.com/mattn/go-runewidth v0.0.14
github.com/mattn/go-shellwords v1.0.12
github.com/rivo/uniseg v0.4.4
Expand Down
3 changes: 1 addition & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ github.com/gdamore/tcell/v2 v2.5.4 h1:TGU4tSjD3sCL788vFNeJnTdzpNKIw1H5dgLnJRQVv/
github.com/gdamore/tcell/v2 v2.5.4/go.mod h1:dZgRy5v4iMobMEcWNYBtREnDZAT9DYmfqIkrgEMxLyw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
Expand All @@ -31,6 +29,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
46 changes: 43 additions & 3 deletions src/terminal_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,66 @@

package fzf

/*
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

// Wrapper for kill(2)
int native_kill(pid_t pid, int sig) {
return kill(pid, sig);
}

// Wrapper for getpgid(2)
pid_t native_getpgid(pid_t pid) {
return getpgid(pid);
}
*/
import "C"
import (
"os"
"os/signal"
"strings"
"syscall"
"fmt"

"golang.org/x/sys/unix"
// "golang.org/x/sys/unix"
)

// Kill sends a signal to a process.
func Kill(pid int, signal syscall.Signal) error {
// C.kill returns 0 on success, -1 on failure
res := C.native_kill(C.pid_t(pid), C.int(signal))
if res != 0 {
return fmt.Errorf("kill failed for pid %d", pid)
}
return nil
}


// Getpgid returns the process group ID for the given process ID.
func Getpgid(pid int) (int, error) {
// C.getpgid returns the PGID or -1 on failure
res := C.native_getpgid(C.pid_t(pid))
if res < 0 {
return 0, fmt.Errorf("getpgid failed for pid %d", pid)
}
return int(res), nil
}



func notifyOnResize(resizeChan chan<- os.Signal) {
signal.Notify(resizeChan, syscall.SIGWINCH)
}

func notifyStop(p *os.Process) {
pid := p.Pid
pgid, err := unix.Getpgid(pid)
pgid, err := Getpgid(pid)
if err == nil {
pid = pgid * -1
}
unix.Kill(pid, syscall.SIGSTOP)
Kill(pid, syscall.SIGSTOP)
}

func notifyOnCont(resizeChan chan<- os.Signal) {
Expand Down
135 changes: 125 additions & 10 deletions src/tui/light_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,113 @@

package tui

/*
#include <sys/ioctl.h>
#include <unistd.h>
#include <termios.h>

// Simple wrapper to call the ioctl
int native_get_winsize(int fd, struct winsize *ws) {
return ioctl(fd, TIOCGWINSZ, ws);
}

// Wrapper to call the stable POSIX tcgetattr function
int get_terminal_state(int fd, struct termios *t) {
return tcgetattr(fd, t);
}

// Helper to manually set the terminal to raw mode using Haiku's C headers
int haiku_make_raw(int fd, struct termios *old) {
struct termios raw;
if (tcgetattr(fd, old) != 0) return -1;
raw = *old;

// POSIX raw mode flags
raw.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
raw.c_oflag &= ~OPOST;
raw.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
raw.c_cflag &= ~(CSIZE | PARENB);
raw.c_cflag |= CS8;
raw.c_cc[VMIN] = 1;
raw.c_cc[VTIME] = 0;

return tcsetattr(fd, TCSAFLUSH, &raw);
}

int haiku_restore(int fd, struct termios *old) {
return tcsetattr(fd, TCSAFLUSH, old);
}
*/
import "C"
import (
"fmt"
"os"
"os/exec"
"strings"
"syscall"
"errors"
"unsafe"

"github.com/junegunn/fzf/src/util"
"golang.org/x/sys/unix"
// "golang.org/x/sys/unix"
"golang.org/x/term"
)

// State wraps the C termios structure to keep it compatible with your existing code.
type State struct {
state
}

type state struct {
termios C.struct_termios
}

func MakeRaw(fd int) (*State, error) {
var oldState state
if C.haiku_make_raw(C.int(fd), &oldState.termios) != 0 {
return nil, fmt.Errorf("failed to set raw mode on Haiku via CGO")
}
return &State{state: oldState}, nil
}

func Restore(fd int, oldState *State) error {
//term_state := (*term.State)(unsafe.Pointer(oldState))
if C.haiku_restore(C.int(fd), &oldState.termios) != 0 {
return fmt.Errorf("haiku: failed to restore terminal")
}
return nil
}

// Attempt to replace:
// Ref: https://cs.opensource.google/go/x/term/+/refs/tags/v0.38.0:term_unix.go
// func getState(fd int) (*State, error) {
// termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
// if err != nil {
// return nil, err
// }
//
// return &State{state{termios: *termios}}, nil
//}

func GetState(fd int) (*State, error) {
var t C.struct_termios

// Call the C wrapper. 0 is success, -1 is failure.
if C.get_terminal_state(C.int(fd), &t) != 0 {
return nil, errors.New("failed to get terminal state (tcgetattr)")
}

return &State{state{termios: t}}, nil
}

// Winsize matches the POSIX terminal window size structure
type Winsize struct {
Rows uint16
Cols uint16
Xpixel uint16
Ypixel uint16
}

func IsLightRendererSupported() bool {
return true
}
Expand All @@ -35,12 +130,16 @@ func (r *LightRenderer) fd() int {

func (r *LightRenderer) initPlatform() error {
fd := r.fd()
origState, err := term.GetState(fd)
if err != nil {
origState, err := GetState(fd)
// if err != nil {
// return err
// }
if false {
return err
}
r.origState = origState
term.MakeRaw(fd)
r.origState = (*term.State)(unsafe.Pointer(origState))

MakeRaw(fd)
return nil
}

Expand All @@ -64,11 +163,14 @@ func openTtyIn() *os.File {
}

func (r *LightRenderer) setupTerminal() {
term.MakeRaw(r.fd())
MakeRaw(r.fd())
}

func (r *LightRenderer) restoreTerminal() {
term.Restore(r.fd(), r.origState)

state := (*State)(unsafe.Pointer(r.origState))
Restore(r.fd(), state)
//Restore(r.fd(), r.origState)
}

func (r *LightRenderer) updateTerminalSize() {
Expand Down Expand Up @@ -111,9 +213,22 @@ func (r *LightRenderer) getch(nonblock bool) (int, bool) {
}

func (r *LightRenderer) Size() TermSize {
ws, err := unix.IoctlGetWinsize(int(r.ttyin.Fd()), unix.TIOCGWINSZ)
if err != nil {
var ws C.struct_winsize
res := C.native_get_winsize(C.int(r.ttyin.Fd()), &ws)

if res != 0 {
return TermSize{}
}
return TermSize{int(ws.Row), int(ws.Col), int(ws.Xpixel), int(ws.Ypixel)}

return TermSize{int(ws.ws_row), int(ws.ws_col), int(ws.ws_xpixel), int(ws.ws_ypixel)}

// var cRows, cCols C.int
// rs := C.get_terminal_size(C.int(r.ttyin.Fd()), &cRows, &cCols)

// ws, err := unix.IoctlGetWinsize(int(r.ttyin.Fd()), unix.TIOCGWINSZ)
// if err != nil {
// return TermSize{}
// }
// return TermSize{int(ws.Row), int(ws.Col), int(ws.Xpixel), int(ws.Ypixel)}
// return TermSize{0,0,0,0}
}
14 changes: 11 additions & 3 deletions src/util/util.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package util

/*
#include <unistd.h>
*/
import "C"
import (
"math"
"os"
"strings"
"time"

"github.com/mattn/go-isatty"
// "github.com/mattn/go-isatty"
"github.com/mattn/go-runewidth"
"github.com/rivo/uniseg"
)
Expand Down Expand Up @@ -140,12 +144,16 @@ func DurWithin(

// IsTty returns true if stdin is a terminal
func IsTty() bool {
return isatty.IsTerminal(os.Stdin.Fd())
fd := C.int(os.Stdin.Fd())
return (C.isatty(fd) != 0)
//return isatty.IsTerminal(os.Stdin.Fd())
}

// ToTty returns true if stdout is a terminal
func ToTty() bool {
return isatty.IsTerminal(os.Stdout.Fd())
fd := C.int(os.Stdout.Fd())
return (C.isatty(fd) != 0)
//return isatty.IsTerminal(os.Stdout.Fd())
}

// Once returns a function that returns the specified boolean value only once
Expand Down
8 changes: 6 additions & 2 deletions src/util/util_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"os/exec"
"syscall"

"golang.org/x/sys/unix"
// "golang.org/x/sys/unix"
)

// ExecCommand executes the given command with $SHELL
Expand Down Expand Up @@ -49,5 +49,9 @@ func Read(fd int, b []byte) (int, error) {
}

func SetStdin(file *os.File) {
unix.Dup2(int(file.Fd()), 0)
//unix.Dup2(int(file.Fd()), 0)
//unix.Close(0)
//r1, _, errno :=
syscall.Syscall(syscall.SYS_DUP2, uintptr(file.Fd()), uintptr(0), 0)
//_ = r1
}