summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2015-01-12 03:01:24 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2015-01-12 03:18:40 +0900
commit7a2bc2cada971c7a390d09b0afda34780ff56fb6 (patch)
treecaa19fa8bf404a854c9e2cdf6eb08194e1733a6f /src
parent9dbf6b02d24b52ae43e36905bbb1e83087e1dfe9 (diff)
downloadfzf-7a2bc2cada971c7a390d09b0afda34780ff56fb6.tar.gz
Lint
Diffstat (limited to 'src')
-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 MatchRequest, limit int) (*Merger, bool) {
return NewMerger(partialResults, !empty && m.sort), false
}
+// Reset is called to interrupt/signal the ongoing search
func (m *Matcher) Reset(chunks []*Chunk, patternRunes []rune, cancel bool) {
pattern := m.patternBuilder(patternRunes)
var event EventType
if cancel {
- event = REQ_RESET
+ event = reqReset
} else {
- event = REQ_RETRY
+ event = reqRetry
}
m.reqBox.Set(event, MatchRequest{chunks, pattern})
}
diff --git a/src/merger.go b/src/merger.go
index 16afdafc..bd2158d1 100644
--- a/src/merger.go
+++ b/src/merger.go
@@ -2,8 +2,11 @@ package fzf
import "fmt"
-var EmptyMerger *Merger = NewMerger([][]*Item{}, false)
+// Merger with no data
+var EmptyMerger = NewMerger([][]*Item{}, false)
+// Merger holds a set of locally sorted lists of items and provides the view of
+// a single, globally-sorted list
type Merger struct {
lists [][]*Item
merged []*Item
@@ -12,6 +15,7 @@ type Merger struct {
count int
}
+// NewMerger returns a new Merger
func NewMerger(lists [][]*Item, sorted bool) *Merger {
mg := Merger{
lists: lists,
@@ -26,10 +30,12 @@ func NewMerger(lists [][]*Item, sorted bool) *Merger {
return &mg
}
+// Length returns the number of items
func (mg *Merger) Length() int {
return mg.count
}
+// Get returns the pointer to the Item object indexed by the given integer
func (mg *Merger) Get(idx int) *Item {
if len(mg.lists) == 1 {
return mg.lists[0][idx]
@@ -69,7 +75,7 @@ func (mg *Merger) mergedGet(idx int) *Item {
if minIdx >= 0 {
chosen := mg.lists[minIdx]
mg.merged = append(mg.merged, chosen[mg.cursors[minIdx]])
- mg.cursors[minIdx] += 1
+ mg.cursors[minIdx]++
} else {
panic(fmt.Sprintf("Index out of bounds (sorted, %d/%d)", i, mg.count))
}
diff --git a/src/options.go b/src/options.go
index 4929dfd7..cf0608bd 100644
--- a/src/options.go
+++ b/src/options.go
@@ -8,7 +8,7 @@ import (
"strings"
)
-const USAGE = `usage: fzf [options]
+const usage = `usage: fzf [options]
Search
-x, --extended Extended-search mode
@@ -47,22 +47,27 @@ const USAGE = `usage: fzf [options]
`
+// Mode denotes the current search mode
type Mode int
+// Search modes
const (
- MODE_FUZZY Mode = iota
- MODE_EXTENDED
- MODE_EXTENDED_EXACT
+ ModeFuzzy Mode = iota
+ ModeExtended
+ ModeExtendedExact
)
+// Case denotes case-sensitivity of search
type Case int
+// Case-sensitivities
const (
- CASE_SMART Case = iota
- CASE_IGNORE
- CASE_RESPECT
+ CaseSmart Case = iota
+ CaseIgnore
+ CaseRespect
)
+// Options stores the values of command-line options
type Options struct {
Mode Mode
Case Case
@@ -85,10 +90,10 @@ type Options struct {
Version bool
}
-func DefaultOptions() *Options {
+func defaultOptions() *Options {
return &Options{
- Mode: MODE_FUZZY,
- Case: CASE_SMART,
+ Mode: ModeFuzzy,
+ Case: CaseSmart,
Nth: make([]Range, 0),
WithNth: make([]Range, 0),
Delimiter: nil,
@@ -109,7 +114,7 @@ func DefaultOptions() *Options {
}
func help(ok int) {
- os.Stderr.WriteString(USAGE)
+ os.Stderr.WriteString(usage)
os.Exit(ok)
}
@@ -123,9 +128,8 @@ func optString(arg string, prefix string) (bool, string) {
matches := rx.FindStringSubmatch(arg)
if len(matches) > 1 {
return true, matches[1]
- } else {
- return false, ""
}
+ return false, ""
}
func nextString(args []string, i *int, message string) string {
@@ -183,11 +187,11 @@ func parseOptions(opts *Options, allArgs []string) {
case "-h", "--help":
help(0)
case "-x", "--extended":
- opts.Mode = MODE_EXTENDED
+ opts.Mode = ModeExtended
case "-e", "--extended-exact":
- opts.Mode = MODE_EXTENDED_EXACT
+ opts.Mode = ModeExtendedExact
case "+x", "--no-extended", "+e", "--no-extended-exact":
- opts.Mode = MODE_FUZZY
+ opts.Mode = ModeFuzzy
case "-q", "--query":
opts.Query = nextString(allArgs, &i, "query string required")
case "-f", "--filter":
@@ -204,9 +208,9 @@ func parseOptions(opts *Options, allArgs []string) {
case "+s", "--no-sort":
opts.Sort = 0
case "-i":
- opts.Case = CASE_IGNORE
+ opts.Case = CaseIgnore
case "+i":
- opts.Case = CASE_RESPECT
+ opts.Case = CaseRespect
case "-m", "--multi":
opts.Multi = true
case "+m", "--no-multi":
@@ -263,8 +267,9 @@ func parseOptions(opts *Options, allArgs []string) {
}
}
+// ParseOptions parses command-line options
func ParseOptions() *Options {
- opts := DefaultOptions()
+ opts := defaultOptions()
// Options from Env var
words, _ := shellwords.Parse(os.Getenv("FZF_DEFAULT_OPTS"))
diff --git a/src/options_test.go b/src/options_test.go
index f0aa3a0d..e10ec569 100644
--- a/src/options_test.go
+++ b/src/options_test.go
@@ -15,20 +15,20 @@ func TestSplitNth(t *testing.T) {
{
ranges := splitNth("..")
if len(ranges) != 1 ||
- ranges[0].begin != RANGE_ELLIPSIS ||
- ranges[0].end != RANGE_ELLIPSIS {
+ ranges[0].begin != rangeEllipsis ||
+ ranges[0].end != rangeEllipsis {
t.Errorf("%s", ranges)
}
}
{
ranges := splitNth("..3,1..,2..3,4..-1,-3..-2,..,2,-2")
if len(ranges) != 8 ||
- ranges[0].begin != RANGE_ELLIPSIS || ranges[0].end != 3 ||
- ranges[1].begin != 1 || ranges[1].end != RANGE_ELLIPSIS ||
+ ranges[0].begin != rangeEllipsis || ranges[0].end != 3 ||
+ ranges[1].begin != 1 || ranges[1].end != rangeEllipsis ||
ranges[2].begin != 2 || ranges[2].end != 3 ||
ranges[3].begin != 4 || ranges[3].end != -1 ||
ranges[4].begin != -3 || ranges[4].end != -2 ||
- ranges[5].begin != RANGE_ELLIPSIS || ranges[5].end != RANGE_ELLIPSIS ||
+ ranges[5].begin != rangeEllipsis || ranges[5].end != rangeEllipsis ||
ranges[6].begin != 2 || ranges[6].end != 2 ||
ranges[7].begin != -2 || ranges[7].end != -2 {
t.Errorf("%s", ranges)
diff --git a/src/pattern.go b/src/pattern.go
index 2e7d6f91..9f32de60 100644
--- a/src/pattern.go
+++ b/src/pattern.go
@@ -6,7 +6,7 @@ import (
"strings"
)
-const UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+const uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// fuzzy
// 'exact
@@ -17,31 +17,32 @@ const UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// !^not-exact-prefix
// !not-exact-suffix$
-type TermType int
+type termType int
const (
- TERM_FUZZY TermType = iota
- TERM_EXACT
- TERM_PREFIX
- TERM_SUFFIX
+ termFuzzy termType = iota
+ termExact
+ termPrefix
+ termSuffix
)
-type Term struct {
- typ TermType
+type term struct {
+ typ termType
inv bool
text []rune
origText []rune
}
+// Pattern represents search pattern
type Pattern struct {
mode Mode
caseSensitive bool
text []rune
- terms []Term
+ terms []term
hasInvTerm bool
delimiter *regexp.Regexp
nth []Range
- procFun map[TermType]func(bool, *string, []rune) (int, int)
+ procFun map[termType]func(bool, *string, []rune) (int, int)
}
var (
@@ -62,12 +63,13 @@ func clearPatternCache() {
_patternCache = make(map[string]*Pattern)
}
+// BuildPattern builds Pattern object from the given arguments
func BuildPattern(mode Mode, caseMode Case,
nth []Range, delimiter *regexp.Regexp, runes []rune) *Pattern {
var asString string
switch mode {
- case MODE_EXTENDED, MODE_EXTENDED_EXACT:
+ case ModeExtended, ModeExtendedExact:
asString = strings.Trim(string(runes), " ")
default:
asString = string(runes)
@@ -79,19 +81,19 @@ func BuildPattern(mode Mode, caseMode Case,
}
caseSensitive, hasInvTerm := true, false
- terms := []Term{}
+ terms := []term{}
switch caseMode {
- case CASE_SMART:
- if !strings.ContainsAny(asString, UPPERCASE) {
+ case CaseSmart:
+ if !strings.ContainsAny(asString, uppercaseLetters) {
runes, caseSensitive = []rune(strings.ToLower(asString)), false
}
- case CASE_IGNORE:
+ case CaseIgnore:
runes, caseSensitive = []rune(strings.ToLower(asString)), false
}
switch mode {
- case MODE_EXTENDED, MODE_EXTENDED_EXACT:
+ case ModeExtended, ModeExtendedExact:
terms = parseTerms(mode, string(runes))
for _, term := range terms {
if term.inv {
@@ -108,25 +110,25 @@ func BuildPattern(mode Mode, caseMode Case,
hasInvTerm: hasInvTerm,
nth: nth,
delimiter: delimiter,
- procFun: make(map[TermType]func(bool, *string, []rune) (int, int))}
+ procFun: make(map[termType]func(bool, *string, []rune) (int, int))}
- ptr.procFun[TERM_FUZZY] = FuzzyMatch
- ptr.procFun[TERM_EXACT] = ExactMatchNaive
- ptr.procFun[TERM_PREFIX] = PrefixMatch
- ptr.procFun[TERM_SUFFIX] = SuffixMatch
+ ptr.procFun[termFuzzy] = FuzzyMatch
+ ptr.procFun[termExact] = ExactMatchNaive
+ ptr.procFun[termPrefix] = PrefixMatch
+ ptr.procFun[termSuffix] = SuffixMatch
_patternCache[asString] = ptr
return ptr
}
-func parseTerms(mode Mode, str string) []Term {
+func parseTerms(mode Mode, str string) []term {
tokens := _splitRegex.Split(str, -1)
- terms := []Term{}
+ terms := []term{}
for _, token := range tokens {
- typ, inv, text := TERM_FUZZY, false, token
+ typ, inv, text := termFuzzy, false, token
origText := []rune(text)
- if mode == MODE_EXTENDED_EXACT {
- typ = TERM_EXACT
+ if mode == ModeExtendedExact {
+ typ = termExact
}
if strings.HasPrefix(text, "!") {
@@ -135,20 +137,20 @@ func parseTerms(mode Mode, str string) []Term {
}
if strings.HasPrefix(text, "'") {
- if mode == MODE_EXTENDED {
- typ = TERM_EXACT
+ if mode == ModeExtended {
+ typ = termExact
text = text[1:]
}
} else if strings.HasPrefix(text, "^") {
- typ = TERM_PREFIX
+ typ = termPrefix
text = text[1:]
} else if strings.HasSuffix(text, "$") {
- typ = TERM_SUFFIX
+ typ = termSuffix
text = text[:len(text)-1]
}
if len(text) > 0 {
- terms = append(terms, Term{
+ terms = append(terms, term{
typ: typ,
inv: inv,
text: []rune(text),
@@ -158,20 +160,22 @@ func parseTerms(mode Mode, str string) []Term {
return terms
}
+// IsEmpty returns true if the pattern is effectively empty
func (p *Pattern) IsEmpty() bool {
- if p.mode == MODE_FUZZY {
+ if p.mode == ModeFuzzy {
return len(p.text) == 0
- } else {
- return len(p.terms) == 0
}
+ return len(p.terms) == 0
}
+// AsString returns the search query in string type
func (p *Pattern) AsString() string {
return string(p.text)
}
+// CacheKey is used to build string to be used as the key of result cache
func (p *Pattern) CacheKey() string {
- if p.mode == MODE_FUZZY {
+ if p.mode == ModeFuzzy {
return p.AsString()
}
cacheableTerms := []string{}
@@ -184,6 +188,7 @@ func (p *Pattern) CacheKey() string {
return strings.Join(cacheableTerms, " ")
}
+// Match returns the list of matches Items in the given Chunk
func (p *Pattern) Match(chunk *Chunk) []*Item {
space := chunk
@@ -213,7 +218,7 @@ Loop:
}
var matches []*Item
- if p.mode == MODE_FUZZY {
+ if p.mode == ModeFuzzy {
matches = p.fuzzyMatch(space)
} else {
matches = p.extendedMatch(space)
diff --git a/src/pattern_test.go b/src/pattern_test.go
index 2635b6c7..c006c451 100644
--- a/src/pattern_test.go
+++ b/src/pattern_test.go
@@ -3,17 +3,17 @@ package fzf
import "testing"
func TestParseTermsExtended(t *testing.T) {
- terms := parseTerms(MODE_EXTENDED,
+ terms := parseTerms(ModeExtended,
"aaa 'bbb ^ccc ddd$ !eee !'fff !^ggg !hhh$")
if len(terms) != 8 ||
- terms[0].typ != TERM_FUZZY || terms[0].inv ||
- terms[1].typ != TERM_EXACT || terms[1].inv ||
- terms[2].typ != TERM_PREFIX || terms[2].inv ||
- terms[3].typ != TERM_SUFFIX || terms[3].inv ||
- terms[4].typ != TERM_FUZZY || !terms[4].inv ||
- terms[5].typ != TERM_EXACT || !terms[5].inv ||
- terms[6].typ != TERM_PREFIX || !terms[6].inv ||
- terms[7].typ != TERM_SUFFIX || !terms[7].inv {
+ terms[0].typ != termFuzzy || terms[0].inv ||
+ terms[1].typ != termExact || terms[1].inv ||
+ terms[2].typ != termPrefix || terms[2].inv ||
+ terms[3].typ != termSuffix || terms[3].inv ||
+ terms[4].typ != termFuzzy || !terms[4].inv ||
+ terms[5].typ != termExact || !terms[5].inv ||
+ terms[6].typ != termPrefix || !terms[6].inv ||
+ terms[7].typ != termSuffix || !terms[7].inv {
t.Errorf("%s", terms)
}
for idx, term := range terms {
@@ -27,23 +27,23 @@ func TestParseTermsExtended(t *testing.T) {
}
func TestParseTermsExtendedExact(t *testing.T) {
- terms := parseTerms(MODE_EXTENDED_EXACT,
+ terms := parseTerms(ModeExtendedExact,
"aaa 'bbb ^ccc ddd$ !eee !'fff !^ggg !hhh$")
if len(terms) != 8 ||
- terms[0].typ != TERM_EXACT || terms[0].inv || len(terms[0].text) != 3 ||
- terms[1].typ != TERM_EXACT || terms[1].inv || len(terms[1].text) != 4 ||
- terms[2].typ != TERM_PREFIX || terms[2].inv || len(terms[2].text) != 3 ||
- terms[3].typ != TERM_SUFFIX || terms[3].inv || len(terms[3].text) != 3 ||
- terms[4].typ != TERM_EXACT || !terms[4].inv || len(terms[4].text) != 3 ||
- terms[5].typ != TERM_EXACT || !terms[5].inv || len(terms[5].text) != 4 ||
- terms[6].typ != TERM_PREFIX || !terms[6].inv || len(terms[6].text) != 3 ||
- terms[7].typ != TERM_SUFFIX || !terms[7].inv || len(terms[7].text) != 3 {
+ terms[0].typ != termExact || terms[0].inv || len(terms[0].text) != 3 ||
+ terms[1].typ != termExact || terms[1].inv || len(terms[1].text) != 4 ||
+ terms[2].typ != termPrefix || terms[2].inv || len(terms[2].text) != 3 ||
+ terms[3].typ != termSuffix || terms[3].inv || len(terms[3].text) != 3 ||
+ terms[4].typ != termExact || !terms[4].inv || len(terms[4].text) != 3 ||
+ terms[5].typ != termExact || !terms[5].inv || len(terms[5].text) != 4 ||
+ terms[6].typ != termPrefix || !terms[6].inv || len(terms[6].text) != 3 ||
+ terms[7].typ != termSuffix || !terms[7].inv || len(terms[7].text) != 3 {
t.Errorf("%s", terms)
}
}
func TestParseTermsEmpty(t *testing.T) {
- terms := parseTerms(MODE_EXTENDED, "' $ ^ !' !^ !$")
+ terms := parseTerms(ModeExtended, "' $ ^ !' !^ !$")
if len(terms) != 0 {
t.Errorf("%s", terms)
}
@@ -52,7 +52,7 @@ func TestParseTermsEmpty(t *testing.T) {
func TestExact(t *testing.T) {
defer clearPatternCache()
clearPatternCache()
- pattern := BuildPattern(MODE_EXTENDED, CASE_SMART,
+ pattern := BuildPattern(ModeExtended, CaseSmart,
[]Range{}, nil, []rune("'abc"))
str := "aabbcc abc"
sidx, eidx := ExactMatchNaive(pattern.caseSensitive, &str, pattern.terms[0].text)
@@ -64,17 +64,17 @@ func TestExact(t *testing.T) {
func TestCaseSensitivity(t *testing.T) {
defer clearPatternCache()
clearPatternCache()
- pat1 := BuildPattern(MODE_FUZZY, CASE_SMART, []Range{}, nil, []rune("abc"))
+ pat1 := BuildPattern(ModeFuzzy, CaseSmart, []Range{}, nil, []rune("abc"))
clearPatternCache()
- pat2 := BuildPattern(MODE_FUZZY, CASE_SMART, []Range{}, nil, []rune("Abc"))
+ pat2 := BuildPattern(ModeFuzzy, CaseSmart, []Range{}, nil, []rune("Abc"))
clearPatternCache()
- pat3 := BuildPattern(MODE_FUZZY, CASE_IGNORE, []Range{}, nil, []rune("abc"))
+ pat3 := BuildPattern(ModeFuzzy, CaseIgnore, []Range{}, nil, []rune("abc"))
clearPatternCache()
- pat4 := BuildPattern(MODE_FUZZY, CASE_IGNORE, []Range{}, nil, []rune("Abc"))
+ pat4 := BuildPattern(ModeFuzzy, CaseIgnore, []Range{}, nil, []rune("Abc"))
clearPatternCache()
- pat5 := BuildPattern(MODE_FUZZY, CASE_RESPECT, []Range{}, nil, []rune("abc"))
+ pat5 := BuildPattern(ModeFuzzy, CaseRespect, []Range{}, nil, []rune("abc"))
clearPatternCache()
- pat6 := BuildPattern(MODE_FUZZY, CASE_RESPECT, []Range{}, nil, []rune("Abc"))
+ pat6 := BuildPattern(ModeFuzzy, CaseRespect, []Range{}, nil, []rune("Abc"))
if string(pat1.text) != "abc" || pat1.caseSensitive != false ||
string(pat2.text) != "Abc" || pat2.caseSensitive != true ||
@@ -90,7 +90,7 @@ func TestOrigTextAndTransformed(t *testing.T) {
strptr := func(str string) *string {
return &str
}
- pattern := BuildPattern(MODE_EXTENDED, CASE_SMART, []Range{}, nil, []rune("jg"))
+ pattern := BuildPattern(ModeExtended, CaseSmart, []Range{}, nil, []rune("jg"))
tokens := Tokenize(strptr("junegunn"), nil)
trans := Transform(tokens, []Range{Range{1, 1}})
diff --git a/src/reader.go b/src/reader.go
index 39fa70cd..269a2fdc 100644
--- a/src/reader.go
+++ b/src/reader.go
@@ -10,31 +10,33 @@ import (
"os/exec"
)
-const DEFAULT_COMMAND = `find * -path '*/\.*' -prune -o -type f -print -o -type l -print 2> /dev/null`
+const defaultCommand = `find * -path '*/\.*' -prune -o -type f -print -o -type l -print 2> /dev/null`
+// Reader reads from command or standard input
type Reader struct {
pusher func(string)
eventBox *EventBox
}
+// ReadSource reads data from the default command or from standard input
func (r *Reader) ReadSource() {
if int(C.isatty(C.int(os.Stdin.Fd()))) != 0 {
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
if len(cmd) == 0 {
- cmd = DEFAULT_COMMAND
+ cmd = defaultCommand
}
r.readFromCommand(cmd)
} else {
r.readFromStdin()
}
- r.eventBox.Set(EVT_READ_FIN, nil)
+ r.eventBox.Set(EvtReadFin, nil)
}
func (r *Reader) feed(src io.Reader) {
if scanner := bufio.NewScanner(src); scanner != nil {
for scanner.Scan() {
r.pusher(scanner.Text())
- r.eventBox.Set(EVT_READ_NEW, nil)
+ r.eventBox.Set(EvtReadNew, nil)
}
}
}
diff --git a/src/reader_test.go b/src/reader_test.go
index f51ccab0..630f6faa 100644
--- a/src/reader_test.go
+++ b/src/reader_test.go
@@ -10,8 +10,8 @@ func TestReadFromCommand(t *testing.T) {
eventBox: eb}
// Check EventBox
- if eb.Peak(EVT_READ_NEW) {
- t.Error("EVT_READ_NEW should not be set yet")
+ if eb.Peak(EvtReadNew) {
+ t.Error("EvtReadNew should not be set yet")
}
// Normal command
@@ -21,21 +21,21 @@ func TestReadFromCommand(t *testing.T) {
}
// Check EventBox again
- if !eb.Peak(EVT_READ_NEW) {
- t.Error("EVT_READ_NEW should be set yet")
+ if !eb.Peak(EvtReadNew) {
+ t.Error("EvtReadNew should be set yet")
}
// Wait should return immediately
eb.Wait(func(events *Events) {
- if _, found := (*events)[EVT_READ_NEW]; !found {
+ if _, found := (*events)[EvtReadNew]; !found {
t.Errorf("%s", events)
}
events.Clear()
})
// EventBox is cleared
- if eb.Peak(EVT_READ_NEW) {
- t.Error("EVT_READ_NEW should not be set yet")
+ if eb.Peak(EvtReadNew) {
+ t.Error("EvtReadNew should not be set yet")
}
// Failing command
@@ -46,7 +46,7 @@ func TestReadFromCommand(t *testing.T) {
}
// Check EventBox again
- if eb.Peak(EVT_READ_NEW) {
- t.Error("Command failed. EVT_READ_NEW should be set")
+ if eb.Peak(EvtReadNew) {
+ t.Error("Command failed. EvtReadNew should be set")
}
}
diff --git a/src/terminal.go b/src/terminal.go
index 7d8bc5b2..daf63c5c 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -11,6 +11,7 @@ import (
"time"
)
+// Terminal represents terminal input/output
type Terminal struct {
prompt string
reverse bool
@@ -34,23 +35,24 @@ type Terminal struct {
suppress bool
}
-var _spinner []string = []string{`-`, `\`, `|`, `/`, `-`, `\`, `|`, `/`}
+var _spinner = []string{`-`, `\`, `|`, `/`, `-`, `\`, `|`, `/`}
const (
- REQ_PROMPT EventType = iota
- REQ_INFO
- REQ_LIST
- REQ_REFRESH
- REQ_REDRAW
- REQ_CLOSE
- REQ_QUIT
+ reqPrompt EventType = iota
+ reqInfo
+ reqList
+ reqRefresh
+ reqRedraw
+ reqClose
+ reqQuit
)
const (
- INITIAL_DELAY = 100 * time.Millisecond
- SPINNER_DURATION = 200 * time.Millisecond
+ initialDelay = 100 * time.Millisecond
+ spinnerDuration = 200 * time.Millisecond
)
+// NewTerminal returns new Terminal object
func NewTerminal(opts *Options, eventBox *EventBox) *Terminal {
input := []rune(opts.Query)
return &Terminal{
@@ -75,23 +77,26 @@ func NewTerminal(opts *Options, eventBox *EventBox) *Terminal {
}}
}
+// Input returns current query string
func (t *Terminal) Input() []rune {
t.mutex.Lock()
defer t.mutex.Unlock()
return copySlice(t.input)
}
+// UpdateCount updates the count information
func (t *Terminal) UpdateCount(cnt int, final bool) {
t.mutex.Lock()
t.count = cnt
t.reading = !final
t.mutex.Unlock()
- t.reqBox.Set(REQ_INFO, nil)
+ t.reqBox.Set(reqInfo, nil)
if final {
- t.reqBox.Set(REQ_REFRESH, nil)
+ t.reqBox.Set(reqRefresh, nil)
}
}
+// UpdateProgress updates the search progress
func (t *Terminal) UpdateProgress(progress float32) {
t.mutex.Lock()
newProgress := int(progress * 100)
@@ -100,25 +105,25 @@ func (t *Terminal) UpdateProgress(progress float32) {
t.mutex.Unlock()
if changed {
- t.reqBox.Set(REQ_INFO, nil)
+ t.reqBox.Set(reqInfo, nil)
}
}
+// UpdateList updates Merger to display the list
func (t *Terminal) UpdateList(merger *Merger) {
t.mutex.Lock()
t.progress = 100
t.merger = merger
t.mutex.Unlock()
- t.reqBox.Set(REQ_INFO, nil)
- t.reqBox.Set(REQ_LIST, nil)
+ t.reqBox.Set(reqInfo, nil)
+ t.reqBox.Set(reqList, nil)
}
func (t *Terminal) listIndex(y int) int {
if t.tac {
return t.merger.Length() - y - 1
- } else {
- return y
}
+ return y
}
func (t *Terminal) output() {
@@ -127,7 +132,7 @@ func (t *Terminal) output() {
}
if len(t.selected) == 0 {
if t.merger.Length() > t.cy {
- t.merger.Get(t.listIndex(t.cy)).Print()
+ fmt.Println(t.merger.Get(t.listIndex(t.cy)).AsString())
}
} else {
for ptr, orig := range t.selected {
@@ -167,16 +172,16 @@ func (t *Terminal) placeCursor() {
func (t *Terminal) printPrompt() {
t.move(0, 0, true)
- C.CPrint(C.COL_PROMPT, true, t.prompt)
- C.CPrint(C.COL_NORMAL, true, string(t.input))
+ C.CPrint(C.ColPrompt, true, t.prompt)
+ C.CPrint(C.ColNormal, true, string(t.input))
}
func (t *Terminal) printInfo() {
t.move(1, 0, true)
if t.reading {
- duration := int64(SPINNER_DURATION)
+ duration := int64(spinnerDuration)
idx := (time.Now().UnixNano() % (duration * int64(len(_spinner)))) / duration
- C.CPrint(C.COL_SPINNER, true, _spinner[idx])
+ C.CPrint(C.ColSpinner, true, _spinner[idx])
}
t.move(1, 2, false)
@@ -187,7 +192,7 @@ func (t *Terminal) printInfo() {
if t.progress > 0 && t.progress < 100 {
output += fmt.Sprintf(" (%d%%)", t.progress)
}
- C.CPrint(C.COL_INFO, false, output)
+ C.CPrint(C.ColInfo, false, output)
}
func (t *Terminal) printList() {
@@ -206,21 +211,21 @@ func (t *Terminal) printList() {
func (t *Terminal) printItem(item *Item, current bool) {
_, selected := t.selected[item.text]
if current {
- C.CPrint(C.COL_CURSOR, true, ">")
+ C.CPrint(C.ColCursor, true, ">")
if selected {
- C.CPrint(C.COL_CURRENT, true, ">")
+ C.CPrint(C.ColCurrent, true, ">")
} else {
- C.CPrint(C.COL_CURRENT, true, " ")
+ C.CPrint(C.ColCurrent, true, " ")
}
- t.printHighlighted(item, true, C.COL_CURRENT, C.COL_CURRENT_MATCH)
+ t.printHighlighted(item, true, C.ColCurrent, C.ColCurrentMatch)
} else {
- C.CPrint(C.COL_CURSOR, true, " ")
+ C.CPrint(C.ColCursor, true, " ")
if selected {
- C.CPrint(C.COL_SELECTED, true, ">")
+ C.CPrint(C.ColSelected, true, ">")
} else {
C.Print(" ")
}
- t.printHighlighted(item, false, 0, C.COL_MATCH)
+ t.printHighlighted(item, false, 0, C.ColMatch)
}
}
@@ -232,25 +237,25 @@ func trimRight(runes []rune, width int) ([]rune, int) {
sz := len(runes)
currentWidth -= runewidth.RuneWidth(runes[sz-1])
runes = runes[:sz-1]
- trimmed += 1
+ trimmed++
}
return runes, trimmed
}
func trimLeft(runes []rune, width int) ([]rune, int32) {
currentWidth := displayWidth(runes)
- var trimmed int32 = 0
+ var trimmed int32
for currentWidth > width && len(runes) > 0 {
currentWidth -= runewidth.RuneWidth(runes[0])
runes = runes[1:]
- trimmed += 1
+ trimmed++
}
return runes, trimmed
}
func (*Terminal) printHighlighted(item *Item, bold bool, col1 int, col2 int) {
- var maxe int32 = 0
+ var maxe int32
for _, offset := range item.offsets {
if offset[1] > maxe {
maxe = offset[1]
@@ -293,7 +298,7 @@ func (*Terminal) printHighlighted(item *Item, bold bool, col1 int, col2 int) {
}
sort.Sort(ByOrder(offsets))
- var index int32 = 0
+ var index int32
for _, offset := range offsets {
b := Max32(index, offset[0])
e := Max32(index, offset[1])
@@ -364,6 +369,7 @@ func (t *Terminal) rubout(pattern string) {
t.input = append(t.input[:t.cx], after...)
}
+// Loop is called to start Terminal I/O
func (t *Terminal) Loop() {
{ // Late initialization
t.mutex.Lock()
@@ -374,9 +380,9 @@ func (t *Terminal) Loop() {
t.printInfo()
t.mutex.Unlock()
go func() {
- timer := time.NewTimer(INITIAL_DELAY)
+ timer := time.NewTimer(initialDelay)
<-timer.C
- t.reqBox.Set(REQ_REFRESH, nil)
+ t.reqBox.Set(reqRefresh, nil)
}()
}
@@ -387,22 +393,22 @@ func (t *Terminal) Loop() {
t.mutex.Lock()
for req := range *events {
switch req {
- case REQ_PROMPT:
+ case reqPrompt:
t.printPrompt()
- case REQ_INFO:
+ case reqInfo:
t.printInfo()
- case REQ_LIST:
+ case reqList:
t.printList()
- case REQ_REFRESH:
+ case reqRefresh:
t.suppress = false
- case REQ_REDRAW:
+ case reqRedraw:
C.Clear()
t.printAll()
- case REQ_CLOSE:
+ case reqClose:
C.Close()
t.output()
os.Exit(0)
- case REQ_QUIT:
+ case reqQuit:
C.Close()
os.Exit(1)
}
@@ -420,11 +426,11 @@ func (t *Terminal) Loop() {
t.mutex.Lock()
previousInput := t.input
- events := []EventType{REQ_PROMPT}
+ events := []EventType{reqPrompt}
req := func(evts ...EventType) {
for _, event := range evts {
events = append(events, event)
- if event == REQ_CLOSE || event == REQ_QUIT {
+ if event == reqClose || event == reqQuit {
looping = false
}
}
@@ -438,99 +444,99 @@ func (t *Terminal) Loop() {
} else {
delete(t.selected, item.text)
}
- req(REQ_INFO)
+ req(reqInfo)
}
}
switch event.Type {
- case C.INVALID:
+ case C.Invalid:
t.mutex.Unlock()
continue
- case C.CTRL_A:
+ case C.CtrlA:
t.cx = 0
- case C.CTRL_B:
+ case C.CtrlB:
if t.cx > 0 {
- t.cx -= 1
+ t.cx--
}
- case C.CTRL_C, C.CTRL_G, C.CTRL_Q, C.ESC:
- req(REQ_QUIT)
- case C.CTRL_D:
+ case C.CtrlC, C.CtrlG, C.CtrlQ, C.ESC:
+ req(reqQuit)
+ case C.CtrlD:
if !t.delChar() && t.cx == 0 {
- req(REQ_QUIT)
+ req(reqQuit)
}
- case C.CTRL_E:
+ case C.CtrlE:
t.cx = len(t.input)
- case C.CTRL_F:
+ case C.CtrlF:
if t.cx < len(t.input) {
- t.cx += 1
+ t.cx++
}
- case C.CTRL_H:
+ case C.CtrlH:
if t.cx > 0 {
t.input = append(t.input[:t.cx-1], t.input[t.cx:]...)
- t.cx -= 1
+ t.cx--
}
- case C.TAB:
+ case C.Tab:
if t.multi && t.merger.Length() > 0 {
toggle()
t.vmove(-1)
- req(REQ_LIST)
+ req(reqList)
}
- case C.BTAB:
+ case C.BTab:
if t.multi && t.merger.Length() > 0 {
toggle()
t.vmove(1)
- req(REQ_LIST)
+ req(reqList)
}
- case C.CTRL_J, C.CTRL_N:
+ case C.CtrlJ, C.CtrlN:
t.vmove(-1)
- req(REQ_LIST)
- case C.CTRL_K, C.CTRL_P:
+ req(reqList)
+ case C.CtrlK, C.CtrlP:
t.vmove(1)
- req(REQ_LIST)
- case C.CTRL_M:
- req(REQ_CLOSE)
- case C.CTRL_L:
- req(REQ_REDRAW)
- case C.CTRL_U:
+ req(reqList)
+ case C.CtrlM:
+ req(reqClose)
+ case C.CtrlL:
+ req(reqRedraw)
+ case C.CtrlU:
if t.cx > 0 {
t.yanked = copySlice(t.input[:t.cx])
t.input = t.input[t.cx:]
t.cx = 0
}
- case C.CTRL_W:
+ case C.CtrlW:
if t.cx > 0 {
t.rubout("\\s\\S")
}
- case C.ALT_BS:
+ case C.AltBS:
if t.cx > 0 {
t.rubout("[^[:alnum:]][[:alnum:]]")
}
- case C.CTRL_Y:
+ case C.CtrlY:
t.input = append(append(t.input[:t.cx], t.yanked...), t.input[t.cx:]...)
t.cx += len(t.yanked)
- case C.DEL:
+ case C.Del:
t.delChar()
- case C.PGUP:
+ case C.PgUp:
t.vmove(maxItems() - 1)
- req(REQ_LIST)
- case C.PGDN:
+ req(reqList)
+ case C.PgDn:
t.vmove(-(maxItems() - 1))
- req(REQ_LIST)
- case C.ALT_B:
+ req(reqList)
+ case C.AltB:
t.cx = findLastMatch("[^[:alnum:]][[:alnum:]]", string(t.input[:t.cx])) + 1
- case C.ALT_F:
+ case C.AltF:
t.cx += findFirstMatch("[[:alnum:]][^[:alnum:]]|(.$)", string(t.input[t.cx:])) + 1
- case C.ALT_D:
+ case C.AltD:
ncx := t.cx +
findFirstMatch("[[:alnum:]][^[:alnum:]]|(.$)", string(t.input[t.cx:])) + 1
if ncx > t.cx {
t.yanked = copySlice(t.input[t.cx:ncx])
t.input = append(t.input[:t.cx], t.input[ncx:]...)
}
- case C.RUNE:
+ case C.Rune:
prefix := copySlice(t.input[:t.cx])
t.input = append(append(prefix, event.Char), t.input[t.cx:]...)
- t.cx += 1
- case C.MOUSE:
+ t.cx++
+ case C.Mouse:
me := event.MouseEvent
mx, my := Min(len(t.input), Max(0, me.X-len(t.prompt))), me.Y
if !t.reverse {
@@ -543,13 +549,13 @@ func (t *Terminal) Loop() {
toggle()
}
t.vmove(me.S)
- req(REQ_LIST)
+ req(reqList)
}
} else if me.Double {
// Double-click
if my >= 2 {
if t.vset(my-2) && t.listIndex(t.cy) < t.merger.Length() {
- req(REQ_CLOSE)
+ req(reqClose)
}
}
} else if me.Down {
@@ -561,7 +567,7 @@ func (t *Terminal) Loop() {
if t.vset(t.offset+my-2) && t.multi && me.Mod {
toggle()
}
- req(REQ_LIST)
+ req(reqList)
}
}
}
@@ -569,7 +575,7 @@ func (t *Terminal) Loop() {
t.mutex.Unlock() // Must be unlocked before touching reqBox
if changed {
- t.eventBox.Set(EVT_SEARCH_NEW, nil)
+ t.eventBox.Set(EvtSearchNew, nil)
}
for _, event := range events {
t.reqBox.Set(event, nil)
diff --git a/src/tokenizer.go b/src/tokenizer.go
index d62f395d..294329b0 100644
--- a/src/tokenizer.go
+++ b/src/tokenizer.go
@@ -6,40 +6,42 @@ import (
"strings"
)
-const RANGE_ELLIPSIS = 0
+const rangeEllipsis = 0
+// Range represents nth-expression
type Range struct {
begin int
end int
}
+// Transformed holds the result of tokenization and transformation
type Transformed struct {
whole *string
parts []Token
}
+// Token contains the tokenized part of the strings and its prefix length
type Token struct {
text *string
prefixLength int
}
+// ParseRange parses nth-expression and returns the corresponding Range object
func ParseRange(str *string) (Range, bool) {
if (*str) == ".." {
- return Range{RANGE_ELLIPSIS, RANGE_ELLIPSIS}, true
+ return Range{rangeEllipsis, rangeEllipsis}, true
} else if strings.HasPrefix(*str, "..") {
end, err := strconv.Atoi((*str)[2:])
if err != nil || end == 0 {
return Range{}, false
- } else {
- return Range{RANGE_ELLIPSIS, end}, true
}
+ return Range{rangeEllipsis, end}, true
} else if strings.HasSuffix(*str, "..") {
begin, err := strconv.Atoi((*str)[:len(*str)-2])
if err != nil || begin == 0 {
return Range{}, false
- } else {
- return Range{begin, RANGE_ELLIPSIS}, true
}
+ return Range{begin, rangeEllipsis}, true
} else if strings.Contains(*str, "..") {
ns := strings.Split(*str, "..")
if len(ns) != 2 {
@@ -75,9 +77,9 @@ func withPrefixLengths(tokens []string, begin int) []Token {
}
const (
- AWK_NIL = iota
- AWK_BLACK
- AWK_WHITE
+ awkNil = iota
+ awkBlack
+ awkWhite
)
func awkTokenizer(input *string) ([]string, int) {
@@ -85,28 +87,28 @@ func awkTokenizer(input *string) ([]string, int) {
ret := []string{}
str := []rune{}
prefixLength := 0
- state := AWK_NIL
+ state := awkNil
for _, r := range []rune(*input) {
white := r == 9 || r == 32
switch state {
- case AWK_NIL:
+ case awkNil:
if white {
prefixLength++
} else {
- state = AWK_BLACK
+ state = awkBlack
str = append(str, r)
}
- case AWK_BLACK:
+ case awkBlack:
str = append(str, r)
if white {
- state = AWK_WHITE
+ state = awkWhite
}
- case AWK_WHITE:
+ case awkWhite:
if white {
str = append(str, r)
} else {
ret = append(ret, string(str))
- state = AWK_BLACK
+ state = awkBlack
str = []rune{r}
}
}
@@ -117,15 +119,15 @@ func awkTokenizer(input *string) ([]string, int) {
return ret, prefixLength
}
+// Tokenize tokenizes the given string with the delimiter
func Tokenize(str *string, delimiter *regexp.Regexp) []Token {
if delimiter == nil {
// AWK-style (\S+\s*)
tokens, prefixLength := awkTokenizer(str)
return withPrefixLengths(tokens, prefixLength)
- } else {
- tokens := delimiter.FindAllString(*str, -1)
- return withPrefixLengths(tokens, 0)
}
+ tokens := delimiter.FindAllString(*str, -1)
+ return withPrefixLengths(tokens, 0)
}
func joinTokens(tokens []Token) string {
@@ -136,6 +138,7 @@ func joinTokens(tokens []Token) string {
return ret
}
+// Transform is used to transform the input when --with-nth option is given
func Transform(tokens []Token, withNth []Range) *Transformed {
transTokens := make([]Token, len(withNth))
numTokens := len(tokens)
@@ -145,7 +148,7 @@ func Transform(tokens []Token, withNth []Range) *Transformed {
minIdx := 0
if r.begin == r.end {
idx := r.begin
- if idx == RANGE_ELLIPSIS {
+ if idx == rangeEllipsis {
part += joinTokens(tokens)
} else {
if idx < 0 {
@@ -158,12 +161,12 @@ func Transform(tokens []Token, withNth []Range) *Transformed {
}
} else {
var begin, end int
- if r.begin == RANGE_ELLIPSIS { // ..N
+ if r.begin == rangeEllipsis { // ..N
begin, end = 1, r.end
if end < 0 {
end += numTokens + 1
}
- } else if r.end == RANGE_ELLIPSIS { // N..
+ } else if r.end == rangeEllipsis { // N..
begin, end = r.begin, numTokens
if begin < 0 {
begin += numTokens + 1
diff --git a/src/tokenizer_test.go b/src/tokenizer_test.go
index 1ae0c7ee..5195a1b6 100644
--- a/src/tokenizer_test.go
+++ b/src/tokenizer_test.go
@@ -6,14 +6,14 @@ func TestParseRange(t *testing.T) {
{
i := ".."
r, _ := ParseRange(&i)
- if r.begin != RANGE_ELLIPSIS || r.end != RANGE_ELLIPSIS {
+ if r.begin != rangeEllipsis || r.end != rangeEllipsis {
t.Errorf("%s", r)
}
}
{
i := "3.."
r, _ := ParseRange(&i)
- if r.begin != 3 || r.end != RANGE_ELLIPSIS {
+ if r.begin != 3 || r.end != rangeEllipsis {
t.Errorf("%s", r)
}
}
diff --git a/src/util.go b/src/util.go
index de6f3654..5461705f 100644
--- a/src/util.go
+++ b/src/util.go
@@ -2,6 +2,7 @@ package fzf
import "time"
+// Max returns the largest integer
func Max(first int, items ...int) int {
max := first
for _, item := range items {
@@ -12,6 +13,7 @@ func Max(first int, items ...int) int {
return max
}
+// Max32 returns the largest 32-bit integer
func Max32(first int32, second int32) int32 {
if first > second {
return first
@@ -19,6 +21,7 @@ func Max32(first int32, second int32) int32 {
return second
}
+// Min returns the smallest integer
func Min(first int, items ...int) int {
min := first
for _, item := range items {
@@ -29,6 +32,7 @@ func Min(first int, items ...int) int {
return min
}
+// DurWithin limits the given time.Duration with the upper and lower bounds
func DurWithin(
val time.Duration, min time.Duration, max time.Duration) time.Duration {
if val < min {