Skip to content

Commit 76cf6db

Browse files
alecthomasclaude
andcommitted
refactor: replace sort package usage with slices/cmp
Modernise pre-1.21 sorting idioms: sort.Strings/Ints/Slice become slices.Sort/SortFunc, Names() collapses to slices.Sorted(maps.Keys), and the sort-then-take-first pattern in the lexer registry becomes slices.MinFunc, which is O(n) and deterministically breaks priority ties by registration order. The exported Lexers/PrioritisedLexers sort.Interface method sets are retained for external users; PrioritisedLexers.Less now delegates to the new compareLexersByPriority comparator so the ordering logic has a single source of truth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 50f98ad commit 76cf6db

6 files changed

Lines changed: 38 additions & 48 deletions

File tree

formatters/api.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ package formatters
33
import (
44
"io"
55
"iter"
6-
"sort"
6+
"maps"
7+
"slices"
78

89
"github.com/alecthomas/chroma/v3"
910
"github.com/alecthomas/chroma/v3/formatters/html"
@@ -32,12 +33,7 @@ var registry = map[string]chroma.Formatter{}
3233

3334
// Names of registered formatters.
3435
func Names() []string {
35-
out := []string{}
36-
for name := range registry {
37-
out = append(out, name)
38-
}
39-
sort.Strings(out)
40-
return out
36+
return slices.Sorted(maps.Keys(registry))
4137
}
4238

4339
// Get formatter by name.

formatters/html/html.go

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package html
22

33
import (
4+
"cmp"
45
"fmt"
56
"html"
67
"io"
78
"iter"
9+
"maps"
810
"slices"
9-
"sort"
1011
"strconv"
1112
"strings"
1213
"sync"
@@ -127,7 +128,7 @@ func WithLinkableLineNumbers(b bool, prefix string) Option {
127128
func HighlightLines(ranges [][2]int) Option {
128129
return func(f *Formatter) {
129130
f.highlightRanges = ranges
130-
sort.Sort(f.highlightRanges)
131+
f.highlightRanges.sort()
131132
}
132133
}
133134

@@ -138,7 +139,7 @@ func WithLinePrompts(prompt string, ranges [][2]int) Option {
138139
return func(f *Formatter) {
139140
f.linePrompt = prompt
140141
f.linePromptRanges = ranges
141-
sort.Sort(f.linePromptRanges)
142+
f.linePromptRanges.sort()
142143
}
143144
}
144145

@@ -238,9 +239,9 @@ type Formatter struct {
238239

239240
type lineRanges [][2]int
240241

241-
func (r lineRanges) Len() int { return len(r) }
242-
func (r lineRanges) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
243-
func (r lineRanges) Less(i, j int) bool { return r[i][0] < r[j][0] }
242+
func (r lineRanges) sort() {
243+
slices.SortFunc(r, func(a, b [2]int) int { return cmp.Compare(a[0], b[0]) })
244+
}
244245

245246
func (r lineRanges) match(rangeIndex, line int) (bool, int) {
246247
for rangeIndex < len(r) && line > r[rangeIndex][1] {
@@ -525,13 +526,7 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
525526
}
526527
}
527528
}
528-
tts := []int{}
529-
for tt := range css {
530-
tts = append(tts, int(tt))
531-
}
532-
sort.Ints(tts)
533-
for _, ti := range tts {
534-
tt := chroma.TokenType(ti)
529+
for _, tt := range slices.Sorted(maps.Keys(css)) {
535530
switch tt {
536531
case chroma.Background, chroma.PreWrapper:
537532
continue

lexer.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package chroma
22

33
import (
4+
"cmp"
45
"fmt"
56
"iter"
67
"strings"
@@ -160,15 +161,21 @@ type PrioritisedLexers []Lexer
160161
func (l PrioritisedLexers) Len() int { return len(l) }
161162
func (l PrioritisedLexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
162163
func (l PrioritisedLexers) Less(i, j int) bool {
163-
ip := l[i].Config().Priority
164-
if ip == 0 {
165-
ip = 1
164+
return compareLexersByPriority(l[i], l[j]) < 0
165+
}
166+
167+
// compareLexersByPriority orders lexers by descending priority, treating an
168+
// unset priority as 1.
169+
func compareLexersByPriority(a, b Lexer) int {
170+
ap := a.Config().Priority
171+
if ap == 0 {
172+
ap = 1
166173
}
167-
jp := l[j].Config().Priority
168-
if jp == 0 {
169-
jp = 1
174+
bp := b.Config().Priority
175+
if bp == 0 {
176+
bp = 1
170177
}
171-
return ip > jp
178+
return cmp.Compare(bp, ap)
172179
}
173180

174181
// Analyser determines how appropriate this lexer is for the given text.

regexp.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package chroma
22

33
import (
4+
"cmp"
45
"encoding/json"
56
"fmt"
67
"iter"
@@ -9,7 +10,6 @@ import (
910
"path/filepath"
1011
"regexp"
1112
"slices"
12-
"sort"
1313
"strings"
1414
"sync"
1515
"time"
@@ -27,8 +27,8 @@ type Rule struct {
2727

2828
// Words creates a regex that matches any of the given literal words.
2929
func Words(prefix, suffix string, words ...string) string {
30-
sort.Slice(words, func(i, j int) bool {
31-
return len(words[j]) < len(words[i])
30+
slices.SortFunc(words, func(a, b string) int {
31+
return cmp.Compare(len(b), len(a))
3232
})
3333
for i, word := range words {
3434
words[i] = regexp.QuoteMeta(word)

registry.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package chroma
22

33
import (
44
"path/filepath"
5-
"sort"
5+
"slices"
66
"strings"
77
)
88

@@ -44,7 +44,7 @@ func (l *LexerRegistry) Names(withAliases bool) []string {
4444
out = append(out, config.Aliases...)
4545
}
4646
}
47-
sort.Strings(out)
47+
slices.Sort(out)
4848
return out
4949
}
5050

@@ -62,7 +62,7 @@ func (l *LexerRegistry) Aliases(skipWithoutAliases bool) []string {
6262
}
6363
out = append(out, config.Aliases...)
6464
}
65-
sort.Strings(out)
65+
slices.Sort(out)
6666
return out
6767
}
6868

@@ -93,8 +93,7 @@ func (l *LexerRegistry) Get(name string) Lexer {
9393
if len(candidates) == 0 {
9494
return nil
9595
}
96-
sort.Sort(candidates)
97-
return candidates[0]
96+
return slices.MinFunc(candidates, compareLexersByPriority)
9897
}
9998

10099
// MatchMimeType attempts to find a lexer for the given MIME type.
@@ -108,8 +107,7 @@ func (l *LexerRegistry) MatchMimeType(mimeType string) Lexer {
108107
}
109108
}
110109
if len(matched) != 0 {
111-
sort.Sort(matched)
112-
return matched[0]
110+
return slices.MinFunc(matched, compareLexersByPriority)
113111
}
114112
return nil
115113
}
@@ -143,8 +141,7 @@ func (l *LexerRegistry) Match(filename string) Lexer {
143141
}
144142
}
145143
if len(matched) > 0 {
146-
sort.Sort(matched)
147-
return matched[0]
144+
return slices.MinFunc(matched, compareLexersByPriority)
148145
}
149146
matched = nil
150147
// Next, try filename aliases.
@@ -170,8 +167,7 @@ func (l *LexerRegistry) Match(filename string) Lexer {
170167
}
171168
}
172169
if len(matched) > 0 {
173-
sort.Sort(matched)
174-
return matched[0]
170+
return slices.MinFunc(matched, compareLexersByPriority)
175171
}
176172
return nil
177173
}

styles/api.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ package styles
33
import (
44
"embed"
55
"io/fs"
6-
"sort"
6+
"maps"
7+
"slices"
78
"strings"
89

910
"github.com/alecthomas/chroma/v3"
@@ -47,12 +48,7 @@ func Register(style *chroma.Style) *chroma.Style {
4748

4849
// Names of all available styles.
4950
func Names() []string {
50-
out := []string{}
51-
for name := range registry {
52-
out = append(out, name)
53-
}
54-
sort.Strings(out)
55-
return out
51+
return slices.Sorted(maps.Keys(registry))
5652
}
5753

5854
// Lookup a named style, returning false if not found.

0 commit comments

Comments
 (0)