pub fn string_width(input: &str) -> usizeExpand 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 strippedExamples 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
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}