From 5f3175379b0109d0256886f640042a1e1e0b01c9 Mon Sep 17 00:00:00 2001 From: Ian Griffin Date: Wed, 12 Nov 2025 20:10:00 +0800 Subject: [PATCH] added syntax highlighting in code blocks using pygments --- pyproject.toml | 1 + term_color_md/__init__.py | 42 +++++++++++++++--- .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 4429 bytes 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 term_color_md/__pycache__/__init__.cpython-311.pyc diff --git a/pyproject.toml b/pyproject.toml index 6deab98..b1d31b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,4 +19,5 @@ requires-python = ">=3.9" # Dependencies that your package needs at install‑time dependencies = [ "termcolor>=3.1.0", + "pygments>=2.12", ] diff --git a/term_color_md/__init__.py b/term_color_md/__init__.py index 2a8ac9f..87740f8 100644 --- a/term_color_md/__init__.py +++ b/term_color_md/__init__.py @@ -6,19 +6,48 @@ import re from termcolor import colored +from pygments import highlight +from pygments.lexers import get_lexer_by_name, TextLexer +from pygments.formatters import Terminal256Formatter def render(text): lines = text.splitlines() formatted_text = "" in_code_block = False + # Track code block state + code_block_lang = None + code_block_lines: list[str] = [] for line in lines: - # Check for code blocks - if line.startswith("```"): - in_code_block = not in_code_block - continue # Skip the line with ``` - elif in_code_block: - formatted_text += colored(line + "\n", "green") + # Check for code blocks (opening/closing) + if line.lstrip().startswith("```"): + # Opening or closing + if not in_code_block: # opening + formatted_text += colored(line.strip(), "light_grey") + "\n" + # Extract optional language + match = re.match(r"^\s*```\s*(\w+)?", line) + if match: + code_block_lang = match.group(1) + else: + code_block_lang = None + in_code_block = True + code_block_lines = [] + continue # Skip fence line + else: # closing + # Highlight accumulated code + code_source = "\n".join(code_block_lines) + if code_source: + lexer = get_lexer_by_name(code_block_lang, stripall=True) if code_block_lang else TextLexer() + highlighted = highlight(code_source, lexer, Terminal256Formatter()) + formatted_text += highlighted + formatted_text += colored(line.strip(), "light_grey") + "\n" + in_code_block = False + code_block_lang = None + code_block_lines = [] + continue + # Inside code block: accumulate lines + if in_code_block: + code_block_lines.append(line) continue # Check for headers @@ -70,3 +99,4 @@ def render(text): formatted_text += line + "\n" return formatted_text + diff --git a/term_color_md/__pycache__/__init__.cpython-311.pyc b/term_color_md/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..670c63466e44bc3c517f66f3da62cb35ffeded31 GIT binary patch literal 4429 zcmcgvUrZZE8lSb-|5zJCFu@Qo1{1(0g(gR%HsoK^q{@+CNa0N50LCyIW3skkcil9; zwd99BxDitQmIUP#x2p2zl83yUlvX{JoKCvDoU|Kll9IMLw`!Mk(o=8WHdpmwlVrs{xohv%C0e*O~jK?X5TyeKTNTS zD9_XEEV1D&{;{I35q+O6o3Q5sD5A=X=_YErTWQV`kjNUKA!~#nOU6LfBoN0z!7%y9 ztXVJ@pSNEbqqk5jN37D11!%m9#@?-rXRioGuAjGTD$SE+8IpqeCbDw3Vkv78EbLCf zQbb5zOwgpaoh6e7>^(GRjTphwG_(}WFOCC1*gDcGSlJH*lC9;PoB9H>bkC~yDCywQ zPAMmS1hO{1uH1v>unIQ5ezUIEy@^)nE?y-qWvc{(P?d22pkITfhk_B|Hx;R}=JUTO zTDsU0VCe_6R+Z>IuM2H@UG{CHX@6d$EbINuQi6fsRqjKmC|Ct4Xpb50IrJEyC4-&k7?%2UEKoUjupaLG44}QO zKOyFAv>TxNHMARH(`#t&g3Yg?-2y!?(?-b6Tae!q4CpRs4XWV7jB$E;I#V+>!3B_j z%I=AaJ^mv# z#_02TGo%ldDmi;8np`IitL95I!=x^*6GFyl6TBJUxv7ajWU_lAFcA<3amT=7K2%LHHkDpL zfQST#=kcx&^v$IbbYDE0jP)(B^L^<0qx;aUmxyS0Xe0r*)FP31GR{XLy$hGttp}NC zVg^PJXWT4}!_|9`NzFzX?l2NcJ!5DVt^*Z0@OO(ia^~sC_~VgrY2>Uta#oy~6QgnQ z!JUz{ztP9`^3?(bl{wP;9MD~ zeX1KB%X4o9CjAqf?o{AMiFPW2NO(1TkkFIoR&3CS5s!j9WRS&gQ+5X`)(P*MfSf=> zxmHxz;_%5(=UfMS#?;8?FMx}kD8|eHsY8AJ@#Cgn>oN8t?N=0pa zl;ydLaehuUu(WDIuj$!2){V@nv zTzbY|t&%)?u&buhWYy<4Ug@NYJU?{s`B@NhNwbE5y_RNs#;8^c)BFp_~;BnN7&Rw4pXjImo$!0%_V|l z521ea6a}0I5poVF_L?t-FAq!h7TMmCJE7D!%42g zcO$+W7rWn;JnzY#_X?C!=fUImDQBj|=EWz?Z{1EkBE{w*sd-3l9zw#C^C{{4qI`a_ zaN-~BJ-1IisDE;FOgb8pkA|f7ak+iGa7uBt7cWSzy@jCS-HqmJ?<_bglde+8L4&Pc zu{S@p`yShU#p9CQFWdd1-LKeP$R`xABbSd{?UyL8Od*`4t$wx1b0e@ExVGo|p8P4r z-t>o9@xuN6E1i#e#P>s@XI%1(%bsyDJSBOiB>Pl8_=DYrBZ%$1BT;QK)%LS?R@|az zQ1T4Qp20_BlIM(MKclm;U!vM&s{M^@Y$E!NM77FPD~d0I-`H}aX}RfI^Y!NZUU_&V%CNd7POA$+;*y7xUzg&RX1Y zOgx^(`Qq;-ryx6pN=L8w_Bos`aISWY7w?JV9YUAfvJMemtJ3Z@zQF#7?T6F-nR0TpXT tf*{ta0a2B+;g14ZM159(N7QEpyeqyeE1+N0=QT1!5KU{~<)s#c{{s7H>remy literal 0 HcmV?d00001