1package chroma
2
3import (
4	"encoding/json"
5	"fmt"
6)
7
8//go:generate stringer -type TokenType
9
10// TokenType is the type of token to highlight.
11//
12// It is also an Emitter, emitting a single token of itself
13type TokenType int
14
15func (t TokenType) MarshalJSON() ([]byte, error) { return json.Marshal(t.String()) }
16func (t *TokenType) UnmarshalJSON(data []byte) error {
17	key := ""
18	err := json.Unmarshal(data, &key)
19	if err != nil {
20		return err
21	}
22	for tt, text := range _TokenType_map {
23		if text == key {
24			*t = tt
25			return nil
26		}
27	}
28	return fmt.Errorf("unknown TokenType %q", data)
29}
30
31// Set of TokenTypes.
32//
33// Categories of types are grouped in ranges of 1000, while sub-categories are in ranges of 100. For
34// example, the literal category is in the range 3000-3999. The sub-category for literal strings is
35// in the range 3100-3199.
36
37// Meta token types.
38const (
39	// Default background style.
40	Background TokenType = -1 - iota
41	// Line numbers in output.
42	LineNumbers
43	// Line numbers in output when in table.
44	LineNumbersTable
45	// Line higlight style.
46	LineHighlight
47	// Line numbers table wrapper style.
48	LineTable
49	// Line numbers table TD wrapper style.
50	LineTableTD
51	// Input that could not be tokenised.
52	Error
53	// Other is used by the Delegate lexer to indicate which tokens should be handled by the delegate.
54	Other
55	// No highlighting.
56	None
57	// Used as an EOF marker / nil token
58	EOFType TokenType = 0
59)
60
61// Keywords.
62const (
63	Keyword TokenType = 1000 + iota
64	KeywordConstant
65	KeywordDeclaration
66	KeywordNamespace
67	KeywordPseudo
68	KeywordReserved
69	KeywordType
70)
71
72// Names.
73const (
74	Name TokenType = 2000 + iota
75	NameAttribute
76	NameBuiltin
77	NameBuiltinPseudo
78	NameClass
79	NameConstant
80	NameDecorator
81	NameEntity
82	NameException
83	NameFunction
84	NameFunctionMagic
85	NameKeyword
86	NameLabel
87	NameNamespace
88	NameOperator
89	NameOther
90	NamePseudo
91	NameProperty
92	NameTag
93	NameVariable
94	NameVariableAnonymous
95	NameVariableClass
96	NameVariableGlobal
97	NameVariableInstance
98	NameVariableMagic
99)
100
101// Literals.
102const (
103	Literal TokenType = 3000 + iota
104	LiteralDate
105	LiteralOther
106)
107
108// Strings.
109const (
110	LiteralString TokenType = 3100 + iota
111	LiteralStringAffix
112	LiteralStringAtom
113	LiteralStringBacktick
114	LiteralStringBoolean
115	LiteralStringChar
116	LiteralStringDelimiter
117	LiteralStringDoc
118	LiteralStringDouble
119	LiteralStringEscape
120	LiteralStringHeredoc
121	LiteralStringInterpol
122	LiteralStringName
123	LiteralStringOther
124	LiteralStringRegex
125	LiteralStringSingle
126	LiteralStringSymbol
127)
128
129// Literals.
130const (
131	LiteralNumber TokenType = 3200 + iota
132	LiteralNumberBin
133	LiteralNumberFloat
134	LiteralNumberHex
135	LiteralNumberInteger
136	LiteralNumberIntegerLong
137	LiteralNumberOct
138)
139
140// Operators.
141const (
142	Operator TokenType = 4000 + iota
143	OperatorWord
144)
145
146// Punctuation.
147const (
148	Punctuation TokenType = 5000 + iota
149)
150
151// Comments.
152const (
153	Comment TokenType = 6000 + iota
154	CommentHashbang
155	CommentMultiline
156	CommentSingle
157	CommentSpecial
158)
159
160// Preprocessor "comments".
161const (
162	CommentPreproc TokenType = 6100 + iota
163	CommentPreprocFile
164)
165
166// Generic tokens.
167const (
168	Generic TokenType = 7000 + iota
169	GenericDeleted
170	GenericEmph
171	GenericError
172	GenericHeading
173	GenericInserted
174	GenericOutput
175	GenericPrompt
176	GenericStrong
177	GenericSubheading
178	GenericTraceback
179	GenericUnderline
180)
181
182// Text.
183const (
184	Text TokenType = 8000 + iota
185	TextWhitespace
186	TextSymbol
187	TextPunctuation
188)
189
190// Aliases.
191const (
192	Whitespace = TextWhitespace
193
194	Date = LiteralDate
195
196	String          = LiteralString
197	StringAffix     = LiteralStringAffix
198	StringBacktick  = LiteralStringBacktick
199	StringChar      = LiteralStringChar
200	StringDelimiter = LiteralStringDelimiter
201	StringDoc       = LiteralStringDoc
202	StringDouble    = LiteralStringDouble
203	StringEscape    = LiteralStringEscape
204	StringHeredoc   = LiteralStringHeredoc
205	StringInterpol  = LiteralStringInterpol
206	StringOther     = LiteralStringOther
207	StringRegex     = LiteralStringRegex
208	StringSingle    = LiteralStringSingle
209	StringSymbol    = LiteralStringSymbol
210
211	Number            = LiteralNumber
212	NumberBin         = LiteralNumberBin
213	NumberFloat       = LiteralNumberFloat
214	NumberHex         = LiteralNumberHex
215	NumberInteger     = LiteralNumberInteger
216	NumberIntegerLong = LiteralNumberIntegerLong
217	NumberOct         = LiteralNumberOct
218)
219
220var (
221	StandardTypes = map[TokenType]string{
222		Background:       "chroma",
223		LineNumbers:      "ln",
224		LineNumbersTable: "lnt",
225		LineHighlight:    "hl",
226		LineTable:        "lntable",
227		LineTableTD:      "lntd",
228		Text:             "",
229		Whitespace:       "w",
230		Error:            "err",
231		Other:            "x",
232		// I have no idea what this is used for...
233		// Escape:     "esc",
234
235		Keyword:            "k",
236		KeywordConstant:    "kc",
237		KeywordDeclaration: "kd",
238		KeywordNamespace:   "kn",
239		KeywordPseudo:      "kp",
240		KeywordReserved:    "kr",
241		KeywordType:        "kt",
242
243		Name:                 "n",
244		NameAttribute:        "na",
245		NameBuiltin:          "nb",
246		NameBuiltinPseudo:    "bp",
247		NameClass:            "nc",
248		NameConstant:         "no",
249		NameDecorator:        "nd",
250		NameEntity:           "ni",
251		NameException:        "ne",
252		NameFunction:         "nf",
253		NameFunctionMagic:    "fm",
254		NameProperty:         "py",
255		NameLabel:            "nl",
256		NameNamespace:        "nn",
257		NameOther:            "nx",
258		NameTag:              "nt",
259		NameVariable:         "nv",
260		NameVariableClass:    "vc",
261		NameVariableGlobal:   "vg",
262		NameVariableInstance: "vi",
263		NameVariableMagic:    "vm",
264
265		Literal:     "l",
266		LiteralDate: "ld",
267
268		String:          "s",
269		StringAffix:     "sa",
270		StringBacktick:  "sb",
271		StringChar:      "sc",
272		StringDelimiter: "dl",
273		StringDoc:       "sd",
274		StringDouble:    "s2",
275		StringEscape:    "se",
276		StringHeredoc:   "sh",
277		StringInterpol:  "si",
278		StringOther:     "sx",
279		StringRegex:     "sr",
280		StringSingle:    "s1",
281		StringSymbol:    "ss",
282
283		Number:            "m",
284		NumberBin:         "mb",
285		NumberFloat:       "mf",
286		NumberHex:         "mh",
287		NumberInteger:     "mi",
288		NumberIntegerLong: "il",
289		NumberOct:         "mo",
290
291		Operator:     "o",
292		OperatorWord: "ow",
293
294		Punctuation: "p",
295
296		Comment:            "c",
297		CommentHashbang:    "ch",
298		CommentMultiline:   "cm",
299		CommentPreproc:     "cp",
300		CommentPreprocFile: "cpf",
301		CommentSingle:      "c1",
302		CommentSpecial:     "cs",
303
304		Generic:           "g",
305		GenericDeleted:    "gd",
306		GenericEmph:       "ge",
307		GenericError:      "gr",
308		GenericHeading:    "gh",
309		GenericInserted:   "gi",
310		GenericOutput:     "go",
311		GenericPrompt:     "gp",
312		GenericStrong:     "gs",
313		GenericSubheading: "gu",
314		GenericTraceback:  "gt",
315		GenericUnderline:  "gl",
316	}
317)
318
319func (t TokenType) Parent() TokenType {
320	if t%100 != 0 {
321		return t / 100 * 100
322	}
323	if t%1000 != 0 {
324		return t / 1000 * 1000
325	}
326	return 0
327}
328
329func (t TokenType) Category() TokenType {
330	return t / 1000 * 1000
331}
332
333func (t TokenType) SubCategory() TokenType {
334	return t / 100 * 100
335}
336
337func (t TokenType) InCategory(other TokenType) bool {
338	return t/1000 == other/1000
339}
340
341func (t TokenType) InSubCategory(other TokenType) bool {
342	return t/100 == other/100
343}
344
345func (t TokenType) Emit(groups []string, _ *LexerState) Iterator {
346	return Literator(Token{Type: t, Value: groups[0]})
347}
348