streamdown 0.20.0__py3-none-any.whl → 0.22.0__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
@@ -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
 
@@ -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
@@ -0,0 +1,9 @@
1
+ streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ streamdown/sd.py,sha256=unpjFxiUkjHw9XNZ8ziaOaka4s9qPpV5lwaeGz6pzlo,41981
3
+ streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
4
+ streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
5
+ streamdown-0.22.0.dist-info/METADATA,sha256=jN3R2SE6M7UWfpb9a2IdNGDMfKNL5CBAEj0UaunowKg,9658
6
+ streamdown-0.22.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ streamdown-0.22.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
8
+ streamdown-0.22.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
9
+ streamdown-0.22.0.dist-info/RECORD,,
streamdown/ss DELETED
@@ -1 +0,0 @@
1
- * **Model Card:** Always read the model card on the Hugging Face Hub ([https://huggingface.co/microsoft/bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T)) for important information about the model, its intended use, limitations, and potential biases.
streamdown/ss1 DELETED
@@ -1,42 +0,0 @@
1
- * `model.safetensors`: The name of the file you want to download. You'll need to know the exact filename. You can find the files in the model repository on the Hugging Face Hub website ([https://huggingface.co/microsoft/bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T)). Look under the "Files and versions" tab. `safetensors` is the preferred format for model weights now. If it's a `.bin` file, you can download that instead.
2
- * `--local-dir ./bitnet-b1.58-2B-4T`: The directory to save the file to.
3
-
4
- * **Download using `transformers` library (recommended for most use cases):**
5
-
6
- The `transformers` library provides a convenient way to download and cache models. This is often the easiest approach if you're using the model with `transformers`. You don't *directly* use the `huggingface-cli` for this, but it's worth knowing.
7
-
8
- ```python
9
- from transformers import AutoModelForCausalLM, AutoTokenizer
10
-
11
- model_name = "microsoft/bitnet-b1.58-2B-4T"
12
-
13
- tokenizer = AutoTokenizer.from_pretrained(model_name)
14
- model = AutoModelForCausalLM.from_pretrained(model_name)
15
-
16
- # The model and tokenizer will be downloaded and cached in your
17
- # transformers cache directory (usually ~/.cache/huggingface/transformers).
18
- ```
19
-
20
- This approach automatically handles downloading the necessary files and caching them for future use. It also handles the correct file formats and configurations.
21
-
22
- **4. Checking the Download**
23
-
24
- After the download completes, verify that the files are in the specified directory. You can use `ls` (Linux/macOS) or `dir` (Windows) to list the contents of the directory.
25
-
26
- **Important Considerations:**
27
-
28
- * **Disk Space:** The `bitnet-b1.58-2B-4T` model is quite large (several gigabytes). Make sure you have enough free disk space before downloading.
29
- * **Network Connection:** A stable and fast internet connection is essential for a smooth download.
30
- * **Caching:** The Hugging Face Hub and `transformers` library use caching to avoid re-downloading models unnecessarily. The default cache directory is usually `~/.cache/huggingface/transformers`.
31
- * **File Formats:** Models are often stored in `safetensors` or `.bin` formats. `safetensors` is generally preferred for security and performance.
32
- * **Model Card:** Always read the model card on the Hugging Face Hub ([https://huggingface.co/microsoft/bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T)) for important information about the model, its intended use, limitations, and potential biases.
33
- * **Gated Models:** Some models require you to accept terms of use before you can download them. The `huggingface-cli login` command will guide you through this process if necessary.
34
-
35
- **Example Workflow (Recommended):**
36
-
37
- 1. `huggingface-cli login` (if not already logged in)
38
- 2. Use the `transformers` library in a Python script to download and load the model (as shown in the example above). This is the most convenient and reliable method for most use cases.
39
-
40
- Let me know if you have any other questions or if you'd like help with a specific task related to this model!
41
-
42
- >
@@ -1,11 +0,0 @@
1
- streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- streamdown/sd.py,sha256=ggXlCGovA6cS3686BLnk0ISzf2xXrx7UwuKjwjs6RUM,41475
3
- streamdown/ss,sha256=sel_phpaecrw6WGIHRLROsD7BFShf0rSDHheflwdUn8,277
4
- streamdown/ss1,sha256=CUVf86_2zeAle2oQCeTfWYqtHBrAFR_UgvptuYMQzFU,3151
5
- streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
6
- streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
7
- streamdown-0.20.0.dist-info/METADATA,sha256=LpTl5FFiZJMk_9OC9Kqqq72satHDEHn19rGnJ93XSKY,8843
8
- streamdown-0.20.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- streamdown-0.20.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
10
- streamdown-0.20.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
11
- streamdown-0.20.0.dist-info/RECORD,,