Skip to content

Commit

Permalink
Raw nREPL: Support colored output in output console #99
Browse files Browse the repository at this point in the history
  • Loading branch information
tonsky committed Mar 12, 2024
1 parent 16ff584 commit 2521da9
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 10 deletions.
115 changes: 115 additions & 0 deletions cs_colors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import re, sublime

RE_REPLACE_GLOB = re.compile(r"\*\*|[\*\?\.\(\)\[\]\{\}\$\^\+\|]")

region_id = 0

# Colors
FG_ANSI = {
30: 'black',
31: 'red',
32: 'green',
33: 'brown',
34: 'blue',
35: 'magenta',
36: 'cyan',
37: 'white',
39: 'default',
90: 'light_black',
91: 'light_red',
92: 'light_green',
93: 'light_brown',
94: 'light_blue',
95: 'light_magenta',
96: 'light_cyan',
97: 'light_white'
}

BG_ANSI = {
40: 'black',
41: 'red',
42: 'green',
43: 'brown',
44: 'blue',
45: 'magenta',
46: 'cyan',
47: 'white',
49: 'default',
100: 'light_black',
101: 'light_red',
102: 'light_green',
103: 'light_brown',
104: 'light_blue',
105: 'light_magenta',
106: 'light_cyan',
107: 'light_white'
}

SCOPES = {
'red': 'redish',
'green': 'greenish',
'brown': 'orangish',
'blue': 'bluish',
'magenta': 'pinkish', # purplish
'cyan': 'cyanish',
'light_red': 'redish',
'light_green': 'greenish',
'light_brown': 'orangish',
'light_blue': 'bluish',
'light_magenta': 'pinkish',
'light_cyan': 'cyanish'
}

RE_UNKNOWN_ESCAPES = re.compile(r"\x1b[^a-zA-Z]*[a-zA-Z]")
RE_COLOR_ESCAPES = re.compile(r"\x1b\[((?:;?\d+)*)m")
RE_NOTSPACE = re.compile(r"[^\s]+")

def write(view, characters):
decolorized = ""
original_pos = 0
decolorized_pos = 0
fg = "default"
bg = "default"
regions = []
def iteration(start, end, group):
nonlocal decolorized, original_pos, decolorized_pos, fg, bg, regions
text = characters[original_pos:start]
text = RE_UNKNOWN_ESCAPES.sub("", text)
decolorized += text
if len(text) > 0 and (fg != "default" or bg != "default"):
regions.append({"text": text,
"start": decolorized_pos,
"end": decolorized_pos + len(text),
"fg": fg,
"bg": bg})
digits = re.findall(r"\d+", group) or ["0"]
for digit in digits:
digit = int(digit)
if digit in FG_ANSI:
fg = FG_ANSI[digit]
if digit in BG_ANSI:
bg = BG_ANSI[digit]
if digit == 0:
fg = 'default'
bg = 'default'
original_pos = end
decolorized_pos += len(text)

for m in RE_COLOR_ESCAPES.finditer(characters):
iteration(m.start(), m.end(), m.group(1))
iteration(len(characters), len(characters), "")

insertion_point = view.size()
view.run_command('append', {'characters': decolorized, 'force': True, 'scroll_to_end': True})

global region_id
for region in regions:
if scope := SCOPES.get(region['bg'], None) or SCOPES.get(region['fg'], None):
for m in RE_NOTSPACE.finditer(region['text']):
start = insertion_point + region['start'] + m.start()
end = start + len(m.group(0))
region_id += 1
view.add_regions(
"executor#{}".format(region_id),
[sublime.Region(start, end)],
'region.' + scope)
14 changes: 5 additions & 9 deletions cs_conn_nrepl_raw.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os, sublime, sublime_plugin, threading
from . import cs_bencode, cs_common, cs_conn, cs_eval
from . import cs_bencode, cs_colors, cs_common, cs_conn, cs_eval

class ConnectionNreplRaw(cs_conn.Connection):
"""
Expand Down Expand Up @@ -132,20 +132,16 @@ def get_output_view(self):
self.output_view = window.create_output_panel('repl')
return self.output_view

def output(self, text):
output_view = self.get_output_view()
self.window.run_command("show_panel", {"panel": "output.repl"})
output_view.run_command('append', {'characters': text, 'force': True, 'scroll_to_end': True})

def handle_out(self, msg):
if 'out' in msg:
self.output(str(self))
self.output(msg['out'])
self.window.run_command("show_panel", {"panel": "output.repl"})
cs_colors.write(self.get_output_view(), msg['out'])
return True

def handle_err(self, msg):
if 'err' in msg:
self.output(msg['err'])
self.window.run_command("show_panel", {"panel": "output.repl"})
cs_colors.write(self.get_output_view(), msg['err'])
return True

def handle_done(self, msg):
Expand Down
2 changes: 1 addition & 1 deletion script/nrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
if __name__ == '__main__':
os.chdir(os.path.dirname(__file__) + "/..")
subprocess.check_call(['clojure',
'-Sdeps', '{:deps {nrepl/nrepl {:mvn/version "1.0.0"}}}',
'-Sdeps', '{:deps {nrepl/nrepl {:mvn/version "1.0.0"}, mvxcvi/puget {:mvn/version "1.3.4"}}}',
'-M', '-m', 'nrepl.cmdline',
'--interactive'
])
13 changes: 13 additions & 0 deletions test_repl/colors.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(require ' [puget.printer :as puget])

(puget/cprint [nil
true
\space
"string"
{:omega 123N
:alpha '(func x y)
:gamma 3.14159}
#{\a "heterogeneous" :set}
(java.util.Currency/getInstance "USD")
(java.util.Date.)
(java.util.UUID/randomUUID)])

0 comments on commit 2521da9

Please sign in to comment.