@@ -2,6 +2,7 @@ package main
2
2
3
3
import (
4
4
"bufio"
5
+ "errors"
5
6
"fmt"
6
7
"io"
7
8
"io/ioutil"
@@ -82,6 +83,54 @@ type nopFlushableWriter struct{ io.Writer }
82
83
83
84
func (n * nopFlushableWriter ) Flush () error { return nil }
84
85
86
+ // prepareLenient prepares contents and lexer for input, using fallback lexer if no specific one is available for it.
87
+ func prepareLenient (ctx * kong.Context , r io.Reader , filename string ) (string , chroma.Lexer ) {
88
+ data , err := ioutil .ReadAll (r )
89
+ ctx .FatalIfErrorf (err )
90
+
91
+ contents := string (data )
92
+ lexer := selexer (filename , contents )
93
+ if lexer == nil {
94
+ lexer = lexers .Fallback
95
+ }
96
+
97
+ return contents , lexer
98
+ }
99
+
100
+ // prepareSpecific prepares contents and lexer for input, exiting if there is no specific lexer available for it.
101
+ // Input is consumed only up to peekSize for lexer selection. With fullSize -1, consume r until EOF.
102
+ func prepareSpecific (ctx * kong.Context , r io.Reader , filename string , peekSize , fullSize int ) (string , chroma.Lexer ) {
103
+ data := make ([]byte , peekSize )
104
+ n , err := io .ReadFull (r , data )
105
+ if err != nil && ! errors .Is (err , io .ErrUnexpectedEOF ) {
106
+ ctx .FatalIfErrorf (err )
107
+ }
108
+
109
+ lexer := selexer (filename , string (data [:n ]))
110
+ if lexer == nil {
111
+ ctx .Exit (1 )
112
+ }
113
+
114
+ if n < peekSize {
115
+ return string (data [:n ]), lexer
116
+ }
117
+ var ndata []byte
118
+ if fullSize == - 1 {
119
+ rest , err := io .ReadAll (r )
120
+ ctx .FatalIfErrorf (err )
121
+ ndata = make ([]byte , n + len (rest ))
122
+ copy (ndata , data [:n ])
123
+ copy (ndata [n :], rest )
124
+ } else {
125
+ ndata = make ([]byte , fullSize )
126
+ copy (ndata , data [:n ])
127
+ _ , err = io .ReadFull (r , ndata [n :])
128
+ ctx .FatalIfErrorf (err )
129
+ }
130
+
131
+ return string (ndata ), lexer
132
+ }
133
+
85
134
func main () {
86
135
ctx := kong .Parse (& cli , kong .Description (description ), kong.Vars {
87
136
"version" : fmt .Sprintf ("%s-%s-%s" , version , commit , date ),
@@ -160,18 +209,37 @@ func main() {
160
209
configureHTMLFormatter (ctx )
161
210
}
162
211
if len (cli .Files ) == 0 {
163
- contents , err := ioutil .ReadAll (os .Stdin )
164
- ctx .FatalIfErrorf (err )
165
- format (ctx , w , style , lex (ctx , cli .Filename , string (contents )))
212
+ var contents string
213
+ var lexer chroma.Lexer
214
+ if cli .Fail {
215
+ contents , lexer = prepareSpecific (ctx , os .Stdin , cli .Filename , 1024 , - 1 )
216
+ } else {
217
+ contents , lexer = prepareLenient (ctx , os .Stdin , cli .Filename )
218
+ }
219
+ format (ctx , w , style , lex (ctx , lexer , contents ))
166
220
} else {
167
221
for _ , filename := range cli .Files {
168
- contents , err := ioutil . ReadFile (filename )
222
+ file , err := os . Open (filename )
169
223
ctx .FatalIfErrorf (err )
224
+
170
225
if cli .Check {
171
- check (filename , lex (ctx , filename , string (contents )))
226
+ contents , lexer := prepareLenient (ctx , file , filename )
227
+ check (filename , lex (ctx , lexer , contents ))
172
228
} else {
173
- format (ctx , w , style , lex (ctx , filename , string (contents )))
229
+ var contents string
230
+ var lexer chroma.Lexer
231
+ if cli .Fail {
232
+ fi , err := file .Stat ()
233
+ ctx .FatalIfErrorf (err )
234
+ contents , lexer = prepareSpecific (ctx , file , filename , 1024 , int (fi .Size ()))
235
+ } else {
236
+ contents , lexer = prepareLenient (ctx , file , filename )
237
+ }
238
+ format (ctx , w , style , lex (ctx , lexer , contents ))
174
239
}
240
+
241
+ err = file .Close ()
242
+ ctx .FatalIfErrorf (err )
175
243
}
176
244
}
177
245
}
@@ -241,14 +309,7 @@ func listAll() {
241
309
fmt .Println ()
242
310
}
243
311
244
- func lex (ctx * kong.Context , path string , contents string ) chroma.Iterator {
245
- lexer := selexer (path , contents )
246
- if lexer == nil {
247
- if cli .Fail {
248
- ctx .Exit (1 )
249
- }
250
- lexer = lexers .Fallback
251
- }
312
+ func lex (ctx * kong.Context , lexer chroma.Lexer , contents string ) chroma.Iterator {
252
313
if rel , ok := lexer .(* chroma.RegexLexer ); ok {
253
314
rel .Trace (cli .Trace )
254
315
}
0 commit comments