-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to render markdown dynamically in real time #42
Comments
+1. I also wonder how this can be implemented. My current idea to work around this is to print raw strings and store these chunks, then once the completion is finished, clear the previous output and render the full content in md using termimad. |
Why wait for the end ? If you receive those chunks in an application, you can render them like in this example: https://github.com/Canop/termimad/tree/main/examples/render-input-markdown |
A word of caution: termimad isn't a universal renderer (there's not even any support for images). Its main use cases are for building terminal applications and it may not be suited to render what chatgpt outputs (no idea here). |
OK, I'm looking into it and will try to make a PR to add a simpler example. |
OK |
I think this is the minimum code to do this use std::io::{stdout, Write};
use std::thread::sleep;
use termimad::crossterm::{cursor, ExecutableCommand};
use termimad::{FmtText, MadSkin};
use termimad::crossterm::terminal::Clear;
use termimad::crossterm::terminal::ClearType::FromCursorDown;
const MARKDOWN_TEXT: &str = r#"
# Hello
This is inline code `print("hello")`.
// wrap the below line in a code block
print("hello")
Here ends it.
"#;
fn main() {
let skin = MadSkin::default();
stdout().execute(cursor::Hide).unwrap();
let mut string_buffer = String::new();
for (i, chunk) in MARKDOWN_TEXT.chars().enumerate() {
stdout()
.execute(cursor::SavePosition).unwrap()
.execute(Clear(FromCursorDown)).unwrap();
string_buffer.push(chunk);
let formatted_text = FmtText::from(&skin, &string_buffer, None); // can have Some(width) to enable hard wrapping
print!("{}", formatted_text);
stdout().flush().unwrap();
let is_last_one = i == MARKDOWN_TEXT.len() - 1;
if !is_last_one {
stdout().execute(cursor::RestorePosition).unwrap();
}
sleep(std::time::Duration::from_millis(100));
}
stdout().execute(cursor::Show).unwrap();
sleep(std::time::Duration::from_millis(500));
} I got the idea from
and
These two lines essentially do the same, which is rendering over and over again rather than incrementally rendering texts. |
Code text similar to the stream returned by CHATGPT is rendered dynamically as a complement
The actual rendering looks like this:
The text was updated successfully, but these errors were encountered: