### TextView Creation and Display Example - Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/views/text_view Demonstrates how to create and display a TextView with scrollable markdown content within a specified area using the termimad crate. It involves setting up a markdown string, an Area, and a MadSkin, then creating a TextView and writing it to the terminal. ```rust use termimad::*; // You typically borrow those 3 vars from elsewhere let markdown = "#title\n* item 1\n* item 2"; let area = Area::new(0, 0, 10, 12); let skin = MadSkin::default(); // displaying let text = skin.area_text(markdown, &area); let view = TextView::from(&area, &text); view.write().unwrap(); ``` -------------------------------- ### Rust Macro: Define Prompt with Answers Source: https://docs.rs/termimad/0.34.0/src/termimad/ask This macro defines a Rust `Question` struct with a markdown-formatted prompt and a vector of `Answer` structs. It handles the case where a default answer is not provided. The `ask` method is called to get user input, and a `match` statement selects the appropriate response block based on the user's input key. ```rust macro_rules! ask_macro { ( $skin: expr, $question: expr, { $(($key: expr, $answer: expr) => $r: block)+ } ) => {{ let mut question = $crate::Question { md: Some($question.to_string()), answers: vec![$($crate::Answer { key: $key.to_string(), md: $answer.to_string() }),*], default_answer: None, }; let key = question.ask($skin).unwrap(); let mut answers = question.answers.drain(..); match key { $(_ if answers.next().unwrap().key == key => { $r })* _ => { unreachable!(); } } }}; ( $skin: expr, $question: expr, ($default_answer: expr) { $(($key: expr, $answer: expr) => $r: block)+ } ) => {{ let mut question = $crate::Question { md: Some($question.to_string()), answers: vec![$($crate::Answer { key: $key.to_string(), md: $answer.to_string() }),*], default_answer: Some($default_answer.to_string()), }; if question.has_exotic_default() { // I should rewrite this macro as a proc macro... panic!("default answer when using the ask! macro must be among declared answers"); } let key = question.ask($skin).unwrap(); let mut answers = question.answers.drain(..); match key { $(_ if answers.next().unwrap().key == key => { $r })* _ => { unreachable!() } } }} } ``` -------------------------------- ### Rust InputFieldContent Line Accessors Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field_content Provides methods for `InputFieldContent` to get the number of lines, access specific lines by index, and get a reference to the current line. ```Rust impl InputFieldContent { pub fn line_count(&self) -> usize { self.lines.len() } pub fn line(&self, y: usize) -> Option<&Line> { self.lines.get(y) } pub fn line_saturating(&self, y: usize) -> &Line { self.lines .get(y) .unwrap_or(&self.lines[self.lines.len() - 1]) } pub fn current_line(&self) -> &Line { self.lines .get(self.pos.y) .expect("current line should exist") } pub fn lines(&self) -> &[Line] { &self.lines } } ``` -------------------------------- ### Rustdoc Keyboard Shortcuts Source: https://docs.rs/termimad/0.34.0/help This section details the keyboard shortcuts available in rustdoc for navigating and interacting with the documentation. It covers actions like showing help, focusing the search field, moving through search results, expanding/collapsing sections, and more. ```text `?` Show this help dialog `S` / `/` Focus the search field `↑` Move up in search results `↓` Move down in search results `←` / `→` Switch result tab (when results focused) `⏎` Go to active search result `+` Expand all sections `-` Collapse all sections `_` Collapse all sections, including impl blocks ``` -------------------------------- ### Sequence Start/End Key Detection Source: https://docs.rs/termimad/0.34.0/src/termimad/events/event_source Helper functions to detect specific key events that mark the start or end of an escape sequence. These are defined as `ALT + '_'` for start and `ALT + '\'` for end. ```rust fn is_seq_start(key: KeyEvent) -> bool { key.code == KeyCode::Char('_') && key.modifiers == KeyModifiers::ALT } fn is_seq_end(key: KeyEvent) -> bool { key.code == KeyCode::Char('\') && key.modifiers == KeyModifiers::ALT } ``` -------------------------------- ### Start New Tick Beam with Payload Source: https://docs.rs/termimad/0.34.0/src/termimad/events/tick_beam Starts a new `TickBeam` within the `Ticker`. It assigns a unique ID, creates an interrupt channel, and spawns a thread to handle the beam's timing and payload sending. The beam can be configured to run a specific number of times or infinitely. ```Rust impl Ticker

{ /// Start a new beam, returning its id, wich can be used to stop it /// /// You may drop the id if you don't plan to manually stop the beam. pub fn start_beam(&mut self, mission: TickBeam

) -> TickBeamId { let id = self.next_id; self.next_id += 1; let (interrupt_sender, interrupt_receiver) = crossbeam::channel::bounded(1); let tick_sender = self.tick_sender.clone(); thread::spawn(move || { let mut remaining_count = mission.remaining_count; loop { if let Some(remaining_count) = remaining_count.as_mut() { if *remaining_count == 0 { break; } *remaining_count -= 1; } if interrupt_receiver.recv_timeout(mission.period).is_ok() { // we received an interrupt break; } let _ = tick_sender.send(mission.payload); } }); self.beams.push(TickBeamHandle { id, interrupt_sender, }); id } ``` -------------------------------- ### EventSource Initialization Source: https://docs.rs/termimad/0.34.0/src/termimad/events/event_source Provides methods to create a new `EventSource` with default or custom options. It requires mouse support to be enabled in crossterm. The `new` function uses default options, while `with_options` allows for specific configurations. ```rust impl EventSource { /// create a new source with default options /// /// If desired, mouse support must be enabled and disabled in crossterm. pub fn new() -> Result { Self::with_options(EventSourceOptions::default()) } /// create a new source /// /// If desired, mouse support must be enabled and disabled in crossterm. pub fn with_options(options: EventSourceOptions) -> Result { let mut combiner = Combiner::default(); ``` -------------------------------- ### Get InputField Area Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field Returns a constant reference to the current display area of the input field. ```rust pub const fn area(&self) -> &Area { &self.area } ``` -------------------------------- ### Create and Display Formatted Text with Markdown Source: https://docs.rs/termimad/0.34.0/src/termimad/text Demonstrates how to create a `FmtText` instance from a markdown string using a default `MadSkin` and a specified width. It then shows how to print the formatted text. ```rust use termimad::* let skin = MadSkin::default(); let my_markdown = "#title\n* item 1\n* item 2"; let text = FmtText::from(&skin, &my_markdown, Some(80)); println!("{}", &text); ``` -------------------------------- ### Rust: Implement Any for StyleToken Source: https://docs.rs/termimad/0.34.0/termimad/enum Provides the `type_id` method to get the `TypeId` of the StyleToken. This is part of the `Any` trait implementation. ```rust impl Any for T where T: 'static + ?Sized, { fn type_id(&self) -> TypeId } ``` -------------------------------- ### Create Light Terminal Skin Source: https://docs.rs/termimad/0.34.0/src/termimad/skin Builds a customizable skin with gray levels suitable for terminals with a light background. It sets foreground and background colors for code blocks, inline code, and headers. ```rust pub fn default_light() -> Self { let mut skin = Self::default(); skin.code_block.set_fgbg(gray(3), gray(20)); skin.inline_code.set_fgbg(gray(4), gray(20)); skin.headers[0].set_fg(gray(0)); skin.headers[1].set_fg(gray(2)); skin.headers[2].set_fg(gray(4)); skin } ``` -------------------------------- ### Initialize FmtComposite Source: https://docs.rs/termimad/0.34.0/src/termimad/composite Provides methods to create new instances of FmtComposite. `new` creates a default instance, `from` initializes from a Minimad Composite and MadSkin, and `from_compound` creates an instance from a single Compound. ```rust pub fn new() -> Self { FmtComposite { kind: CompositeKind::Paragraph, compounds: Vec::new(), visible_length: 0, spacing: None, } } pub fn from(composite: Composite<'s>, skin: &MadSkin) -> Self { let kind: CompositeKind = composite.style.into(); FmtComposite { visible_length: skin.visible_composite_length(kind, &composite.compounds), kind, compounds: composite.compounds, spacing: None, } } pub fn from_compound(compound: Compound<'s>) -> Self { let mut fc = Self::new(); fc.add_compound(compound); fc } ``` -------------------------------- ### Get InputField Scroll Position Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field Returns the current scrolling state of the input field on both axes as a `Pos` struct. ```rust pub const fn scroll(&self) -> Pos { self.scroll } ``` -------------------------------- ### Get Default Skin Source: https://docs.rs/termimad/0.34.0/termimad Returns a reference to the global skin used for terminal rendering. This is likely a default configuration for styling. ```rust fn get_default_skin() -> &'static Skin // Return a reference to the global skin ``` -------------------------------- ### Implement ask! Macro for Interactive Prompts Source: https://docs.rs/termimad/0.34.0/src/termimad/ask Provides the `ask!` macro for simplifying the creation of interactive user prompts. It allows defining questions with multiple-choice answers, optional default values, and executing code blocks based on user selection. The macro supports chained questions for complex interactions. ```Rust #[macro_export] macro_rules! ask { ( $skin: expr, $question: expr, { $(($key: expr, $answer: expr) => $r: block)+ } ) => {{ ... }}; } ``` -------------------------------- ### MadView Initialization Source: https://docs.rs/termimad/0.34.0/src/termimad/views/mad_view Provides a constant function `from` to create a new MadView instance with provided markdown, area, and skin. Initializes scroll to 0. ```Rust pub const fn from(markdown: String, area: Area, skin: MadSkin) -> MadView { MadView { markdown, area, skin, scroll: 0, } } ``` -------------------------------- ### Get Default Skin Source: https://docs.rs/termimad/0.34.0/termimad/index Returns a reference to the global skin used for terminal rendering. This is likely a default configuration for styling. ```rust fn get_default_skin() -> &'static Skin // Return a reference to the global skin ``` -------------------------------- ### Default MadSkin Initialization (Rust) Source: https://docs.rs/termimad/0.34.0/src/termimad/skin Provides a default MadSkin configuration with sensible gray-level settings suitable for most terminals. It initializes styles for various markdown elements, including bold, italic, code, headers, and table borders. ```Rust impl Default for MadSkin { /// Build a customizable skin. /// /// It's initialized with sensible gray level settings which should work /// whatever the terminal colors. /// /// If you want a default skin and you already know if your terminal /// is light or dark, you may use [MadSkin::default_light] /// or [MadSkin::default_dark]. fn default() -> Self { let mut skin = Self { paragraph: LineStyle::default(), bold: CompoundStyle::with_attr(Attribute::Bold), italic: CompoundStyle::with_attr(Attribute::Italic), strikeout: CompoundStyle::with_attr(Attribute::CrossedOut), inline_code: CompoundStyle::with_fgbg(gray(17), gray(3)), code_block: LineStyle::default(), headers: Default::default(), scrollbar: ScrollBarStyle::new(), table: CompoundStyle::with_fg(gray(7)).into(), bullet: StyledChar::from_fg_char(gray(8), '•'), quote_mark: StyledChar::new( CompoundStyle::new(Some(gray(12)), None, Attribute::Bold.into()), '▐', ), horizontal_rule: StyledChar::from_fg_char(gray(6), '―'), ellipsis: CompoundStyle::default(), table_border_chars: STANDARD_TABLE_BORDER_CHARS, list_items_indentation_mode: Default::default(), #[cfg(feature = "special-renders")] special_chars: std::collections::HashMap::new(), }; skin.code_block.set_fgbg(gray(17), gray(3)); for h in &mut skin.headers { h.add_attr(Attribute::Underlined); } skin.headers[0].add_attr(Attribute::Bold); skin.headers[0].align = Alignment::Center; skin } } ``` -------------------------------- ### Rust: Get Row Counts Source: https://docs.rs/termimad/0.34.0/src/termimad/views/list_view Returns a tuple containing the number of displayed rows and the total number of rows in the table. ```Rust pub fn row_counts(&self) -> (usize, usize) { (self.displayed_rows_count, self.rows.len()) } ``` -------------------------------- ### Get Default Skin Source: https://docs.rs/termimad/0.34.0/index Returns a reference to the global skin used for terminal rendering. This is likely a default configuration for styling. ```rust fn get_default_skin() -> &'static Skin // Return a reference to the global skin ``` -------------------------------- ### Manage FmtComposite Spacing and Width Source: https://docs.rs/termimad/0.34.0/src/termimad/composite Includes methods for managing spacing and width of FmtComposite. `completions` returns padding, `add_compound` appends a compound and updates width, and `recompute_width` recalculates the visible length. ```rust pub const fn completions(&self) -> (usize, usize) { match &self.spacing { Some(spacing) => spacing.completions_for(self.visible_length), None => (0, 0), } } #[inline(always)] pub fn add_compound(&mut self, compound: Compound<'s>) { self.visible_length += compound.src.width(); self.compounds.push(compound); } pub fn recompute_width(&mut self, skin: &MadSkin) { self.visible_length = skin.visible_composite_length(self.kind, &self.compounds); } ``` -------------------------------- ### Get Terminal Size Source: https://docs.rs/termimad/0.34.0/termimad Returns a tuple containing the width and height of the available terminal in characters. This is essential for responsive terminal rendering. ```rust fn terminal_size() -> Option<(u16, u16)> // Return a (width, height) with the dimensions of the available terminal in characters. ``` -------------------------------- ### Build Formatted Text from Minimad Text Object Source: https://docs.rs/termimad/0.34.0/src/termimad/text Initializes a `FmtText` object from an existing `minimad::Text` object. This method handles the internal processing, including table fixing, code block justification, and hard wrapping of lines based on the provided width and skin. ```rust pub fn from_text( skin: &'k MadSkin, mut text: Text<'s>, width: Option, ) -> FmtText<'k, 's> { let mut lines = text .lines .drain(..) .map(|mline| FmtLine::from(mline, skin)) .collect(); tbl::fix_all_tables(&mut lines, width.unwrap_or(usize::MAX), skin); code::justify_blocks(&mut lines); if let Some(width) = width { if width >= 3 { lines = wrap::hard_wrap_lines(lines, width, skin).expect("width should be wide enough"); } } FmtText { skin, lines, width } } ``` -------------------------------- ### Get Terminal Size Source: https://docs.rs/termimad/0.34.0/termimad/index Returns a tuple containing the width and height of the available terminal in characters. This is essential for responsive terminal rendering. ```rust fn terminal_size() -> Option<(u16, u16)> // Return a (width, height) with the dimensions of the available terminal in characters. ``` -------------------------------- ### Create CropWriter Instance Source: https://docs.rs/termimad/0.34.0/src/termimad/fit/crop_writer Initializes a new CropWriter with a given writer and a column limit. The writer is wrapped to enforce the specified width constraint. ```Rust pub fn new(w: &'w mut W, limit: usize) -> Self { Self { w, allowed: limit, tab_replacement: DEFAULT_TAB_REPLACEMENT, } } ``` -------------------------------- ### Create and Style Characters with StyledChar in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/styled_char Demonstrates the creation of StyledChar instances with default and custom styles, including setting foreground and background colors. It also shows how to retrieve the current character and its style. ```rust pub fn new(compound_style: CompoundStyle, nude_char: char) -> StyledChar { Self { nude_char, styled_char: compound_style.apply_to(nude_char), compound_style, } } pub fn nude(nude_char: char) -> StyledChar { Self::new(CompoundStyle::default(), nude_char) } pub fn from_fg_char(fg: Color, nude_char: char) -> StyledChar { Self::new(CompoundStyle::with_fg(fg), nude_char) } ``` -------------------------------- ### Get Terminal Size Source: https://docs.rs/termimad/0.34.0/termimad/fn Retrieves the current dimensions of the terminal window in characters. This function returns a tuple containing the width and height. ```Rust pub fn terminal_size() -> (u16, u16) ``` -------------------------------- ### Create and Initialize InputField Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field Provides a constructor for creating a new `InputField` instance with a specified area. It initializes default styles for focused and unfocused states, including a reversed style for the cursor. ```rust pub fn new(area: Area) -> Self { let focused_style = CompoundStyle::default(); let unfocused_style = CompoundStyle::default(); let mut cursor_style = focused_style.clone(); cursor_style.add_attr(Attribute::Reverse); Self { content: InputFieldContent::default(), area, focused_style, unfocused_style, cursor_style, password_mode: false, focused: true, scroll: Pos::default(), new_line_keys: Vec::default(), } } ``` -------------------------------- ### Get Terminal Size Source: https://docs.rs/termimad/0.34.0/index Returns a tuple containing the width and height of the available terminal in characters. This is essential for responsive terminal rendering. ```rust fn terminal_size() -> Option<(u16, u16)> // Return a (width, height) with the dimensions of the available terminal in characters. ``` -------------------------------- ### Get Attributes in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/compound_style Retrieves the `Attributes` associated with the MadSkin's `object_style`. These attributes define the visual properties like color and boldness. ```Rust pub fn attrs(&self) -> Attributes { self.object_style.attributes } ``` -------------------------------- ### Rust: Initialize Table Fitter Source: https://docs.rs/termimad/0.34.0/src/termimad/fit/tbl_fit Implements the `new` function for the `TblFit` struct, which initializes the table fitter. It takes the number of columns and the total available width as input. It returns an error if the available width is insufficient for the minimum required width of the columns and borders. ```Rust impl TblFit { /// Build a new fitter, or return an error if the width isn't enough /// for the given number of columns. /// /// available_width: total available width, including external borders pub fn new(cols_count: usize, available_width: usize) -> Result { if available_width < cols_count * 4 + 1 { return Err(InsufficientWidthError { available_width }); } let cols = vec![ColData::default(); cols_count]; let available_sum_width = available_width - 1 - cols_count; Ok(Self { cols, available_sum_width, }) } // ... other methods ``` -------------------------------- ### Rust Macros for Terminal Output Source: https://docs.rs/termimad/0.34.0/termimad/all Provides macros for inline printing and asking questions in the terminal. These macros simplify common terminal interaction patterns. ```Rust /// Ask a question in the terminal and return the answer. /// /// # Examples /// /// ```no_run /// let answer = ask("What is your name?"); /// println!("Hello, {}", answer); /// ``` macro_rules! ask { ($question:expr) => { ... }; } /// Print text inline in the terminal. /// /// # Examples /// /// ```no_run /// mad_print_inline!("This is inline text."); /// ``` macro_rules! mad_print_inline { ($($arg:tt)*) => { ... }; } /// Print text inline in the terminal with styling. /// /// # Examples /// /// ```no_run /// mad_write_inline!("This is styled inline text."); /// ``` macro_rules! mad_write_inline { ($($arg:tt)*) => { ... }; } ``` -------------------------------- ### Rust: Get Buffer End Position Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field_content Returns the position at the very end of the text buffer, useful for operations that need to reference the last character or line. ```Rust /// return the position on end, where the cursor should be put /// initially pub fn end(&self) -> Pos { let y = self.lines.len() - 1; Pos { x: self.lines[y].chars.len(), y, } } ``` -------------------------------- ### Rust InputFieldContent Cursor Position Management Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field_content Provides methods to get the current cursor position and set a new cursor position, ensuring validity. ```Rust impl InputFieldContent { pub const fn cursor_pos(&self) -> Pos { self.pos } /// Set the cursor position. /// /// The position set may be different to ensure consistency /// (for example if it's after the end, it will be set back). pub fn set_cursor_pos(&mut self, new_pos: Pos) { self.pos = self.make_valid_pos(new_pos); } /// Return the given pos, maybe modified to be valid for the content pub fn make_valid_pos(&self, mut pos: Pos) -> Pos { if pos.y >= self.lines.len() { self.end() } else { pos.x = pos.x.min(self.lines[pos.y].chars.len()); pos } } } ``` -------------------------------- ### Define Question Struct for User Input Source: https://docs.rs/termimad/0.34.0/src/termimad/ask Defines the `Question` struct used to build interactive prompts. It includes the question text, a list of possible answers, and an optional default answer. The struct supports adding answers with keys and setting a default response. ```Rust pub struct Question { pub md: Option, pub answers: Vec, pub default_answer: Option, } pub struct Answer { pub key: String, pub md: String, } impl Question { pub fn new>(md: S) -> Self { Self { md: Some(md.into()), answers: Vec::new(), default_answer: None, } } pub fn add_answer>(&mut self, key: K, md: S) { self.answers.push(Answer { key: key.to_string(), md: md.into(), }); } pub fn set_default(&mut self, default_answer: K) { self.default_answer = Some(default_answer.to_string()); } pub fn has_exotic_default(&self) -> bool { if let Some(da) = self.default_answer.as_ref() { for answer in &self.answers { if &answer.key == da { return false; } } true } else { false } } pub fn ask(&self, skin: &MadSkin) -> io::Result { if let Some(md) = &self.md { skin.print_text(md); } for a in &self.answers { if self.default_answer.as_ref() == Some(&a.key) { mad_print_inline!(skin, "[**$0**] ", a.key); } else { mad_print_inline!(skin, "[$0] ", a.key); } skin.print_text(&a.md); } loop { let mut input = String::new(); io::stdin().read_line(&mut input)?; input.truncate(input.trim_end().len()); if input.is_empty() { if let Some(da) = &self.default_answer { return Ok(da.clone()); } } for a in &self.answers { if a.key == input { return Ok(input); } } println!("answer {:?} not understood", input); } } } ``` -------------------------------- ### Create and Queue Filling String in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/fit/filling Demonstrates how to create a filling string with a specified character and queue it for unstyled or styled output using crossterm. It handles filling large lengths efficiently by using a pre-defined string. ```Rust use { crate::{ crossterm::{ style::Print, QueueableCommand, }, *, }, std::io::Write, }; const FILLING_STRING_CHAR_LEN: usize = 1000; /// something to fill with pub struct Filling { filling_string: String, char_size: usize, } impl Filling { pub fn from_char(filling_char: char) -> Self { let char_size = String::from(filling_char).len(); let mut filling_string = String::with_capacity(char_size * FILLING_STRING_CHAR_LEN); for _ in 0..FILLING_STRING_CHAR_LEN { filling_string.push(filling_char); } Self { filling_string, char_size, } } pub fn queue_unstyled(&self, w: &mut W, mut len: usize) -> Result<(), Error> { while len > 0 { let sl = len.min(FILLING_STRING_CHAR_LEN); w.queue(Print(&self.filling_string[0..sl * self.char_size]))?; len -= sl; } Ok(()) } pub fn queue_styled( &self, w: &mut W, cs: &CompoundStyle, mut len: usize, ) -> Result<(), Error> { while len > 0 { let sl = len.min(FILLING_STRING_CHAR_LEN); cs.queue_str(w, &self.filling_string[0..sl * self.char_size])?; len -= sl; } Ok(()) } } ``` -------------------------------- ### Get Input Field Content Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field Provides access to the input field's content. It offers a direct reference to the content and a method to convert it to a `String`. ```Rust pub const fn content(&self) -> &InputFieldContent { &self.content } pub fn get_content(&self) -> String { self.content.to_string() } ``` -------------------------------- ### Rust: Move Cursor to Start of Document Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field_content Moves the cursor to the beginning of the document (first character of the first line). Returns true if the position changed. ```Rust pub fn move_to_start(&mut self) -> bool { let pos = Pos { x: 0, y: 0 }; if pos == self.pos { false } else { self.pos = pos; true } } ``` -------------------------------- ### Get Compound Style Source: https://docs.rs/termimad/0.34.0/src/termimad/skin Constructs a `CompoundStyle` for a given compound, composing base styles from the skin. It applies styles for italics, strikeout, bold, and inline code. ```Rust pub fn compound_style(&self, line_style: &LineStyle, compound: &Compound<'_>) -> CompoundStyle { if *compound.src == *crate::fit::ELLIPSIS { return self.ellipsis.clone(); } let mut os = line_style.compound_style.clone(); if compound.italic { os.overwrite_with(&self.italic); } if compound.strikeout { os.overwrite_with(&self.strikeout); } if compound.bold { os.overwrite_with(&self.bold); } if compound.code { os.overwrite_with(&self.inline_code); } os } ``` -------------------------------- ### Test MadSkin JSON Roundtrip Source: https://docs.rs/termimad/0.34.0/src/termimad/serde/serde_skin Tests the serialization and deserialization process for the `MadSkin` struct by converting a default `MadSkin` instance to JSON and then back, asserting that the original and deserialized versions are identical. ```Rust #[test] fn skin_json_roundtrip() { use { crate::{ crossterm::style::{ Attribute, Color::*, }, gray, rgb, StyledChar, ROUNDED_TABLE_BORDER_CHARS, }, pretty_assertions::assert_eq, }; let skin = MadSkin::default(); let serialized = serde_json::to_string_pretty(&skin).unwrap(); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(skin, deserialized); } ``` -------------------------------- ### Get StyledChar Information in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/styled_char Includes methods to retrieve the current character, foreground color, background color, and the overall compound style of a StyledChar instance. ```rust pub const fn get_char(&self) -> char { self.nude_char } pub const fn get_fg(&self) -> Option { self.compound_style.get_fg() } pub const fn get_bg(&self) -> Option { self.compound_style.get_bg() } pub fn compound_style(&self) -> &CompoundStyle { &self.compound_style } ``` -------------------------------- ### Create Dark Terminal Skin Source: https://docs.rs/termimad/0.34.0/src/termimad/skin Builds a customizable skin with gray levels suitable for terminals with a dark background. It sets foreground and background colors for code blocks, inline code, and headers. ```rust pub fn default_dark() -> Self { let mut skin = Self::default(); skin.code_block.set_fgbg(gray(20), gray(5)); skin.inline_code.set_fgbg(gray(20), gray(5)); skin.headers[0].set_fg(gray(22)); skin.headers[1].set_fg(gray(21)); skin.headers[2].set_fg(gray(20)); skin } ``` -------------------------------- ### Get Timed Event Receiver in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/events/event_source Returns a new receiver for the channel that emits `TimedEvent`s. This allows other parts of the application to listen for and process events as they occur. ```Rust pub fn receiver(&self) -> Receiver { self.rx_events.clone() } ``` -------------------------------- ### Initialize LineStyle in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/line_style Provides a constructor for `LineStyle` with a given `CompoundStyle` and `Alignment`. It initializes margins to zero. ```Rust pub fn new(compound_style: CompoundStyle, align: Alignment) -> Self { Self { compound_style, align, left_margin: 0, right_margin: 0, } } ``` -------------------------------- ### Get Line Style Source: https://docs.rs/termimad/0.34.0/src/termimad/skin Returns the appropriate `LineStyle` for a given `CompositeKind`. It handles specific styles for code blocks and headers based on their level, defaulting to the paragraph style. ```Rust pub const fn line_style(&self, kind: CompositeKind) -> &LineStyle { match kind { CompositeKind::Code => &self.code_block, CompositeKind::Header(level) if level <= MAX_HEADER_DEPTH as u8 => { &self.headers[level as usize - 1] } _ => &self.paragraph, } } ``` -------------------------------- ### Repeat and Queue Styled Characters in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/styled_char Demonstrates how to create a styled string by repeating a character multiple times and how to queue this styled string for terminal output. It also shows a direct method to queue a single styled character. ```rust pub fn repeated(&self, count: usize) -> StyledContent { let mut s = String::new(); for _ in 0..count { s.push(self.nude_char); } self.compound_style.apply_to(s) } pub fn queue_repeat(&self, w: &mut W, count: usize) -> Result<()> { let mut s = String::new(); for _ in 0..count { s.push(self.nude_char); } self.compound_style.queue(w, s) } pub fn queue(&self, w: &mut W) -> Result<()> { w.queue(PrintStyledContent(self.styled_char))?; Ok(()) } ``` -------------------------------- ### Create Follow-up Composite for Wrapping Source: https://docs.rs/termimad/0.34.0/src/termimad/fit/wrap Generates a new `FmtComposite` suitable for subsequent lines after a text wrap. It adjusts the `CompositeKind` to `ListItemFollowUp` if the original was a list item and calculates the appropriate `visible_length` based on skin settings for list item indentation. ```Rust 1#[allow(unused_imports)] 2use { 3 crate::{ 4 minimad::*, 5 *, 6 }, 7 unicode_width::UnicodeWidthStr, 8}; 9 10/// build a composite which can be a new line after wrapping. 11fn follow_up_composite<'s>(fc: &FmtComposite<'s>, skin: &MadSkin) -> FmtComposite<'s> { 12 let kind = match fc.kind { 13 CompositeKind::ListItem(l) => CompositeKind::ListItemFollowUp(l), 14 k => k, 15 }; 16 let visible_length = match kind { 17 CompositeKind::ListItemFollowUp(l) 18 if skin.list_items_indentation_mode == ListItemsIndentationMode::Block => 19 { 20 2 + l as usize 21 } 22 CompositeKind::Quote => 2, 23 _ => 0, 24 }; 25 FmtComposite { 26 kind, 27 compounds: Vec::new(), 28 visible_length, 29 spacing: fc.spacing, 30 } 31} ``` -------------------------------- ### Rust: Move Cursor to Start of Line Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field_content Moves the cursor to the beginning of the current line (column 0). Returns true if the cursor's X position changed. ```Rust pub fn move_to_line_start(&mut self) -> bool { if self.pos.x > 0 { self.pos.x = 0; true } else { false } } ``` -------------------------------- ### Get Cropped String and Width Source: https://docs.rs/termimad/0.34.0/src/termimad/fit/crop_writer Returns a Cow containing either the original string or a portion of it that fits within the remaining allowed columns, along with the width of the returned string. ```Rust pub fn cropped_str<'a>(&self, s: &'a str) -> (Cow<'a, str>, usize) { StrFit::make_cow(s, self.allowed) } ``` -------------------------------- ### Rust: Implement CloneToUninit for StyleToken (Nightly) Source: https://docs.rs/termimad/0.34.0/termimad/enum A nightly-only experimental API that performs copy-assignment from a StyleToken to an uninitialized memory location. Requires the `Clone` trait. ```rust impl CloneToUninit for T where T: Clone, { unsafe fn clone_to_uninit(&self, dest: *mut u8) } ``` -------------------------------- ### Get Position from Mouse Event in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/views/input_field Retrieves the cursor position (Pos) from a given mouse event. It utilizes the `get_pos` function to translate screen coordinates to text content coordinates. ```Rust pub fn get_mouse_event_pos(&self, mouse_event: MouseEvent) -> Option { self.get_pos(mouse_event.row, mouse_event.column) } ``` -------------------------------- ### TextView Initialization - Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/views/text_view Defines a constant function `from` to create a new TextView instance. It takes references to an Area and FmtText, initializing the TextView with default scroll position and scrollbar visibility. ```rust pub const fn from(area: &'a Area, text: &'t FmtText<'_, '_>) -> TextView<'a, 't> { TextView { area, text, scroll: 0, show_scrollbar: true, } } ``` -------------------------------- ### Get Scrollbar Position in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/views/list_view Implements the `scrollbar` method for `ListView`, which returns the position of the vertical scrollbar if the content exceeds the available display area. It returns `None` if the content fits. ```Rust impl<'t, T> ListView<'t, T> { // ... other methods ... /// return an option which when filled contains /// a tupple with the top and bottom of the vertical /// scrollbar. Return none when the content fits /// the available space. #[inline(always)] pub fn scrollbar(&self) -> Option<(u16, u16)> { // Implementation details for scrollbar calculation would go here } } ``` -------------------------------- ### Initialize ListView in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/views/list_view Provides the `new` function for the `ListView` struct, which initializes a new list view with specified area, columns, and skin. It handles merging titles for columns with identical titles. ```Rust pub struct ListView<'t, T> { titles: Vec, columns: Vec<ListViewColumn<'t, T>>, rows: Vec<Row<T>>, pub area: Area, scroll: usize, pub skin: &'t MadSkin, filter: Option<Box<dyn Fn(&T) -> bool>>, displayed_rows_count: usize, row_order: Option<Box<dyn Fn(&T, &T) -> Ordering>>, selection: Option<usize>, selection_background: Color, } impl<'t, T> ListView<'t, T> { /// Create a new list view with the passed columns. /// /// The columns can't be changed afterwards but the area can be modified. /// When two columns have the same title, those titles are merged (but /// the columns below stay separated). pub fn new(area: Area, columns: Vec<ListViewColumn<'t, T>>, skin: &'t MadSkin) -> Self { let mut titles: Vec<Title> = Vec::new(); for (column_idx, column) in columns.iter().enumerate() { if let Some(last_title) = titles.last_mut() { if columns[last_title.columns[0]].title == column.title { // we merge those columns titles last_title.columns.push(column_idx); continue; } } // this is a new title titles.push(Title { columns: vec![column_idx], }); } Self { titles, columns, rows: Vec::new(), area, scroll: 0, skin, filter: None, displayed_rows_count: 0, row_order: None, selection: None, selection_background: gray(5), } } // ... other methods ... ``` -------------------------------- ### Write Formatted Composite (Rust) Source: https://docs.rs/termimad/0.34.0/src/termimad/skin Internal function for writing a formatted composite to a `fmt::Formatter`. It handles margins and completions based on provided options. ```rust pub fn write_fmt_composite( &self, f: &mut fmt::Formatter<'_>, fc: &FmtComposite<'_>, outer_width: Option<usize>, with_right_completion: bool, with_margins: bool, ) -> fmt::Result { let ls = self.line_style(fc.kind); let (left_margin, right_margin) = if with_margins { ls.margins_in(outer_width) } else { (0, 0) }; let (lpi, rpi) = fc.completions(); // inner completion // ... rest of the function implementation ``` -------------------------------- ### Get Escape Sequence Receiver in Rust Source: https://docs.rs/termimad/0.34.0/src/termimad/events/event_source Provides a new receiver for the channel emitting escape sequences. This is a bounded channel, meaning any escape sequences will be dropped if the channel becomes full. ```Rust pub fn escape_sequence_receiver(&self) -> Receiver<EscapeSequence> { self.rx_seqs.clone() } ``` -------------------------------- ### Rust StrFit: Create fitting Cow string with tab replacement Source: https://docs.rs/termimad/0.34.0/src/termimad/fit/str_fit The `make_cow` method creates a `Cow<'_, str>` (Clone-on-Write string) representing the fitting portion of the input string. If tabs are present, it creates an owned `String`; otherwise, it returns a borrowed slice, optimizing memory usage. ```rust pub fn make_cow(s: &str, cols_max: usize) -> (Cow<'_, str>, usize) { let fit = StrFit::from(s, cols_max); if fit.has_tab { // we can't just borrow, as we insert chars let string = (s[0..fit.bytes_count]).replace('\t', TAB_REPLACEMENT); (Cow::Owned(string), fit.cols_count) } else { (Cow::Borrowed(&s[0..fit.bytes_count]), fit.cols_count) } } ```