use super::*;
use crate::config::ToolDisplayMode;
use crate::config::loader::SyntaxHighlightingConfig;
use crate::ui::tui::{InlineHandle, InlineMessageKind};
use crate::utils::ansi_capabilities::AnsiCapabilities;
use anstream::{AutoStream, ColorChoice};
use std::io;
use vtcode_commons::color_policy::{self, ColorOutputPolicySource};
use vtcode_commons::ui_protocol::ToolOutputId;
impl AnsiRenderer {
pub fn stdout() -> Self {
let mut capabilities = AnsiCapabilities::detect();
let policy = color_policy::current_color_output_policy();
if !policy.enabled {
capabilities.no_color = true;
capabilities.force_color = false;
} else if matches!(
policy.source,
ColorOutputPolicySource::CliColorAlways | ColorOutputPolicySource::ConfigOverride
) {
capabilities.no_color = false;
capabilities.force_color = true;
}
let color = capabilities.supports_color();
let choice = if !color {
ColorChoice::Never
} else if matches!(
policy.source,
ColorOutputPolicySource::CliColorAlways | ColorOutputPolicySource::ConfigOverride
) {
ColorChoice::Always
} else {
ColorChoice::Auto
};
Self {
writer: AutoStream::new(io::stdout(), choice),
buffer: String::with_capacity(1024),
color,
sink: None,
last_line_was_empty: false,
highlight_config: SyntaxHighlightingConfig::default(),
capabilities,
reasoning_visible: true,
screen_reader_mode: false,
show_diagnostics_in_transcript: false,
tool_display_mode: ToolDisplayMode::Compact,
diff_preview_mode: vtcode_commons::ui_protocol::DiffPreviewMode::Inline,
compact_command_group: None,
next_compact_group_id: 0,
pending_tool_output_anchor: None,
session_expand_anchor: None,
session_body: false,
}
}
pub fn with_inline_ui(handle: InlineHandle, highlight_config: SyntaxHighlightingConfig) -> Self {
let mut renderer = Self::stdout();
renderer.highlight_config = highlight_config.clone();
renderer.sink = Some(InlineSink::new(handle, highlight_config));
renderer.last_line_was_empty = false;
renderer
}
pub fn set_highlight_config(&mut self, config: SyntaxHighlightingConfig) {
if let Some(sink) = &mut self.sink {
sink.set_highlight_config(config.clone());
}
self.highlight_config = config;
}
pub fn set_next_tool_output_anchor(&mut self, id: ToolOutputId) {
self.pending_tool_output_anchor = Some(id);
}
pub fn set_session_expand_anchor(&mut self, id: ToolOutputId) {
self.session_expand_anchor = Some(id);
}
pub fn take_session_expand_anchor(&mut self) -> Option<ToolOutputId> {
self.session_expand_anchor.take()
}
pub fn set_session_body(&mut self, session_body: bool) {
self.session_body = session_body;
}
pub fn session_body_active(&self) -> bool {
self.session_body
}
pub fn was_previous_line_empty(&self) -> bool {
self.last_line_was_empty
}
pub(super) fn message_kind(style: MessageStyle) -> InlineMessageKind {
style.message_kind()
}
pub fn supports_streaming_markdown(&self) -> bool {
self.sink.is_some()
}
pub fn prefers_untruncated_output(&self) -> bool {
self.sink.is_some()
}
pub fn supports_inline_ui(&self) -> bool {
self.sink.is_some()
}
pub fn set_reasoning_visible(&mut self, visible: bool) {
self.reasoning_visible = visible;
}
pub fn reasoning_visible(&self) -> bool {
self.reasoning_visible
}
pub fn writes_to_inline_sink(&self) -> bool {
self.sink.is_some()
}
pub fn set_screen_reader_mode(&mut self, enabled: bool) {
self.screen_reader_mode = enabled;
}
pub fn set_show_diagnostics_in_transcript(&mut self, enabled: bool) {
self.show_diagnostics_in_transcript = if cfg!(debug_assertions) { enabled } else { false };
}
pub fn set_tool_display_mode(&mut self, mode: ToolDisplayMode) {
self.flush_compact_command_group();
self.tool_display_mode = match mode {
ToolDisplayMode::Compact => ToolDisplayMode::Compact,
ToolDisplayMode::Expanded | ToolDisplayMode::Unknown => ToolDisplayMode::Expanded,
};
}
pub fn tool_display_mode(&self) -> ToolDisplayMode {
self.tool_display_mode
}
pub fn is_compact_display(&self) -> bool {
self.tool_display_mode == ToolDisplayMode::Compact
}
pub fn set_diff_preview_mode(&mut self, mode: vtcode_commons::ui_protocol::DiffPreviewMode) {
self.diff_preview_mode = mode;
}
pub fn record_diff_review(&self, anchor: vtcode_commons::ui_protocol::DiffReviewAnchor) {
if let Some(sink) = &self.sink {
sink.handle.record_diff_review(anchor);
}
}
pub fn diff_preview_mode(&self) -> vtcode_commons::ui_protocol::DiffPreviewMode {
self.diff_preview_mode
}
pub fn toggle_tool_display_mode(&mut self) -> ToolDisplayMode {
self.flush_compact_command_group();
let next = match self.tool_display_mode {
ToolDisplayMode::Expanded | ToolDisplayMode::Unknown => ToolDisplayMode::Compact,
ToolDisplayMode::Compact => ToolDisplayMode::Expanded,
};
self.tool_display_mode = next;
next
}
}