mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-18 08:13:40 -05:00
This commit enables cpu, mem, block, and mutex profling of the FZF executable. To support flushing the profiles at program exit it adds util.AtExit to register "at exit" functions and mandates that util.Exit is used instead of os.Exit to stop the program. Co-authored-by: Junegunn Choi <junegunn.c@gmail.com>
120 lines
2.5 KiB
Go
120 lines
2.5 KiB
Go
//go:build !windows
|
|
|
|
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/junegunn/fzf/src/util"
|
|
"golang.org/x/sys/unix"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
func IsLightRendererSupported() bool {
|
|
return true
|
|
}
|
|
|
|
func (r *LightRenderer) defaultTheme() *ColorTheme {
|
|
if strings.Contains(os.Getenv("TERM"), "256") {
|
|
return Dark256
|
|
}
|
|
colors, err := exec.Command("tput", "colors").Output()
|
|
if err == nil && atoi(strings.TrimSpace(string(colors)), 16) > 16 {
|
|
return Dark256
|
|
}
|
|
return Default16
|
|
}
|
|
|
|
func (r *LightRenderer) fd() int {
|
|
return int(r.ttyin.Fd())
|
|
}
|
|
|
|
func (r *LightRenderer) initPlatform() error {
|
|
fd := r.fd()
|
|
origState, err := term.GetState(fd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.origState = origState
|
|
term.MakeRaw(fd)
|
|
return nil
|
|
}
|
|
|
|
func (r *LightRenderer) closePlatform() {
|
|
// NOOP
|
|
}
|
|
|
|
func openTtyIn() *os.File {
|
|
in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0)
|
|
if err != nil {
|
|
tty := ttyname()
|
|
if len(tty) > 0 {
|
|
if in, err := os.OpenFile(tty, syscall.O_RDONLY, 0); err == nil {
|
|
return in
|
|
}
|
|
}
|
|
fmt.Fprintln(os.Stderr, "Failed to open "+consoleDevice)
|
|
util.Exit(2)
|
|
}
|
|
return in
|
|
}
|
|
|
|
func (r *LightRenderer) setupTerminal() {
|
|
term.MakeRaw(r.fd())
|
|
}
|
|
|
|
func (r *LightRenderer) restoreTerminal() {
|
|
term.Restore(r.fd(), r.origState)
|
|
}
|
|
|
|
func (r *LightRenderer) updateTerminalSize() {
|
|
width, height, err := term.GetSize(r.fd())
|
|
|
|
if err == nil {
|
|
r.width = width
|
|
r.height = r.maxHeightFunc(height)
|
|
} else {
|
|
r.width = getEnv("COLUMNS", defaultWidth)
|
|
r.height = r.maxHeightFunc(getEnv("LINES", defaultHeight))
|
|
}
|
|
}
|
|
|
|
func (r *LightRenderer) findOffset() (row int, col int) {
|
|
r.csi("6n")
|
|
r.flush()
|
|
bytes := []byte{}
|
|
for tries := 0; tries < offsetPollTries; tries++ {
|
|
bytes = r.getBytesInternal(bytes, tries > 0)
|
|
offsets := offsetRegexp.FindSubmatch(bytes)
|
|
if len(offsets) > 3 {
|
|
// Add anything we skipped over to the input buffer
|
|
r.buffer = append(r.buffer, offsets[1]...)
|
|
return atoi(string(offsets[2]), 0) - 1, atoi(string(offsets[3]), 0) - 1
|
|
}
|
|
}
|
|
return -1, -1
|
|
}
|
|
|
|
func (r *LightRenderer) getch(nonblock bool) (int, bool) {
|
|
b := make([]byte, 1)
|
|
fd := r.fd()
|
|
util.SetNonblock(r.ttyin, nonblock)
|
|
_, err := util.Read(fd, b)
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
return int(b[0]), true
|
|
}
|
|
|
|
func (r *LightRenderer) Size() TermSize {
|
|
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)}
|
|
}
|