mirror of
https://github.com/junegunn/fzf.git
synced 2025-08-01 20:52:06 -07:00
Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
52771a6226 | ||
|
b00bcf506e | ||
|
fdbfe36c0b | ||
|
446e822723 |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,6 +1,18 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
0.9.13
|
||||||
|
------
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
- Color customization with the extended `--color` option
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Fixed premature termination of Reader in the presence of a long line which
|
||||||
|
is longer than 64KB
|
||||||
|
|
||||||
0.9.12
|
0.9.12
|
||||||
------
|
------
|
||||||
|
|
||||||
@@ -11,6 +23,7 @@ CHANGELOG
|
|||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
- Fixed to update "inline-info" immediately after terminal resize
|
- Fixed to update "inline-info" immediately after terminal resize
|
||||||
|
- Fixed ANSI code offset calculation
|
||||||
|
|
||||||
0.9.11
|
0.9.11
|
||||||
------
|
------
|
||||||
|
2
install
2
install
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
version=0.9.12
|
version=0.9.13
|
||||||
|
|
||||||
cd $(dirname $BASH_SOURCE)
|
cd $(dirname $BASH_SOURCE)
|
||||||
fzf_base=$(pwd)
|
fzf_base=$(pwd)
|
||||||
|
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf 1 "May 2015" "fzf 0.9.12" "fzf - a command-line fuzzy finder"
|
.TH fzf 1 "June 2015" "fzf 0.9.13" "fzf - a command-line fuzzy finder"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf - a command-line fuzzy finder
|
fzf - a command-line fuzzy finder
|
||||||
@@ -91,21 +91,38 @@ Enable processing of ANSI color codes
|
|||||||
.B "--no-mouse"
|
.B "--no-mouse"
|
||||||
Disable mouse
|
Disable mouse
|
||||||
.TP
|
.TP
|
||||||
.B "--color=COL"
|
.BI "--color=" "[BASE_SCHEME][,COLOR:ANSI]"
|
||||||
Color scheme: [dark|light|16|bw]
|
Color configuration. The name of the base color scheme is followed by custom
|
||||||
.br
|
color mappings. Ansi color code of -1 denotes terminal default
|
||||||
(default: dark on 256-color terminal, otherwise 16)
|
foreground/background color.
|
||||||
.br
|
|
||||||
.R ""
|
.RS
|
||||||
.br
|
e.g. \fBfzf --color=bg+:24\fR
|
||||||
.BR dark " Color scheme for dark 256-color terminal"
|
\fBfzf --color=light,fg:232,bg:255,bg+:116,info:27\fR
|
||||||
.br
|
.RE
|
||||||
.BR light " Color scheme for light 256-color terminal"
|
|
||||||
.br
|
.RS
|
||||||
.BR 16 " Color scheme for 16-color terminal"
|
.B BASE SCHEME:
|
||||||
.br
|
(default: dark on 256-color terminal, otherwise 16)
|
||||||
.BR bw " No colors"
|
|
||||||
.br
|
\fBdark \fRColor scheme for dark 256-color terminal
|
||||||
|
\fBlight \fRColor scheme for light 256-color terminal
|
||||||
|
\fB16 \fRColor scheme for 16-color terminal
|
||||||
|
\fBbw \fRNo colors
|
||||||
|
|
||||||
|
.B COLOR:
|
||||||
|
\fBfg \fRText
|
||||||
|
\fBbg \fRBackground
|
||||||
|
\fBhl \fRHighlighted substrings
|
||||||
|
\fBfg+ \fRText (current line)
|
||||||
|
\fBbg+ \fRBackground (current line)
|
||||||
|
\fBhl+ \fRHighlighted substrings (current line)
|
||||||
|
\fBinfo \fRInfo
|
||||||
|
\fBprompt \fRPrompt
|
||||||
|
\fBpointer \fRPointer to the current line
|
||||||
|
\fBmarker \fRMulti-select marker
|
||||||
|
\fBspinner \fRStreaming input indicator
|
||||||
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B "--black"
|
.B "--black"
|
||||||
Use black background
|
Use black background
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Current version
|
// Current version
|
||||||
Version = "0.9.12"
|
Version = "0.9.13"
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
coordinatorDelayMax time.Duration = 100 * time.Millisecond
|
coordinatorDelayMax time.Duration = 100 * time.Millisecond
|
||||||
|
@@ -106,15 +106,18 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ColorTheme struct {
|
type ColorTheme struct {
|
||||||
darkBg C.short
|
UseDefault bool
|
||||||
prompt C.short
|
Fg int16
|
||||||
match C.short
|
Bg int16
|
||||||
current C.short
|
DarkBg int16
|
||||||
currentMatch C.short
|
Prompt int16
|
||||||
spinner C.short
|
Match int16
|
||||||
info C.short
|
Current int16
|
||||||
cursor C.short
|
CurrentMatch int16
|
||||||
selected C.short
|
Spinner int16
|
||||||
|
Info int16
|
||||||
|
Cursor int16
|
||||||
|
Selected int16
|
||||||
}
|
}
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
@@ -142,7 +145,10 @@ var (
|
|||||||
Default16 *ColorTheme
|
Default16 *ColorTheme
|
||||||
Dark256 *ColorTheme
|
Dark256 *ColorTheme
|
||||||
Light256 *ColorTheme
|
Light256 *ColorTheme
|
||||||
DarkBG C.short
|
FG int
|
||||||
|
CurrentFG int
|
||||||
|
BG int
|
||||||
|
DarkBG int
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -150,35 +156,44 @@ func init() {
|
|||||||
_clickY = []int{}
|
_clickY = []int{}
|
||||||
_colorMap = make(map[int]int)
|
_colorMap = make(map[int]int)
|
||||||
Default16 = &ColorTheme{
|
Default16 = &ColorTheme{
|
||||||
darkBg: C.COLOR_BLACK,
|
UseDefault: true,
|
||||||
prompt: C.COLOR_BLUE,
|
Fg: 15,
|
||||||
match: C.COLOR_GREEN,
|
Bg: 0,
|
||||||
current: C.COLOR_YELLOW,
|
DarkBg: C.COLOR_BLACK,
|
||||||
currentMatch: C.COLOR_GREEN,
|
Prompt: C.COLOR_BLUE,
|
||||||
spinner: C.COLOR_GREEN,
|
Match: C.COLOR_GREEN,
|
||||||
info: C.COLOR_WHITE,
|
Current: C.COLOR_YELLOW,
|
||||||
cursor: C.COLOR_RED,
|
CurrentMatch: C.COLOR_GREEN,
|
||||||
selected: C.COLOR_MAGENTA}
|
Spinner: C.COLOR_GREEN,
|
||||||
|
Info: C.COLOR_WHITE,
|
||||||
|
Cursor: C.COLOR_RED,
|
||||||
|
Selected: C.COLOR_MAGENTA}
|
||||||
Dark256 = &ColorTheme{
|
Dark256 = &ColorTheme{
|
||||||
darkBg: 236,
|
UseDefault: true,
|
||||||
prompt: 110,
|
Fg: 15,
|
||||||
match: 108,
|
Bg: 0,
|
||||||
current: 254,
|
DarkBg: 236,
|
||||||
currentMatch: 151,
|
Prompt: 110,
|
||||||
spinner: 148,
|
Match: 108,
|
||||||
info: 144,
|
Current: 254,
|
||||||
cursor: 161,
|
CurrentMatch: 151,
|
||||||
selected: 168}
|
Spinner: 148,
|
||||||
|
Info: 144,
|
||||||
|
Cursor: 161,
|
||||||
|
Selected: 168}
|
||||||
Light256 = &ColorTheme{
|
Light256 = &ColorTheme{
|
||||||
darkBg: 251,
|
UseDefault: true,
|
||||||
prompt: 25,
|
Fg: 15,
|
||||||
match: 66,
|
Bg: 0,
|
||||||
current: 237,
|
DarkBg: 251,
|
||||||
currentMatch: 23,
|
Prompt: 25,
|
||||||
spinner: 65,
|
Match: 66,
|
||||||
info: 101,
|
Current: 237,
|
||||||
cursor: 161,
|
CurrentMatch: 23,
|
||||||
selected: 168}
|
Spinner: 65,
|
||||||
|
Info: 101,
|
||||||
|
Cursor: 161,
|
||||||
|
Selected: 168}
|
||||||
}
|
}
|
||||||
|
|
||||||
func attrColored(pair int, bold bool) C.int {
|
func attrColored(pair int, bold bool) C.int {
|
||||||
@@ -268,23 +283,35 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initPairs(theme *ColorTheme, black bool) {
|
func initPairs(theme *ColorTheme, black bool) {
|
||||||
var bg C.short
|
fg := C.short(theme.Fg)
|
||||||
|
bg := C.short(theme.Bg)
|
||||||
if black {
|
if black {
|
||||||
bg = C.COLOR_BLACK
|
bg = C.COLOR_BLACK
|
||||||
} else {
|
} else if theme.UseDefault {
|
||||||
C.use_default_colors()
|
fg = -1
|
||||||
bg = -1
|
bg = -1
|
||||||
|
C.use_default_colors()
|
||||||
|
}
|
||||||
|
if theme.UseDefault {
|
||||||
|
FG = -1
|
||||||
|
BG = -1
|
||||||
|
} else {
|
||||||
|
FG = int(fg)
|
||||||
|
BG = int(bg)
|
||||||
|
C.assume_default_colors(C.int(theme.Fg), C.int(bg))
|
||||||
}
|
}
|
||||||
|
|
||||||
DarkBG = theme.darkBg
|
CurrentFG = int(theme.Current)
|
||||||
C.init_pair(ColPrompt, theme.prompt, bg)
|
DarkBG = int(theme.DarkBg)
|
||||||
C.init_pair(ColMatch, theme.match, bg)
|
darkBG := C.short(DarkBG)
|
||||||
C.init_pair(ColCurrent, theme.current, DarkBG)
|
C.init_pair(ColPrompt, C.short(theme.Prompt), bg)
|
||||||
C.init_pair(ColCurrentMatch, theme.currentMatch, DarkBG)
|
C.init_pair(ColMatch, C.short(theme.Match), bg)
|
||||||
C.init_pair(ColSpinner, theme.spinner, bg)
|
C.init_pair(ColCurrent, C.short(theme.Current), darkBG)
|
||||||
C.init_pair(ColInfo, theme.info, bg)
|
C.init_pair(ColCurrentMatch, C.short(theme.CurrentMatch), darkBG)
|
||||||
C.init_pair(ColCursor, theme.cursor, DarkBG)
|
C.init_pair(ColSpinner, C.short(theme.Spinner), bg)
|
||||||
C.init_pair(ColSelected, theme.selected, DarkBG)
|
C.init_pair(ColInfo, C.short(theme.Info), bg)
|
||||||
|
C.init_pair(ColCursor, C.short(theme.Cursor), darkBG)
|
||||||
|
C.init_pair(ColSelected, C.short(theme.Selected), darkBG)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close() {
|
func Close() {
|
||||||
|
18
src/item.go
18
src/item.go
@@ -143,13 +143,25 @@ func (item *Item) colorOffsets(color int, bold bool, current bool) []colorOffset
|
|||||||
offset: Offset{int32(start), int32(idx)}, color: color, bold: bold})
|
offset: Offset{int32(start), int32(idx)}, color: color, bold: bold})
|
||||||
} else {
|
} else {
|
||||||
ansi := item.colors[curr-1]
|
ansi := item.colors[curr-1]
|
||||||
|
fg := ansi.color.fg
|
||||||
|
if fg == -1 {
|
||||||
|
if current {
|
||||||
|
fg = curses.CurrentFG
|
||||||
|
} else {
|
||||||
|
fg = curses.FG
|
||||||
|
}
|
||||||
|
}
|
||||||
bg := ansi.color.bg
|
bg := ansi.color.bg
|
||||||
if current && bg == -1 {
|
if bg == -1 {
|
||||||
bg = int(curses.DarkBG)
|
if current {
|
||||||
|
bg = curses.DarkBG
|
||||||
|
} else {
|
||||||
|
bg = curses.BG
|
||||||
|
}
|
||||||
}
|
}
|
||||||
offsets = append(offsets, colorOffset{
|
offsets = append(offsets, colorOffset{
|
||||||
offset: Offset{int32(start), int32(idx)},
|
offset: Offset{int32(start), int32(idx)},
|
||||||
color: curses.PairFor(ansi.color.fg, bg),
|
color: curses.PairFor(fg, bg),
|
||||||
bold: ansi.color.bold || bold})
|
bold: ansi.color.bold || bold})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
111
src/options.go
111
src/options.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
@@ -35,8 +36,7 @@ const usage = `usage: fzf [options]
|
|||||||
-m, --multi Enable multi-select with tab/shift-tab
|
-m, --multi Enable multi-select with tab/shift-tab
|
||||||
--ansi Enable processing of ANSI color codes
|
--ansi Enable processing of ANSI color codes
|
||||||
--no-mouse Disable mouse
|
--no-mouse Disable mouse
|
||||||
--color=COL Color scheme; [dark|light|16|bw]
|
--color=COLSPEC Base scheme (dark|light|16|bw) and/or custom colors
|
||||||
(default: dark on 256-color terminal, otherwise 16)
|
|
||||||
--black Use black background
|
--black Use black background
|
||||||
--reverse Reverse orientation
|
--reverse Reverse orientation
|
||||||
--no-hscroll Disable horizontal scroll
|
--no-hscroll Disable horizontal scroll
|
||||||
@@ -121,14 +121,14 @@ type Options struct {
|
|||||||
Version bool
|
Version bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultOptions() *Options {
|
func defaultTheme() *curses.ColorTheme {
|
||||||
var defaultTheme *curses.ColorTheme
|
|
||||||
if strings.Contains(os.Getenv("TERM"), "256") {
|
if strings.Contains(os.Getenv("TERM"), "256") {
|
||||||
defaultTheme = curses.Dark256
|
return curses.Dark256
|
||||||
} else {
|
|
||||||
defaultTheme = curses.Default16
|
|
||||||
}
|
}
|
||||||
|
return curses.Default16
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultOptions() *Options {
|
||||||
return &Options{
|
return &Options{
|
||||||
Mode: ModeFuzzy,
|
Mode: ModeFuzzy,
|
||||||
Case: CaseSmart,
|
Case: CaseSmart,
|
||||||
@@ -141,7 +141,7 @@ func defaultOptions() *Options {
|
|||||||
Multi: false,
|
Multi: false,
|
||||||
Ansi: false,
|
Ansi: false,
|
||||||
Mouse: true,
|
Mouse: true,
|
||||||
Theme: defaultTheme,
|
Theme: defaultTheme(),
|
||||||
Black: false,
|
Black: false,
|
||||||
Reverse: false,
|
Reverse: false,
|
||||||
Hscroll: true,
|
Hscroll: true,
|
||||||
@@ -187,6 +187,14 @@ func nextString(args []string, i *int, message string) string {
|
|||||||
return args[*i]
|
return args[*i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func optionalNextString(args []string, i *int) string {
|
||||||
|
if len(args) > *i+1 {
|
||||||
|
*i++
|
||||||
|
return args[*i]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func optionalNumeric(args []string, i *int) int {
|
func optionalNumeric(args []string, i *int) int {
|
||||||
if len(args) > *i+1 {
|
if len(args) > *i+1 {
|
||||||
if strings.IndexAny(args[*i+1], "0123456789") == 0 {
|
if strings.IndexAny(args[*i+1], "0123456789") == 0 {
|
||||||
@@ -277,20 +285,72 @@ func parseTiebreak(str string) tiebreak {
|
|||||||
return byLength
|
return byLength
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTheme(str string) *curses.ColorTheme {
|
func dupeTheme(theme *curses.ColorTheme) *curses.ColorTheme {
|
||||||
switch strings.ToLower(str) {
|
dupe := *theme
|
||||||
case "dark":
|
return &dupe
|
||||||
return curses.Dark256
|
}
|
||||||
case "light":
|
|
||||||
return curses.Light256
|
func parseTheme(defaultTheme *curses.ColorTheme, str string) *curses.ColorTheme {
|
||||||
case "16":
|
theme := dupeTheme(defaultTheme)
|
||||||
return curses.Default16
|
for _, str := range strings.Split(strings.ToLower(str), ",") {
|
||||||
case "bw", "no":
|
switch str {
|
||||||
return nil
|
case "dark":
|
||||||
default:
|
theme = dupeTheme(curses.Dark256)
|
||||||
errorExit("invalid color scheme: " + str)
|
case "light":
|
||||||
|
theme = dupeTheme(curses.Light256)
|
||||||
|
case "16":
|
||||||
|
theme = dupeTheme(curses.Default16)
|
||||||
|
case "bw", "no":
|
||||||
|
theme = nil
|
||||||
|
default:
|
||||||
|
fail := func() {
|
||||||
|
errorExit("invalid color specification: " + str)
|
||||||
|
}
|
||||||
|
// Color is disabled
|
||||||
|
if theme == nil {
|
||||||
|
errorExit("colors disabled; cannot customize colors")
|
||||||
|
}
|
||||||
|
|
||||||
|
pair := strings.Split(str, ":")
|
||||||
|
if len(pair) != 2 {
|
||||||
|
fail()
|
||||||
|
}
|
||||||
|
ansi32, err := strconv.Atoi(pair[1])
|
||||||
|
if err != nil || ansi32 < -1 || ansi32 > 255 {
|
||||||
|
fail()
|
||||||
|
}
|
||||||
|
ansi := int16(ansi32)
|
||||||
|
switch pair[0] {
|
||||||
|
case "fg":
|
||||||
|
theme.Fg = ansi
|
||||||
|
theme.UseDefault = theme.UseDefault && ansi < 0
|
||||||
|
case "bg":
|
||||||
|
theme.Bg = ansi
|
||||||
|
theme.UseDefault = theme.UseDefault && ansi < 0
|
||||||
|
case "fg+":
|
||||||
|
theme.Current = ansi
|
||||||
|
case "bg+":
|
||||||
|
theme.DarkBg = ansi
|
||||||
|
case "hl":
|
||||||
|
theme.Match = ansi
|
||||||
|
case "hl+":
|
||||||
|
theme.CurrentMatch = ansi
|
||||||
|
case "prompt":
|
||||||
|
theme.Prompt = ansi
|
||||||
|
case "spinner":
|
||||||
|
theme.Spinner = ansi
|
||||||
|
case "info":
|
||||||
|
theme.Info = ansi
|
||||||
|
case "pointer":
|
||||||
|
theme.Cursor = ansi
|
||||||
|
case "marker":
|
||||||
|
theme.Selected = ansi
|
||||||
|
default:
|
||||||
|
fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return theme
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseKeymap(keymap map[int]actionType, toggleSort bool, str string) (map[int]actionType, bool) {
|
func parseKeymap(keymap map[int]actionType, toggleSort bool, str string) (map[int]actionType, bool) {
|
||||||
@@ -400,7 +460,12 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
case "--bind":
|
case "--bind":
|
||||||
opts.Keymap, opts.ToggleSort = parseKeymap(opts.Keymap, opts.ToggleSort, nextString(allArgs, &i, "bind expression required"))
|
opts.Keymap, opts.ToggleSort = parseKeymap(opts.Keymap, opts.ToggleSort, nextString(allArgs, &i, "bind expression required"))
|
||||||
case "--color":
|
case "--color":
|
||||||
opts.Theme = parseTheme(nextString(allArgs, &i, "color scheme name required"))
|
spec := optionalNextString(allArgs, &i)
|
||||||
|
if len(spec) == 0 {
|
||||||
|
opts.Theme = defaultTheme()
|
||||||
|
} else {
|
||||||
|
opts.Theme = parseTheme(opts.Theme, spec)
|
||||||
|
}
|
||||||
case "--toggle-sort":
|
case "--toggle-sort":
|
||||||
opts.Keymap = checkToggleSort(opts.Keymap, nextString(allArgs, &i, "key name required"))
|
opts.Keymap = checkToggleSort(opts.Keymap, nextString(allArgs, &i, "key name required"))
|
||||||
opts.ToggleSort = true
|
opts.ToggleSort = true
|
||||||
@@ -497,7 +562,7 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
} else if match, value := optString(arg, "--tiebreak="); match {
|
} else if match, value := optString(arg, "--tiebreak="); match {
|
||||||
opts.Tiebreak = parseTiebreak(value)
|
opts.Tiebreak = parseTiebreak(value)
|
||||||
} else if match, value := optString(arg, "--color="); match {
|
} else if match, value := optString(arg, "--color="); match {
|
||||||
opts.Theme = parseTheme(value)
|
opts.Theme = parseTheme(opts.Theme, value)
|
||||||
} else if match, value := optString(arg, "--bind="); match {
|
} else if match, value := optString(arg, "--bind="); match {
|
||||||
opts.Keymap, opts.ToggleSort = parseKeymap(opts.Keymap, opts.ToggleSort, value)
|
opts.Keymap, opts.ToggleSort = parseKeymap(opts.Keymap, opts.ToggleSort, value)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -155,3 +155,49 @@ func TestBind(t *testing.T) {
|
|||||||
}
|
}
|
||||||
check(actAbort, keymap[curses.F1])
|
check(actAbort, keymap[curses.F1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestColorSpec(t *testing.T) {
|
||||||
|
theme := curses.Dark256
|
||||||
|
dark := parseTheme(theme, "dark")
|
||||||
|
if *dark != *theme {
|
||||||
|
t.Errorf("colors should be equivalent")
|
||||||
|
}
|
||||||
|
if dark == theme {
|
||||||
|
t.Errorf("point should not be equivalent")
|
||||||
|
}
|
||||||
|
|
||||||
|
light := parseTheme(theme, "dark,light")
|
||||||
|
if *light == *theme {
|
||||||
|
t.Errorf("should not be equivalent")
|
||||||
|
}
|
||||||
|
if *light != *curses.Light256 {
|
||||||
|
t.Errorf("colors should be equivalent")
|
||||||
|
}
|
||||||
|
if light == theme {
|
||||||
|
t.Errorf("point should not be equivalent")
|
||||||
|
}
|
||||||
|
|
||||||
|
customized := parseTheme(theme, "fg:231,bg:232")
|
||||||
|
if customized.Fg != 231 || customized.Bg != 232 {
|
||||||
|
t.Errorf("color not customized")
|
||||||
|
}
|
||||||
|
if *curses.Dark256 == *customized {
|
||||||
|
t.Errorf("colors should not be equivalent")
|
||||||
|
}
|
||||||
|
customized.Fg = curses.Dark256.Fg
|
||||||
|
customized.Bg = curses.Dark256.Bg
|
||||||
|
if *curses.Dark256 == *customized {
|
||||||
|
t.Errorf("colors should now be equivalent")
|
||||||
|
}
|
||||||
|
|
||||||
|
customized = parseTheme(theme, "fg:231,dark,bg:232")
|
||||||
|
if customized.Fg != curses.Dark256.Fg || customized.Bg == curses.Dark256.Bg {
|
||||||
|
t.Errorf("color not customized")
|
||||||
|
}
|
||||||
|
if customized.UseDefault {
|
||||||
|
t.Errorf("not using default colors")
|
||||||
|
}
|
||||||
|
if !curses.Dark256.UseDefault {
|
||||||
|
t.Errorf("using default colors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -30,9 +30,29 @@ func (r *Reader) ReadSource() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) feed(src io.Reader) {
|
func (r *Reader) feed(src io.Reader) {
|
||||||
if scanner := bufio.NewScanner(src); scanner != nil {
|
reader := bufio.NewReader(src)
|
||||||
for scanner.Scan() {
|
eof := false
|
||||||
r.pusher(scanner.Text())
|
Loop:
|
||||||
|
for !eof {
|
||||||
|
buf := []byte{}
|
||||||
|
iter := 0 // TODO: max size?
|
||||||
|
for {
|
||||||
|
// "ReadLine either returns a non-nil line or it returns an error, never both"
|
||||||
|
line, isPrefix, err := reader.ReadLine()
|
||||||
|
eof = err == io.EOF
|
||||||
|
if eof {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
break Loop
|
||||||
|
}
|
||||||
|
iter++
|
||||||
|
buf = append(buf, line...)
|
||||||
|
if !isPrefix {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if iter > 0 {
|
||||||
|
r.pusher(string(buf))
|
||||||
r.eventBox.Set(EvtReadNew, nil)
|
r.eventBox.Set(EvtReadNew, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -525,6 +525,17 @@ class TestGoFZF < TestBase
|
|||||||
tmux.send_keys 'uuu', 'TTT', 'tt', 'uu', 'ttt', 'C-j'
|
tmux.send_keys 'uuu', 'TTT', 'tt', 'uu', 'ttt', 'C-j'
|
||||||
assert_equal %w[4 5 6 9], readonce.split($/)
|
assert_equal %w[4 5 6 9], readonce.split($/)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_long_line
|
||||||
|
tempname = TEMPNAME + Time.now.to_f.to_s
|
||||||
|
data = '.' * 256 * 1024
|
||||||
|
File.open(tempname, 'w') do |f|
|
||||||
|
f << data
|
||||||
|
end
|
||||||
|
assert_equal data, `cat #{tempname} | #{FZF} -f .`.chomp
|
||||||
|
ensure
|
||||||
|
File.unlink tempname
|
||||||
|
end
|
||||||
private
|
private
|
||||||
def writelines path, lines
|
def writelines path, lines
|
||||||
File.unlink path while File.exists? path
|
File.unlink path while File.exists? path
|
||||||
|
Reference in New Issue
Block a user