aboutsummaryrefslogtreecommitdiff
path: root/mling/src/display.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-20 15:29:22 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-20 15:29:22 +0800
commit62e323c80306d7dca68e47377a0ed6f4e146ba48 (patch)
tree0c6fe91d7197c83af52b08f793d12b0f01646d7d /mling/src/display.rs
parent33da7c8cb4f24caeef4e8127bc484bc9d236a0f3 (diff)
feat: remove deprecated mling scaffolding tool
The mling CLI tool is being rewritten, so remove all its source files, resources, and workspace membership to clean up the repository
Diffstat (limited to 'mling/src/display.rs')
-rw-r--r--mling/src/display.rs384
1 files changed, 0 insertions, 384 deletions
diff --git a/mling/src/display.rs b/mling/src/display.rs
deleted file mode 100644
index 313a054..0000000
--- a/mling/src/display.rs
+++ /dev/null
@@ -1,384 +0,0 @@
-use colored::Colorize;
-use std::collections::VecDeque;
-
-/// Trait for adding markdown formatting to strings
-pub trait Markdown {
- fn markdown(&self) -> String;
-}
-
-impl Markdown for &str {
- fn markdown(&self) -> String {
- markdown(self)
- }
-}
-
-impl Markdown for String {
- fn markdown(&self) -> String {
- markdown(self)
- }
-}
-
-/// Converts a string to colored/formatted text with ANSI escape codes.
-///
-/// Supported syntax:
-/// - Bold: `**text**`
-/// - Italic: `*text*`
-/// - Underline: `_text_`
-/// - Angle-bracketed content: `<text>` (displayed as cyan)
-/// - Inline code: `` `text` `` (displayed as green)
-/// - Color tags: `[[color_name]]` and `[[/]]` to close color
-/// - Escape characters: `\*`, `\<`, `\>`, `` \` ``, `\_` for literal characters
-/// - Headings: `# Heading 1`, `## Heading 2`, up to `###### Heading 6`
-/// - Blockquote: `> text` (displays a gray background marker at the beginning of the line)
-///
-/// Color tags support the following color names:
-/// Color tags support the following color names:
-///
-/// | Type | Color Names |
-/// |-------------------------|-----------------------------------------------------------------------------|
-/// | Standard colors | `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white` |
-/// | Bright colors | `bright_black` |
-/// | | `bright_red` |
-/// | | `bright_green` |
-/// | | `bright_yellow` |
-/// | | `bright_blue` |
-/// | | `bright_magenta` |
-/// | | `bright_cyan` |
-/// | | `bright_white` |
-/// | Bright color shorthands | `b_black` |
-/// | | `b_red` |
-/// | | `b_green` |
-/// | | `b_yellow` |
-/// | | `b_blue` |
-/// | | `b_magenta` |
-/// | | `b_cyan` |
-/// | | `b_white` |
-/// | Gray colors | `gray`/`grey` |
-/// | | `bright_gray`/`bright_grey` |
-/// | | `b_gray`/`b_grey` |
-///
-/// Color tags can be nested, `[[/]]` will close the most recently opened color tag.
-///
-/// # Arguments
-/// * `text` - The text to format, can be any type that implements `AsRef<str>`
-///
-/// # Returns
-/// Returns a `String` containing ANSI escape codes that can display colored/formatted text in ANSI-supported terminals.
-///
-/// # Examples
-/// ```
-/// # use mingling_cli::display::markdown;
-/// let formatted = markdown("Hello **world**!");
-/// println!("{}", formatted);
-///
-/// let colored = markdown("[[red]]Red text[[/]] and normal text");
-/// println!("{}", colored);
-///
-/// let nested = markdown("[[blue]]Blue [[green]]Green[[/]] Blue[[/]] normal");
-/// println!("{}", nested);
-/// ```
-pub fn markdown(text: impl AsRef<str>) -> String {
- let text = text.as_ref();
- let lines: Vec<&str> = text.lines().collect();
- let mut result = String::new();
- let mut content_indent = 0;
-
- for line in lines {
- // Don't trim the line initially, we need to check if it starts with #
- let trimmed_line = line.trim();
- let mut line_result = String::new();
-
- // Check if line starts with # for heading
- // Check if the original line (not trimmed) starts with #
- if line.trim_start().starts_with('#') {
- let chars: Vec<char> = line.trim_start().chars().collect();
- let mut level = 0;
-
- // Count # characters at the beginning
- while level < chars.len() && level < 7 && chars[level] == '#' {
- level += 1;
- }
-
- // Cap level at 6
- let effective_level = if level > 6 { 6 } else { level };
-
- // Skip # characters and any whitespace after them
- let mut content_start = level;
- while content_start < chars.len() && chars[content_start].is_whitespace() {
- content_start += 1;
- }
-
- // Extract heading content
- let heading_content: String = if content_start < chars.len() {
- chars[content_start..].iter().collect()
- } else {
- String::new()
- };
-
- // Process the heading content with formatting
- let processed_content = process_line(&heading_content);
-
- // Format heading as white background, black text, bold
- // ANSI codes: \x1b[1m for bold, \x1b[47m for white background, \x1b[30m for black text
- let formatted_heading = format!("\x1b[1m\x1b[47m\x1b[30m {processed_content} \x1b[0m");
-
- // Add indentation to the heading line itself
- // Heading indentation = level - 1
- let heading_indent = if effective_level > 0 {
- effective_level - 1
- } else {
- 0
- };
- let indent = " ".repeat(heading_indent);
- line_result.push_str(&indent);
- line_result.push_str(&formatted_heading);
-
- // Update content indent level for subsequent content
- // Content after heading should be indented by effective_level
- content_indent = effective_level;
- } else if !trimmed_line.is_empty() {
- // Process regular line with existing formatting
- let processed_line = process_line_with_quote(trimmed_line);
-
- // Add indentation based on content_indent
- let indent = " ".repeat(content_indent);
- line_result.push_str(&indent);
- line_result.push_str(&processed_line);
- } else {
- line_result.push(' ');
- }
-
- if !line_result.is_empty() {
- result.push_str(&line_result);
- result.push('\n');
- }
- }
-
- // Remove trailing newline
- if result.ends_with('\n') {
- result.pop();
- }
-
- result
-}
-
-// Helper function to process a single line with existing formatting and handle > quotes
-fn process_line_with_quote(line: &str) -> String {
- let chars: Vec<char> = line.chars().collect();
-
- // Check if line starts with '>' and not escaped
- if !chars.is_empty() && chars[0] == '>' {
- // Check if it's escaped
- if chars.len() > 1 && chars[1] == '\\' {
- // It's \>, so treat as normal text starting from position 0
- return process_line(line);
- }
-
- // It's a regular > at the beginning, replace with gray background gray text space
- let gray_bg_space = "\x1b[48;5;242m\x1b[38;5;242m \x1b[0m";
- let rest_of_line = if chars.len() > 1 {
- chars[1..].iter().collect::<String>()
- } else {
- String::new()
- };
-
- // Process the rest of the line normally
- let processed_rest = process_line(&rest_of_line);
-
- // Combine the gray background space with the processed rest
- format!("{gray_bg_space}{processed_rest}")
- } else {
- // No > at the beginning, process normally
- process_line(line)
- }
-}
-
-// Helper function to process a single line with existing formatting
-fn process_line(line: &str) -> String {
- let mut result = String::new();
- let mut color_stack: VecDeque<String> = VecDeque::new();
-
- let chars: Vec<char> = line.chars().collect();
- let mut i = 0;
-
- while i < chars.len() {
- // Check for escape character \
- if chars[i] == '\\' && i + 1 < chars.len() {
- let escaped_char = chars[i + 1];
- // Only escape specific characters
- if matches!(escaped_char, '*' | '<' | '>' | '`' | '_') {
- let mut escaped_text = escaped_char.to_string();
- apply_color_stack(&mut escaped_text, &color_stack);
- result.push_str(&escaped_text);
- i += 2;
- continue;
- }
- }
-
- // Check for color tag start [[color]]
- if i + 1 < chars.len()
- && chars[i] == '['
- && chars[i + 1] == '['
- && let Some(end) = find_tag_end(&chars, i)
- {
- let tag_content: String = chars[i + 2..end].iter().collect();
-
- // Check if it's a closing tag [[/]]
- if tag_content == "/" {
- color_stack.pop_back();
- } else {
- // It's a color tag
- color_stack.push_back(tag_content.clone());
- }
- i = end + 2;
- continue;
- }
-
- // Check for bold **text**
- if i + 1 < chars.len()
- && chars[i] == '*'
- && chars[i + 1] == '*'
- && let Some(end) = find_matching(&chars, i + 2, "**")
- {
- let bold_text: String = chars[i + 2..end].iter().collect();
- let mut formatted_text = bold_text.bold().to_string();
- apply_color_stack(&mut formatted_text, &color_stack);
- result.push_str(&formatted_text);
- i = end + 2;
- continue;
- }
-
- // Check for italic *text*
- if chars[i] == '*'
- && let Some(end) = find_matching(&chars, i + 1, "*")
- {
- let italic_text: String = chars[i + 1..end].iter().collect();
- let mut formatted_text = italic_text.italic().to_string();
- apply_color_stack(&mut formatted_text, &color_stack);
- result.push_str(&formatted_text);
- i = end + 1;
- continue;
- }
-
- // Check for underline _text_
- if chars[i] == '_'
- && let Some(end) = find_matching(&chars, i + 1, "_")
- {
- let underline_text: String = chars[i + 1..end].iter().collect();
- let mut formatted_text = format!("\x1b[4m{underline_text}\x1b[0m");
- apply_color_stack(&mut formatted_text, &color_stack);
- result.push_str(&formatted_text);
- i = end + 1;
- continue;
- }
-
- // Check for angle-bracketed content <text>
- if chars[i] == '<'
- && let Some(end) = find_matching(&chars, i + 1, ">")
- {
- // Include the angle brackets in the output
- let angle_text: String = chars[i..=end].iter().collect();
- let mut formatted_text = angle_text.cyan().to_string();
- apply_color_stack(&mut formatted_text, &color_stack);
- result.push_str(&formatted_text);
- i = end + 1;
- continue;
- }
-
- // Check for inline code `text`
- if chars[i] == '`'
- && let Some(end) = find_matching(&chars, i + 1, "`")
- {
- // Include the backticks in the output
- let code_text: String = chars[i..=end].iter().collect();
- let mut formatted_text = code_text.green().to_string();
- apply_color_stack(&mut formatted_text, &color_stack);
- result.push_str(&formatted_text);
- i = end + 1;
- continue;
- }
-
- // Regular character
- let mut current_char = chars[i].to_string();
- apply_color_stack(&mut current_char, &color_stack);
- result.push_str(&current_char);
- i += 1;
- }
-
- result
-}
-
-// Helper function to find matching delimiter
-fn find_matching(chars: &[char], start: usize, delimiter: &str) -> Option<usize> {
- let delim_chars: Vec<char> = delimiter.chars().collect();
- let delim_len = delim_chars.len();
-
- let mut j = start;
- while j < chars.len() {
- if delim_len == 1 {
- if chars[j] == delim_chars[0] {
- return Some(j);
- }
- } else if j + 1 < chars.len()
- && chars[j] == delim_chars[0]
- && chars[j + 1] == delim_chars[1]
- {
- return Some(j);
- }
- j += 1;
- }
- None
-}
-
-// Helper function to find color tag end
-fn find_tag_end(chars: &[char], start: usize) -> Option<usize> {
- let mut j = start + 2;
- while j + 1 < chars.len() {
- if chars[j] == ']' && chars[j + 1] == ']' {
- return Some(j);
- }
- j += 1;
- }
- None
-}
-
-// Helper function to apply color stack to text
-fn apply_color_stack(text: &mut String, color_stack: &VecDeque<String>) {
- let mut result = text.clone();
- for color in color_stack.iter().rev() {
- result = apply_color(&result, color);
- }
- *text = result;
-}
-
-// Helper function to apply color to text
-fn apply_color(text: impl AsRef<str>, color_name: impl AsRef<str>) -> String {
- let text = text.as_ref();
- let color_name = color_name.as_ref();
- match color_name {
- // Normal colors
- "black" => text.black().to_string(),
- "red" => text.red().to_string(),
- "green" => text.green().to_string(),
- "yellow" => text.yellow().to_string(),
- "blue" => text.blue().to_string(),
- "magenta" => text.magenta().to_string(),
- "cyan" => text.cyan().to_string(),
- "white" | "b_white" | "bright_gray" | "bright_grey" | "b_gray" | "b_grey" => {
- text.white().to_string()
- }
-
- // Bright colors and their b_ short aliases
- "bright_black" | "b_black" | "gray" | "grey" => text.bright_black().to_string(),
- "bright_red" | "b_red" => text.bright_red().to_string(),
- "bright_green" | "b_green" => text.bright_green().to_string(),
- "bright_yellow" | "b_yellow" => text.bright_yellow().to_string(),
- "bright_blue" | "b_blue" => text.bright_blue().to_string(),
- "bright_magenta" | "b_magenta" => text.bright_magenta().to_string(),
- "bright_cyan" | "b_cyan" => text.bright_cyan().to_string(),
- "bright_white" => text.bright_white().to_string(),
-
- // Default to white if color not recognized
- _ => text.to_string(),
- }
-}