diff --git a/src/options.go b/src/options.go index e1dba29..b11328e 100644 --- a/src/options.go +++ b/src/options.go @@ -266,6 +266,17 @@ func parseOptions(opts *Options, allArgs []string) { } } } + + // If we're not using extended search mode, --nth option becomes irrelevant + // if it contains the whole range + if opts.Mode == ModeFuzzy || len(opts.Nth) == 1 { + for _, r := range opts.Nth { + if r.begin == rangeEllipsis && r.end == rangeEllipsis { + opts.Nth = make([]Range, 0) + return + } + } + } } // ParseOptions parses command-line options diff --git a/src/options_test.go b/src/options_test.go index e10ec56..782ad79 100644 --- a/src/options_test.go +++ b/src/options_test.go @@ -21,17 +21,47 @@ func TestSplitNth(t *testing.T) { } } { - ranges := splitNth("..3,1..,2..3,4..-1,-3..-2,..,2,-2") - if len(ranges) != 8 || + ranges := splitNth("..3,1..,2..3,4..-1,-3..-2,..,2,-2,2..-2,1..-1") + if len(ranges) != 10 || ranges[0].begin != rangeEllipsis || ranges[0].end != 3 || - ranges[1].begin != 1 || ranges[1].end != rangeEllipsis || + ranges[1].begin != rangeEllipsis || ranges[1].end != rangeEllipsis || ranges[2].begin != 2 || ranges[2].end != 3 || - ranges[3].begin != 4 || ranges[3].end != -1 || + ranges[3].begin != 4 || ranges[3].end != rangeEllipsis || ranges[4].begin != -3 || ranges[4].end != -2 || ranges[5].begin != rangeEllipsis || ranges[5].end != rangeEllipsis || ranges[6].begin != 2 || ranges[6].end != 2 || - ranges[7].begin != -2 || ranges[7].end != -2 { + ranges[7].begin != -2 || ranges[7].end != -2 || + ranges[8].begin != 2 || ranges[8].end != -2 || + ranges[9].begin != rangeEllipsis || ranges[9].end != rangeEllipsis { t.Errorf("%s", ranges) } } } + +func TestIrrelevantNth(t *testing.T) { + { + opts := defaultOptions() + words := []string{"--nth", "..", "-x"} + parseOptions(opts, words) + if len(opts.Nth) != 0 { + t.Errorf("nth should be empty: %s", opts.Nth) + } + } + for _, words := range [][]string{[]string{"--nth", "..,3"}, []string{"--nth", "3,1.."}, []string{"--nth", "..-1,1"}} { + { + opts := defaultOptions() + parseOptions(opts, words) + if len(opts.Nth) != 0 { + t.Errorf("nth should be empty: %s", opts.Nth) + } + } + { + opts := defaultOptions() + words = append(words, "-x") + parseOptions(opts, words) + if len(opts.Nth) != 2 { + t.Errorf("nth should not be empty: %s", opts.Nth) + } + } + } +} diff --git a/src/tokenizer.go b/src/tokenizer.go index 26aebd9..d38f46f 100644 --- a/src/tokenizer.go +++ b/src/tokenizer.go @@ -28,22 +28,32 @@ type Token struct { prefixLength int } +func newRange(begin int, end int) Range { + if begin == 1 { + begin = rangeEllipsis + } + if end == -1 { + end = rangeEllipsis + } + return Range{begin, end} +} + // ParseRange parses nth-expression and returns the corresponding Range object func ParseRange(str *string) (Range, bool) { if (*str) == ".." { - return Range{rangeEllipsis, rangeEllipsis}, true + return newRange(rangeEllipsis, rangeEllipsis), true } else if strings.HasPrefix(*str, "..") { end, err := strconv.Atoi((*str)[2:]) if err != nil || end == 0 { return Range{}, false } - return Range{rangeEllipsis, end}, true + return newRange(rangeEllipsis, end), true } else if strings.HasSuffix(*str, "..") { begin, err := strconv.Atoi((*str)[:len(*str)-2]) if err != nil || begin == 0 { return Range{}, false } - return Range{begin, rangeEllipsis}, true + return newRange(begin, rangeEllipsis), true } else if strings.Contains(*str, "..") { ns := strings.Split(*str, "..") if len(ns) != 2 { @@ -51,17 +61,17 @@ func ParseRange(str *string) (Range, bool) { } begin, err1 := strconv.Atoi(ns[0]) end, err2 := strconv.Atoi(ns[1]) - if err1 != nil || err2 != nil { + if err1 != nil || err2 != nil || begin == 0 || end == 0 { return Range{}, false } - return Range{begin, end}, true + return newRange(begin, end), true } n, err := strconv.Atoi(*str) if err != nil || n == 0 { return Range{}, false } - return Range{n, n}, true + return newRange(n, n), true } func withPrefixLengths(tokens []string, begin int) []Token {