Skip to content

Commit fccbda4

Browse files
authored
feat: Refactor (#7)
1 parent 2772f96 commit fccbda4

File tree

6 files changed

+386
-141
lines changed

6 files changed

+386
-141
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ name: ci
22

33
on:
44
push:
5-
branch:
5+
branches:
6+
- main
7+
8+
pull_request:
9+
types:
10+
- opened
11+
- reopened
12+
- synchronize
613

714
jobs:
815
lint_test:

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Generate an image of code using pygments syntax highlighting.
66

77
For example:
88

9-
![](docs/test.png)
9+
![example](docs/test.png)
1010

1111
## Usage
1212

@@ -19,14 +19,14 @@ Options:
1919
-h, --height TEXT Fixed hight in pixels or percent
2020
--line_numbers Show line numbers
2121
-p, --pad INTEGER Padding in pixels
22-
-f, --font_name TEXT Font size in pt
23-
-s, --font_size INTEGER Font size in pt
22+
--font_name TEXT Font size in pt
23+
--font_size INTEGER Font size in pt
2424
-a, --aa_factor FLOAT Antialias factor
2525
-s, --style TEXT
2626
-l, --lang TEXT
27-
-c, --clipboard Copy image to clipboard
27+
-c, --clipboard Output image to clipboard
2828
-f, --image_format [png|jpeg|bmp|gif]
29-
Antialias factor
29+
Image format
3030
-o, --output FILE Output path for image
3131
--help Show this message and exit.
3232
```

src/codepic/cli.py

Lines changed: 85 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,83 @@
1515
)
1616
from 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

Comments
 (0)