Mercurial > yakumo_izuru > aya
comparison vendor/github.com/alecthomas/chroma/v2/emitters.go @ 66:787b5ee0289d draft
Use vendored modules
Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
| author | yakumo.izuru |
|---|---|
| date | Sun, 23 Jul 2023 13:18:53 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 65:6d985efa0f7a | 66:787b5ee0289d |
|---|---|
| 1 package chroma | |
| 2 | |
| 3 import ( | |
| 4 "fmt" | |
| 5 ) | |
| 6 | |
| 7 // An Emitter takes group matches and returns tokens. | |
| 8 type Emitter interface { | |
| 9 // Emit tokens for the given regex groups. | |
| 10 Emit(groups []string, state *LexerState) Iterator | |
| 11 } | |
| 12 | |
| 13 // SerialisableEmitter is an Emitter that can be serialised and deserialised to/from JSON. | |
| 14 type SerialisableEmitter interface { | |
| 15 Emitter | |
| 16 EmitterKind() string | |
| 17 } | |
| 18 | |
| 19 // EmitterFunc is a function that is an Emitter. | |
| 20 type EmitterFunc func(groups []string, state *LexerState) Iterator | |
| 21 | |
| 22 // Emit tokens for groups. | |
| 23 func (e EmitterFunc) Emit(groups []string, state *LexerState) Iterator { | |
| 24 return e(groups, state) | |
| 25 } | |
| 26 | |
| 27 type Emitters []Emitter | |
| 28 | |
| 29 type byGroupsEmitter struct { | |
| 30 Emitters | |
| 31 } | |
| 32 | |
| 33 // ByGroups emits a token for each matching group in the rule's regex. | |
| 34 func ByGroups(emitters ...Emitter) Emitter { | |
| 35 return &byGroupsEmitter{Emitters: emitters} | |
| 36 } | |
| 37 | |
| 38 func (b *byGroupsEmitter) EmitterKind() string { return "bygroups" } | |
| 39 | |
| 40 func (b *byGroupsEmitter) Emit(groups []string, state *LexerState) Iterator { | |
| 41 iterators := make([]Iterator, 0, len(groups)-1) | |
| 42 if len(b.Emitters) != len(groups)-1 { | |
| 43 iterators = append(iterators, Error.Emit(groups, state)) | |
| 44 // panic(errors.Errorf("number of groups %q does not match number of emitters %v", groups, emitters)) | |
| 45 } else { | |
| 46 for i, group := range groups[1:] { | |
| 47 if b.Emitters[i] != nil { | |
| 48 iterators = append(iterators, b.Emitters[i].Emit([]string{group}, state)) | |
| 49 } | |
| 50 } | |
| 51 } | |
| 52 return Concaterator(iterators...) | |
| 53 } | |
| 54 | |
| 55 // ByGroupNames emits a token for each named matching group in the rule's regex. | |
| 56 func ByGroupNames(emitters map[string]Emitter) Emitter { | |
| 57 return EmitterFunc(func(groups []string, state *LexerState) Iterator { | |
| 58 iterators := make([]Iterator, 0, len(state.NamedGroups)-1) | |
| 59 if len(state.NamedGroups)-1 == 0 { | |
| 60 if emitter, ok := emitters[`0`]; ok { | |
| 61 iterators = append(iterators, emitter.Emit(groups, state)) | |
| 62 } else { | |
| 63 iterators = append(iterators, Error.Emit(groups, state)) | |
| 64 } | |
| 65 } else { | |
| 66 ruleRegex := state.Rules[state.State][state.Rule].Regexp | |
| 67 for i := 1; i < len(state.NamedGroups); i++ { | |
| 68 groupName := ruleRegex.GroupNameFromNumber(i) | |
| 69 group := state.NamedGroups[groupName] | |
| 70 if emitter, ok := emitters[groupName]; ok { | |
| 71 if emitter != nil { | |
| 72 iterators = append(iterators, emitter.Emit([]string{group}, state)) | |
| 73 } | |
| 74 } else { | |
| 75 iterators = append(iterators, Error.Emit([]string{group}, state)) | |
| 76 } | |
| 77 } | |
| 78 } | |
| 79 return Concaterator(iterators...) | |
| 80 }) | |
| 81 } | |
| 82 | |
| 83 // UsingByGroup emits tokens for the matched groups in the regex using a | |
| 84 // "sublexer". Used when lexing code blocks where the name of a sublexer is | |
| 85 // contained within the block, for example on a Markdown text block or SQL | |
| 86 // language block. | |
| 87 // | |
| 88 // The sublexer will be retrieved using sublexerGetFunc (typically | |
| 89 // internal.Get), using the captured value from the matched sublexerNameGroup. | |
| 90 // | |
| 91 // If sublexerGetFunc returns a non-nil lexer for the captured sublexerNameGroup, | |
| 92 // then tokens for the matched codeGroup will be emitted using the retrieved | |
| 93 // lexer. Otherwise, if the sublexer is nil, then tokens will be emitted from | |
| 94 // the passed emitter. | |
| 95 // | |
| 96 // Example: | |
| 97 // | |
| 98 // var Markdown = internal.Register(MustNewLexer( | |
| 99 // &Config{ | |
| 100 // Name: "markdown", | |
| 101 // Aliases: []string{"md", "mkd"}, | |
| 102 // Filenames: []string{"*.md", "*.mkd", "*.markdown"}, | |
| 103 // MimeTypes: []string{"text/x-markdown"}, | |
| 104 // }, | |
| 105 // Rules{ | |
| 106 // "root": { | |
| 107 // {"^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)", | |
| 108 // UsingByGroup( | |
| 109 // internal.Get, | |
| 110 // 2, 4, | |
| 111 // String, String, String, Text, String, | |
| 112 // ), | |
| 113 // nil, | |
| 114 // }, | |
| 115 // }, | |
| 116 // }, | |
| 117 // )) | |
| 118 // | |
| 119 // See the lexers/m/markdown.go for the complete example. | |
| 120 // | |
| 121 // Note: panic's if the number of emitters does not equal the number of matched | |
| 122 // groups in the regex. | |
| 123 func UsingByGroup(sublexerNameGroup, codeGroup int, emitters ...Emitter) Emitter { | |
| 124 return &usingByGroup{ | |
| 125 SublexerNameGroup: sublexerNameGroup, | |
| 126 CodeGroup: codeGroup, | |
| 127 Emitters: emitters, | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 type usingByGroup struct { | |
| 132 SublexerNameGroup int `xml:"sublexer_name_group"` | |
| 133 CodeGroup int `xml:"code_group"` | |
| 134 Emitters Emitters `xml:"emitters"` | |
| 135 } | |
| 136 | |
| 137 func (u *usingByGroup) EmitterKind() string { return "usingbygroup" } | |
| 138 func (u *usingByGroup) Emit(groups []string, state *LexerState) Iterator { | |
| 139 // bounds check | |
| 140 if len(u.Emitters) != len(groups)-1 { | |
| 141 panic("UsingByGroup expects number of emitters to be the same as len(groups)-1") | |
| 142 } | |
| 143 | |
| 144 // grab sublexer | |
| 145 sublexer := state.Registry.Get(groups[u.SublexerNameGroup]) | |
| 146 | |
| 147 // build iterators | |
| 148 iterators := make([]Iterator, len(groups)-1) | |
| 149 for i, group := range groups[1:] { | |
| 150 if i == u.CodeGroup-1 && sublexer != nil { | |
| 151 var err error | |
| 152 iterators[i], err = sublexer.Tokenise(nil, groups[u.CodeGroup]) | |
| 153 if err != nil { | |
| 154 panic(err) | |
| 155 } | |
| 156 } else if u.Emitters[i] != nil { | |
| 157 iterators[i] = u.Emitters[i].Emit([]string{group}, state) | |
| 158 } | |
| 159 } | |
| 160 return Concaterator(iterators...) | |
| 161 } | |
| 162 | |
| 163 // UsingLexer returns an Emitter that uses a given Lexer for parsing and emitting. | |
| 164 // | |
| 165 // This Emitter is not serialisable. | |
| 166 func UsingLexer(lexer Lexer) Emitter { | |
| 167 return EmitterFunc(func(groups []string, _ *LexerState) Iterator { | |
| 168 it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0]) | |
| 169 if err != nil { | |
| 170 panic(err) | |
| 171 } | |
| 172 return it | |
| 173 }) | |
| 174 } | |
| 175 | |
| 176 type usingEmitter struct { | |
| 177 Lexer string `xml:"lexer,attr"` | |
| 178 } | |
| 179 | |
| 180 func (u *usingEmitter) EmitterKind() string { return "using" } | |
| 181 | |
| 182 func (u *usingEmitter) Emit(groups []string, state *LexerState) Iterator { | |
| 183 if state.Registry == nil { | |
| 184 panic(fmt.Sprintf("no LexerRegistry available for Using(%q)", u.Lexer)) | |
| 185 } | |
| 186 lexer := state.Registry.Get(u.Lexer) | |
| 187 if lexer == nil { | |
| 188 panic(fmt.Sprintf("no such lexer %q", u.Lexer)) | |
| 189 } | |
| 190 it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0]) | |
| 191 if err != nil { | |
| 192 panic(err) | |
| 193 } | |
| 194 return it | |
| 195 } | |
| 196 | |
| 197 // Using returns an Emitter that uses a given Lexer reference for parsing and emitting. | |
| 198 // | |
| 199 // The referenced lexer must be stored in the same LexerRegistry. | |
| 200 func Using(lexer string) Emitter { | |
| 201 return &usingEmitter{Lexer: lexer} | |
| 202 } | |
| 203 | |
| 204 type usingSelfEmitter struct { | |
| 205 State string `xml:"state,attr"` | |
| 206 } | |
| 207 | |
| 208 func (u *usingSelfEmitter) EmitterKind() string { return "usingself" } | |
| 209 | |
| 210 func (u *usingSelfEmitter) Emit(groups []string, state *LexerState) Iterator { | |
| 211 it, err := state.Lexer.Tokenise(&TokeniseOptions{State: u.State, Nested: true}, groups[0]) | |
| 212 if err != nil { | |
| 213 panic(err) | |
| 214 } | |
| 215 return it | |
| 216 } | |
| 217 | |
| 218 // UsingSelf is like Using, but uses the current Lexer. | |
| 219 func UsingSelf(stateName string) Emitter { | |
| 220 return &usingSelfEmitter{stateName} | |
| 221 } |
