string_width

Function string_width 

Source
pub fn string_width(input: &str) -> usize
Expand description

Convenience function for calculating string width with default options

This is the main public API for simple width calculations. It uses default options (no ANSI counting, ambiguous as narrow).

§Arguments

  • input - The string to measure

§Returns

The display width of the string in terminal columns

§Examples

use string_width::string_width;

assert_eq!(string_width("Hello"), 5);
assert_eq!(string_width("你好"), 4);  // Chinese characters
assert_eq!(string_width("😀"), 2);  // Emoji
assert_eq!(string_width("\x1b[31mRed\x1b[0m"), 3);  // ANSI stripped
Examples found in repository?
examples/basic_usage.rs (line 14)
8fn main() {
9    println!("=== Basic String Width Examples ===\n");
10
11    // Basic ASCII text
12    let text = "Hello, World!";
13    println!("Text: '{}'", text);
14    println!("Width: {}\n", string_width(text));
15
16    // East Asian characters (full-width)
17    let text = "你好世界";
18    println!("Text: '{}'", text);
19    println!("Width: {}\n", string_width(text));
20
21    // Mixed content
22    let text = "Hello 世界!";
23    println!("Text: '{}'", text);
24    println!("Width: {}\n", string_width(text));
25
26    // Emoji examples
27    let text = "Hello 👋 World 🌍";
28    println!("Text: '{}'", text);
29    println!("Width: {}\n", string_width(text));
30
31    // Complex emoji sequences
32    let text = "Family: 👨‍👩‍👧‍👦";
33    println!("Text: '{}'", text);
34    println!("Width: {}\n", string_width(text));
35
36    // Keycap sequences
37    let text = "Numbers: 1️⃣ 2️⃣ 3️⃣";
38    println!("Text: '{}'", text);
39    println!("Width: {}\n", string_width(text));
40
41    // Flag sequences
42    let text = "Flags: 🇺🇸 🇯🇵 🇬🇧";
43    println!("Text: '{}'", text);
44    println!("Width: {}\n", string_width(text));
45
46    // ANSI escape sequences (stripped by default)
47    let text = "\x1b[31mRed text\x1b[0m";
48    println!("Text with ANSI: '{}'", text);
49    println!("Width (ANSI stripped): {}", string_width(text));
50
51    let options = StringWidthOptions {
52        count_ansi: true,
53        ambiguous_width: AmbiguousWidthTreatment::Narrow,
54    };
55    println!(
56        "Width (ANSI counted): {}\n",
57        string_width_with_options(text, options)
58    );
59
60    // Ambiguous width characters
61    let text = "±×÷";
62    println!("Text: '{}'", text);
63    println!("Width (narrow): {}", string_width(text));
64
65    let options = StringWidthOptions {
66        count_ansi: false,
67        ambiguous_width: AmbiguousWidthTreatment::Wide,
68    };
69    println!(
70        "Width (wide): {}\n",
71        string_width_with_options(text, options)
72    );
73
74    // Zero-width characters
75    let text = "a\u{200B}b\u{200C}c";
76    println!("Text with zero-width chars: 'a\\u{{200B}}b\\u{{200C}}c'");
77    println!("Width: {}\n", string_width(text));
78
79    // Combining characters
80    let text = "e\u{0301}"; // e with acute accent
81    println!("Text with combining: 'e\\u{{0301}}'");
82    println!("Width: {}\n", string_width(text));
83}
More examples
Hide additional examples
examples/cli_tool.rs (line 61)
12fn main() {
13    let args: Vec<String> = env::args().collect();
14
15    let input = if args.len() > 1 {
16        // Use command line argument
17        args[1..].join(" ")
18    } else {
19        // Read from stdin
20        let mut buffer = String::new();
21        match io::stdin().read_to_string(&mut buffer) {
22            Ok(_) => buffer.trim_end().to_string(),
23            Err(e) => {
24                eprintln!("Error reading from stdin: {}", e);
25                std::process::exit(1);
26            }
27        }
28    };
29
30    if input.is_empty() {
31        eprintln!("Usage: {} <text> or echo <text> | {}", args[0], args[0]);
32        eprintln!("       Measures the display width of Unicode text");
33        std::process::exit(1);
34    }
35
36    println!("Text analysis for: '{}'", input);
37    println!("{}", "─".repeat(50));
38
39    // Basic width
40    let width = input.display_width();
41    println!("Display width: {} characters", width);
42
43    // Character count vs display width
44    let char_count = input.chars().count();
45    let byte_count = input.len();
46    println!("Character count: {}", char_count);
47    println!("Byte count: {}", byte_count);
48
49    if width != char_count {
50        println!("Note: Display width differs from character count");
51        if width > char_count {
52            println!("  → Contains wide characters (CJK, emoji)");
53        } else {
54            println!("  → Contains zero-width or combining characters");
55        }
56    }
57
58    // Detailed analysis
59    println!("\nDetailed breakdown:");
60    for (i, ch) in input.chars().enumerate() {
61        let ch_width = string_width(ch.to_string().as_str());
62        let code_point = ch as u32;
63
64        let char_type = match ch_width {
65            0 => "zero-width",
66            1 => "narrow",
67            2 => "wide",
68            _ => "unknown",
69        };
70
71        println!(
72            "  {}: '{}' (U+{:04X}) - {} width",
73            i + 1,
74            ch,
75            code_point,
76            char_type
77        );
78    }
79
80    // Different width calculation options
81    println!("\nWidth with different options:");
82
83    let narrow_ambiguous = StringWidthOptions {
84        count_ansi: false,
85        ambiguous_width: AmbiguousWidthTreatment::Narrow,
86    };
87    println!(
88        "  Ambiguous as narrow: {}",
89        string_width_with_options(input.as_str(), narrow_ambiguous)
90    );
91
92    let wide_ambiguous = StringWidthOptions {
93        count_ansi: false,
94        ambiguous_width: AmbiguousWidthTreatment::Wide,
95    };
96    println!(
97        "  Ambiguous as wide: {}",
98        string_width_with_options(input.as_str(), wide_ambiguous)
99    );
100
101    let count_ansi = StringWidthOptions {
102        count_ansi: true,
103        ambiguous_width: AmbiguousWidthTreatment::Narrow,
104    };
105    println!(
106        "  Counting ANSI codes: {}",
107        string_width_with_options(input.as_str(), count_ansi)
108    );
109
110    // Terminal formatting example
111    println!("\nTerminal formatting examples:");
112    let box_width = 40;
113    let content_width = input.display_width();
114
115    if content_width <= box_width - 4 {
116        let padding = box_width - content_width - 4;
117        let left_pad = padding / 2;
118        let right_pad = padding - left_pad;
119
120        println!("┌{}┐", "─".repeat(box_width - 2));
121        println!(
122            "│{}{}{}│",
123            " ".repeat(left_pad + 1),
124            input,
125            " ".repeat(right_pad + 1)
126        );
127        println!("└{}┘", "─".repeat(box_width - 2));
128    } else {
129        println!(
130            "Text too wide for box (width: {}, box: {})",
131            content_width,
132            box_width - 4
133        );
134    }
135}