Skip to content

Commit ee0d7df

Browse files
lzwjavaclaude
andcommitted
feat: add syntax highlighting to /read command
Uses pygments with monokai style to highlight code by file extension, with dimmed line numbers matching Claude Code's display style. Falls back to plain text if pygments is unavailable. Also adds @filepath shortcut in the REPL as an alias for /read. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1723b6c commit ee0d7df

2 files changed

Lines changed: 27 additions & 5 deletions

File tree

iclaw/commands/read.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@ def _is_binary(data):
66
return b"\x00" in data
77

88

9+
def _highlighted_lines(text, path):
10+
try:
11+
from pygments import highlight
12+
from pygments.formatters import Terminal256Formatter
13+
from pygments.lexers import TextLexer, get_lexer_for_filename
14+
from pygments.util import ClassNotFound
15+
except ImportError:
16+
return text.splitlines()
17+
try:
18+
lexer = get_lexer_for_filename(path, stripnl=False)
19+
except ClassNotFound:
20+
lexer = TextLexer(stripnl=False)
21+
formatter = Terminal256Formatter(style="monokai")
22+
highlighted = highlight(text, lexer, formatter)
23+
return highlighted.splitlines()
24+
25+
926
def handle_read_command(arg):
1027
if not arg:
1128
print("Usage: /read <path>", file=sys.stderr)
@@ -38,9 +55,11 @@ def handle_read_command(arg):
3855
except UnicodeDecodeError:
3956
text = raw.decode("utf-8", errors="replace")
4057

41-
lines = text.splitlines()
42-
print(f"\n{path}{len(lines)} lines")
43-
width = len(str(len(lines))) if lines else 1
44-
for i, line in enumerate(lines, 1):
45-
print(f"{i:>{width}} {line}")
58+
plain_lines = text.splitlines()
59+
highlighted_lines = _highlighted_lines(text, path)
60+
line_count = len(plain_lines)
61+
print(f"\n{path}{line_count} lines")
62+
width = len(str(line_count)) if line_count else 1
63+
for i, line in enumerate(highlighted_lines, 1):
64+
print(f"\033[2m{i:>{width}}\033[0m {line}")
4665
print()

iclaw/main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ def main():
138138
arg = parts[1] if len(parts) > 1 else None
139139
handle_read_command(arg)
140140
continue
141+
if user_input.startswith("@") and not any(c.isspace() for c in user_input):
142+
handle_read_command(user_input)
143+
continue
141144
if user_input == "/provider_model":
142145
p, t = handle_model_provider_command(CONFIG_PATH, model_provider)
143146
if t:

0 commit comments

Comments
 (0)