1515)
1616from pygments .util import ClassNotFound
1717
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 ()
1977
2078
2179@click .command ()
2280@click .option ('-w' , '--width' , type = str , help = 'Fixed width in pixels or percent' )
2381@click .option ('-h' , '--height' , type = str , help = 'Fixed hight in pixels or percent' )
2482@click .option ('--line_numbers' , is_flag = True , help = 'Show line numbers' )
2583@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' )
2886@click .option ('-a' , '--aa_factor' , type = float , default = 1 , help = 'Antialias factor' )
2987@click .option ('-s' , '--style' , type = str , default = 'one-dark' )
3088@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' )
3290@click .option (
3391 '-f' ,
3492 '--image_format' ,
3593 type = click .Choice (['png' , 'jpeg' , 'bmp' , 'gif' ]),
36- help = 'Antialias factor ' ,
94+ help = 'Image format ' ,
3795)
3896@click .option (
3997 '-o' ,
@@ -62,44 +120,36 @@ def cli(
62120 height : str | None ,
63121 line_numbers : bool ,
64122 pad : int ,
65- font_name : str | None ,
123+ font_name : str ,
66124 font_size : int ,
67125 aa_factor : float ,
68126 image_format : str | None ,
69127 style : str ,
70128 lang : str | None ,
71129 clipboard : bool ,
72130):
73- code = ''
74-
75- if font_name is None :
76- font_name = ''
77-
131+ # Use output file extension to detect image format, otherwise png
78132 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 } ' )
88137
138+ # Only png format can be stored in the clipboard
89139 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' )
91145
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 )
95148
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 )
102151
152+ # Setup image formatting
103153 formatter = ImageFormatter (
104154 font_name = font_name ,
105155 font_size = font_size * aa_factor ,
@@ -109,66 +159,10 @@ def cli(
109159 image_format = image_format ,
110160 )
111161
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 )
169164
170- if width and height :
171- img = img .resize ((width , height ), resample = Image .Resampling .LANCZOS )
165+ # GARBAGE AFTER HERE
172166
173167 buff = io .BytesIO ()
174168 img .save (buff , format = 'PNG' )
@@ -181,8 +175,8 @@ def cli(
181175 run (f'xclip -selection clipboard -target image/png < { fp .name } ' , shell = True )
182176 fp .flush ()
183177
184- if write_to_stdout :
185- sys .stdout .buffer .write (buff )
178+ # if write_to_stdout:
179+ # sys.stdout.buffer.write(buff)
186180
187181 elif output and output != '-' :
188182 with open (output , 'wb' ) as f :
0 commit comments