streamdown 0.35.0__py3-none-any.whl → 0.35.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
streamdown/sd.py CHANGED
@@ -117,6 +117,7 @@ visible = lambda x: re.sub(ANSIESCAPE, "", x)
117
117
  # many characters have different widths
118
118
  visible_length = lambda x: sum(wcwidth(c) for c in visible(x))
119
119
  extract_ansi_codes = lambda text: re.findall(ESCAPE, text)
120
+ strip_ansi = lambda line: re.sub(ANSIESCAPE, '', line)
120
121
  remove_ansi = lambda line, codeList: reduce(lambda line, code: line.replace(code, ''), codeList, line)
121
122
  split_up = lambda line: re.findall(r'(\x1b[^m]*m|[^\x1b]*)', line)
122
123
 
@@ -129,7 +130,10 @@ def gettmpdir():
129
130
  else:
130
131
  tmp_dir = tmp_dir_all
131
132
 
133
+ prev_mask = os.umask(0)
134
+ # This is shared among all users
132
135
  os.makedirs(tmp_dir, exist_ok=True)
136
+ os.umask(prev_mask)
133
137
  return tmp_dir
134
138
 
135
139
  def debug_write(text):
@@ -138,6 +142,10 @@ def debug_write(text):
138
142
  state.Logging = tempfile.NamedTemporaryFile(dir=gettmpdir(), prefix="dbg", delete=False, mode="wb")
139
143
  state.Logging.write(text)
140
144
 
145
+ def sub_extract(line, upto):
146
+ # this takes the line up to the upto string and then returns the ansi codes
147
+ return ''.join(extract_ansi_codes(line[:line.find(upto)]))
148
+
141
149
  def savebrace():
142
150
  if state.Savebrace and state.code_buffer_raw and os.name != 'nt':
143
151
  path = os.path.join(gettmpdir(), 'savebrace')
@@ -446,7 +454,7 @@ def text_wrap(text, width = -1, indent = 0, first_line_prefix="", subsequent_lin
446
454
  # that we have closed our hyperlink OSC
447
455
  if LINK[0] in line_content:
448
456
  line_content += LINK[1]
449
- lines.append(line_content + resetter + state.bg + ' ' * margin)
457
+ lines.append(line_content + resetter + sub_extract(line_content, LINK[0]) + state.bg + ' ' * margin)
450
458
 
451
459
  current_line = (" " * indent) + "".join(current_style) + word
452
460
 
@@ -496,6 +504,9 @@ def line_format(line):
496
504
 
497
505
  # Apply OSC 8 hyperlink formatting after other formatting
498
506
  def process_links(match):
507
+ #import pdb
508
+ #pdb.set_trace()
509
+ print(match)
499
510
  description = match.group(1)
500
511
  url = match.group(2)
501
512
  return f'{LINK[0]}{url}\033\\{Style.Link}{description}{UNDERLINE[1]}{LINK[1]}{FGRESET}'
@@ -1026,6 +1037,11 @@ def parse(stream):
1026
1037
  for wrapped_line in wrapped_lines:
1027
1038
  yield f"{state.space_left()}{wrapped_line}\n"
1028
1039
 
1040
+ def terminal_prep(what):
1041
+ if Style.Plaintext:
1042
+ return strip_ansi(what)
1043
+ return what
1044
+
1029
1045
  def emit(inp):
1030
1046
  buffer = []
1031
1047
  flush = False
@@ -1065,10 +1081,10 @@ def emit(inp):
1065
1081
  else:
1066
1082
  chunk = buffer.pop(0)
1067
1083
 
1068
- print(chunk, end="", file=sys.stdout, flush=True)
1084
+ print(terminal_prep(chunk), end="", file=sys.stdout, flush=True)
1069
1085
 
1070
1086
  if len(buffer):
1071
- print(buffer.pop(0), file=sys.stdout, end="", flush=True)
1087
+ print(terminal_prep(buffer.pop(0)), file=sys.stdout, end="", flush=True)
1072
1088
 
1073
1089
  def ansi2hex(ansi_code):
1074
1090
  parts = ansi_code.strip('m').split(";")
@@ -1127,6 +1143,7 @@ def main():
1127
1143
  parser.add_argument("-p", "--prompt", default="^.*>\\s+$", help="A PCRE regex prompt to detect (default: %(default)s)")
1128
1144
  parser.add_argument("-s", "--scrape", help="Scrape code snippets to a directory SCRAPE")
1129
1145
  parser.add_argument("-v", "--version", action="store_true", help="Show version information")
1146
+ parser.add_argument("--strip", action="store_true", help="Just strip the markdown and output plaintext")
1130
1147
  args = parser.parse_args()
1131
1148
 
1132
1149
  if args.version:
@@ -1156,7 +1173,7 @@ def main():
1156
1173
 
1157
1174
  for color in ["Dark", "Mid", "Symbol", "Head", "Grey", "Bright"]:
1158
1175
  setattr(Style, color, apply_multipliers(style, color, H, S, V))
1159
- for attr in ['PrettyPad', 'PrettyBroken', 'Margin', 'ListIndent', 'Syntax']:
1176
+ for attr in ['PrettyPad', 'PrettyBroken', 'Margin', 'ListIndent', 'Syntax', 'Plaintext']:
1160
1177
  setattr(Style, attr, style.get(attr))
1161
1178
  for attr in ['Links', 'Images', 'CodeSpaces', 'Clipboard', 'Logging', 'Timeout', 'Savebrace']:
1162
1179
  setattr(state, attr, features.get(attr))
@@ -1166,6 +1183,7 @@ def main():
1166
1183
  os.makedirs(args.scrape, exist_ok=True)
1167
1184
  state.scrape = args.scrape
1168
1185
 
1186
+ Style.Plaintext = args.strip
1169
1187
  Style.MarginSpaces = " " * Style.Margin
1170
1188
  state.WidthArg = int(args.width) or style.get("Width") or 0
1171
1189
  state.prompt_regex = re.compile(args.prompt)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamdown
3
- Version: 0.35.0
3
+ Version: 0.35.1
4
4
  Summary: A streaming markdown renderer for modern terminals with syntax highlighting
5
5
  Project-URL: Homepage, https://github.com/day50-dev/Streamdown
6
6
  Project-URL: Bug Tracker, https://github.com/day50-dev/Streamdown/issues
@@ -156,6 +156,8 @@ $ sd --exec "llm chat"
156
156
 
157
157
  And now you have all your readline stuff. It's pretty great. (Also see the DAY50 shellwrap project.)
158
158
 
159
+ This relies on "guessing" what a prompt will look like. But don't worry, you can change that with the `--prompt` option if yours is a bit unique. It's a PCRE regex, so you can be a bit flexible.
160
+
159
161
  It's also worth noting that things like the `-c` aren't "broken" with regard to file input. You can do something like this:
160
162
 
161
163
  ```shell
@@ -188,6 +190,8 @@ optional arguments:
188
190
  -w WIDTH, --width WIDTH
189
191
  Set the width WIDTH
190
192
  -e EXEC, --exec EXEC Wrap a program EXEC for more 'proper' i/o handling
193
+ -p PROMPT, --prompt PROMPT
194
+ A PCRE regex prompt to detect (default: ^.*>\s+$)
191
195
  -s SCRAPE, --scrape SCRAPE
192
196
  Scrape code snippets to a directory SCRAPE
193
197
  -v, --version Show version information
@@ -1,13 +1,13 @@
1
1
  streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  streamdown/qwen3.md,sha256=1e7ELkK-quwUeOmBDwXodFH-DlnfAcQWj32rjK6Zex4,542
3
- streamdown/sd.py,sha256=38nDZjHXQKorpUesXlTa0LkeR-gP6DPEw9h6exTthJo,45901
3
+ streamdown/sd.py,sha256=4huBv890pt3QOcwUnhUkRSHOus_E-8QSEBf2D2LAJdQ,46604
4
4
  streamdown/ss,sha256=sel_phpaecrw6WGIHRLROsD7BFShf0rSDHheflwdUn8,277
5
5
  streamdown/ss1,sha256=CUVf86_2zeAle2oQCeTfWYqtHBrAFR_UgvptuYMQzFU,3151
6
6
  streamdown/test.txt,sha256=j0NDRmSPa5bfid2pAcUXaxCm2Dlh3TwayItZstwyeqQ,2
7
7
  streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
8
8
  streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
9
- streamdown-0.35.0.dist-info/METADATA,sha256=LnPBbC-QwFbxttWL3Kf46lwCYEpt8RPCZsLm5IHo47Y,10195
10
- streamdown-0.35.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
11
- streamdown-0.35.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
12
- streamdown-0.35.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
13
- streamdown-0.35.0.dist-info/RECORD,,
9
+ streamdown-0.35.1.dist-info/METADATA,sha256=n9vnRuHZpIYmiHtqJ-2nWFWD93UCJQjo7Z0EOhaIES4,10494
10
+ streamdown-0.35.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
11
+ streamdown-0.35.1.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
12
+ streamdown-0.35.1.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
13
+ streamdown-0.35.1.dist-info/RECORD,,