summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/algo.go29
-rw-r--r--src/atomicbool.go5
-rw-r--r--src/cache.go6
-rw-r--r--src/cache_test.go2
-rw-r--r--src/chunklist.go20
-rw-r--r--src/chunklist_test.go4
-rw-r--r--src/constants.go19
-rw-r--r--src/core.go43
-rw-r--r--src/curses/curses.go214
-rw-r--r--src/eventbox.go11
-rw-r--r--src/eventbox_test.go14
-rw-r--r--src/item.go16
-rw-r--r--src/matcher.go31
-rw-r--r--src/merger.go10
-rw-r--r--src/options.go43
-rw-r--r--src/options_test.go10
-rw-r--r--src/pattern.go77
-rw-r--r--src/pattern_test.go54
-rw-r--r--src/reader.go10
-rw-r--r--src/reader_test.go18
-rw-r--r--src/terminal.go188
-rw-r--r--src/tokenizer.go47
-rw-r--r--src/tokenizer_test.go4
-rw-r--r--src/util.go4
24 files changed, 476 insertions, 403 deletions
diff --git a/src/algo.go b/src/algo.go
index e0c173f2..5f15ab3b 100644
--- a/src/algo.go
+++ b/src/algo.go
@@ -10,6 +10,7 @@ import "strings"
* In short: They try to do as little work as possible.
*/
+// FuzzyMatch performs fuzzy-match
func FuzzyMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
runes := []rune(*input)
@@ -36,7 +37,7 @@ func FuzzyMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
if sidx < 0 {
sidx = index
}
- if pidx += 1; pidx == len(pattern) {
+ if pidx++; pidx == len(pattern) {
eidx = index + 1
break
}
@@ -44,14 +45,14 @@ func FuzzyMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
}
if sidx >= 0 && eidx >= 0 {
- pidx -= 1
+ pidx--
for index := eidx - 1; index >= sidx; index-- {
char := runes[index]
if !caseSensitive && char >= 65 && char <= 90 {
char += 32
}
if char == pattern[pidx] {
- if pidx -= 1; pidx < 0 {
+ if pidx--; pidx < 0 {
sidx = index
break
}
@@ -62,6 +63,8 @@ func FuzzyMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
return -1, -1
}
+// ExactMatchStrings performs exact-match using strings package.
+// Currently not used.
func ExactMatchStrings(caseSensitive bool, input *string, pattern []rune) (int, int) {
var str string
if caseSensitive {
@@ -77,15 +80,13 @@ func ExactMatchStrings(caseSensitive bool, input *string, pattern []rune) (int,
return -1, -1
}
-/*
- * This is a basic string searching algorithm that handles case sensitivity.
- * Although naive, it still performs better than the combination of
- * strings.ToLower + strings.Index for typical fzf use cases where input
- * strings and patterns are not very long.
- *
- * We might try to implement better algorithms in the future:
- * http://en.wikipedia.org/wiki/String_searching_algorithm
- */
+// ExactMatchNaive is a basic string searching algorithm that handles case
+// sensitivity. Although naive, it still performs better than the combination
+// of strings.ToLower + strings.Index for typical fzf use cases where input
+// strings and patterns are not very long.
+//
+// We might try to implement better algorithms in the future:
+// http://en.wikipedia.org/wiki/String_searching_algorithm
func ExactMatchNaive(caseSensitive bool, input *string, pattern []rune) (int, int) {
runes := []rune(*input)
numRunes := len(runes)
@@ -101,7 +102,7 @@ func ExactMatchNaive(caseSensitive bool, input *string, pattern []rune) (int, in
char += 32
}
if pattern[pidx] == char {
- pidx += 1
+ pidx++
if pidx == plen {
return index - plen + 1, index + 1
}
@@ -113,6 +114,7 @@ func ExactMatchNaive(caseSensitive bool, input *string, pattern []rune) (int, in
return -1, -1
}
+// PrefixMatch performs prefix-match
func PrefixMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
runes := []rune(*input)
if len(runes) < len(pattern) {
@@ -131,6 +133,7 @@ func PrefixMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
return 0, len(pattern)
}
+// SuffixMatch performs suffix-match
func SuffixMatch(caseSensitive bool, input *string, pattern []rune) (int, int) {
runes := []rune(strings.TrimRight(*input, " "))
trimmedLen := len(runes)
diff --git a/src/atomicbool.go b/src/atomicbool.go
index f2f4894f..b264724c 100644
--- a/src/atomicbool.go
+++ b/src/atomicbool.go
@@ -2,23 +2,28 @@ package fzf
import "sync"
+// AtomicBool is a boxed-class that provides synchronized access to the
+// underlying boolean value
type AtomicBool struct {
mutex sync.Mutex
state bool
}
+// NewAtomicBool returns a new AtomicBool
func NewAtomicBool(initialState bool) *AtomicBool {
return &AtomicBool{
mutex: sync.Mutex{},
state: initialState}
}
+// Get returns the current boolean value synchronously
func (a *AtomicBool) Get() bool {
a.mutex.Lock()
defer a.mutex.Unlock()
return a.state
}
+// Set updates the boolean value synchronously
func (a *AtomicBool) Set(newState bool) bool {
a.mutex.Lock()
defer a.mutex.Unlock()
diff --git a/src/cache.go b/src/cache.go
index 340f3258..f2f84a0a 100644
--- a/src/cache.go
+++ b/src/cache.go
@@ -2,16 +2,21 @@ package fzf
import "sync"
+// QueryCache associates strings to lists of items
type QueryCache map[string][]*Item
+
+// ChunkCache associates Chunk and query string to lists of items
type ChunkCache struct {
mutex sync.Mutex
cache map[*Chunk]*QueryCache
}
+// NewChunkCache returns a new ChunkCache
func NewChunkCache() ChunkCache {
return ChunkCache{sync.Mutex{}, make(map[*Chunk]*QueryCache)}
}
+// Add adds the list to the cache
func (cc *ChunkCache) Add(chunk *Chunk, key string, list []*Item) {
if len(key) == 0 || !chunk.IsFull() {
return
@@ -28,6 +33,7 @@ func (cc *ChunkCache) Add(chunk *Chunk, key string, list []*Item) {
(*qc)[key] = list
}
+// Find is called to lookup ChunkCache
func (cc *ChunkCache) Find(chunk *Chunk, key string) ([]*Item, bool) {
if len(key) == 0 || !chunk.IsFull() {
return nil, false
diff --git a/src/cache_test.go b/src/cache_test.go
index 2a8b0480..3975eaa3 100644
--- a/src/cache_test.go
+++ b/src/cache_test.go
@@ -4,7 +4,7 @@ import "testing"
func TestChunkCache(t *testing.T) {
cache := NewChunkCache()
- chunk2 := make(Chunk, CHUNK_SIZE)
+ chunk2 := make(Chunk, ChunkSize)
chunk1p := &Chunk{}
chunk2p := &chunk2
items1 := []*Item{&Item{}}
diff --git a/src/chunklist.go b/src/chunklist.go
index 5bca6da8..73983b1d 100644
--- a/src/chunklist.go
+++ b/src/chunklist.go
@@ -2,12 +2,17 @@ package fzf
import "sync"
-const CHUNK_SIZE int = 100
+// Capacity of each chunk
+const ChunkSize int = 100
+// Chunk is a list of Item pointers whose size has the upper limit of ChunkSize
type Chunk []*Item // >>> []Item
+// Transformer is a closure type that builds Item object from a pointer to a
+// string and an integer
type Transformer func(*string, int) *Item
+// ChunkList is a list of Chunks
type ChunkList struct {
chunks []*Chunk
count int
@@ -15,6 +20,7 @@ type ChunkList struct {
trans Transformer
}
+// NewChunkList returns a new ChunkList
func NewChunkList(trans Transformer) *ChunkList {
return &ChunkList{
chunks: []*Chunk{},
@@ -27,34 +33,38 @@ func (c *Chunk) push(trans Transformer, data *string, index int) {
*c = append(*c, trans(data, index))
}
+// IsFull returns true if the Chunk is full
func (c *Chunk) IsFull() bool {
- return len(*c) == CHUNK_SIZE
+ return len(*c) == ChunkSize
}
func (cl *ChunkList) lastChunk() *Chunk {
return cl.chunks[len(cl.chunks)-1]
}
+// CountItems returns the total number of Items
func CountItems(cs []*Chunk) int {
if len(cs) == 0 {
return 0
}
- return CHUNK_SIZE*(len(cs)-1) + len(*(cs[len(cs)-1]))
+ return ChunkSize*(len(cs)-1) + len(*(cs[len(cs)-1]))
}
+// Push adds the item to the list
func (cl *ChunkList) Push(data string) {
cl.mutex.Lock()
defer cl.mutex.Unlock()
if len(cl.chunks) == 0 || cl.lastChunk().IsFull() {
- newChunk := Chunk(make([]*Item, 0, CHUNK_SIZE))
+ newChunk := Chunk(make([]*Item, 0, ChunkSize))
cl.chunks = append(cl.chunks, &newChunk)
}
cl.lastChunk().push(cl.trans, &data, cl.count)
- cl.count += 1
+ cl.count++
}
+// Snapshot returns immutable snapshot of the ChunkList
func (cl *ChunkList) Snapshot() ([]*Chunk, int) {
cl.mutex.Lock()
defer cl.mutex.Unlock()
diff --git a/src/chunklist_test.go b/src/chunklist_test.go
index 09e4aadd..02288d9f 100644
--- a/src/chunklist_test.go
+++ b/src/chunklist_test.go
@@ -45,7 +45,7 @@ func TestChunkList(t *testing.T) {
}
// Add more data
- for i := 0; i < CHUNK_SIZE*2; i++ {
+ for i := 0; i < ChunkSize*2; i++ {
cl.Push(fmt.Sprintf("item %d", i))
}
@@ -57,7 +57,7 @@ func TestChunkList(t *testing.T) {
// New snapshot
snapshot, count = cl.Snapshot()
if len(snapshot) != 3 || !snapshot[0].IsFull() ||
- !snapshot[1].IsFull() || snapshot[2].IsFull() || count != CHUNK_SIZE*2+2 {
+ !snapshot[1].IsFull() || snapshot[2].IsFull() || count != ChunkSize*2+2 {
t.Error("Expected two full chunks and one more chunk")
}
if len(*snapshot[2]) != 2 {
diff --git a/src/constants.go b/src/constants.go
index b0b64dbb..80eb6345 100644
--- a/src/constants.go
+++ b/src/constants.go
@@ -1,12 +1,17 @@
package fzf
-const VERSION = "0.9.0"
+// Current version
+const Version = "0.9.0"
+// EventType is the type for fzf events
+type EventType int
+
+// fzf events
const (
- EVT_READ_NEW EventType = iota
- EVT_READ_FIN
- EVT_SEARCH_NEW
- EVT_SEARCH_PROGRESS
- EVT_SEARCH_FIN
- EVT_CLOSE
+ EvtReadNew EventType = iota
+ EvtReadFin
+ EvtSearchNew
+ EvtSearchProgress
+ EvtSearchFin
+ EvtClose
)
diff --git a/src/core.go b/src/core.go
index ab2a48fa..65e641c2 100644
--- a/src/core.go
+++ b/src/core.go
@@ -32,28 +32,29 @@ import (
"time"
)
-const COORDINATOR_DELAY_MAX time.Duration = 100 * time.Millisecond
-const COORDINATOR_DELAY_STEP time.Duration = 10 * time.Millisecond
+const coordinatorDelayMax time.Duration = 100 * time.Millisecond
+const coordinatorDelayStep time.Duration = 10 * time.Millisecond
func initProcs() {
runtime.GOMAXPROCS(runtime.NumCPU())
}
/*
-Reader -> EVT_READ_FIN
-Reader -> EVT_READ_NEW -> Matcher (restart)
-Terminal -> EVT_SEARCH_NEW -> Matcher (restart)
-Matcher -> EVT_SEARCH_PROGRESS -> Terminal (update info)
-Matcher -> EVT_SEARCH_FIN -> Terminal (update list)
+Reader -> EvtReadFin
+Reader -> EvtReadNew -> Matcher (restart)
+Terminal -> EvtSearchNew -> Matcher (restart)
+Matcher -> EvtSearchProgress -> Terminal (update info)
+Matcher -> EvtSearchFin -> Terminal (update list)
*/
+// Run starts fzf
func Run(options *Options) {
initProcs()
opts := ParseOptions()
if opts.Version {
- fmt.Println(VERSION)
+ fmt.Println(Version)
os.Exit(0)
}
@@ -108,12 +109,12 @@ func Run(options *Options) {
pattern := patternBuilder([]rune(patternString))
looping := true
- eventBox.Unwatch(EVT_READ_NEW)
+ eventBox.Unwatch(EvtReadNew)
for looping {
eventBox.Wait(func(events *Events) {
- for evt, _ := range *events {
+ for evt := range *events {
switch evt {
- case EVT_READ_FIN:
+ case EvtReadFin:
looping = false
return
}
@@ -133,7 +134,7 @@ func Run(options *Options) {
fmt.Println(patternString)
}
for i := 0; i < merger.Length(); i++ {
- merger.Get(i).Print()
+ fmt.Println(merger.Get(i).AsString())
}
os.Exit(0)
}
@@ -149,33 +150,33 @@ func Run(options *Options) {
// Event coordination
reading := true
ticks := 0
- eventBox.Watch(EVT_READ_NEW)
+ eventBox.Watch(EvtReadNew)
for {
delay := true
- ticks += 1
+ ticks++
eventBox.Wait(func(events *Events) {
defer events.Clear()
for evt, value := range *events {
switch evt {
- case EVT_READ_NEW, EVT_READ_FIN:
- reading = reading && evt == EVT_READ_NEW
+ case EvtReadNew, EvtReadFin:
+ reading = reading && evt == EvtReadNew
snapshot, count := chunkList.Snapshot()
terminal.UpdateCount(count, !reading)
matcher.Reset(snapshot, terminal.Input(), false)
- case EVT_SEARCH_NEW:
+ case EvtSearchNew:
snapshot, _ := chunkList.Snapshot()
matcher.Reset(snapshot, terminal.Input(), true)
delay = false
- case EVT_SEARCH_PROGRESS:
+ case EvtSearchProgress:
switch val := value.(type) {
case float32:
terminal.UpdateProgress(val)
}
- case EVT_SEARCH_FIN:
+ case EvtSearchFin:
switch val := value.(type) {
case *Merger:
terminal.UpdateList(val)
@@ -185,8 +186,8 @@ func Run(options *Options) {
})
if delay && reading {
dur := DurWithin(
- time.Duration(ticks)*COORDINATOR_DELAY_STEP,
- 0, COORDINATOR_DELAY_MAX)
+ time.Duration(ticks)*coordinatorDelayStep,
+ 0, coordinatorDelayMax)
time.Sleep(dur)
}
}
diff --git a/src/curses/curses.go b/src/curses/curses.go
index 736ccf6b..8ebb5835 100644
--- a/src/curses/curses.go
+++ b/src/curses/curses.go
@@ -20,66 +20,68 @@ import (
"unicode/utf8"
)
+// Types of user action
const (
- RUNE = iota
-
- CTRL_A
- CTRL_B
- CTRL_C
- CTRL_D
- CTRL_E
- CTRL_F
- CTRL_G
- CTRL_H
- TAB
- CTRL_J
- CTRL_K
- CTRL_L
- CTRL_M
- CTRL_N
- CTRL_O
- CTRL_P
- CTRL_Q
- CTRL_R
- CTRL_S
- CTRL_T
- CTRL_U
- CTRL_V
- CTRL_W
- CTRL_X
- CTRL_Y
- CTRL_Z
+ Rune = iota
+
+ CtrlA
+ CtrlB
+ CtrlC
+ CtrlD
+ CtrlE
+ CtrlF
+ CtrlG
+ CtrlH
+ Tab
+ CtrlJ
+ CtrlK
+ CtrlL
+ CtrlM
+ CtrlN
+ CtrlO
+ CtrlP
+ CtrlQ
+ CtrlR
+ CtrlS
+ CtrlT
+ CtrlU
+ CtrlV
+ CtrlW
+ CtrlX
+ CtrlY
+ CtrlZ
ESC
- INVALID
- MOUSE
+ Invalid
+ Mouse
- BTAB
+ BTab
- DEL
- PGUP
- PGDN
+ Del
+ PgUp
+ PgDn
- ALT_B
- ALT_F
- ALT_D
- ALT_BS
+ AltB
+ AltF
+ AltD
+ AltBS
)
+// Pallete
const (
- COL_NORMAL = iota
- COL_PROMPT
- COL_MATCH
- COL_CURRENT
- COL_CURRENT_MATCH
- COL_SPINNER
- COL_INFO
- COL_CURSOR
- COL_SELECTED
+ ColNormal = iota
+ ColPrompt
+ ColMatch
+ ColCurrent
+ ColCurrentMatch
+ ColSpinner
+ ColInfo
+ ColCursor
+ ColSelected
)
const (
- DOUBLE_CLICK_DURATION = 500 * time.Millisecond
+ doubleClickDuration = 500 * time.Millisecond
)
type Event struct {
@@ -112,8 +114,8 @@ func init() {
}
func attrColored(pair int, bold bool) C.int {
- var attr C.int = 0
- if pair > COL_NORMAL {
+ var attr C.int
+ if pair > ColNormal {
attr = C.COLOR_PAIR(C.int(pair))
}
if bold {
@@ -123,15 +125,15 @@ func attrColored(pair int, bold bool) C.int {
}
func attrMono(pair int, bold bool) C.int {
- var attr C.int = 0
+ var attr C.int
switch pair {
- case COL_CURRENT:
+ case ColCurrent:
if bold {
attr = C.A_REVERSE
}
- case COL_MATCH:
+ case ColMatch:
attr = C.A_UNDERLINE
- case COL_CURRENT_MATCH:
+ case ColCurrentMatch:
attr = C.A_UNDERLINE | C.A_REVERSE
}
if bold {
@@ -198,23 +200,23 @@ func Init(color bool, color256 bool, black bool, mouse bool) {
bg = -1
}
if color256 {
- C.init_pair(COL_PROMPT, 110, bg)
- C.init_pair(COL_MATCH, 108, bg)
- C.init_pair(COL_CURRENT, 254, 236)
- C.init_pair(COL_CURRENT_MATCH, 151, 236)
- C.init_pair(COL_SPINNER, 148, bg)
- C.init_pair(COL_INFO, 144, bg)
- C.init_pair(COL_CURSOR, 161, 236)
- C.init_pair(COL_SELECTED, 168, 236)
+ C.init_pair(ColPrompt, 110, bg)
+ C.init_pair(ColMatch, 108, bg)
+ C.init_pair(ColCurrent, 254, 236)
+ C.init_pair(ColCurrentMatch, 151, 236)
+ C.init_pair(ColSpinner, 148, bg)
+ C.init_pair(ColInfo, 144, bg)
+ C.init_pair(ColCursor, 161, 236)
+ C.init_pair(ColSelected, 168, 236)
} else {
- C.init_pair(COL_PROMPT, C.COLOR_BLUE, bg)
- C.init_pair(COL_MATCH, C.COLOR_GREEN, bg)
- C.init_pair(COL_CURRENT, C.COLOR_YELLOW, C.COLOR_BLACK)
- C.init_pair(COL_CURRENT_MATCH, C.COLOR_GREEN, C.COLOR_BLACK)
- C.init_pair(COL_SPINNER, C.COLOR_GREEN, bg)
- C.init_pair(COL_INFO, C.COLOR_WHITE, bg)
- C.init_pair(COL_CURSOR, C.COLOR_RED, C.COLOR_BLACK)
- C.init_pair(COL_SELECTED, C.COLOR_MAGENTA, C.COLOR_BLACK)
+ C.init_pair(ColPrompt, C.COLOR_BLUE, bg)
+ C.init_pair(ColMatch, C.COLOR_GREEN, bg)
+ C.init_pair(ColCurrent, C.COLOR_YELLOW, C.COLOR_BLACK)
+ C.init_pair(ColCurrentMatch, C.COLOR_GREEN, C.COLOR_BLACK)
+ C.init_pair(ColSpinner, C.COLOR_GREEN, bg)
+ C.init_pair(ColInfo, C.COLOR_WHITE, bg)
+ C.init_pair(ColCursor, C.COLOR_RED, C.COLOR_BLACK)
+ C.init_pair(ColSelected, C.COLOR_MAGENTA, C.COLOR_BLACK)
}
_color = attrColored
} else {
@@ -245,7 +247,7 @@ func GetBytes() []byte {
// 27 (91 79) 77 type x y
func mouseSequence(sz *int) Event {
if len(_buf) < 6 {
- return Event{INVALID, 0, nil}
+ return Event{Invalid, 0, nil}
}
*sz = 6
switch _buf[3] {
@@ -258,7 +260,7 @@ func mouseSequence(sz *int) Event {
double := false
if down {
now := time.Now()
- if now.Sub(_prevDownTime) < DOUBLE_CLICK_DURATION {
+ if now.Sub(_prevDownTime) < doubleClickDuration {
_clickY = append(_clickY, y)
} else {
_clickY = []int{y}
@@ -266,18 +268,18 @@ func mouseSequence(sz *int) Event {
_prevDownTime = now
} else {
if len(_clickY) > 1 && _clickY[0] == _clickY[1] &&
- time.Now().Sub(_prevDownTime) < DOUBLE_CLICK_DURATION {
+ time.Now().Sub(_prevDownTime) < doubleClickDuration {
double = true
}
}
- return Event{MOUSE, 0, &MouseEvent{y, x, 0, down, double, mod}}
+ return Event{Mouse, 0, &MouseEvent{y, x, 0, down, double, mod}}
case 96, 100, 104, 112, // scroll-up / shift / cmd / ctrl
97, 101, 105, 113: // scroll-down / shift / cmd / ctrl
mod := _buf[3] >= 100
s := 1 - int(_buf[3]%2)*2
- return Event{MOUSE, 0, &MouseEvent{0, 0, s, false, false, mod}}
+ return Event{Mouse, 0, &MouseEvent{0, 0, s, false, false, mod}}
}
- return Event{INVALID, 0, nil}
+ return Event{Invalid, 0, nil}
}
func escSequence(sz *int) Event {
@@ -287,81 +289,81 @@ func escSequence(sz *int) Event {
*sz = 2
switch _buf[1] {
case 98:
- return Event{ALT_B, 0, nil}
+ return Event{AltB, 0, nil}
case 100:
- return Event{ALT_D, 0, nil}
+ return Event{AltD, 0, nil}
case 102:
- return Event{ALT_F, 0, nil}
+ return Event{AltF, 0, nil}
case 127:
- return Event{ALT_BS, 0, nil}
+ return Event{AltBS, 0, nil}
case 91, 79:
if len(_buf) < 3 {
- return Event{INVALID, 0, nil}
+ return Event{Invalid, 0, nil}
}
*sz = 3
switch _buf[2] {
case 68:
- return Event{CTRL_B, 0, nil}
+ return Event{CtrlB, 0, nil}
case 67:
- return Event{CTRL_F, 0, nil}
+ return Event{CtrlF, 0, nil}
case 66:
- return Event{CTRL_J, 0, nil}
+ return Event{CtrlJ, 0, nil}
case 65:
- return Event{CTRL_K, 0, nil}
+ return Event{CtrlK, 0, nil}
case 90:
- return Event{BTAB, 0, nil}
+ return Event{BTab, 0, nil}
case 72:
- return Event{CTRL_A, 0, nil}
+ return Event{CtrlA, 0, nil}
case 70:
- return Event{CTRL_E, 0, nil}
+ return Event{CtrlE, 0, nil}
case 77:
return mouseSequence(sz)
case 49, 50, 51, 52, 53, 54:
if len(_buf) < 4 {
- return Event{INVALID, 0, nil}
+ return Event{Invalid, 0, nil}
}
*sz = 4
switch _buf[2] {
case 50:
- return Event{INVALID, 0, nil} // INS
+ return Event{Invalid, 0, nil} // INS
case 51:
- return Event{DEL, 0, nil}
+ return Event{Del, 0, nil}
case 52:
- return Event{CTRL_E, 0, nil}
+ return Event{CtrlE, 0, nil}
case 53:
- return Event{PGUP, 0, nil}
+ return Event{PgUp, 0, nil}
case 54:
- return Event{PGDN, 0, nil}
+ return Event{PgDn, 0, nil}
case 49:
switch _buf[3] {
case 126:
- return Event{CTRL_A, 0, nil}
+ return Event{CtrlA, 0, nil}
case 59:
if len(_buf) != 6 {
- return Event{INVALID, 0, nil}
+ return Event{Invalid, 0, nil}
}
*sz = 6
switch _buf[4] {
case 50:
switch _buf[5] {
case 68:
- return Event{CTRL_A, 0, nil}
+ return Event{CtrlA, 0, nil}
case 67:
- return Event{CTRL_E, 0, nil}
+ return Event{CtrlE, 0, nil}
}
case 53:
switch _buf[5] {
case 68:
- return Event{ALT_B, 0, nil}
+ return Event{AltB, 0, nil}
case 67:
- return Event{ALT_F, 0, nil}
+ return Event{AltF, 0, nil}
}
} // _buf[4]
} // _buf[3]
} // _buf[2]
} // _buf[2]
} // _buf[1]
- return Event{INVALID, 0, nil}
+ return Event{Invalid, 0, nil}
}
func GetChar() Event {
@@ -378,21 +380,21 @@ func GetChar() Event {
}()
switch _buf[0] {
- case CTRL_C, CTRL_G, CTRL_Q:
- return Event{CTRL_C, 0, nil}
+ case CtrlC, CtrlG, CtrlQ:
+ return Event{CtrlC, 0, nil}
case 127:
- return Event{CTRL_H, 0, nil}
+ return Event{CtrlH, 0, nil}
case ESC:
return escSequence(&sz)
}
// CTRL-A ~ CTRL-Z
- if _buf[0] <= CTRL_Z {
+ if _buf[0] <= CtrlZ {
return Event{int(_buf[0]), 0, nil}
}
r, rsz := utf8.DecodeRune(_buf)
sz = rsz
- return Event{RUNE, r, nil}
+ return Event{Rune, r, nil}
}
func Move(y int, x int) {
diff --git a/src/eventbox.go b/src/eventbox.go
index 95126cca..0c8f922a 100644
--- a/src/eventbox.go
+++ b/src/eventbox.go
@@ -2,16 +2,17 @@ package fzf
import "sync"
-type EventType int
-
+// Events is a type that associates EventType to any data
type Events map[EventType]interface{}
+// EventBox is used for coordinating events
type EventBox struct {
events Events
cond *sync.Cond
ignore map[EventType]bool
}
+// NewEventBox returns a new EventBox
func NewEventBox() *EventBox {
return &EventBox{
events: make(Events),
@@ -19,6 +20,7 @@ func NewEventBox() *EventBox {
ignore: make(map[EventType]bool)}
}
+// Wait blocks the goroutine until signaled
func (b *EventBox) Wait(callback func(*Events)) {
b.cond.L.Lock()
defer b.cond.L.Unlock()
@@ -30,6 +32,7 @@ func (b *EventBox) Wait(callback func(*Events)) {
callback(&b.events)
}
+// Set turns on the event type on the box
func (b *EventBox) Set(event EventType, value interface{}) {
b.cond.L.Lock()
defer b.cond.L.Unlock()
@@ -39,6 +42,7 @@ func (b *EventBox) Set(event EventType, value interface{}) {
}
}
+// Clear clears the events
// Unsynchronized; should be called within Wait routine
func (events *Events) Clear() {
for event := range *events {
@@ -46,6 +50,7 @@ func (events *Events) Clear() {
}
}
+// Peak peaks at the event box if the given event is set
func (b *EventBox) Peak(event EventType) bool {
b.cond.L.Lock()
defer b.cond.L.Unlock()
@@ -53,6 +58,7 @@ func (b *EventBox) Peak(event EventType) bool {
return ok
}
+// Watch deletes the events from the ignore list
func (b *EventBox) Watch(events ...EventType) {
b.cond.L.Lock()
defer b.cond.L.Unlock()
@@ -61,6 +67,7 @@ func (b *EventBox) Watch(events ...EventType) {
}
}
+// Unwatch adds the events to the ignore list
func (b *EventBox) Unwatch(events ...EventType) {
b.cond.L.Lock()
defer b.cond.L.Unlock()
diff --git a/src/eventbox_test.go b/src/eventbox_test.go
index fb0ceedf..1cd7f220 100644
--- a/src/eventbox_test.go
+++ b/src/eventbox_test.go
@@ -9,16 +9,16 @@ func TestEventBox(t *testing.T) {
ch := make(chan bool)
go func() {
- eb.Set(EVT_READ_NEW, 10)
+ eb.Set(EvtReadNew, 10)
ch <- true
<-ch
- eb.Set(EVT_SEARCH_NEW, 10)
- eb.Set(EVT_SEARCH_NEW, 15)
- eb.Set(EVT_SEARCH_NEW, 20)
- eb.Set(EVT_SEARCH_PROGRESS, 30)
+ eb.Set(EvtSearchNew, 10)
+ eb.Set(EvtSearchNew, 15)
+ eb.Set(EvtSearchNew, 20)
+ eb.Set(EvtSearchProgress, 30)
ch <- true
<-ch
- eb.Set(EVT_SEARCH_FIN, 40)
+ eb.Set(EvtSearchFin, 40)
ch <- true
<-ch
}()
@@ -39,7 +39,7 @@ func TestEventBox(t *testing.T) {
events.Clear()
})
ch <- true
- count += 1
+ count++
}
if count != 3 {
diff --git a/src/item.go b/src/item.go
index 41aa34bd..4cbd3f98 100644
--- a/src/item.go
+++ b/src/item.go
@@ -1,9 +1,9 @@
package fzf
-import "fmt"
-
+// Offset holds two 32-bit integers denoting the offsets of a matched substring
type Offset [2]int32
+// Item represents each input line
type Item struct {
text *string
origText *string
@@ -13,12 +13,14 @@ type Item struct {
rank Rank
}
+// Rank is used to sort the search result
type Rank struct {
matchlen uint16
strlen uint16
index uint32
}
+// Rank calculates rank of the Item
func (i *Item) Rank(cache bool) Rank {
if cache && (i.rank.matchlen > 0 || i.rank.strlen > 0) {
return i.rank
@@ -45,14 +47,15 @@ func (i *Item) Rank(cache bool) Rank {
return rank
}
-func (i *Item) Print() {
+// AsString returns the original string
+func (i *Item) AsString() string {
if i.origText != nil {
- fmt.Println(*i.origText)
- } else {
- fmt.Println(*i.text)
+ return *i.origText
}
+ return *i.text
}
+// ByOrder is for sorting substring offsets
type ByOrder []Offset
func (a ByOrder) Len() int {
@@ -69,6 +72,7 @@ func (a ByOrder) Less(i, j int) bool {
return (ioff[0] < joff[0]) || (ioff[0] == joff[0]) && (ioff[1] <= joff[1])
}
+// ByRelevance is for sorting Items
type ByRelevance []*Item
func (a ByRelevance) Len() int {
diff --git a/src/matcher.go b/src/matcher.go
index 713b4dd6..b8be2870 100644
--- a/src/matcher.go
+++ b/src/matcher.go
@@ -8,11 +8,13 @@ import (
"time"
)
+// MatchRequest represents a search request
type MatchRequest struct {
chunks []*Chunk
pattern *Pattern
}
+// Matcher is responsible for performing search
type Matcher struct {
patternBuilder func([]rune) *Pattern
sort bool
@@ -23,20 +25,15 @@ type Matcher struct {
}
const (
- REQ_RETRY EventType = iota
- REQ_RESET
+ reqRetry EventType = iota
+ reqReset
)
const (
- STAT_CANCELLED int = iota
- STAT_QCH
- STAT_CHUNKS
-)
-
-const (
- PROGRESS_MIN_DURATION = 200 * time.Millisecond
+ progressMinDuration = 200 * time.Millisecond
)
+// NewMatcher returns a new Matcher
func NewMatcher(patternBuilder func([]rune) *Pattern,
sort bool, eventBox *EventBox) *Matcher {
return &Matcher{
@@ -48,6 +45,7 @@ func NewMatcher(patternBuilder func([]rune) *Pattern,
mergerCache: make(map[string]*Merger)}
}
+// Loop puts Matcher in action
func (m *Matcher) Loop() {
prevCount := 0
@@ -91,7 +89,7 @@ func (m *Matcher) Loop() {
if !cancelled {
m.mergerCache[patternString] = merger
- m.eventBox.Set(EVT_SEARCH_FIN, merger)
+ m.eventBox.Set(EvtSearchFin, merger)
}
}
}
@@ -172,7 +170,7 @@ func (m *Matcher) scan(request MatchRequest, limit int) (*Merger, bool) {
count := 0
matchCount := 0
for matchesInChunk := range countChan {
- count += 1
+ count++
matchCount += matchesInChunk
if limit > 0 && matchCount > limit {
@@ -183,12 +181,12 @@ func (m *Matcher) scan(request MatchRequest, limit int) (*Merger, bool) {
break
}
- if !empty && m.reqBox.Peak(REQ_RESET) {
+ if !empty && m.reqBox.Peak(reqReset) {
return nil, wait()
}
- if time.Now().Sub(startedAt) > PROGRESS_MIN_DURATION {
- m.eventBox.Set(EVT_SEARCH_PROGRESS, float32(count)/float32(numChunks))
+ if time.Now().Sub(startedAt) > progressMinDuration {
+ m.eventBox.Set(EvtSearchProgress, float32(count)/float32(numChunks))
}
}
@@ -200,14 +198,15 @@ func (m *Matcher) scan(request MatchRequ