mirror of
https://github.com/peco/peco.git
synced 2026-09-10 07:16:29 -04:00
back to being able to draw the screen
This commit is contained in:
parent
7064a04efa
commit
39d36c41b8
11
action.go
11
action.go
|
|
@ -219,11 +219,12 @@ func doToggleRangeMode(ctx context.Context, state *Peco, _ termbox.Event) {
|
|||
trace("doToggleRangeMode: START")
|
||||
defer trace("doToggleRangeMode: END")
|
||||
|
||||
if state.RangeMode() {
|
||||
state.SetSelectionRangeStart(invalidSelectionRange)
|
||||
r := state.SelectionRangeStart()
|
||||
if r.Valid() {
|
||||
r.Reset()
|
||||
} else {
|
||||
cl := state.Location().LineNumber()
|
||||
state.SetSelectionRangeStart(cl)
|
||||
r.SetValue(cl)
|
||||
if l, err := state.CurrentLineBuffer().LineAt(cl); err == nil {
|
||||
state.selection.Add(l)
|
||||
}
|
||||
|
|
@ -231,7 +232,7 @@ func doToggleRangeMode(ctx context.Context, state *Peco, _ termbox.Event) {
|
|||
}
|
||||
|
||||
func doCancelRangeMode(ctx context.Context, state *Peco, _ termbox.Event) {
|
||||
state.SetSelectionRangeStart(invalidSelectionRange)
|
||||
state.SelectionRangeStart().Reset()
|
||||
}
|
||||
|
||||
func doSelectNone(ctx context.Context, state *Peco, _ termbox.Event) {
|
||||
|
|
@ -298,7 +299,7 @@ func doCancel(ctx context.Context, state *Peco, e termbox.Event) {
|
|||
return
|
||||
}
|
||||
|
||||
if state.RangeMode() {
|
||||
if state.SelectionRangeStart().Valid() {
|
||||
doCancelRangeMode(ctx, state, e)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
82
buffer.go
82
buffer.go
|
|
@ -3,7 +3,6 @@ package peco
|
|||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -163,78 +162,51 @@ func (rlb *RawLineBuffer) AppendLine(l Line) (Line, error) {
|
|||
return rlb.Append(l)
|
||||
}
|
||||
|
||||
func NewFilteredLineBuffer(src LineBuffer) *FilteredLineBuffer {
|
||||
flb := &FilteredLineBuffer{
|
||||
simplePipeline: simplePipeline{},
|
||||
src: src,
|
||||
selection: []int{},
|
||||
func NewFilteredBuffer(src Buffer, page, perPage int) *FilteredBuffer {
|
||||
fb := FilteredBuffer{
|
||||
src: src,
|
||||
}
|
||||
src.Register(flb)
|
||||
|
||||
runtime.SetFinalizer(flb, func(x *FilteredLineBuffer) {
|
||||
x.src.Unregister(x)
|
||||
})
|
||||
trace("src.Size = %d", src.Size())
|
||||
s := perPage * (page - 1)
|
||||
trace("s = %d", s)
|
||||
if s > src.Size() {
|
||||
return &fb
|
||||
}
|
||||
|
||||
return flb
|
||||
selection := make([]int, 0, src.Size())
|
||||
e := s + perPage
|
||||
if e >= src.Size() {
|
||||
e = src.Size()
|
||||
}
|
||||
|
||||
for i := s; i < e; i++ {
|
||||
selection = append(selection, i)
|
||||
}
|
||||
fb.selection = selection
|
||||
|
||||
return &fb
|
||||
}
|
||||
|
||||
func (flb *FilteredLineBuffer) Accept(p Pipeliner) {
|
||||
cancelCh, incomingCh := p.Pipeline()
|
||||
flb.cancelCh = cancelCh
|
||||
flb.outputCh = make(chan Line)
|
||||
go acceptPipeline(cancelCh, incomingCh, flb.outputCh,
|
||||
&pipelineCtx{flb.Append, nil})
|
||||
}
|
||||
|
||||
func (flb *FilteredLineBuffer) Append(l Line) (Line, error) {
|
||||
func (flb *FilteredBuffer) Append(l Line) (Line, error) {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (flb *FilteredLineBuffer) InvalidateUpTo(x int) {
|
||||
p := -1
|
||||
for i := 0; i < len(flb.selection); i++ {
|
||||
if flb.selection[i] > x {
|
||||
break
|
||||
}
|
||||
p = i
|
||||
}
|
||||
|
||||
if p >= 0 {
|
||||
flb.selection = append([]int(nil), flb.selection[p:]...)
|
||||
}
|
||||
|
||||
for _, b := range flb.buffers {
|
||||
b.InvalidateUpTo(p)
|
||||
}
|
||||
}
|
||||
|
||||
// LineAt returns the line at index `i`. Note that the i-th element
|
||||
// in this filtered buffer may actually correspond to a totally
|
||||
// different line number in the source buffer.
|
||||
func (flb FilteredLineBuffer) LineAt(i int) (Line, error) {
|
||||
if i < 0 || i >= len(flb.selection) {
|
||||
func (flb FilteredBuffer) LineAt(i int) (Line, error) {
|
||||
if i >= int(len(flb.selection)) {
|
||||
return nil, ErrBufferOutOfRange
|
||||
}
|
||||
return flb.src.LineAt(flb.selection[i])
|
||||
}
|
||||
|
||||
// Size returns the number of lines in the buffer
|
||||
func (flb FilteredLineBuffer) Size() int {
|
||||
func (flb FilteredBuffer) Size() int {
|
||||
return len(flb.selection)
|
||||
}
|
||||
|
||||
func (flb *FilteredLineBuffer) SelectSourceLineAt(i int) {
|
||||
flb.selection = append(flb.selection, i)
|
||||
}
|
||||
|
||||
func (flb *FilteredLineBuffer) Register(lb LineBuffer) {
|
||||
flb.buffers.Register(lb)
|
||||
}
|
||||
|
||||
func (flb *FilteredLineBuffer) Unregister(lb LineBuffer) {
|
||||
flb.buffers.Unregister(lb)
|
||||
}
|
||||
|
||||
// Buffer interface is used for containers for lines to be
|
||||
// processed by peco.
|
||||
type Buffer interface {
|
||||
|
|
@ -259,7 +231,7 @@ func (mb MemoryBuffer) Size() int {
|
|||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
return len(mb.lines)
|
||||
return int(len(mb.lines))
|
||||
}
|
||||
|
||||
func (mb MemoryBuffer) LineAt(n int) (Line, error) {
|
||||
|
|
@ -267,7 +239,7 @@ func (mb MemoryBuffer) LineAt(n int) (Line, error) {
|
|||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
if n > mb.Size() || n < 0 {
|
||||
if n > mb.Size() {
|
||||
return nil, errors.New("empty buffer")
|
||||
}
|
||||
|
||||
|
|
|
|||
24
interface.go
24
interface.go
|
|
@ -89,7 +89,7 @@ type PagingRequest interface {
|
|||
Type() PagingRequestType
|
||||
}
|
||||
|
||||
type JumpToLineRequest uint
|
||||
type JumpToLineRequest int
|
||||
|
||||
// Selection stores the line ids that were selected by the user.
|
||||
// The contents of the Selection is always sorted from smallest to
|
||||
|
|
@ -280,28 +280,14 @@ type RawLineBuffer struct {
|
|||
onEnd func()
|
||||
}
|
||||
|
||||
// FilteredLineBuffer holds a "filtered" buffer. It holds a reference to
|
||||
// FilteredBuffer holds a "filtered" buffer. It holds a reference to
|
||||
// the source buffer (note: should be immutable) and a list of indices
|
||||
// into the source buffer
|
||||
type FilteredLineBuffer struct {
|
||||
simplePipeline
|
||||
buffers dependentBuffers
|
||||
src LineBuffer
|
||||
// maps from our index to src's index
|
||||
selection []int
|
||||
type FilteredBuffer struct {
|
||||
src Buffer
|
||||
selection []int // maps from our index to src's index
|
||||
}
|
||||
|
||||
/*
|
||||
// Input handles input events from termbox.
|
||||
type Input struct {
|
||||
*Ctx
|
||||
mutex sync.Locker // Currently only used for protecting Alt/Esc workaround
|
||||
mod *time.Timer
|
||||
keymap Keymap
|
||||
currentKeySeq []string
|
||||
}
|
||||
*/
|
||||
|
||||
// Config holds all the data that can be configured in the
|
||||
// external configuran file
|
||||
type Config struct {
|
||||
|
|
|
|||
107
layout.go
107
layout.go
|
|
@ -2,6 +2,7 @@ package peco
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
|
|
@ -10,7 +11,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var extraOffset = 0
|
||||
var extraOffset int = 0
|
||||
|
||||
const (
|
||||
DefaultLayoutType = LayoutTypeTopDown
|
||||
|
|
@ -63,14 +64,14 @@ func printScreenWithOffset(x, y, xOffset int, fg, bg termbox.Attribute, msg stri
|
|||
if c == '\t' {
|
||||
// In case we found a tab, we draw it as 4 spaces
|
||||
n := 4 - (x+xOffset)%4
|
||||
for i := 0; i <= n; i++ {
|
||||
screen.SetCell(x+i, y, ' ', fg, bg)
|
||||
for i := int(0); i <= n; i++ {
|
||||
screen.SetCell(int(x+i), int(y), ' ', fg, bg)
|
||||
}
|
||||
written += n
|
||||
x += n
|
||||
} else {
|
||||
screen.SetCell(x, y, c, fg, bg)
|
||||
n := runewidth.RuneWidth(c)
|
||||
screen.SetCell(int(x), int(y), c, fg, bg)
|
||||
n := int(runewidth.RuneWidth(c))
|
||||
x += n
|
||||
written += n
|
||||
}
|
||||
|
|
@ -81,10 +82,10 @@ func printScreenWithOffset(x, y, xOffset int, fg, bg termbox.Attribute, msg stri
|
|||
}
|
||||
|
||||
width, _ := screen.Size()
|
||||
for ; x < width; x++ {
|
||||
screen.SetCell(x, y, ' ', fg, bg)
|
||||
for ; x < int(width); x++ {
|
||||
screen.SetCell(int(x), int(y), ' ', fg, bg)
|
||||
}
|
||||
written += width - x
|
||||
written += int(width) - x
|
||||
return written
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +96,10 @@ func NewAnchorSettings(anchor VerticalAnchor, offset int) *AnchorSettings {
|
|||
panic("Invalid vertical anchor specified")
|
||||
}
|
||||
|
||||
return &AnchorSettings{anchor, offset}
|
||||
return &AnchorSettings{
|
||||
anchor: anchor,
|
||||
anchorOffset: offset,
|
||||
}
|
||||
}
|
||||
|
||||
// AnchorPosition returns the starting y-offset, based on the
|
||||
|
|
@ -107,7 +111,7 @@ func (as AnchorSettings) AnchorPosition() int {
|
|||
pos = as.anchorOffset
|
||||
case AnchorBottom:
|
||||
_, h := screen.Size()
|
||||
pos = h - as.anchorOffset - 1 // -1 is required because y is 0 base, but h is 1 base
|
||||
pos = int(h) - as.anchorOffset - 1 // -1 is required because y is 0 base, but h is 1 base
|
||||
default:
|
||||
panic("Unknown anchor type!")
|
||||
}
|
||||
|
|
@ -125,8 +129,8 @@ func NewUserPrompt(anchor VerticalAnchor, anchorOffset int, prompt string, style
|
|||
return &UserPrompt{
|
||||
AnchorSettings: &AnchorSettings{anchor, anchorOffset},
|
||||
prompt: prompt,
|
||||
promptLen: promptLen,
|
||||
styles: styles,
|
||||
promptLen: int(promptLen),
|
||||
styles: styles,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,12 +164,15 @@ func (u UserPrompt) Draw(state *Peco) {
|
|||
printScreen(u.promptLen+1, location, fg|termbox.AttrReverse, bg|termbox.AttrReverse, " ", false)
|
||||
case c.Pos():
|
||||
// the entire string + the caret after the string
|
||||
printScreen(u.promptLen, location, fg, bg, "", true)
|
||||
printScreen(u.promptLen+1, location, fg, bg, qs, false)
|
||||
printScreen(u.promptLen+runewidth.StringWidth(qs)+1, location, fg|termbox.AttrReverse, bg|termbox.AttrReverse, " ", false)
|
||||
pos := u.promptLen
|
||||
printScreen(pos, location, fg, bg, "", true)
|
||||
pos += 1
|
||||
printScreen(pos, location, fg, bg, qs, false)
|
||||
pos += int(runewidth.StringWidth(qs))
|
||||
printScreen(pos, location, fg|termbox.AttrReverse, bg|termbox.AttrReverse, " ", false)
|
||||
default:
|
||||
// the caret is in the middle of the string
|
||||
prev := 0
|
||||
prev := int(0)
|
||||
for i, r := range q.Runes() {
|
||||
fg := u.styles.Query.fg
|
||||
bg := u.styles.Query.bg
|
||||
|
|
@ -173,8 +180,8 @@ func (u UserPrompt) Draw(state *Peco) {
|
|||
fg |= termbox.AttrReverse
|
||||
bg |= termbox.AttrReverse
|
||||
}
|
||||
screen.SetCell(u.promptLen+1+prev, location, r, fg, bg)
|
||||
prev += runewidth.RuneWidth(r)
|
||||
screen.SetCell(int(u.promptLen+1+prev), int(location), r, fg, bg)
|
||||
prev += int(runewidth.RuneWidth(r))
|
||||
}
|
||||
fg := u.styles.Query.fg
|
||||
bg := u.styles.Query.bg
|
||||
|
|
@ -185,7 +192,7 @@ func (u UserPrompt) Draw(state *Peco) {
|
|||
|
||||
loc := state.Location()
|
||||
pmsg := fmt.Sprintf("%s [%d (%d/%d)]", state.Filters().GetCurrent().String(), loc.Total(), loc.Page(), loc.MaxPage())
|
||||
printScreen(width-runewidth.StringWidth(pmsg), location, u.styles.Basic.fg, u.styles.Basic.bg, pmsg, false)
|
||||
printScreen(int(width-runewidth.StringWidth(pmsg)), location, u.styles.Basic.fg, u.styles.Basic.bg, pmsg, false)
|
||||
|
||||
screen.Flush()
|
||||
}
|
||||
|
|
@ -195,7 +202,7 @@ func NewStatusBar(anchor VerticalAnchor, anchorOffset int, styles *StyleSet) *St
|
|||
return &StatusBar{
|
||||
AnchorSettings: NewAnchorSettings(anchor, anchorOffset),
|
||||
clearTimer: nil,
|
||||
styles: styles,
|
||||
styles: styles,
|
||||
timerMutex: newMutex(),
|
||||
}
|
||||
}
|
||||
|
|
@ -248,7 +255,7 @@ func (s *StatusBar) PrintStatus(msg string, clearDelay time.Duration) {
|
|||
}
|
||||
|
||||
if width > 0 {
|
||||
printScreen(w-width, location, fgAttr|termbox.AttrReverse|termbox.AttrBold|termbox.AttrReverse, bgAttr|termbox.AttrReverse, msg, false)
|
||||
printScreen(int(w-width), location, fgAttr|termbox.AttrReverse|termbox.AttrBold|termbox.AttrReverse, bgAttr|termbox.AttrReverse, msg, false)
|
||||
}
|
||||
screen.Flush()
|
||||
|
||||
|
|
@ -266,11 +273,11 @@ func (s *StatusBar) PrintStatus(msg string, clearDelay time.Duration) {
|
|||
// NewListArea creates a new ListArea struct
|
||||
func NewListArea(anchor VerticalAnchor, anchorOffset int, sortTopDown bool, styles *StyleSet) *ListArea {
|
||||
return &ListArea{
|
||||
AnchorSettings: NewAnchorSettings(anchor, anchorOffset),
|
||||
displayCache: []Line{},
|
||||
dirty: false,
|
||||
sortTopDown: sortTopDown,
|
||||
styles: styles,
|
||||
AnchorSettings: NewAnchorSettings(anchor, anchorOffset),
|
||||
displayCache: []Line{},
|
||||
dirty: false,
|
||||
sortTopDown: sortTopDown,
|
||||
styles: styles,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -295,8 +302,13 @@ func selectionContains(state *Peco, n int) bool {
|
|||
|
||||
// Draw displays the ListArea on the screen
|
||||
func (l *ListArea) Draw(state *Peco, parent Layout, perPage int, runningQuery bool) {
|
||||
trace("ListArea.Draw: START")
|
||||
defer trace("ListArea.Draw: END")
|
||||
trace("START ListArea.Draw perPage = %d, runningQuery = %t", perPage, runningQuery)
|
||||
defer trace("END ListArea.Draw")
|
||||
|
||||
if perPage < 1 {
|
||||
panic("perPage < 1 (was " + strconv.Itoa(perPage) + ")")
|
||||
}
|
||||
|
||||
loc := state.Location()
|
||||
|
||||
linebuf := state.CurrentLineBuffer()
|
||||
|
|
@ -336,7 +348,7 @@ func (l *ListArea) Draw(state *Peco, parent Layout, perPage int, runningQuery bo
|
|||
|
||||
// previously drawn lines are cached. first, truncate the cache
|
||||
// to current size of the drawable area
|
||||
if ldc := len(l.displayCache); ldc != perPage {
|
||||
if ldc := int(len(l.displayCache)); ldc != perPage {
|
||||
newCache := make([]Line, perPage)
|
||||
copy(newCache, l.displayCache)
|
||||
l.displayCache = newCache
|
||||
|
|
@ -362,12 +374,12 @@ func (l *ListArea) Draw(state *Peco, parent Layout, perPage int, runningQuery bo
|
|||
|
||||
var cached, written int
|
||||
var fgAttr, bgAttr termbox.Attribute
|
||||
for n := 0; n < perPage; n++ {
|
||||
for n := int(0); n < perPage; n++ {
|
||||
switch {
|
||||
case n+loc.Offset() == loc.LineNumber():
|
||||
fgAttr = l.styles.Selected.fg
|
||||
bgAttr = l.styles.Selected.bg
|
||||
case selectionContains(state, n + loc.Offset()):
|
||||
case selectionContains(state, n+loc.Offset()):
|
||||
fgAttr = l.styles.SavedSelection.fg
|
||||
bgAttr = l.styles.SavedSelection.bg
|
||||
default:
|
||||
|
|
@ -400,13 +412,15 @@ func (l *ListArea) Draw(state *Peco, parent Layout, perPage int, runningQuery bo
|
|||
written++
|
||||
l.displayCache[n] = target
|
||||
|
||||
x := -1 * loc.Column()
|
||||
// XXX https://github.com/peco/peco/pull/249 this used to be
|
||||
// x := -loc.Column(), may need to look at it again
|
||||
x := int(0)
|
||||
xOffset := loc.Column()
|
||||
line := target.DisplayString()
|
||||
|
||||
if state.SingleKeyJumpMode() || state.SingleKeyJumpShowPrefix() {
|
||||
prefixes := state.SingleKeyJumpPrefixes()
|
||||
if n < len(prefixes) {
|
||||
if n < int(len(prefixes)) {
|
||||
printScreenWithOffset(x, y, xOffset, fgAttr|termbox.AttrBold|termbox.AttrReverse, bgAttr, string(prefixes[n]), false)
|
||||
printScreenWithOffset(x+1, y, xOffset, fgAttr, bgAttr, " ", false)
|
||||
} else {
|
||||
|
|
@ -534,7 +548,11 @@ func linesPerPage() int {
|
|||
|
||||
// list area is always the display area - 2 lines for prompt and status
|
||||
reservedLines := 2 + extraOffset
|
||||
return height - reservedLines
|
||||
pp := height - reservedLines
|
||||
if pp < 1 {
|
||||
panic("linesPerPage is < 1 (height = " +strconv.Itoa(height) +", reservedLines = " + strconv.Itoa(reservedLines) + ")")
|
||||
}
|
||||
return pp
|
||||
}
|
||||
|
||||
// MovePage scrolls the screen
|
||||
|
|
@ -616,21 +634,22 @@ func verticalScroll(state *Peco, l *BasicLayout, p PagingRequest) bool {
|
|||
|
||||
// if we were in range mode, we need to do stuff. otherwise
|
||||
// just bail out
|
||||
if !state.RangeMode() {
|
||||
r := state.SelectionRangeStart()
|
||||
if !r.Valid() {
|
||||
return true
|
||||
}
|
||||
|
||||
sel := state.Selection()
|
||||
if l.list.sortTopDown {
|
||||
if loc.LineNumber() < state.SelectionRangeStart() {
|
||||
for lineno := loc.LineNumber(); lineno <= state.SelectionRangeStart(); lineno++ {
|
||||
if loc.LineNumber() < r.Value() {
|
||||
for lineno := loc.LineNumber(); lineno <= r.Value(); lineno++ {
|
||||
if line, err := buf.LineAt(lineno); err == nil {
|
||||
sel.Add(line)
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case state.SelectionRangeStart() <= lineBefore:
|
||||
for lineno := state.SelectionRangeStart(); lineno <= lcur && lineno < lineBefore; lineno++ {
|
||||
case r.Value() <= lineBefore:
|
||||
for lineno := r.Value(); lineno <= lcur && lineno < lineBefore; lineno++ {
|
||||
if line, err := buf.LineAt(lineno); err == nil {
|
||||
sel.Remove(line)
|
||||
}
|
||||
|
|
@ -643,15 +662,15 @@ func verticalScroll(state *Peco, l *BasicLayout, p PagingRequest) bool {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for lineno := state.SelectionRangeStart(); lineno <= lcur && lineno <= loc.LineNumber(); lineno++ {
|
||||
for lineno := r.Value(); lineno <= lcur && lineno <= loc.LineNumber(); lineno++ {
|
||||
if line, err := buf.LineAt(lineno); err == nil {
|
||||
sel.Add(line)
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case lineBefore <= state.SelectionRangeStart():
|
||||
for lineno := lineBefore; lineno < state.SelectionRangeStart(); lineno++ {
|
||||
case lineBefore <= r.Value():
|
||||
for lineno := lineBefore; lineno < r.Value(); lineno++ {
|
||||
if line, err := buf.LineAt(lineno); err == nil {
|
||||
sel.Remove(line)
|
||||
}
|
||||
|
|
@ -674,9 +693,9 @@ func horizontalScroll(state *Peco, l *BasicLayout, p PagingRequest) bool {
|
|||
width, _ := screen.Size()
|
||||
loc := state.Location()
|
||||
if p.Type() == ToScrollRight {
|
||||
loc.SetColumn(loc.Column() + width / 2)
|
||||
loc.SetColumn(loc.Column() + width/2)
|
||||
} else if loc.Column() > 0 {
|
||||
loc.SetColumn(loc.Column() - width / 2)
|
||||
loc.SetColumn(loc.Column() - width/2)
|
||||
if loc.Column() < 0 {
|
||||
loc.SetColumn(0)
|
||||
}
|
||||
|
|
|
|||
24
page.go
24
page.go
|
|
@ -63,25 +63,9 @@ func (l Location) PageCrop() PageCrop {
|
|||
}
|
||||
}
|
||||
|
||||
// Crop returns a new LineBuffer whose contents are
|
||||
// Crop returns a new Buffer whose contents are
|
||||
// bound within the given range
|
||||
func (pf PageCrop) Crop(in LineBuffer) LineBuffer {
|
||||
out := &FilteredLineBuffer{
|
||||
src: in,
|
||||
selection: []int{},
|
||||
}
|
||||
|
||||
s := pf.perPage * (pf.currentPage - 1)
|
||||
e := s + pf.perPage
|
||||
if s > in.Size() {
|
||||
return out
|
||||
}
|
||||
if e >= in.Size() {
|
||||
e = in.Size()
|
||||
}
|
||||
|
||||
for i := s; i < e; i++ {
|
||||
out.SelectSourceLineAt(i)
|
||||
}
|
||||
return out
|
||||
func (pf PageCrop) Crop(in Buffer) Buffer {
|
||||
trace("Cropping for page %d, %d entries per page", pf.currentPage, pf.perPage)
|
||||
return NewFilteredBuffer(in, pf.currentPage, pf.perPage)
|
||||
}
|
||||
|
|
|
|||
81
peco.go
81
peco.go
|
|
@ -64,7 +64,7 @@ type Peco struct {
|
|||
queryExecTimer *time.Timer
|
||||
resultCh chan Line
|
||||
selection *Selection
|
||||
selectionRangeStart int
|
||||
selectionRangeStart RangeStart
|
||||
singleKeyJumpMode bool
|
||||
singleKeyJumpPrefixes []rune
|
||||
singleKeyJumpShowPrefix bool
|
||||
|
|
@ -84,9 +84,8 @@ type Peco struct {
|
|||
|
||||
func New() *Peco {
|
||||
return &Peco{
|
||||
activeLineBuffer: &MemoryBuffer{}, // XXX revisit this
|
||||
selection: NewSelection(),
|
||||
selectionRangeStart: invalidSelectionRange,
|
||||
activeLineBuffer: &MemoryBuffer{}, // XXX revisit this
|
||||
selection: NewSelection(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -106,10 +105,6 @@ func (p Peco) Context() context.Context {
|
|||
return p.ctx
|
||||
}
|
||||
|
||||
func (p Peco) CurrentLineBuffer() LineBuffer {
|
||||
return nil // XXX DUMMY
|
||||
}
|
||||
|
||||
func (p Peco) LayoutType() string {
|
||||
return p.layoutType
|
||||
}
|
||||
|
|
@ -130,18 +125,30 @@ func (p Peco) Selection() *Selection {
|
|||
return p.selection
|
||||
}
|
||||
|
||||
func (p Peco) SelectionRangeStart() int {
|
||||
return p.selectionRangeStart
|
||||
type RangeStart struct {
|
||||
val int
|
||||
valid bool
|
||||
}
|
||||
|
||||
func (p Peco) SetSelectionRangeStart(s int) {
|
||||
if s >= invalidSelectionRange {
|
||||
p.selectionRangeStart = s
|
||||
}
|
||||
func (s RangeStart) Valid() bool {
|
||||
return s.valid
|
||||
}
|
||||
|
||||
func (p Peco) RangeMode() bool {
|
||||
return p.selectionRangeStart != invalidSelectionRange
|
||||
func (s RangeStart) Value() int {
|
||||
return s.val
|
||||
}
|
||||
|
||||
func (s *RangeStart) SetValue(n int) {
|
||||
s.val = n
|
||||
s.valid = true
|
||||
}
|
||||
|
||||
func (s *RangeStart) Reset() {
|
||||
s.valid = false
|
||||
}
|
||||
|
||||
func (p Peco) SelectionRangeStart() *RangeStart {
|
||||
return &p.selectionRangeStart
|
||||
}
|
||||
|
||||
func (p Peco) SingleKeyJumpShowPrefix() bool {
|
||||
|
|
@ -243,6 +250,11 @@ func (p *Peco) Run() error {
|
|||
if err := p.Setup(); err != nil {
|
||||
return errors.Wrap(err, "failed to setup peco")
|
||||
}
|
||||
// screen.Init must be called within Run() because we
|
||||
// want to make sure to call screen.Close() after getting
|
||||
// out of Run()
|
||||
screen.Init()
|
||||
defer screen.Close()
|
||||
|
||||
var ctx context.Context
|
||||
var cancel func()
|
||||
|
|
@ -342,18 +354,43 @@ func (p *Peco) ApplyConfig() error {
|
|||
}
|
||||
|
||||
if err := p.populateCommandList(); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to populate command list")
|
||||
}
|
||||
|
||||
if err := p.populateFilters(); err != nil {
|
||||
return errors.Wrap(err, "failed to populate filters")
|
||||
}
|
||||
|
||||
if err := p.populateKeymap(); err != nil {
|
||||
return errors.Wrap(err, "failed to populate keymap")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Peco) ActiveLineBuffer() Buffer {
|
||||
func (p *Peco) populateFilters() error {
|
||||
p.filters.Add(NewIgnoreCaseFilter())
|
||||
p.filters.Add(NewCaseSensitiveFilter())
|
||||
p.filters.Add(NewSmartCaseFilter())
|
||||
p.filters.Add(NewRegexpFilter())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Peco) populateKeymap() error {
|
||||
// Create a new keymap object
|
||||
k := NewKeymap(p, p.config.Keymap, p.config.Action)
|
||||
k.ApplyKeybinding()
|
||||
p.keymap = k
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Peco) CurrentLineBuffer() Buffer {
|
||||
return p.activeLineBuffer
|
||||
}
|
||||
|
||||
func (p *Peco) ResetActiveLineBuffer() {
|
||||
p.activeLineBuffer = p.source
|
||||
p.Hub().SendDraw(false)
|
||||
}
|
||||
|
||||
func (p *Peco) ExecQuery() bool {
|
||||
|
|
@ -364,11 +401,9 @@ func (p *Peco) ExecQuery() bool {
|
|||
// the raw source buffer
|
||||
q := p.Query()
|
||||
if q.Len() <= 0 {
|
||||
if p.ActiveLineBuffer() != nil {
|
||||
p.ResetActiveLineBuffer()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
trace("empty query, reset buffer")
|
||||
p.ResetActiveLineBuffer()
|
||||
return true
|
||||
}
|
||||
|
||||
delay := p.QueryExecDelay()
|
||||
|
|
|
|||
Loading…
Reference in a new issue