Skip to content

Commit df8752f

Browse files
authored
feat: implement chat DisableMarkdownRendering setting (#2236)
1 parent ae134a9 commit df8752f

File tree

3 files changed

+89
-10
lines changed

3 files changed

+89
-10
lines changed

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,10 @@ impl ChatSession {
20122012
let mut buf = String::new();
20132013
let mut offset = 0;
20142014
let mut ended = false;
2015-
let mut state = ParseState::new(Some(self.terminal_width()));
2015+
let mut state = ParseState::new(
2016+
Some(self.terminal_width()),
2017+
os.database.settings.get_bool(Setting::ChatDisableMarkdownRendering),
2018+
);
20162019
let mut response_prefix_printed = false;
20172020

20182021
let mut tool_uses = Vec::new();
@@ -2042,10 +2045,13 @@ impl ChatSession {
20422045
},
20432046
parser::ResponseEvent::AssistantText(text) => {
20442047
// Add Q response prefix before the first assistant text.
2045-
// This must be markdown - using a code tick, which is printed
2046-
// as green.
20472048
if !response_prefix_printed && !text.trim().is_empty() {
2048-
buf.push_str("`>` ");
2049+
queue!(
2050+
self.stdout,
2051+
style::SetForegroundColor(Color::Green),
2052+
style::Print("> "),
2053+
style::SetForegroundColor(Color::Reset)
2054+
)?;
20492055
response_prefix_printed = true;
20502056
}
20512057
buf.push_str(&text);

crates/chat-cli/src/cli/chat/parse.rs

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ impl<'a> ParserError<Partial<&'a str>> for Error<'a> {
8282
#[derive(Debug)]
8383
pub struct ParseState {
8484
pub terminal_width: Option<usize>,
85+
pub markdown_disabled: Option<bool>,
8586
pub column: usize,
8687
pub in_codeblock: bool,
8788
pub bold: bool,
@@ -93,9 +94,10 @@ pub struct ParseState {
9394
}
9495

9596
impl ParseState {
96-
pub fn new(terminal_width: Option<usize>) -> Self {
97+
pub fn new(terminal_width: Option<usize>, markdown_disabled: Option<bool>) -> Self {
9798
Self {
9899
terminal_width,
100+
markdown_disabled,
99101
column: 0,
100102
in_codeblock: false,
101103
bold: false,
@@ -135,8 +137,12 @@ pub fn interpret_markdown<'a, 'b>(
135137
};
136138
}
137139

138-
match state.in_codeblock {
139-
false => {
140+
match (state.in_codeblock, state.markdown_disabled.unwrap_or(false)) {
141+
(_, true) => {
142+
// If markdown is disabled, do not include markdown-related parsers
143+
stateful_alt!(text, line_ending, fallback);
144+
},
145+
(false, false) => {
140146
stateful_alt!(
141147
// This pattern acts as a short circuit for alphanumeric plaintext
142148
// More importantly, it's needed to support manual wordwrapping
@@ -167,7 +173,7 @@ pub fn interpret_markdown<'a, 'b>(
167173
fallback
168174
);
169175
},
170-
true => {
176+
(true, false) => {
171177
stateful_alt!(
172178
codeblock_less_than,
173179
codeblock_greater_than,
@@ -646,7 +652,7 @@ mod tests {
646652
use super::*;
647653

648654
macro_rules! validate {
649-
($test:ident, $input:literal, [$($commands:expr),+ $(,)?]) => {
655+
($test:ident, $input:literal, [$($commands:expr),+ $(,)?], $markdown_enabled:expr) => {
650656
#[test]
651657
fn $test() -> eyre::Result<()> {
652658
use crossterm::ExecutableCommand;
@@ -655,7 +661,7 @@ mod tests {
655661
input.push(' ');
656662
input.push(' ');
657663

658-
let mut state = ParseState::new(Some(80));
664+
let mut state = ParseState::new(Some(80), Some($markdown_enabled));
659665
let mut presult = vec![];
660666
let mut offset = 0;
661667

@@ -686,6 +692,10 @@ mod tests {
686692
Ok(())
687693
}
688694
};
695+
696+
($test:ident, $input:literal, [$($commands:expr),+ $(,)?]) => {
697+
validate!($test, $input, [$($commands),+], false);
698+
};
689699
}
690700

691701
validate!(text_1, "hello world!", [style::Print("hello world!")]);
@@ -759,4 +769,53 @@ mod tests {
759769
validate!(square_bracket_url_like_2, "[text](without url part", [style::Print(
760770
"[text](without url part"
761771
)]);
772+
773+
validate!(markdown_disabled_bold, "**hello**", [style::Print("**hello**")], true);
774+
validate!(markdown_disabled_italic, "*hello*", [style::Print("*hello*")], true);
775+
validate!(markdown_disabled_code, "`print`", [style::Print("`print`")], true);
776+
validate!(
777+
markdown_disabled_heading,
778+
"# Hello World",
779+
[style::Print("# Hello World")],
780+
true
781+
);
782+
validate!(markdown_disabled_bullet, "- bullet", [style::Print("- bullet")], true);
783+
validate!(markdown_disabled_number, "1. number", [style::Print("1. number")], true);
784+
validate!(markdown_disabled_blockquote, "> hello", [style::Print("> hello")], true);
785+
validate!(
786+
markdown_disabled_url,
787+
"[amazon](amazon.com)",
788+
[style::Print("[amazon](amazon.com)")],
789+
true
790+
);
791+
validate!(
792+
markdown_disabled_codeblock,
793+
"```java hello world!```",
794+
[style::Print("```java hello world!```")],
795+
true
796+
);
797+
validate!(
798+
markdown_disabled_text,
799+
"hello world!",
800+
[style::Print("hello world!")],
801+
true
802+
);
803+
validate!(
804+
markdown_disabled_line_ending,
805+
"line one\nline two",
806+
[
807+
style::Print("line one"),
808+
style::ResetColor,
809+
style::SetAttribute(style::Attribute::Reset),
810+
style::Print("\n"),
811+
style::Print("line two")
812+
],
813+
true
814+
);
815+
validate!(
816+
markdown_disabled_fallback,
817+
"+ % @ . ?",
818+
[style::Print("+ % @ . ?")],
819+
true
820+
);
762821
}

crates/chat-cli/src/database/settings.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub enum Setting {
3333
McpNoInteractiveTimeout,
3434
McpLoadedBefore,
3535
ChatDefaultModel,
36+
ChatDisableMarkdownRendering,
3637
ChatDefaultAgent,
3738
ChatDisableAutoCompaction,
3839
ChatEnableHistoryHints,
@@ -57,6 +58,7 @@ impl AsRef<str> for Setting {
5758
Self::McpNoInteractiveTimeout => "mcp.noInteractiveTimeout",
5859
Self::McpLoadedBefore => "mcp.loadedBefore",
5960
Self::ChatDefaultModel => "chat.defaultModel",
61+
Self::ChatDisableMarkdownRendering => "chat.disableMarkdownRendering",
6062
Self::ChatDefaultAgent => "chat.defaultAgent",
6163
Self::ChatDisableAutoCompaction => "chat.disableAutoCompaction",
6264
Self::ChatEnableHistoryHints => "chat.enableHistoryHints",
@@ -91,6 +93,7 @@ impl TryFrom<&str> for Setting {
9193
"mcp.noInteractiveTimeout" => Ok(Self::McpNoInteractiveTimeout),
9294
"mcp.loadedBefore" => Ok(Self::McpLoadedBefore),
9395
"chat.defaultModel" => Ok(Self::ChatDefaultModel),
96+
"chat.disableMarkdownRendering" => Ok(Self::ChatDisableMarkdownRendering),
9497
"chat.defaultAgent" => Ok(Self::ChatDefaultAgent),
9598
"chat.disableAutoCompaction" => Ok(Self::ChatDisableAutoCompaction),
9699
"chat.enableHistoryHints" => Ok(Self::ChatEnableHistoryHints),
@@ -213,12 +216,17 @@ mod test {
213216
assert_eq!(settings.get(Setting::ShareCodeWhispererContent), None);
214217
assert_eq!(settings.get(Setting::McpLoadedBefore), None);
215218
assert_eq!(settings.get(Setting::ChatDefaultModel), None);
219+
assert_eq!(settings.get(Setting::ChatDisableMarkdownRendering), None);
216220

217221
settings.set(Setting::TelemetryEnabled, true).await.unwrap();
218222
settings.set(Setting::OldClientId, "test").await.unwrap();
219223
settings.set(Setting::ShareCodeWhispererContent, false).await.unwrap();
220224
settings.set(Setting::McpLoadedBefore, true).await.unwrap();
221225
settings.set(Setting::ChatDefaultModel, "model 1").await.unwrap();
226+
settings
227+
.set(Setting::ChatDisableMarkdownRendering, false)
228+
.await
229+
.unwrap();
222230

223231
assert_eq!(settings.get(Setting::TelemetryEnabled), Some(&Value::Bool(true)));
224232
assert_eq!(
@@ -234,15 +242,21 @@ mod test {
234242
settings.get(Setting::ChatDefaultModel),
235243
Some(&Value::String("model 1".to_string()))
236244
);
245+
assert_eq!(
246+
settings.get(Setting::ChatDisableMarkdownRendering),
247+
Some(&Value::Bool(false))
248+
);
237249

238250
settings.remove(Setting::TelemetryEnabled).await.unwrap();
239251
settings.remove(Setting::OldClientId).await.unwrap();
240252
settings.remove(Setting::ShareCodeWhispererContent).await.unwrap();
241253
settings.remove(Setting::McpLoadedBefore).await.unwrap();
254+
settings.remove(Setting::ChatDisableMarkdownRendering).await.unwrap();
242255

243256
assert_eq!(settings.get(Setting::TelemetryEnabled), None);
244257
assert_eq!(settings.get(Setting::OldClientId), None);
245258
assert_eq!(settings.get(Setting::ShareCodeWhispererContent), None);
246259
assert_eq!(settings.get(Setting::McpLoadedBefore), None);
260+
assert_eq!(settings.get(Setting::ChatDisableMarkdownRendering), None);
247261
}
248262
}

0 commit comments

Comments
 (0)