Skip to main content

oino_ui/extras/
code.rs

1//! `Code` node (§4.5.2).
2
3use serde::{Deserialize, Serialize};
4
5use crate::node::{Common, IntoNode, Node};
6
7/// Syntax-highlighted code (§4.5.2). TUI: syntect; app: the chat code-block renderer.
8#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Code {
11    /// Common node props (`key`, `style`, `block`, `fallback`).
12    #[serde(flatten)]
13    pub common: Common,
14    /// Code source.
15    pub source: String,
16    /// Language id (`rust`, `mermaid`, …).
17    #[serde(default, skip_serializing_if = "Option::is_none")]
18    pub language: Option<String>,
19    /// Render line numbers.
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    pub line_numbers: Option<bool>,
22    /// First line number (default 1).
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    pub start_line: Option<u32>,
25    /// Highlighted (1-based) line numbers.
26    #[serde(default, skip_serializing_if = "Vec::is_empty")]
27    pub highlight_lines: Vec<u32>,
28    /// Wrap long lines (default `false` = horizontal scroll).
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub wrap: Option<bool>,
31}
32
33impl Code {
34    /// A code node.
35    #[must_use]
36    pub fn new(source: impl Into<String>) -> Self {
37        Self {
38            common: Common::new(),
39            source: source.into(),
40            language: None,
41            line_numbers: None,
42            start_line: None,
43            highlight_lines: Vec::new(),
44            wrap: None,
45        }
46    }
47
48    /// Sets the language id.
49    #[must_use]
50    pub fn language(mut self, language: impl Into<String>) -> Self {
51        self.language = Some(language.into());
52        self
53    }
54
55    /// Renders line numbers.
56    #[must_use]
57    pub fn line_numbers(mut self, line_numbers: bool) -> Self {
58        self.line_numbers = Some(line_numbers);
59        self
60    }
61
62    /// Sets the first line number.
63    #[must_use]
64    pub fn start_line(mut self, start_line: u32) -> Self {
65        self.start_line = Some(start_line);
66        self
67    }
68
69    /// Sets the highlighted (1-based) lines.
70    #[must_use]
71    pub fn highlight_lines(mut self, lines: impl IntoIterator<Item = u32>) -> Self {
72        self.highlight_lines = lines.into_iter().collect();
73        self
74    }
75
76    /// Wraps long lines.
77    #[must_use]
78    pub fn wrap(mut self, wrap: bool) -> Self {
79        self.wrap = Some(wrap);
80        self
81    }
82}
83
84impl IntoNode for Code {}
85impl From<Code> for Node {
86    fn from(c: Code) -> Self {
87        Node::Code(c)
88    }
89}