mirror of
https://github.com/peco/peco.git
synced 2026-09-10 07:16:29 -04:00
Implement #242: Made the fuzzy filter configurable
This commit is contained in:
parent
4c4b4535ed
commit
21179c2c38
22
README.md
22
README.md
|
|
@ -58,13 +58,15 @@ Not only can you select multiple lines one by one, you can select a range of lin
|
|||
|
||||
## Select Filters
|
||||
|
||||
Different types of filters are available. Default is case-insensitive filter, so lines with any case will match. You can toggle between IgnoreCase, CaseSensitive, SmartCase and RegExp filters.
|
||||
Different types of filters are available. Default is case-insensitive filter, so lines with any case will match. You can toggle between IgnoreCase, CaseSensitive, SmartCase RegExp and Fuzzy filters.
|
||||
|
||||
The SmartCase filter uses case-*insensitive* matching when all of the queries are lower case, and case-*sensitive* matching otherwise.
|
||||
|
||||
The RegExp filter allows you to use any valid regular expression to match lines
|
||||
|
||||

|
||||
The Fuzzy filter allows you to find matches using partial patterns. For example, when searching for `ALongString`, you can enable the Fuzzy filter and search `ALS` to find it. The Fuzzy filter uses smart case search like the SmartCase filter. The Fuzzy filter is not enabled by default, but can be enabled using option `--enable-fuzzy`.
|
||||
|
||||

|
||||
|
||||
## Selectable Layout
|
||||
|
||||
|
|
@ -158,9 +160,13 @@ Changes how peco interprets incoming data. When this flag is set, you may insert
|
|||
|
||||
Specifies the initial line position upon start up. E.g. If you want to start out with the second line selected, set it to "1" (because the index is 0 based)
|
||||
|
||||
### --initial-filter `IgnoreCase|CaseSensitive|SmartCase|Regexp`
|
||||
### --fuzzy-filter `enabled|disabled`
|
||||
|
||||
Specifies the initial filter to use upon start up. You should specify the name of the filter like `IgnoreCase`, `CaseSensitive`, `SmartCase` and `Regexp`. Default is `IgnoreCase`.
|
||||
Make the Fuzzy filter available. The command line option can override the value in the configuration file. Default is `disabled`.
|
||||
|
||||
### --initial-filter `IgnoreCase|CaseSensitive|SmartCase|Regexp|Fuzzy`
|
||||
|
||||
Specifies the initial filter to use upon start up. You should specify the name of the filter like `IgnoreCase`, `CaseSensitive`, `SmartCase`, `Regexp` and `Fuzzy` (if enabled). Default is `IgnoreCase`.
|
||||
|
||||
### --prompt
|
||||
|
||||
|
|
@ -217,9 +223,13 @@ You can change the query line's prompt, which is `QUERY>` by default.
|
|||
|
||||
*InitialMatcher* has been deprecated. Please use `InitialFilter` instead.
|
||||
|
||||
### FuzzyFilter
|
||||
|
||||
Set to `enabled` to make the Fuzzy filter available. Default is `disabled`.
|
||||
|
||||
### InitialFilter
|
||||
|
||||
Specifies the filter name to start peco with. You should specify the name of the filter, such as `IgnoreCase`, `CaseSensitive`, `SmartCase` and `Regexp`
|
||||
Specifies the filter name to start peco with. You should specify the name of the filter, such as `IgnoreCase`, `CaseSensitive`, `SmartCase`, `Regexp` and `Fuzzy` (if [enabled](#FuzzyFilter)).
|
||||
|
||||
### StickySelection
|
||||
|
||||
|
|
@ -473,7 +483,7 @@ For now, styles of following 5 items can be customized in `config.json`.
|
|||
|
||||
This is an experimental feature. Please note that some details of this specification may change
|
||||
|
||||
By default `peco` comes with `IgnoreCase`, `CaseSensitive`, `SmartCase` and `Regexp` filters, but since v0.1.3, it is possible to create your own custom filter.
|
||||
By default `peco` comes with `IgnoreCase`, `CaseSensitive`, `SmartCase`, `Regexp` and `Fuzzy` filters, but since v0.1.3, it is possible to create your own custom filter.
|
||||
|
||||
The filter will be executed via `Command.Run()` as an external process, and it will be passed the query values in the command line, and the original unaltered buffer is passed via `os.Stdin`. Your filter must perform the matching, and print out to `os.Stdout` matched lines. You filter MAY be called multiple times if the buffer
|
||||
given to peco is big enough. See `BufferThreshold` below.
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ func (c *Config) Init() error {
|
|||
c.Style.Init()
|
||||
c.Prompt = "QUERY>"
|
||||
c.Layout = LayoutTypeTopDown
|
||||
c.FuzzyFilter = OptionDisabled
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ func TestReadRC(t *testing.T) {
|
|||
InitialMatcher: IgnoreCaseMatch,
|
||||
Layout: DefaultLayoutType,
|
||||
Prompt: "[peco]",
|
||||
FuzzyFilter: "disabled",
|
||||
Style: StyleSet{
|
||||
Matched: Style{
|
||||
fg: termbox.ColorCyan | termbox.AttrBold,
|
||||
|
|
|
|||
|
|
@ -433,9 +433,8 @@ func NewFuzzyFilter() *RegexpFilter {
|
|||
return []string{"i"}
|
||||
})
|
||||
rf.quotemeta = true
|
||||
rf.name = "FuzzySearch"
|
||||
rf.name = FuzzyFilter
|
||||
rf.queryTrans = queryTransformerFunc(func(q string) string {
|
||||
// Assume that all characters are runes
|
||||
qr := []rune(q)
|
||||
res := make([]rune, 5*len(qr))
|
||||
i := 0
|
||||
|
|
|
|||
13
interface.go
13
interface.go
|
|
@ -46,6 +46,11 @@ const (
|
|||
RegexpMatch = "Regexp"
|
||||
)
|
||||
|
||||
// Filter names, used in the config file
|
||||
const (
|
||||
FuzzyFilter = "Fuzzy"
|
||||
)
|
||||
|
||||
// lineIDGenerator defines an interface for things that generate
|
||||
// unique IDs for lines used within peco.
|
||||
type lineIDGenerator interface {
|
||||
|
|
@ -56,6 +61,11 @@ type idgen struct {
|
|||
ch chan uint64
|
||||
}
|
||||
|
||||
const (
|
||||
OptionEnabled = "enabled"
|
||||
OptionDisabled = "disabled"
|
||||
)
|
||||
|
||||
// Peco is the global object containing everything required to run peco.
|
||||
// It also contains the global state of the program.
|
||||
type Peco struct {
|
||||
|
|
@ -74,6 +84,7 @@ type Peco struct {
|
|||
enableSep bool // Enable parsing on separators
|
||||
filters FilterSet
|
||||
idgen *idgen
|
||||
enableFuzzy bool
|
||||
initialFilter string
|
||||
initialQuery string // populated if --query is specified
|
||||
inputseq Inputseq // current key sequence (just the names)
|
||||
|
|
@ -343,6 +354,7 @@ type Config struct {
|
|||
Keymap map[string]string `json:"Keymap"`
|
||||
Matcher string `json:"Matcher"` // Deprecated.
|
||||
InitialMatcher string `json:"InitialMatcher"` // Use this instead of Matcher
|
||||
FuzzyFilter string `json:"FuzzyFilter"`
|
||||
InitialFilter string `json:"InitialFilter"`
|
||||
Style StyleSet `json:"Style"`
|
||||
Prompt string `json:"Prompt"`
|
||||
|
|
@ -475,6 +487,7 @@ type CLIOptions struct {
|
|||
OptEnableNullSep bool `long:"null" description:"expect NUL (\\0) as separator for target/output"`
|
||||
OptInitialIndex int `long:"initial-index" description:"position of the initial index of the selection (0 base)"`
|
||||
OptInitialMatcher string `long:"initial-matcher" description:"specify the default matcher (deprecated)"`
|
||||
OptFuzzyFilter string `short:"z" long:"fuzzy-filter" description:"enable/disable the Fuzzy filter"`
|
||||
OptInitialFilter string `long:"initial-filter" description:"specify the default filter"`
|
||||
OptPrompt string `long:"prompt" description:"specify the prompt string"`
|
||||
OptLayout string `long:"layout" description:"layout to be used 'top-down' or 'bottom-up'. default is 'top-down'"`
|
||||
|
|
|
|||
21
peco.go
21
peco.go
|
|
@ -500,6 +500,20 @@ func (p *Peco) ApplyConfig(opts CLIOptions) error {
|
|||
p.bufferSize = opts.OptBufferSize
|
||||
p.selectOneAndExit = opts.OptSelect1
|
||||
p.initialQuery = opts.OptQuery
|
||||
// Option EnableFuzzy is a string to allow overriding the value on the command line
|
||||
fuzzyFilter := opts.OptFuzzyFilter
|
||||
if len(fuzzyFilter) <= 0 {
|
||||
fuzzyFilter = p.config.FuzzyFilter
|
||||
}
|
||||
if len(fuzzyFilter) > 0 {
|
||||
if fuzzyFilter == OptionEnabled {
|
||||
p.enableFuzzy = true
|
||||
} else if fuzzyFilter == OptionDisabled {
|
||||
p.enableFuzzy = false
|
||||
} else {
|
||||
return errors.Errorf("Unexpected value for FuzzyFilter option: %v (expected %v/%v)", fuzzyFilter, OptionEnabled, OptionDisabled)
|
||||
}
|
||||
}
|
||||
p.initialFilter = opts.OptInitialFilter
|
||||
if len(p.initialFilter) <= 0 {
|
||||
p.initialFilter = p.config.InitialFilter
|
||||
|
|
@ -507,6 +521,9 @@ func (p *Peco) ApplyConfig(opts CLIOptions) error {
|
|||
if len(p.initialFilter) <= 0 {
|
||||
p.initialFilter = opts.OptInitialMatcher
|
||||
}
|
||||
if len(p.initialFilter) > 0 && !p.enableFuzzy && p.initialFilter == FuzzyFilter {
|
||||
return errors.New("Fuzzy filter is not enabled, can not set it to the initial filter.")
|
||||
}
|
||||
|
||||
if err := p.populateCommandList(); err != nil {
|
||||
return errors.Wrap(err, "failed to populate command list")
|
||||
|
|
@ -566,7 +583,9 @@ func (p *Peco) populateFilters() error {
|
|||
p.filters.Add(NewCaseSensitiveFilter())
|
||||
p.filters.Add(NewSmartCaseFilter())
|
||||
p.filters.Add(NewRegexpFilter())
|
||||
p.filters.Add(NewFuzzyFilter())
|
||||
if p.enableFuzzy {
|
||||
p.filters.Add(NewFuzzyFilter())
|
||||
}
|
||||
|
||||
for name, c := range p.config.CustomFilter {
|
||||
f := NewExternalCmdFilter(name, c.Cmd, c.Args, c.BufferThreshold, p.idgen, p.enableSep)
|
||||
|
|
|
|||
38
peco_test.go
38
peco_test.go
|
|
@ -197,6 +197,44 @@ func TestGHIssue331(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConfigFuzzyFilter(t *testing.T) {
|
||||
var opts CLIOptions
|
||||
p := newPeco()
|
||||
|
||||
// Ensure that it's possible to enable the Fuzzy filter
|
||||
opts.OptFuzzyFilter = "enabled"
|
||||
if !assert.NoError(t, p.ApplyConfig(opts), "p.ApplyConfig should succeed") {
|
||||
return
|
||||
}
|
||||
if !assert.Equal(t, true, p.enableFuzzy, "p.enableFuzzy should be equal to opts.OptEnableFuzzy") {
|
||||
return
|
||||
}
|
||||
opts.OptFuzzyFilter = "abc"
|
||||
if !assert.Error(t, p.ApplyConfig(opts), "p.ApplyConfig should not succeed") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigInitialFilterFuzzy(t *testing.T) {
|
||||
var opts CLIOptions
|
||||
p := newPeco()
|
||||
|
||||
// If Fuzzy is not enabled, initialFilter=Fuzzy should cause peco to fail
|
||||
opts.OptFuzzyFilter = "disabled"
|
||||
opts.OptInitialFilter = "Fuzzy"
|
||||
if !assert.Error(t, p.ApplyConfig(opts), "p.ApplyConfig should not succeed") {
|
||||
return
|
||||
}
|
||||
// If Fuzzy is enabled, it should be possible to set the initial filter to Fuzzy
|
||||
opts.OptFuzzyFilter = "enabled"
|
||||
if !assert.NoError(t, p.ApplyConfig(opts), "p.ApplyConfig should succeed") {
|
||||
return
|
||||
}
|
||||
if !assert.Equal(t, true, p.enableFuzzy, "p.enableFuzzy should be equal to opts.OptEnableFuzzy") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyConfig(t *testing.T) {
|
||||
// XXX We should add all the possible configurations that needs to be
|
||||
// propagated to Peco from config
|
||||
|
|
|
|||
Loading…
Reference in a new issue