-
Notifications
You must be signed in to change notification settings - Fork 12
feat: introduce from_str_with_options() to support custom stylesheets #80
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
base: main
Are you sure you want to change the base?
Conversation
This introduces the use of the `tui-markdown` crate to parse an assistant message as Markdown and style it using ANSI for a better user experience. As shown in the screenshot below, it has support for syntax highlighting for _tagged_ fenced code blocks: <img width="907" alt="image" src="https://github.com/user-attachments/assets/900dc229-80bb-46e8-b1bb-efee4c70ba3c" /> That said, `tui-markdown` is not as configurable (or stylish!) as https://www.npmjs.com/package/marked-terminal, which is what we use in the TypeScript CLI. In particular: * The styles are hardcoded and `tui_markdown::from_str()` does not take any options whatsoever. It uses "bold white" for inline code style which does not stand out as much as the yellow used by `marked-terminal`: https://github.com/joshka/tui-markdown/blob/65402cbda70325f34e7ddf6fe1ec629bcd9459cf/tui-markdown/src/lib.rs#L464 I asked Codex to take a first pass at this and it came up with: joshka/tui-markdown#80 * If a fenced code block is not tagged, then it does not get highlighted. I would rather add some logic here: https://github.com/joshka/tui-markdown/blob/65402cbda70325f34e7ddf6fe1ec629bcd9459cf/tui-markdown/src/lib.rs#L262 that uses something like https://pypi.org/project/guesslang/ to examine the value of `text` and try to use the appropriate syntax highlighter. * When we have a fenced code block, we do not want to show the opening and closing triple backticks in the output. To unblock ourselves, we might want to bundle our own fork of `tui-markdown` temporarily until we figure out what the shape of the API should be and then try to upstream it.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #80 +/- ##
==========================================
+ Coverage 38.22% 45.27% +7.05%
==========================================
Files 5 7 +2
Lines 450 508 +58
==========================================
+ Hits 172 230 +58
Misses 278 278 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of nits and a couple of main comments:
First up, thanks for making this configurable. It's something that was on my todo list for sometime when I had some time and energy to do it, so I'm always happy to see a contribution that pushes things forward.
In my initial thinking about this, I'd anticipated that Styling like this would have generally just been a struct with values rather than a trait. This obviously means that there would be more fields for headings to deal with. I'm curious whether you'd thought about any downsides with that approach that using a trait instead solves neatly. The only thing I can really think of is that there's some sort of dynamic values being returned, but I'm not sure that I can think of a good use case for that. This is not a hard blocker, but it's an interesting question, and we face a similar question with Ratatui core when thinking about how to implement theming, so it's worth getting some ideas / understanding here.
The main other questions I have:
- non_exhaustive
- Default vs BuiltIn
Overall I'm mostly fine with the approach you've taken - I mostly want to understand a few things to work out whether it's the best we can do, and would anticipate pushing forward with this once those are resolved.
tui-markdown/src/lib.rs
Outdated
|
|
||
| // Public-facing theming and configuration APIs -------------------------------- | ||
| mod style_sheet; | ||
| pub use style_sheet::{BuiltinStyleSheet, DefaultStyleSheet, StyleSheet}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Builtin vs Default distinction is a little confusing. Can you expand on why this is necessary / what it solves? Without understanding this, I'd intuitively suggest perhaps keep only one of these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed this for now.
|
@bolinfest are you keen to get this over the line? |
|
For now, I changed this so that there's a constructor that accepts a stylesheet, I'd anticipate that adding more options would add builder style methods similar to the way that we do these in Ratatui (Matklad describes this as the builder-lite pattern in https://matklad.github.io/2022/05/29/builder-lite.html). I've removed the wrapping and line number options, and will add them when that feature is added. |
This introduces the use of the `tui-markdown` crate to parse an assistant message as Markdown and style it using ANSI for a better user experience. As shown in the screenshot below, it has support for syntax highlighting for _tagged_ fenced code blocks: <img width="907" alt="image" src="https://github.com/user-attachments/assets/900dc229-80bb-46e8-b1bb-efee4c70ba3c" /> That said, `tui-markdown` is not as configurable (or stylish!) as https://www.npmjs.com/package/marked-terminal, which is what we use in the TypeScript CLI. In particular: * The styles are hardcoded and `tui_markdown::from_str()` does not take any options whatsoever. It uses "bold white" for inline code style which does not stand out as much as the yellow used by `marked-terminal`: https://github.com/joshka/tui-markdown/blob/65402cbda70325f34e7ddf6fe1ec629bcd9459cf/tui-markdown/src/lib.rs#L464 I asked Codex to take a first pass at this and it came up with: joshka/tui-markdown#80 * If a fenced code block is not tagged, then it does not get highlighted. I would rather add some logic here: https://github.com/joshka/tui-markdown/blob/65402cbda70325f34e7ddf6fe1ec629bcd9459cf/tui-markdown/src/lib.rs#L262 that uses something like https://pypi.org/project/guesslang/ to examine the value of `text` and try to use the appropriate syntax highlighter. * When we have a fenced code block, we do not want to show the opening and closing triple backticks in the output. To unblock ourselves, we might want to bundle our own fork of `tui-markdown` temporarily until we figure out what the shape of the API should be and then try to upstream it.
This introduces the use of the `tui-markdown` crate to parse an assistant message as Markdown and style it using ANSI for a better user experience. As shown in the screenshot below, it has support for syntax highlighting for _tagged_ fenced code blocks: <img width="907" alt="image" src="https://github.com/user-attachments/assets/900dc229-80bb-46e8-b1bb-efee4c70ba3c" /> That said, `tui-markdown` is not as configurable (or stylish!) as https://www.npmjs.com/package/marked-terminal, which is what we use in the TypeScript CLI. In particular: * The styles are hardcoded and `tui_markdown::from_str()` does not take any options whatsoever. It uses "bold white" for inline code style which does not stand out as much as the yellow used by `marked-terminal`: https://github.com/joshka/tui-markdown/blob/65402cbda70325f34e7ddf6fe1ec629bcd9459cf/tui-markdown/src/lib.rs#L464 I asked Codex to take a first pass at this and it came up with: joshka/tui-markdown#80 * If a fenced code block is not tagged, then it does not get highlighted. I would rather add some logic here: https://github.com/joshka/tui-markdown/blob/65402cbda70325f34e7ddf6fe1ec629bcd9459cf/tui-markdown/src/lib.rs#L262 that uses something like https://pypi.org/project/guesslang/ to examine the value of `text` and try to use the appropriate syntax highlighter. * When we have a fenced code block, we do not want to show the opening and closing triple backticks in the output. To unblock ourselves, we might want to bundle our own fork of `tui-markdown` temporarily until we figure out what the shape of the API should be and then try to upstream it.
|
@codex take a look at the original commit on this and the updated version with the current PR. Review both the original commit and the updated changes to help validate the usefulness of both approaches and then compare to see if any problems were caused by simplifying this. Try to synthesize or provide an understanding of why the more complex approach might be necessary (use cases etc.). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if self.needs_newline { | ||
| self.push_line(Line::default()); | ||
| } | ||
| let style = match level { | ||
| HeadingLevel::H1 => styles::H1, | ||
| HeadingLevel::H2 => styles::H2, | ||
| HeadingLevel::H3 => styles::H3, | ||
| HeadingLevel::H4 => styles::H4, | ||
| HeadingLevel::H5 => styles::H5, | ||
| HeadingLevel::H6 => styles::H6, | ||
| }; | ||
| let style = self.styles.heading(level as u8); | ||
| let content = format!("{} ", "#".repeat(level as usize)); | ||
| self.push_line(Line::styled(content, style)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preserve 1‑based heading levels when styling
The new start_heading now passes level as u8 into StyleSheet::heading, but HeadingLevel’s discriminants start at 0. This means # H1 is now handed the value 0, ## H2 the value 1, etc., so the default sheet (and any user sheet expecting 1–6) will use the wrong colours and modifiers—H1 currently renders with the fallback style intended for H4+. The original commit explicitly mapped HeadingLevel::{H1…H6} to 1–6 to avoid this off‑by‑one. Please restore that mapping to keep existing themes working.
Useful? React with 👍 / 👎.
No description provided.