streamdown 0.20.0__tar.gz → 0.22.0__tar.gz

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.
Files changed (73) hide show
  1. {streamdown-0.20.0 → streamdown-0.22.0}/PKG-INFO +30 -11
  2. {streamdown-0.20.0 → streamdown-0.22.0}/README.md +29 -10
  3. {streamdown-0.20.0 → streamdown-0.22.0}/pyproject.toml +1 -1
  4. {streamdown-0.20.0 → streamdown-0.22.0}/streamdown/sd.py +51 -38
  5. streamdown-0.22.0/tests/slash.md +11 -0
  6. streamdown-0.20.0/.aider.chat.history.md +0 -1379
  7. streamdown-0.20.0/.aider.input.history +0 -69
  8. streamdown-0.20.0/.aider.tags.cache.v4/cache.db +0 -0
  9. streamdown-0.20.0/.vimrc +0 -1
  10. streamdown-0.20.0/24-bit-color.sh +0 -99
  11. streamdown-0.20.0/assets/logo.png +0 -0
  12. streamdown-0.20.0/assets/logo.svg +0 -116
  13. streamdown-0.20.0/configurable.png +0 -0
  14. streamdown-0.20.0/copyable.png +0 -0
  15. streamdown-0.20.0/dunder.png +0 -0
  16. streamdown-0.20.0/error.txt +0 -0
  17. streamdown-0.20.0/fucking-garbage.md +0 -19
  18. streamdown-0.20.0/newdir/file_0.py +0 -22
  19. streamdown-0.20.0/newdir/file_1.rb +0 -43
  20. streamdown-0.20.0/newdir/file_2.jl +0 -23
  21. streamdown-0.20.0/passthrough.py +0 -60
  22. streamdown-0.20.0/python-go.png +0 -0
  23. streamdown-0.20.0/somelog.txt +0 -401
  24. streamdown-0.20.0/ss-new.py +0 -45
  25. streamdown-0.20.0/ss.py +0 -73
  26. streamdown-0.20.0/streamdown/ss +0 -1
  27. streamdown-0.20.0/streamdown/ss1 +0 -42
  28. streamdown-0.20.0/table.png +0 -0
  29. streamdown-0.20.0/temp.py +0 -75
  30. streamdown-0.20.0/test.py +0 -13
  31. streamdown-0.20.0/test_input.md +0 -8
  32. streamdown-0.20.0/tester.py +0 -29
  33. streamdown-0.20.0/tests/bg-messed-up.md +0 -8
  34. streamdown-0.20.0/tests/chinese.md +0 -4
  35. streamdown-0.20.0/tests/cjj.mv +0 -4
  36. {streamdown-0.20.0 → streamdown-0.22.0}/.gitignore +0 -0
  37. {streamdown-0.20.0 → streamdown-0.22.0}/LICENSE.MIT +0 -0
  38. {streamdown-0.20.0 → streamdown-0.22.0}/requirements.txt +0 -0
  39. {streamdown-0.20.0 → streamdown-0.22.0}/streamdown/__init__.py +0 -0
  40. {streamdown-0.20.0 → streamdown-0.22.0}/streamdown/plugins/README.md +0 -0
  41. {streamdown-0.20.0 → streamdown-0.22.0}/streamdown/plugins/latex.py +0 -0
  42. {streamdown-0.20.0 → streamdown-0.22.0}/tests/README.md +0 -0
  43. {streamdown-0.20.0 → streamdown-0.22.0}/tests/backtick-with-post-spaces.md +0 -0
  44. {streamdown-0.20.0 → streamdown-0.22.0}/tests/block.md +0 -0
  45. {streamdown-0.20.0 → streamdown-0.22.0}/tests/bold_reset_with_link.md +0 -0
  46. {streamdown-0.20.0 → streamdown-0.22.0}/tests/broken-code.md +0 -0
  47. {streamdown-0.20.0 → streamdown-0.22.0}/tests/broken-example.md +0 -0
  48. {streamdown-0.20.0 → streamdown-0.22.0}/tests/chunk-buffer.sh +0 -0
  49. {streamdown-0.20.0 → streamdown-0.22.0}/tests/cjk-table.md +0 -0
  50. {streamdown-0.20.0 → streamdown-0.22.0}/tests/cjk-wrap.md +0 -0
  51. {streamdown-0.20.0 → streamdown-0.22.0}/tests/code.md +0 -0
  52. {streamdown-0.20.0 → streamdown-0.22.0}/tests/example.md +0 -0
  53. {streamdown-0.20.0 → streamdown-0.22.0}/tests/fizzbuzz.md +0 -0
  54. {streamdown-0.20.0 → streamdown-0.22.0}/tests/inline.md +0 -0
  55. {streamdown-0.20.0 → streamdown-0.22.0}/tests/jimmy_webb.md +0 -0
  56. {streamdown-0.20.0 → streamdown-0.22.0}/tests/line-buffer.sh +0 -0
  57. {streamdown-0.20.0 → streamdown-0.22.0}/tests/line-wrap.md +0 -0
  58. {streamdown-0.20.0 → streamdown-0.22.0}/tests/links.md +0 -0
  59. {streamdown-0.20.0 → streamdown-0.22.0}/tests/managerie.md +0 -0
  60. {streamdown-0.20.0 → streamdown-0.22.0}/tests/mandlebrot.md +0 -0
  61. {streamdown-0.20.0 → streamdown-0.22.0}/tests/markdown.md +0 -0
  62. {streamdown-0.20.0 → streamdown-0.22.0}/tests/nested-example.md +0 -0
  63. {streamdown-0.20.0 → streamdown-0.22.0}/tests/outline.md +0 -0
  64. {streamdown-0.20.0 → streamdown-0.22.0}/tests/pvgo_512.jpg +0 -0
  65. {streamdown-0.20.0 → streamdown-0.22.0}/tests/pythonvgo.md +0 -0
  66. {streamdown-0.20.0 → streamdown-0.22.0}/tests/qwen3.md +0 -0
  67. {streamdown-0.20.0 → streamdown-0.22.0}/tests/rerun.zsh +0 -0
  68. {streamdown-0.20.0 → streamdown-0.22.0}/tests/strip-chunks.sh +0 -0
  69. {streamdown-0.20.0 → streamdown-0.22.0}/tests/table-break.md +0 -0
  70. {streamdown-0.20.0 → streamdown-0.22.0}/tests/table_test.md +0 -0
  71. {streamdown-0.20.0 → streamdown-0.22.0}/tests/test.md +0 -0
  72. {streamdown-0.20.0 → streamdown-0.22.0}/tests/test_input.md +0 -0
  73. {streamdown-0.20.0 → streamdown-0.22.0}/tests/wm.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamdown
3
- Version: 0.20.0
3
+ Version: 0.22.0
4
4
  Summary: A streaming markdown renderer for modern terminals with syntax highlighting
5
5
  Project-URL: Homepage, https://github.com/kristopolous/Streamdown
6
6
  Project-URL: Bug Tracker, https://github.com/kristopolous/Streamdown/issues
@@ -38,6 +38,10 @@ Description-Content-Type: text/markdown
38
38
 
39
39
  Streamdown works with any streaming markdown such as [simonw's llm](https://github.com/simonw/llm) or even something basic like curl.
40
40
 
41
+ It is designed for AI and can be used to do parser based sophisticated pipelines and routing, cracking open various monolithic AI solutions to permit them to integrate. Think of it as output level routing at the semantic level.
42
+
43
+ You can also just use it like a normal person.
44
+
41
45
  It supports standard piping and files as arguments like any normal pager but can also run as a wrapper so you retain full keyboard interactivity. Arrow keys, control, alt, all still work.
42
46
  ```bash
43
47
  $ pip install streamdown
@@ -59,7 +63,7 @@ The optional `Clipboard` feature puts the final codeblock into your clipboard. S
59
63
  [links.webm](https://github.com/user-attachments/assets/a5f71791-7c58-4183-ad3b-309f470c08a3)
60
64
 
61
65
  ### As well as everything else...
62
- Here's the `Savebrace` feature with `screen-query` and `sd-picker` from [llmehelp](https://github.com/kristopolous/llmehelp). You can have an ongoing conversation in tmux with your terminal session. Then use popups and fzf to insert command or coding blocks all with a keystroke.
66
+ Here's the `Savebrace` feature with `screen-query` and `sq-picker` from [llmehelp](https://github.com/kristopolous/llmehelp). You can have an ongoing conversation in tmux with your terminal session. Then use popups and fzf to insert command or coding blocks all with a keystroke.
63
67
 
64
68
  This allows you to interactively debug in a way that the agent doesn't just wander off doing silly things.
65
69
 
@@ -135,26 +139,41 @@ Clipboard = false
135
139
  ## Command Line
136
140
  The most exciting feature here is `--exec` with it you can do full readline support like this:
137
141
 
138
- $ sd --exec "llm chat"
142
+ ```shell
143
+ $ sd --exec "llm chat"
144
+ ```
145
+
146
+ And now you have all your readline stuff. It's pretty great. (Also see the Day50 shellwrap project.)
139
147
 
140
- And now you have all your readline stuff. It's pretty great.
148
+ It's also worth noting that things like the `-c` aren't "broken" with regard to file input. You can do something like this:
141
149
 
142
150
  ```shell
143
- Streamdown - A markdown renderer for modern terminals
151
+ $ sd -c <(echo "[style]\nMargin=10")
152
+ ```
153
+
154
+ To override the margin.
155
+
156
+ ```shell
157
+ usage: sd [-h] [-l LOGLEVEL] [-b BASE] [-c CONFIG] [-w WIDTH] [-e EXEC]
158
+ [-s SCRAPE] [filenameList ...]
159
+
160
+ Streamdown - A Streaming markdown renderer for modern terminals
144
161
 
145
162
  positional arguments:
146
163
  filenameList Input file to process (also takes stdin)
147
164
 
148
- options:
165
+ optional arguments:
149
166
  -h, --help show this help message and exit
150
167
  -l LOGLEVEL, --loglevel LOGLEVEL
151
168
  Set the logging level
152
- -c COLOR, --color COLOR
153
- Set the hsv base: h,s,v
169
+ -b BASE, --base BASE Set the hsv base: h,s,v
170
+ -c CONFIG, --config CONFIG
171
+ Use a custom config
154
172
  -w WIDTH, --width WIDTH
155
- Set the width
156
- -e EXEC, --exec EXEC Wrap a program for more 'proper' i/o handling
157
-
173
+ Set the width WIDTH
174
+ -e EXEC, --exec EXEC Wrap a program EXEC for more 'proper' i/o handling
175
+ -s SCRAPE, --scrape SCRAPE
176
+ Scrape code snippets to a directory SCRAPE
158
177
  ```
159
178
 
160
179
  ## Demo
@@ -9,6 +9,10 @@
9
9
 
10
10
  Streamdown works with any streaming markdown such as [simonw's llm](https://github.com/simonw/llm) or even something basic like curl.
11
11
 
12
+ It is designed for AI and can be used to do parser based sophisticated pipelines and routing, cracking open various monolithic AI solutions to permit them to integrate. Think of it as output level routing at the semantic level.
13
+
14
+ You can also just use it like a normal person.
15
+
12
16
  It supports standard piping and files as arguments like any normal pager but can also run as a wrapper so you retain full keyboard interactivity. Arrow keys, control, alt, all still work.
13
17
  ```bash
14
18
  $ pip install streamdown
@@ -30,7 +34,7 @@ The optional `Clipboard` feature puts the final codeblock into your clipboard. S
30
34
  [links.webm](https://github.com/user-attachments/assets/a5f71791-7c58-4183-ad3b-309f470c08a3)
31
35
 
32
36
  ### As well as everything else...
33
- Here's the `Savebrace` feature with `screen-query` and `sd-picker` from [llmehelp](https://github.com/kristopolous/llmehelp). You can have an ongoing conversation in tmux with your terminal session. Then use popups and fzf to insert command or coding blocks all with a keystroke.
37
+ Here's the `Savebrace` feature with `screen-query` and `sq-picker` from [llmehelp](https://github.com/kristopolous/llmehelp). You can have an ongoing conversation in tmux with your terminal session. Then use popups and fzf to insert command or coding blocks all with a keystroke.
34
38
 
35
39
  This allows you to interactively debug in a way that the agent doesn't just wander off doing silly things.
36
40
 
@@ -106,26 +110,41 @@ Clipboard = false
106
110
  ## Command Line
107
111
  The most exciting feature here is `--exec` with it you can do full readline support like this:
108
112
 
109
- $ sd --exec "llm chat"
113
+ ```shell
114
+ $ sd --exec "llm chat"
115
+ ```
116
+
117
+ And now you have all your readline stuff. It's pretty great. (Also see the Day50 shellwrap project.)
110
118
 
111
- And now you have all your readline stuff. It's pretty great.
119
+ It's also worth noting that things like the `-c` aren't "broken" with regard to file input. You can do something like this:
112
120
 
113
121
  ```shell
114
- Streamdown - A markdown renderer for modern terminals
122
+ $ sd -c <(echo "[style]\nMargin=10")
123
+ ```
124
+
125
+ To override the margin.
126
+
127
+ ```shell
128
+ usage: sd [-h] [-l LOGLEVEL] [-b BASE] [-c CONFIG] [-w WIDTH] [-e EXEC]
129
+ [-s SCRAPE] [filenameList ...]
130
+
131
+ Streamdown - A Streaming markdown renderer for modern terminals
115
132
 
116
133
  positional arguments:
117
134
  filenameList Input file to process (also takes stdin)
118
135
 
119
- options:
136
+ optional arguments:
120
137
  -h, --help show this help message and exit
121
138
  -l LOGLEVEL, --loglevel LOGLEVEL
122
139
  Set the logging level
123
- -c COLOR, --color COLOR
124
- Set the hsv base: h,s,v
140
+ -b BASE, --base BASE Set the hsv base: h,s,v
141
+ -c CONFIG, --config CONFIG
142
+ Use a custom config
125
143
  -w WIDTH, --width WIDTH
126
- Set the width
127
- -e EXEC, --exec EXEC Wrap a program for more 'proper' i/o handling
128
-
144
+ Set the width WIDTH
145
+ -e EXEC, --exec EXEC Wrap a program EXEC for more 'proper' i/o handling
146
+ -s SCRAPE, --scrape SCRAPE
147
+ Scrape code snippets to a directory SCRAPE
129
148
  ```
130
149
 
131
150
  ## Demo
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "streamdown"
7
- version = "0.20.0"
7
+ version = "0.22.0"
8
8
  description = "A streaming markdown renderer for modern terminals with syntax highlighting"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -55,7 +55,7 @@ Savebrace = true
55
55
  [style]
56
56
  Margin = 2
57
57
  ListIndent = 2
58
- PrettyPad = false
58
+ PrettyPad = true
59
59
  PrettyBroken = true
60
60
  Width = 0
61
61
  HSV = [0.8, 0.5, 0.5]
@@ -68,19 +68,18 @@ Bright = { H = 1.00, S = 2.00, V = 2.00 }
68
68
  Syntax = "dracula"
69
69
  """
70
70
 
71
- def ensure_config_file():
72
- config_dir = appdirs.user_config_dir("streamdown")
73
- os.makedirs(config_dir, exist_ok=True)
74
- config_path = os.path.join(config_dir, "config.toml")
75
- if not os.path.exists(config_path):
76
- open(config_path, 'w').write(default_toml)
71
+ def ensure_config_file(config):
72
+ if config:
73
+ config_path = config
74
+ else:
75
+ config_dir = appdirs.user_config_dir("streamdown")
76
+ os.makedirs(config_dir, exist_ok=True)
77
+ config_path = os.path.join(config_dir, "config.toml")
78
+ if not os.path.exists(config_path):
79
+ open(config_path, 'w').write(default_toml)
80
+
77
81
  return config_path, open(config_path).read()
78
82
 
79
- config_toml_path, config_toml_content = ensure_config_file()
80
- config = toml.loads(config_toml_content)
81
- _style = toml.loads(default_toml).get('style') | config.get("style", {})
82
- _features = toml.loads(default_toml).get('features') | config.get("features", {})
83
- H, S, V = _style.get("HSV")
84
83
 
85
84
  FG = "\033[38;2;"
86
85
  BG = "\033[48;2;"
@@ -124,7 +123,6 @@ class Goto(Exception):
124
123
  pass
125
124
 
126
125
  class Style:
127
- PrettyPad = _style.get("PrettyPad")
128
126
  pass
129
127
 
130
128
  class Code:
@@ -148,12 +146,6 @@ class ParseState:
148
146
  self.scrape_ix = 0
149
147
  self.terminal = None
150
148
 
151
- self.CodeSpaces = _features.get("CodeSpaces")
152
- self.Clipboard = _features.get("Clipboard")
153
- self.Logging = _features.get("Logging")
154
- self.Timeout = _features.get("Timeout")
155
- self.Savebrace = _features.get("Savebrace")
156
-
157
149
  self.WidthArg = None
158
150
  self.WidthFull = None
159
151
  self.WidthWrap = False
@@ -317,6 +309,10 @@ def code_wrap(text_in):
317
309
  for i in range(mywidth, len(text), mywidth):
318
310
  res.append(text[i : i + mywidth])
319
311
 
312
+ # sometimes just a newline wraps ... this isn't what we want actually
313
+ if res[-1].strip() == '':
314
+ res.pop()
315
+
320
316
  return (indent, res)
321
317
 
322
318
 
@@ -698,8 +694,13 @@ def parse(stream):
698
694
  state.code_first_line = True
699
695
  state.bg = f"{BG}{Style.Dark}"
700
696
  state.where_from = "code pad"
701
- if Style.PrettyPad:
697
+ if Style.PrettyPad or Style.PrettyBroken:
698
+ if not Style.PrettyPad:
699
+ yield ""
700
+
702
701
  yield Style.Codepad[0]
702
+ else:
703
+ yield ""
703
704
 
704
705
  logging.debug(f"In code: ({state.in_code})")
705
706
 
@@ -732,8 +733,13 @@ def parse(stream):
732
733
  state.bg = BGRESET
733
734
 
734
735
  state.where_from = "code pad"
735
- if Style.PrettyPad:
736
- yield Style.Codepad[1]
736
+ if Style.PrettyPad or Style.PrettyBroken:
737
+ yield Style.Codepad[1]
738
+ if not Style.PrettyPad:
739
+ yield ""
740
+
741
+ else:
742
+ yield RESET
737
743
 
738
744
  logging.debug(f"code: {state.in_code}")
739
745
  state.emit_flush = True
@@ -796,12 +802,10 @@ def parse(stream):
796
802
  if highlighted_code.endswith(FGRESET + "\n"):
797
803
  highlighted_code = highlighted_code[: -(1 + len(FGRESET))]
798
804
 
799
- #print(bytes(highlighted_code, 'utf-8'))
800
-
801
805
  # turns out highlight will eat leading newlines on empty lines
802
806
  vislen = visible_length(state.code_buffer.lstrip())
803
807
 
804
- delta = 0
808
+ delta = -2
805
809
  while visible_length(highlighted_code[:(state.code_gen-delta)]) > vislen:
806
810
  delta += 1
807
811
 
@@ -990,8 +994,8 @@ def ansi2hex(ansi_code):
990
994
  r, g, b = map(int, parts)
991
995
  return f"#{r:02x}{g:02x}{b:02x}"
992
996
 
993
- def apply_multipliers(name, H, S, V):
994
- m = _style.get(name)
997
+ def apply_multipliers(style, name, H, S, V):
998
+ m = style.get(name)
995
999
  r, g, b = colorsys.hsv_to_rgb(min(1.0, H * m["H"]), min(1.0, S * m["S"]), min(1.0, V * m["V"]))
996
1000
  return ';'.join([str(int(x * 256)) for x in [r, g, b]]) + "m"
997
1001
 
@@ -1012,40 +1016,49 @@ def width_calc():
1012
1016
 
1013
1017
  state.Width = state.WidthFull - 2 * Style.Margin
1014
1018
  pre = state.space_left(listwidth=True) if Style.PrettyBroken else ''
1019
+ design = [FG, '▄','▀'] if Style.PrettyPad else [BG, ' ',' ']
1015
1020
  Style.Codepad = [
1016
- f"{pre}{RESET}{FG}{Style.Dark}{'▄' * state.full_width()}{RESET}\n",
1017
- f"{pre}{RESET}{FG}{Style.Dark}{'▀' * state.full_width()}{RESET}"
1021
+ f"{pre}{RESET}{design[0]}{Style.Dark}{design[1] * state.full_width()}{RESET}\n",
1022
+ f"{pre}{RESET}{design[0]}{Style.Dark}{design[2] * state.full_width()}{RESET}"
1018
1023
  ]
1019
1024
 
1020
1025
  def main():
1021
- global H, S, V
1022
-
1023
1026
  parser = ArgumentParser(description="Streamdown - A Streaming markdown renderer for modern terminals")
1024
1027
  parser.add_argument("filenameList", nargs="*", help="Input file to process (also takes stdin)")
1025
1028
  parser.add_argument("-l", "--loglevel", default="INFO", help="Set the logging level")
1026
- parser.add_argument("-c", "--color", default=None, help="Set the hsv base: h,s,v")
1029
+ parser.add_argument("-b", "--base", default=None, help="Set the hsv base: h,s,v")
1030
+ parser.add_argument("-c", "--config", default=None, help="Use a custom config")
1027
1031
  parser.add_argument("-w", "--width", default="0", help="Set the width WIDTH")
1028
1032
  parser.add_argument("-e", "--exec", help="Wrap a program EXEC for more 'proper' i/o handling")
1029
1033
  parser.add_argument("-s", "--scrape", help="Scrape code snippets to a directory SCRAPE")
1030
1034
  args = parser.parse_args()
1031
1035
 
1032
- if args.color:
1033
- env_colors = args.color.split(",")
1036
+ config_toml_path, config_toml_content = ensure_config_file(args.config)
1037
+ config = toml.loads(config_toml_content)
1038
+ style = toml.loads(default_toml).get('style') | config.get("style", {})
1039
+ features = toml.loads(default_toml).get('features') | config.get("features", {})
1040
+ H, S, V = style.get("HSV")
1041
+
1042
+ if args.base:
1043
+ env_colors = args.base.split(",")
1034
1044
  if len(env_colors) > 0: H = float(env_colors[0])
1035
1045
  if len(env_colors) > 1: S = float(env_colors[1])
1036
1046
  if len(env_colors) > 2: V = float(env_colors[2])
1037
1047
 
1038
1048
  for color in ["Dark", "Mid", "Symbol", "Head", "Grey", "Bright"]:
1039
- setattr(Style, color, apply_multipliers(color, H, S, V))
1040
- for attr in ['PrettyBroken', 'Margin', 'ListIndent', 'Syntax']:
1041
- setattr(Style, attr, _style.get(attr))
1049
+ setattr(Style, color, apply_multipliers(style, color, H, S, V))
1050
+ for attr in ['PrettyPad', 'PrettyBroken', 'Margin', 'ListIndent', 'Syntax']:
1051
+ setattr(Style, attr, style.get(attr))
1052
+ for attr in ['CodeSpaces', 'Clipboard', 'Logging', 'Timeout', 'Savebrace']:
1053
+ setattr(state, attr, features.get(attr))
1054
+
1042
1055
 
1043
1056
  if args.scrape:
1044
1057
  os.makedirs(args.scrape, exist_ok=True)
1045
1058
  state.scrape = args.scrape
1046
1059
 
1047
1060
  Style.MarginSpaces = " " * Style.Margin
1048
- state.WidthArg = int(args.width) or _style.get("Width") or 0
1061
+ state.WidthArg = int(args.width) or style.get("Width") or 0
1049
1062
  Style.Blockquote = f"{FG}{Style.Grey}│ "
1050
1063
  width_calc()
1051
1064
 
@@ -0,0 +1,11 @@
1
+ Here's how the corrected section should look:
2
+
3
+ ```dockerfile
4
+ '{ 47
5
+ '( 48 RUN if [ "$BUILD_TYPE" = "development" ]; then \
6
+ 49 make runtest -j8 GIT_DESCRIBE=${GIT_DESCRIBE} BUILD_TYPE=${BUILD_TYPE} || true; \
7
+ 50 fi
8
+ '. 51
9
+ ') 54 COPY prometheus/config-$BUILD_TYPE.yaml prometheus.template.yaml
10
+ '} 55
11
+ ```