mirror of
https://github.com/junegunn/fzf.git
synced 2026-02-27 03:52:32 +08:00
Add --height option
This commit is contained in:
@@ -33,9 +33,39 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type ColorPair int16
|
||||
type Attr C.uint
|
||||
type WindowImpl C.WINDOW
|
||||
|
||||
type CursesWindow struct {
|
||||
impl *C.WINDOW
|
||||
top int
|
||||
left int
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
func (w *CursesWindow) Top() int {
|
||||
return w.top
|
||||
}
|
||||
|
||||
func (w *CursesWindow) Left() int {
|
||||
return w.left
|
||||
}
|
||||
|
||||
func (w *CursesWindow) Width() int {
|
||||
return w.width
|
||||
}
|
||||
|
||||
func (w *CursesWindow) Height() int {
|
||||
return w.height
|
||||
}
|
||||
|
||||
func (w *CursesWindow) Refresh() {
|
||||
C.wnoutrefresh(w.impl)
|
||||
}
|
||||
|
||||
func (w *CursesWindow) FinishFill() {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
const (
|
||||
Bold Attr = C.A_BOLD
|
||||
@@ -51,31 +81,14 @@ const (
|
||||
AttrRegular Attr = 0
|
||||
)
|
||||
|
||||
// Pallete
|
||||
const (
|
||||
ColDefault ColorPair = iota
|
||||
ColNormal
|
||||
ColPrompt
|
||||
ColMatch
|
||||
ColCurrent
|
||||
ColCurrentMatch
|
||||
ColSpinner
|
||||
ColInfo
|
||||
ColCursor
|
||||
ColSelected
|
||||
ColHeader
|
||||
ColBorder
|
||||
ColUser // Should be the last entry
|
||||
)
|
||||
|
||||
var (
|
||||
_screen *C.SCREEN
|
||||
_colorMap map[int]ColorPair
|
||||
_colorMap map[int]int16
|
||||
_colorFn func(ColorPair, Attr) (C.short, C.int)
|
||||
)
|
||||
|
||||
func init() {
|
||||
_colorMap = make(map[int]ColorPair)
|
||||
_colorMap = make(map[int]int16)
|
||||
if strings.HasPrefix(C.GoString(C.curses_version()), "ncurses 5") {
|
||||
Italic = C.A_NORMAL
|
||||
}
|
||||
@@ -85,14 +98,14 @@ func (a Attr) Merge(b Attr) Attr {
|
||||
return a | b
|
||||
}
|
||||
|
||||
func DefaultTheme() *ColorTheme {
|
||||
func (r *FullscreenRenderer) defaultTheme() *ColorTheme {
|
||||
if C.tigetnum(C.CString("colors")) >= 256 {
|
||||
return Dark256
|
||||
}
|
||||
return Default16
|
||||
}
|
||||
|
||||
func Init(theme *ColorTheme, black bool, mouse bool) {
|
||||
func (r *FullscreenRenderer) Init() {
|
||||
C.setlocale(C.LC_ALL, C.CString(""))
|
||||
tty := C.c_tty()
|
||||
if tty == nil {
|
||||
@@ -105,7 +118,7 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
|
||||
os.Exit(2)
|
||||
}
|
||||
C.set_term(_screen)
|
||||
if mouse {
|
||||
if r.mouse {
|
||||
C.mousemask(C.ALL_MOUSE_EVENTS, nil)
|
||||
C.mouseinterval(0)
|
||||
}
|
||||
@@ -124,14 +137,14 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
|
||||
}
|
||||
C.set_escdelay(C.int(delay))
|
||||
|
||||
_color = theme != nil
|
||||
if _color {
|
||||
if r.theme != nil {
|
||||
C.start_color()
|
||||
InitTheme(theme, black)
|
||||
initPairs(theme)
|
||||
C.bkgd(C.chtype(C.COLOR_PAIR(C.int(ColNormal))))
|
||||
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
|
||||
initPairs(r.theme)
|
||||
C.bkgd(C.chtype(C.COLOR_PAIR(C.int(ColNormal.index()))))
|
||||
_colorFn = attrColored
|
||||
} else {
|
||||
initTheme(r.theme, nil, r.forceBlack)
|
||||
_colorFn = attrMono
|
||||
}
|
||||
|
||||
@@ -145,39 +158,39 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
|
||||
|
||||
func initPairs(theme *ColorTheme) {
|
||||
C.assume_default_colors(C.int(theme.Fg), C.int(theme.Bg))
|
||||
initPair := func(group ColorPair, fg Color, bg Color) {
|
||||
C.init_pair(C.short(group), C.short(fg), C.short(bg))
|
||||
for _, pair := range []ColorPair{
|
||||
ColNormal,
|
||||
ColPrompt,
|
||||
ColMatch,
|
||||
ColCurrent,
|
||||
ColCurrentMatch,
|
||||
ColSpinner,
|
||||
ColInfo,
|
||||
ColCursor,
|
||||
ColSelected,
|
||||
ColHeader,
|
||||
ColBorder} {
|
||||
C.init_pair(C.short(pair.index()), C.short(pair.Fg()), C.short(pair.Bg()))
|
||||
}
|
||||
initPair(ColNormal, theme.Fg, theme.Bg)
|
||||
initPair(ColPrompt, theme.Prompt, theme.Bg)
|
||||
initPair(ColMatch, theme.Match, theme.Bg)
|
||||
initPair(ColCurrent, theme.Current, theme.DarkBg)
|
||||
initPair(ColCurrentMatch, theme.CurrentMatch, theme.DarkBg)
|
||||
initPair(ColSpinner, theme.Spinner, theme.Bg)
|
||||
initPair(ColInfo, theme.Info, theme.Bg)
|
||||
initPair(ColCursor, theme.Cursor, theme.DarkBg)
|
||||
initPair(ColSelected, theme.Selected, theme.DarkBg)
|
||||
initPair(ColHeader, theme.Header, theme.Bg)
|
||||
initPair(ColBorder, theme.Border, theme.Bg)
|
||||
}
|
||||
|
||||
func Pause() {
|
||||
func (r *FullscreenRenderer) Pause() {
|
||||
C.endwin()
|
||||
}
|
||||
|
||||
func Resume() bool {
|
||||
func (r *FullscreenRenderer) Resume() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func Close() {
|
||||
func (r *FullscreenRenderer) Close() {
|
||||
C.endwin()
|
||||
C.delscreen(_screen)
|
||||
}
|
||||
|
||||
func NewWindow(top int, left int, width int, height int, border bool) *Window {
|
||||
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, border bool) Window {
|
||||
win := C.newwin(C.int(height), C.int(width), C.int(top), C.int(left))
|
||||
if _color {
|
||||
C.wbkgd(win, C.chtype(C.COLOR_PAIR(C.int(ColNormal))))
|
||||
if r.theme != nil {
|
||||
C.wbkgd(win, C.chtype(C.COLOR_PAIR(C.int(ColNormal.index()))))
|
||||
}
|
||||
if border {
|
||||
pair, attr := _colorFn(ColBorder, 0)
|
||||
@@ -188,66 +201,50 @@ func NewWindow(top int, left int, width int, height int, border bool) *Window {
|
||||
C.wcolor_set(win, 0, nil)
|
||||
}
|
||||
|
||||
return &Window{
|
||||
impl: (*WindowImpl)(win),
|
||||
Top: top,
|
||||
Left: left,
|
||||
Width: width,
|
||||
Height: height,
|
||||
return &CursesWindow{
|
||||
impl: win,
|
||||
top: top,
|
||||
left: left,
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
}
|
||||
|
||||
func attrColored(pair ColorPair, a Attr) (C.short, C.int) {
|
||||
return C.short(pair), C.int(a)
|
||||
func attrColored(color ColorPair, a Attr) (C.short, C.int) {
|
||||
return C.short(color.index()), C.int(a)
|
||||
}
|
||||
|
||||
func attrMono(pair ColorPair, a Attr) (C.short, C.int) {
|
||||
var attr C.int
|
||||
switch pair {
|
||||
case ColCurrent:
|
||||
attr = C.A_REVERSE
|
||||
case ColMatch:
|
||||
attr = C.A_UNDERLINE
|
||||
case ColCurrentMatch:
|
||||
attr = C.A_UNDERLINE | C.A_REVERSE
|
||||
}
|
||||
if C.int(a)&C.A_BOLD == C.A_BOLD {
|
||||
attr = attr | C.A_BOLD
|
||||
}
|
||||
return 0, attr
|
||||
func attrMono(color ColorPair, a Attr) (C.short, C.int) {
|
||||
return 0, C.int(attrFor(color, a))
|
||||
}
|
||||
|
||||
func MaxX() int {
|
||||
func (r *FullscreenRenderer) MaxX() int {
|
||||
return int(C.COLS)
|
||||
}
|
||||
|
||||
func MaxY() int {
|
||||
func (r *FullscreenRenderer) MaxY() int {
|
||||
return int(C.LINES)
|
||||
}
|
||||
|
||||
func (w *Window) win() *C.WINDOW {
|
||||
return (*C.WINDOW)(w.impl)
|
||||
func (w *CursesWindow) Close() {
|
||||
C.delwin(w.impl)
|
||||
}
|
||||
|
||||
func (w *Window) Close() {
|
||||
C.delwin(w.win())
|
||||
func (w *CursesWindow) Enclose(y int, x int) bool {
|
||||
return bool(C.wenclose(w.impl, C.int(y), C.int(x)))
|
||||
}
|
||||
|
||||
func (w *Window) Enclose(y int, x int) bool {
|
||||
return bool(C.wenclose(w.win(), C.int(y), C.int(x)))
|
||||
func (w *CursesWindow) Move(y int, x int) {
|
||||
C.wmove(w.impl, C.int(y), C.int(x))
|
||||
}
|
||||
|
||||
func (w *Window) Move(y int, x int) {
|
||||
C.wmove(w.win(), C.int(y), C.int(x))
|
||||
}
|
||||
|
||||
func (w *Window) MoveAndClear(y int, x int) {
|
||||
func (w *CursesWindow) MoveAndClear(y int, x int) {
|
||||
w.Move(y, x)
|
||||
C.wclrtoeol(w.win())
|
||||
C.wclrtoeol(w.impl)
|
||||
}
|
||||
|
||||
func (w *Window) Print(text string) {
|
||||
C.waddstr(w.win(), C.CString(strings.Map(func(r rune) rune {
|
||||
func (w *CursesWindow) Print(text string) {
|
||||
C.waddstr(w.impl, C.CString(strings.Map(func(r rune) rune {
|
||||
if r < 32 {
|
||||
return -1
|
||||
}
|
||||
@@ -255,69 +252,74 @@ func (w *Window) Print(text string) {
|
||||
}, text)))
|
||||
}
|
||||
|
||||
func (w *Window) CPrint(pair ColorPair, attr Attr, text string) {
|
||||
p, a := _colorFn(pair, attr)
|
||||
C.wcolor_set(w.win(), p, nil)
|
||||
C.wattron(w.win(), a)
|
||||
func (w *CursesWindow) CPrint(color ColorPair, attr Attr, text string) {
|
||||
p, a := _colorFn(color, attr)
|
||||
C.wcolor_set(w.impl, p, nil)
|
||||
C.wattron(w.impl, a)
|
||||
w.Print(text)
|
||||
C.wattroff(w.win(), a)
|
||||
C.wcolor_set(w.win(), 0, nil)
|
||||
C.wattroff(w.impl, a)
|
||||
C.wcolor_set(w.impl, 0, nil)
|
||||
}
|
||||
|
||||
func Clear() {
|
||||
func (r *FullscreenRenderer) Clear() {
|
||||
C.clear()
|
||||
C.endwin()
|
||||
}
|
||||
|
||||
func Refresh() {
|
||||
func (r *FullscreenRenderer) Refresh() {
|
||||
C.refresh()
|
||||
}
|
||||
|
||||
func (w *Window) Erase() {
|
||||
C.werase(w.win())
|
||||
func (w *CursesWindow) Erase() {
|
||||
C.werase(w.impl)
|
||||
}
|
||||
|
||||
func (w *Window) X() int {
|
||||
return int(C.c_getcurx(w.win()))
|
||||
func (w *CursesWindow) X() int {
|
||||
return int(C.c_getcurx(w.impl))
|
||||
}
|
||||
|
||||
func DoesAutoWrap() bool {
|
||||
func (r *FullscreenRenderer) DoesAutoWrap() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *Window) Fill(str string) bool {
|
||||
return C.waddstr(w.win(), C.CString(str)) == C.OK
|
||||
func (w *CursesWindow) Fill(str string) bool {
|
||||
return C.waddstr(w.impl, C.CString(str)) == C.OK
|
||||
}
|
||||
|
||||
func (w *Window) CFill(str string, fg Color, bg Color, attr Attr) bool {
|
||||
pair := PairFor(fg, bg)
|
||||
C.wcolor_set(w.win(), C.short(pair), nil)
|
||||
C.wattron(w.win(), C.int(attr))
|
||||
func (w *CursesWindow) CFill(fg Color, bg Color, attr Attr, str string) bool {
|
||||
index := ColorPair{fg, bg, -1}.index()
|
||||
C.wcolor_set(w.impl, C.short(index), nil)
|
||||
C.wattron(w.impl, C.int(attr))
|
||||
ret := w.Fill(str)
|
||||
C.wattroff(w.win(), C.int(attr))
|
||||
C.wcolor_set(w.win(), 0, nil)
|
||||
C.wattroff(w.impl, C.int(attr))
|
||||
C.wcolor_set(w.impl, 0, nil)
|
||||
return ret
|
||||
}
|
||||
|
||||
func RefreshWindows(windows []*Window) {
|
||||
func (r *FullscreenRenderer) RefreshWindows(windows []Window) {
|
||||
for _, w := range windows {
|
||||
C.wnoutrefresh(w.win())
|
||||
w.Refresh()
|
||||
}
|
||||
C.doupdate()
|
||||
}
|
||||
|
||||
func PairFor(fg Color, bg Color) ColorPair {
|
||||
// ncurses does not support 24-bit colors
|
||||
if fg.is24() || bg.is24() {
|
||||
return ColDefault
|
||||
func (p ColorPair) index() int16 {
|
||||
if p.id >= 0 {
|
||||
return p.id
|
||||
}
|
||||
key := (int(fg) << 8) + int(bg)
|
||||
|
||||
// ncurses does not support 24-bit colors
|
||||
if p.is24() {
|
||||
return ColDefault.index()
|
||||
}
|
||||
|
||||
key := p.key()
|
||||
if found, prs := _colorMap[key]; prs {
|
||||
return found
|
||||
}
|
||||
|
||||
id := ColorPair(len(_colorMap) + int(ColUser))
|
||||
C.init_pair(C.short(id), C.short(fg), C.short(bg))
|
||||
id := int16(len(_colorMap)) + ColUser.id
|
||||
C.init_pair(C.short(id), C.short(p.Fg()), C.short(p.Bg()))
|
||||
_colorMap[key] = id
|
||||
return id
|
||||
}
|
||||
@@ -369,7 +371,7 @@ func escSequence() Event {
|
||||
return Event{Invalid, 0, nil}
|
||||
}
|
||||
|
||||
func GetChar() Event {
|
||||
func (r *FullscreenRenderer) GetChar() Event {
|
||||
c := C.getch()
|
||||
switch c {
|
||||
case C.ERR:
|
||||
@@ -435,17 +437,17 @@ func GetChar() Event {
|
||||
/* Cannot use BUTTON1_DOUBLE_CLICKED due to mouseinterval(0) */
|
||||
if (me.bstate & C.BUTTON1_PRESSED) > 0 {
|
||||
now := time.Now()
|
||||
if now.Sub(_prevDownTime) < doubleClickDuration {
|
||||
_clickY = append(_clickY, y)
|
||||
if now.Sub(r.prevDownTime) < doubleClickDuration {
|
||||
r.clickY = append(r.clickY, y)
|
||||
} else {
|
||||
_clickY = []int{y}
|
||||
_prevDownTime = now
|
||||
r.clickY = []int{y}
|
||||
r.prevDownTime = now
|
||||
}
|
||||
return Event{Mouse, 0, &MouseEvent{y, x, 0, true, false, mod}}
|
||||
} else if (me.bstate & C.BUTTON1_RELEASED) > 0 {
|
||||
double := false
|
||||
if len(_clickY) > 1 && _clickY[0] == _clickY[1] &&
|
||||
time.Now().Sub(_prevDownTime) < doubleClickDuration {
|
||||
if len(r.clickY) > 1 && r.clickY[0] == r.clickY[1] &&
|
||||
time.Now().Sub(r.prevDownTime) < doubleClickDuration {
|
||||
double = true
|
||||
}
|
||||
return Event{Mouse, 0, &MouseEvent{y, x, 0, false, double, mod}}
|
||||
|
||||
Reference in New Issue
Block a user