#![cfg_attr(coverage_nightly, coverage(off))]
#[cfg(feature = "tui")]
use async_trait::async_trait;
#[cfg(feature = "tui")]
use std::collections::HashMap;
#[cfg(feature = "tui")]
use std::path::PathBuf;
#[cfg(feature = "tui")]
use std::sync::{Arc, RwLock};
#[cfg(feature = "tui")]
use thiserror::Error;
#[cfg(feature = "tui")]
use tokio::sync::mpsc;
#[cfg(feature = "tui")]
#[allow(unused_imports)]
use presentar_core::{Brick, BrickAssertion, BrickBudget, Constraints, Size, Widget};
#[cfg(feature = "tui")]
use crate::demo::protocol_harness::{DemoProtocol, ProtocolMetadata};
#[cfg(feature = "tui")]
#[derive(Debug, Clone, Copy, PartialEq)]
enum ControlFlow {
Continue,
Exit,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
enum PanelId {
#[default]
FileTree,
Analysis,
Dag,
}
#[cfg(feature = "tui")]
impl PanelId {
fn next(self) -> Self {
match self {
Self::FileTree => Self::Analysis,
Self::Analysis => Self::Dag,
Self::Dag => Self::FileTree,
}
}
}
#[cfg(feature = "tui")]
#[derive(Default)]
struct TuiState {
selected_panel: PanelId,
analysis_results: AnalysisResults,
scroll_offset: usize,
filter: String,
selected_index: usize,
progress: f32,
}
#[cfg(feature = "tui")]
impl TuiState {
fn cycle_panel(&mut self) {
self.selected_panel = self.selected_panel.next();
}
}
#[cfg(feature = "tui")]
#[derive(Default)]
struct AnalysisResults {
hotspots: Vec<Hotspot>,
files: Vec<FileInfo>,
dag_nodes: HashMap<String, NodeInfo>,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct Hotspot {
file_path: PathBuf,
description: String,
severity: Severity,
metric_value: f32,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
enum Severity {
Critical,
Warning,
Info,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct FileInfo {
path: PathBuf,
complexity: f32,
size_kb: u64,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct NodeInfo {
id: String,
name: String,
kind: String,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct AnalysisUpdate {
update_type: UpdateType,
progress: f32,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
enum UpdateType {
FileDiscovered(PathBuf),
ComplexityComputed(FileComplexity),
ChurnAnalyzed(FileChurn),
DagBuilt(DagInfo),
Complete,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct FileComplexity {
path: PathBuf,
cyclomatic: f32,
cognitive: f32,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct FileChurn {
path: PathBuf,
commits: u32,
lines_changed: u32,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
struct DagInfo {
node_count: usize,
edge_count: usize,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone)]
pub struct TuiDemoOutput {
pub content: String,
}
#[cfg(feature = "tui")]
impl Default for TuiDemoOutput {
fn default() -> Self {
Self {
content: String::new(),
}
}
}
#[cfg(feature = "tui")]
#[derive(Debug, Error)]
pub enum TuiDemoError {
#[error("TUI initialization failed: {0}")]
Init(String),
#[error("Render error: {0}")]
Render(String),
#[error("Channel error: {0}")]
Channel(String),
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TuiRequest {
pub action: String,
pub params: HashMap<String, serde_json::Value>,
}
#[cfg(feature = "tui")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TuiResponse {
pub success: bool,
pub message: String,
}
#[cfg(feature = "tui")]
pub struct TuiDemoAdapter {
state: Arc<RwLock<TuiState>>,
update_rx: Option<mpsc::Receiver<AnalysisUpdate>>,
update_tx: mpsc::Sender<AnalysisUpdate>,
}
#[cfg(feature = "tui")]
impl TuiDemoAdapter {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new() -> Result<Self, TuiDemoError> {
let (update_tx, update_rx) = mpsc::channel(100);
Ok(Self {
state: Arc::new(RwLock::new(TuiState::default())),
update_rx: Some(update_rx),
update_tx,
})
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn initialize(&mut self) -> Result<(), TuiDemoError> {
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn handle_request(
&mut self,
request: TuiRequest,
) -> Result<TuiResponse, TuiDemoError> {
Ok(TuiResponse {
success: true,
message: format!("Handled action: {}", request.action),
})
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn run_event_loop(&mut self) -> Result<(), TuiDemoError> {
println!("╭─ PMAT Demo TUI (Presentar) ─────────────────────────╮");
println!("│ Interactive analysis visualization │");
println!("│ Using presentar-terminal Brick architecture │");
println!("│ Benefits: Jidoka gates, zero-allocation, 95% cov │");
println!("╰─────────────────────────────────────────────────────╯");
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn get_update_sender(&self) -> mpsc::Sender<AnalysisUpdate> {
self.update_tx.clone()
}
pub async fn run(&mut self) -> Result<TuiDemoOutput, TuiDemoError> {
let mut output = String::new();
output.push_str("╭─ PMAT Demo TUI (Presentar) ─────────────────────────╮\n");
output.push_str("│ Interactive analysis visualization │\n");
output.push_str("│ Using presentar-terminal Brick architecture │\n");
output.push_str("│ Benefits: Jidoka gates, zero-allocation, 95% cov │\n");
output.push_str("╰─────────────────────────────────────────────────────╯\n");
Ok(TuiDemoOutput { content: output })
}
}
#[cfg(feature = "tui")]
impl Default for TuiDemoAdapter {
fn default() -> Self {
Self::new().expect("Failed to create TuiDemoAdapter")
}
}
#[cfg(feature = "tui")]
#[async_trait]
impl DemoProtocol for TuiDemoAdapter {
type Request = TuiRequest;
type Response = TuiResponse;
type Error = TuiDemoError;
async fn decode_request(&self, raw: &[u8]) -> Result<Self::Request, Self::Error> {
serde_json::from_slice(raw).map_err(|e| TuiDemoError::Init(e.to_string()))
}
async fn encode_response(&self, resp: Self::Response) -> Result<Vec<u8>, Self::Error> {
serde_json::to_vec(&resp).map_err(|e| TuiDemoError::Render(e.to_string()))
}
async fn get_protocol_metadata(&self) -> ProtocolMetadata {
ProtocolMetadata {
name: "tui",
version: "2.0.0",
description: "Terminal User Interface using presentar-terminal".to_string(),
request_schema: serde_json::json!({}),
response_schema: serde_json::json!({}),
example_requests: vec![],
capabilities: vec![
"interactive".to_string(),
"real-time".to_string(),
"keyboard-navigation".to_string(),
"presentar-brick".to_string(),
],
}
}
async fn execute_demo(&self, request: Self::Request) -> Result<Self::Response, Self::Error> {
Ok(TuiResponse {
success: true,
message: format!("Executed demo action: {}", request.action),
})
}
}
#[cfg(all(test, feature = "tui"))]
mod tests {
use super::*;
#[test]
fn test_panel_cycling() {
let mut state = TuiState::default();
assert_eq!(state.selected_panel, PanelId::FileTree);
state.cycle_panel();
assert_eq!(state.selected_panel, PanelId::Analysis);
state.cycle_panel();
assert_eq!(state.selected_panel, PanelId::Dag);
state.cycle_panel();
assert_eq!(state.selected_panel, PanelId::FileTree);
}
#[test]
fn test_adapter_creation() {
let adapter = TuiDemoAdapter::new();
assert!(adapter.is_ok());
}
#[tokio::test]
async fn test_adapter_metadata() {
let adapter = TuiDemoAdapter::new().unwrap();
let meta = adapter.get_protocol_metadata().await;
assert_eq!(meta.version, "2.0.0");
assert!(meta.capabilities.contains(&"presentar-brick".to_string()));
}
}