Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

add FZF.Quit() and FZF.Abort() #15

Merged
merged 5 commits into from Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 22 additions & 9 deletions fzf.go
Expand Up @@ -13,7 +13,9 @@ var defaultFindOption = findOption{

// Fuzzy Finder.
type FZF struct {
option *option
option *option
model *model
program *tea.Program
}

// New returns a new Fuzzy Finder.
Expand All @@ -23,8 +25,12 @@ func New(opts ...Option) *FZF {
opt(&o)
}

m := newModel(&o)

return &FZF{
option: &o,
option: &o,
model: m,
program: tea.NewProgram(m),
}
}

Expand All @@ -47,22 +53,29 @@ func (fzf *FZF) Find(items interface{}, itemFunc func(i int) string, opts ...Fin
if err != nil {
return nil, err
}
m := newModel(fzf, is, &findOption)
fzf.model.setItems(is)
fzf.model.setFindOption(&findOption)

p := tea.NewProgram(m)
if _, err := p.Run(); err != nil {
if _, err := fzf.program.Run(); err != nil {
return nil, err
}

if m.abort {
if fzf.model.abort {
return nil, ErrAbort
}

return m.choices, nil
return fzf.model.choices, nil
}

// Quit quits the Fuzzy Finder.
func (fzf *FZF) Quit() {
fzf.program.Quit()
}

func (fzf *FZF) multiple() bool {
return fzf.option.noLimit || fzf.option.limit > 1
// Abort aborts the Fuzzy Finder.
func (fzf *FZF) Abort() {
fzf.model.abort = true
fzf.Quit()
}

// Option represents a option for the Find.
Expand Down
76 changes: 41 additions & 35 deletions model.go
Expand Up @@ -14,8 +14,8 @@ var (
)

type model struct {
fzf *FZF
items *items
option *option
findOption *findOption

// state
Expand Down Expand Up @@ -46,45 +46,34 @@ type model struct {
input textinput.Model
}

func newModel(fzf *FZF, items *items, opt *findOption) *model {
func newModel(opt *option) *model {
input := textinput.New()
input.Prompt = fzf.option.prompt
input.Placeholder = fzf.option.inputPlaceholder
input.Prompt = opt.prompt
input.Placeholder = opt.inputPlaceholder
input.Focus()

if !fzf.multiple() {
fzf.option.keymap.Toggle.SetEnabled(false)
}

var matches matches
for i := 0; i < items.Len(); i++ {
matches = append(matches, match{
Str: items.String(i),
Index: i,
})
if !opt.multiple() {
opt.keymap.Toggle.SetEnabled(false)
}

return &model{
fzf: fzf,
items: items,
findOption: opt,
option: opt,
// state
abort: false,

cursor: fzf.option.styles.option.cursor.Render(fzf.option.cursor),
nocursor: strings.Repeat(" ", lipgloss.Width(fzf.option.cursor)),
cursor: opt.styles.option.cursor.Render(opt.cursor),
nocursor: strings.Repeat(" ", lipgloss.Width(opt.cursor)),
cursorPosition: 0,

promptWidth: lipgloss.Width(fzf.option.prompt),
promptWidth: lipgloss.Width(opt.prompt),

selectedPrefix: fzf.option.styles.option.selectedPrefix.Render(fzf.option.selectedPrefix),
unselectedPrefix: fzf.option.styles.option.unselectedPrefix.Render(fzf.option.unselectedPrefix),
selectedPrefix: opt.styles.option.selectedPrefix.Render(opt.selectedPrefix),
unselectedPrefix: opt.styles.option.unselectedPrefix.Render(opt.unselectedPrefix),

matchesStyle: fzf.option.styles.option.matches,
cursorLineStyle: fzf.option.styles.option.cursorLine,
cursorLineMatchesStyle: lipgloss.NewStyle().Inherit(fzf.option.styles.option.matches).Inherit(fzf.option.styles.option.cursorLine),
matchesStyle: opt.styles.option.matches,
cursorLineStyle: opt.styles.option.cursorLine,
cursorLineMatchesStyle: lipgloss.NewStyle().Inherit(opt.styles.option.matches).Inherit(opt.styles.option.cursorLine),

matches: matches,
choices: []int{},
// window
windowWidth: 0,
Expand All @@ -95,6 +84,23 @@ func newModel(fzf *FZF, items *items, opt *findOption) *model {
}
}

func (m *model) setItems(items *items) {
var matches matches
for i := 0; i < items.Len(); i++ {
matches = append(matches, match{
Str: items.String(i),
Index: i,
})
}

m.items = items
m.matches = matches
}

func (m *model) setFindOption(findOption *findOption) {
m.findOption = findOption
}

func (m *model) Init() tea.Cmd {
return tea.Batch(
textinput.Blink,
Expand Down Expand Up @@ -122,9 +128,9 @@ func (m *model) headerView() string {
// input
_, _ = v.WriteString(m.input.View())
// count
if m.fzf.option.countViewEnabled {
if m.option.countViewEnabled {
_, _ = v.WriteRune('\n')
_, _ = v.WriteString(m.fzf.option.countViewFunc(m.items.Len(), len(m.matches), m.windowWidth))
_, _ = v.WriteString(m.option.countViewFunc(m.items.Len(), len(m.matches), m.windowWidth))
}

return v.String()
Expand All @@ -150,7 +156,7 @@ func (m *model) itemsView() string {
}

// write toggle
if m.fzf.multiple() {
if m.option.multiple() {
if intContains(m.choices, match.Index) {
_, _ = v.WriteString(m.selectedPrefix)
} else {
Expand Down Expand Up @@ -197,23 +203,23 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case tea.KeyMsg:
// key
switch {
case key.Matches(msg, m.fzf.option.keymap.Abort):
case key.Matches(msg, m.option.keymap.Abort):
// abort
m.abort = true
return m, tea.Quit
case key.Matches(msg, m.fzf.option.keymap.Choose):
case key.Matches(msg, m.option.keymap.Choose):
// choose
m.choice()
return m, tea.Quit
case key.Matches(msg, m.fzf.option.keymap.Toggle):
case key.Matches(msg, m.option.keymap.Toggle):
// toggle
m.toggle()
case key.Matches(msg, m.fzf.option.keymap.Up):
case key.Matches(msg, m.option.keymap.Up):
// up
m.cursorUp()
m.fixYPosition()
m.fixCursor()
case key.Matches(msg, m.fzf.option.keymap.Down):
case key.Matches(msg, m.option.keymap.Down):
// down
m.cursorDown()
m.fixYPosition()
Expand Down Expand Up @@ -265,7 +271,7 @@ func (m *model) toggle() {
if intContains(m.choices, match.Index) {
m.choices = intFilter(m.choices, func(i int) bool { return i != match.Index })
} else {
if m.fzf.option.noLimit || len(m.choices) < m.fzf.option.limit {
if m.option.noLimit || len(m.choices) < m.option.limit {
m.choices = append(m.choices, match.Index)
}
}
Expand Down
4 changes: 4 additions & 0 deletions option.go
Expand Up @@ -55,6 +55,10 @@ type option struct {
countViewFunc func(itemsCount, matchesCount, windowWidth int) string
}

func (o *option) multiple() bool {
return o.noLimit || o.limit > 1
}

// Option represents a option for the Fuzzy Finder.
type Option func(o *option)

Expand Down