Skip to content
This repository was archived by the owner on Mar 7, 2023. It is now read-only.

Commit 402bc5e

Browse files
committed
add feature of showing line number
1 parent 9838394 commit 402bc5e

File tree

1 file changed

+79
-24
lines changed

1 file changed

+79
-24
lines changed

main.go

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"io/ioutil"
1313
"os"
1414
"path/filepath"
15+
"strconv"
1516
"strings"
1617

1718
"github.com/alecthomas/chroma"
@@ -25,13 +26,21 @@ import (
2526
"golang.org/x/term"
2627
)
2728

28-
var version = "1.1.0"
29+
var version = "1.2.0"
2930

3031
func exitErr(err error) {
3132
fmt.Fprintln(os.Stderr, err)
3233
os.Exit(1)
3334
}
3435

36+
type options struct {
37+
useClipboard bool
38+
source string
39+
output string
40+
ext string
41+
theme string
42+
}
43+
3544
func main() {
3645
name := "code2img"
3746
fs := flag.NewFlagSet(name, flag.ContinueOnError)
@@ -50,6 +59,7 @@ Usage:
5059
-t color theme(default: solarized-dark)
5160
-o output file name(default: out.png)
5261
-c copy to clipboard
62+
-l print line
5363
-ext file extension
5464
`, name, version)
5565
}
@@ -58,6 +68,7 @@ Usage:
5868
ext := fs.String("ext", "", "")
5969
output := fs.String("o", "out.png", "")
6070
useClipboard := fs.Bool("c", false, "")
71+
printLine := fs.Bool("l", false, "")
6172

6273
if err := fs.Parse(os.Args[1:]); err != nil {
6374
if err == flag.ErrHelp {
@@ -103,32 +114,52 @@ Usage:
103114
}
104115
source := buf.String()
105116

106-
w, h := getSize(source)
117+
fontSize := 20
118+
w, h, lw := getSize(*printLine, source, fontSize)
107119
formatters.Register("png", &pngFormat{
108-
width: w,
109-
height: h,
120+
width: w,
121+
height: h,
122+
lineWidth: lw,
123+
fontSize: fontSize,
124+
printLine: *printLine,
110125
})
111126

112-
if err := toImg(*useClipboard, source, *output, *ext, *theme); err != nil {
127+
opts := options{
128+
useClipboard: *useClipboard,
129+
source: source,
130+
output: *output,
131+
ext: *ext,
132+
theme: *theme,
133+
}
134+
if err := toImg(opts); err != nil {
113135
exitErr(err)
114136
}
115137
}
116138

117-
func getSize(s string) (int, int) {
118-
w, h := 0, 0
119-
for _, s := range strings.Split(s, "\n") {
120-
ww := len(s) * 12
139+
func getSize(printLine bool, s string, fontSize int) (w int, h int, lw int) {
140+
lines := strings.Split(s, "\n")
141+
ws := 12
142+
for _, s := range lines {
143+
ww := len(s) * ws
121144
if ww > w {
122145
w = ww
123146
}
124147
h++
125148
}
126149
h = h + 2
127-
return w, h * 20
150+
151+
if printLine {
152+
lw = len(strconv.Itoa(len(lines)))
153+
w = w + lw*ws
154+
}
155+
return w, h * fontSize, lw
128156
}
129157

130158
type pngFormat struct {
159+
fontSize int
131160
width, height int
161+
lineWidth int
162+
printLine bool
132163
}
133164

134165
func (p *pngFormat) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) error {
@@ -146,7 +177,7 @@ func (p *pngFormat) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite
146177
}
147178

148179
opt := truetype.Options{
149-
Size: 20,
180+
Size: float64(p.fontSize),
150181
}
151182
face := truetype.NewFace(ft, &opt)
152183

@@ -162,9 +193,33 @@ func (p *pngFormat) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite
162193
Face: face,
163194
}
164195

196+
// width, height padding
165197
padding := 2
166-
x := fixed.Int26_6(padding)
167-
y := fixed.Int26_6(2)
198+
199+
// draw line
200+
if p.printLine {
201+
i := 1
202+
if bg.Brightness() < 0.5 {
203+
dr.Src = image.NewUniform(color.White)
204+
} else {
205+
dr.Src = image.NewUniform(color.Black)
206+
}
207+
208+
lx := fixed.Int26_6(padding)
209+
210+
lm := p.height/p.fontSize - 2 // remove font size
211+
for i < lm {
212+
dr.Dot.X = fixed.I(10) * lx
213+
dr.Dot.Y = fixed.I(p.fontSize) * fixed.Int26_6(i+1)
214+
dr.DrawString(strconv.Itoa(i))
215+
i++
216+
}
217+
}
218+
219+
// draw source code
220+
ox := fixed.Int26_6(p.lineWidth + 3)
221+
x := ox
222+
y := fixed.Int26_6(padding)
168223

169224
for _, t := range iterator.Tokens() {
170225
s := style.Get(t.Type)
@@ -182,15 +237,15 @@ func (p *pngFormat) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite
182237

183238
for _, c := range t.String() {
184239
if c == '\n' {
185-
x = fixed.Int26_6(padding)
240+
x = ox
186241
y++
187242
continue
188243
} else if c == '\t' {
189-
x += fixed.Int26_6(padding)
244+
x += fixed.Int26_6(4)
190245
continue
191246
}
192247
dr.Dot.X = fixed.I(10) * x
193-
dr.Dot.Y = fixed.I(20) * y
248+
dr.Dot.Y = fixed.I(p.fontSize) * y
194249
s := fmt.Sprintf("%c", c)
195250
dr.DrawString(s)
196251

@@ -206,10 +261,10 @@ func (p *pngFormat) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite
206261
return png.Encode(w, img)
207262
}
208263

209-
func toImg(useClipboard bool, source, outFile string, lexer, style string) error {
210-
l := lexers.Get(lexer)
264+
func toImg(opt options) error {
265+
l := lexers.Get(opt.ext)
211266
if l == nil {
212-
l = lexers.Analyse(source)
267+
l = lexers.Analyse(opt.source)
213268
}
214269
if l == nil {
215270
l = lexers.Fallback
@@ -221,12 +276,12 @@ func toImg(useClipboard bool, source, outFile string, lexer, style string) error
221276
f = formatters.Fallback
222277
}
223278

224-
s := styles.Get(style)
279+
s := styles.Get(opt.theme)
225280
if s == nil {
226281
s = styles.Fallback
227282
}
228283

229-
it, err := l.Tokenise(nil, source)
284+
it, err := l.Tokenise(nil, opt.source)
230285
if err != nil {
231286
return err
232287
}
@@ -237,7 +292,7 @@ func toImg(useClipboard bool, source, outFile string, lexer, style string) error
237292
return err
238293
}
239294

240-
if useClipboard {
295+
if opt.useClipboard {
241296
return clipboard.CopyToClipboard(buf)
242297
}
243298

@@ -249,7 +304,7 @@ func toImg(useClipboard bool, source, outFile string, lexer, style string) error
249304
if _, err := io.Copy(tmp, buf); err != nil {
250305
return err
251306
}
252-
253307
tmp.Close()
254-
return os.Rename(tmp.Name(), outFile)
308+
309+
return os.Rename(tmp.Name(), opt.output)
255310
}

0 commit comments

Comments
 (0)