15
15
)
16
16
from pygments .util import ClassNotFound
17
17
18
- from codepic .render import render_code
18
+ from codepic .render import render_code , resize_image
19
+
20
+
21
+ # Print message to stderr because the image can be written through stdout
22
+ def log (msg ):
23
+ click .echo (msg , err = True )
24
+
25
+
26
+ def format_from_extension (output , default = 'png' ):
27
+ if output :
28
+ ext = os .path .splitext (output )[1 ]
29
+
30
+ if ext :
31
+ ext = ext .lower ()
32
+ if ext == 'jpg' :
33
+ ext = 'jpeg'
34
+
35
+ if ext in ['png' , 'jpeg' , 'bmp' , 'gif' ]:
36
+ log (f'Got output image format { ext } from output file extension' )
37
+ return ext
38
+
39
+ log ('No format provided, defaulting to png' )
40
+ return default
41
+
42
+
43
+ def read_code (source_file ):
44
+ # Read code from stdin
45
+ if source_file == '-' :
46
+ log ('Reading code from stdion' )
47
+ return sys .stdin .read ()
48
+
49
+ # TODO maybe remove these as they might be too verbose
50
+ log (f'Reading code from file { source_file } ' )
51
+
52
+ # Read code from file
53
+ with open (source_file , 'r' ) as f :
54
+ return f .read ()
55
+
56
+
57
+ def get_lexer (lang , source_file , code ):
58
+ # Lexer from language name
59
+ if lang :
60
+ return get_lexer_by_name (lang )
61
+
62
+ # Use source file extension
63
+ if source_file != '-' :
64
+ try :
65
+ return get_lexer_for_filename (code )
66
+
67
+ except ClassNotFound :
68
+ log ('Could not detect language from source file extension' )
69
+ pass
70
+
71
+ try :
72
+ return guess_lexer (code )
73
+
74
+ except ClassNotFound :
75
+ log ('Could not detect language by analyzing code, defaulting to plain text' )
76
+ return TextLexer ()
19
77
20
78
21
79
@click .command ()
22
80
@click .option ('-w' , '--width' , type = str , help = 'Fixed width in pixels or percent' )
23
81
@click .option ('-h' , '--height' , type = str , help = 'Fixed hight in pixels or percent' )
24
82
@click .option ('--line_numbers' , is_flag = True , help = 'Show line numbers' )
25
83
@click .option ('-p' , '--pad' , type = int , default = 30 , help = 'Padding in pixels' )
26
- @click .option ('-f' , '-- font_name' , type = str , help = 'Font size in pt' )
27
- @click .option ('-s' , '- -font_size' , type = int , default = 14 , help = 'Font size in pt' )
84
+ @click .option ('-- font_name' , type = str , help = 'Font size in pt' , default = ' ' )
85
+ @click .option ('--font_size' , type = int , default = 14 , help = 'Font size in pt' )
28
86
@click .option ('-a' , '--aa_factor' , type = float , default = 1 , help = 'Antialias factor' )
29
87
@click .option ('-s' , '--style' , type = str , default = 'one-dark' )
30
88
@click .option ('-l' , '--lang' , type = str )
31
- @click .option ('-c' , '--clipboard' , is_flag = True , help = 'Copy image to clipboard' )
89
+ @click .option ('-c' , '--clipboard' , is_flag = True , help = 'Output image to clipboard' )
32
90
@click .option (
33
91
'-f' ,
34
92
'--image_format' ,
35
93
type = click .Choice (['png' , 'jpeg' , 'bmp' , 'gif' ]),
36
- help = 'Antialias factor ' ,
94
+ help = 'Image format ' ,
37
95
)
38
96
@click .option (
39
97
'-o' ,
@@ -62,44 +120,36 @@ def cli(
62
120
height : str | None ,
63
121
line_numbers : bool ,
64
122
pad : int ,
65
- font_name : str | None ,
123
+ font_name : str ,
66
124
font_size : int ,
67
125
aa_factor : float ,
68
126
image_format : str | None ,
69
127
style : str ,
70
128
lang : str | None ,
71
129
clipboard : bool ,
72
130
):
73
- code = ''
74
-
75
- if font_name is None :
76
- font_name = ''
77
-
131
+ # Use output file extension to detect image format, otherwise png
78
132
if not image_format :
79
- image_format = 'png'
80
- if output :
81
- ext = os .path .splitext (source_file )[1 ]
82
- if ext :
83
- ext = ext .lower ()
84
- if ext in ['png' , 'jpeg' , 'jpg' , 'bmp' , 'gif' ]:
85
- image_format = ext
86
- if image_format == 'jpg' :
87
- image_format = 'jpeg'
133
+ image_format = format_from_extension (output )
134
+
135
+ else :
136
+ log (f'Using image format { image_format } ' )
88
137
138
+ # Only png format can be stored in the clipboard
89
139
if clipboard and image_format != 'png' :
90
- exit ('Image format must be png to use clipboard' )
140
+ raise click .ClickException ('Image format must be png to use -c' )
141
+
142
+ # Must have somewhere to output, clipboard or file / stdout
143
+ if not output and not clipboard :
144
+ raise click .ClickException ('No output location was specified, use -o or -c' )
91
145
92
- write_to_stdout = False
93
- if output == '-' :
94
- write_to_stdout = True
146
+ # Get code before choosing lexer
147
+ code = read_code (source_file )
95
148
96
- elif not output :
97
- if not clipboard :
98
- if source_file == '-' :
99
- write_to_stdout = True
100
- else :
101
- output = os .path .splitext (source_file )[0 ] + '.' + image_format .lower ()
149
+ # Get lexer from lang name or source file extension, defaults to plaintext
150
+ lexer = get_lexer (lang , source_file , code )
102
151
152
+ # Setup image formatting
103
153
formatter = ImageFormatter (
104
154
font_name = font_name ,
105
155
font_size = font_size * aa_factor ,
@@ -109,66 +159,10 @@ def cli(
109
159
image_format = image_format ,
110
160
)
111
161
112
- lexer = None
113
-
114
- if lang :
115
- lexer = get_lexer_by_name (lang )
116
-
117
- if source_file == '-' :
118
- code = sys .stdin .read ()
119
-
120
- if not lexer :
121
- try :
122
- lexer = guess_lexer (code )
123
-
124
- except ClassNotFound :
125
- lexer = TextLexer ()
126
-
127
- img = render_code (code , lexer , formatter , aa_factor )
128
-
129
- else :
130
- with open (source_file , 'r' ) as f :
131
- code = f .read ()
132
-
133
- if not lexer :
134
- try :
135
- lexer = get_lexer_for_filename (code )
136
-
137
- except ClassNotFound :
138
- try :
139
- lexer = guess_lexer (code )
140
-
141
- except ClassNotFound :
142
- lexer = TextLexer ()
143
-
144
- img = render_code (code , lexer , formatter , aa_factor )
145
-
146
- aspect = img .height / img .width
147
-
148
- if height :
149
- if height .endswith ('%' ):
150
- perc = int (height [:- 1 ]) / 100
151
- height = int (img .height * perc )
152
-
153
- else :
154
- height = int (height )
155
-
156
- if width :
157
- if width .endswith ('%' ):
158
- perc = int (width [:- 1 ]) / 100
159
- width = int (img .width * perc )
160
-
161
- else :
162
- width = int (width )
163
-
164
- if not width and height :
165
- width = int (height / aspect )
166
-
167
- if not height and width :
168
- height = int (width * aspect )
162
+ # Render the code
163
+ img = render_code (code , lexer , formatter , width , height , aa_factor )
169
164
170
- if width and height :
171
- img = img .resize ((width , height ), resample = Image .Resampling .LANCZOS )
165
+ # GARBAGE AFTER HERE
172
166
173
167
buff = io .BytesIO ()
174
168
img .save (buff , format = 'PNG' )
@@ -181,8 +175,8 @@ def cli(
181
175
run (f'xclip -selection clipboard -target image/png < { fp .name } ' , shell = True )
182
176
fp .flush ()
183
177
184
- if write_to_stdout :
185
- sys .stdout .buffer .write (buff )
178
+ # if write_to_stdout:
179
+ # sys.stdout.buffer.write(buff)
186
180
187
181
elif output and output != '-' :
188
182
with open (output , 'wb' ) as f :
0 commit comments