aboutsummaryrefslogtreecommitdiff
path: root/vendor/clap_builder/src/output/textwrap
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap_builder/src/output/textwrap')
-rw-r--r--vendor/clap_builder/src/output/textwrap/core.rs158
-rw-r--r--vendor/clap_builder/src/output/textwrap/mod.rs122
-rw-r--r--vendor/clap_builder/src/output/textwrap/word_separators.rs92
-rw-r--r--vendor/clap_builder/src/output/textwrap/wrap_algorithms.rs63
4 files changed, 0 insertions, 435 deletions
diff --git a/vendor/clap_builder/src/output/textwrap/core.rs b/vendor/clap_builder/src/output/textwrap/core.rs
deleted file mode 100644
index 2f6004c..0000000
--- a/vendor/clap_builder/src/output/textwrap/core.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-/// Compute the display width of `text`
-///
-/// # Examples
-///
-/// **Note:** When the `unicode` Cargo feature is disabled, all characters are presumed to take up
-/// 1 width. With the feature enabled, function will correctly deal with [combining characters] in
-/// their decomposed form (see [Unicode equivalence]).
-///
-/// An example of a decomposed character is “é”, which can be decomposed into: “e” followed by a
-/// combining acute accent: “◌́”. Without the `unicode` Cargo feature, every `char` has a width of
-/// 1. This includes the combining accent:
-///
-/// ## Emojis and CJK Characters
-///
-/// Characters such as emojis and [CJK characters] used in the
-/// Chinese, Japanese, and Korean languages are seen as double-width,
-/// even if the `unicode-width` feature is disabled:
-///
-/// # Limitations
-///
-/// The displayed width of a string cannot always be computed from the
-/// string alone. This is because the width depends on the rendering
-/// engine used. This is particularly visible with [emoji modifier
-/// sequences] where a base emoji is modified with, e.g., skin tone or
-/// hair color modifiers. It is up to the rendering engine to detect
-/// this and to produce a suitable emoji.
-///
-/// A simple example is “❤️”, which consists of “❤” (U+2764: Black
-/// Heart Symbol) followed by U+FE0F (Variation Selector-16). By
-/// itself, “❤” is a black heart, but if you follow it with the
-/// variant selector, you may get a wider red heart.
-///
-/// A more complex example would be “👨‍🦰” which should depict a man
-/// with red hair. Here the computed width is too large — and the
-/// width differs depending on the use of the `unicode-width` feature:
-///
-/// This happens because the grapheme consists of three code points:
-/// “👨” (U+1F468: Man), Zero Width Joiner (U+200D), and “🦰”
-/// (U+1F9B0: Red Hair). You can see them above in the test. With
-/// `unicode-width` enabled, the ZWJ is correctly seen as having zero
-/// width, without it is counted as a double-width character.
-///
-/// ## Terminal Support
-///
-/// Modern browsers typically do a great job at combining characters
-/// as shown above, but terminals often struggle more. As an example,
-/// Gnome Terminal version 3.38.1, shows “❤️” as a big red heart, but
-/// shows "👨‍🦰" as “👨🦰”.
-///
-/// [combining characters]: https://en.wikipedia.org/wiki/Combining_character
-/// [Unicode equivalence]: https://en.wikipedia.org/wiki/Unicode_equivalence
-/// [CJK characters]: https://en.wikipedia.org/wiki/CJK_characters
-/// [emoji modifier sequences]: https://unicode.org/emoji/charts/full-emoji-modifiers.html
-#[inline(never)]
-pub(crate) fn display_width(text: &str) -> usize {
- let mut width = 0;
-
- let mut control_sequence = false;
- let control_terminate: char = 'm';
-
- for ch in text.chars() {
- if ch.is_ascii_control() {
- control_sequence = true;
- } else if control_sequence && ch == control_terminate {
- control_sequence = false;
- continue;
- }
-
- if !control_sequence {
- width += ch_width(ch);
- }
- }
- width
-}
-
-#[cfg(feature = "unicode")]
-fn ch_width(ch: char) -> usize {
- unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
-}
-
-#[cfg(not(feature = "unicode"))]
-fn ch_width(_: char) -> usize {
- 1
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[cfg(feature = "unicode")]
- use unicode_width::UnicodeWidthChar;
-
- #[test]
- fn emojis_have_correct_width() {
- use unic_emoji_char::is_emoji;
-
- // Emojis in the Basic Latin (ASCII) and Latin-1 Supplement
- // blocks all have a width of 1 column. This includes
- // characters such as '#' and '©'.
- for ch in '\u{1}'..'\u{FF}' {
- if is_emoji(ch) {
- let desc = format!("{:?} U+{:04X}", ch, ch as u32);
-
- #[cfg(feature = "unicode")]
- assert_eq!(ch.width().unwrap(), 1, "char: {desc}");
-
- #[cfg(not(feature = "unicode"))]
- assert_eq!(ch_width(ch), 1, "char: {desc}");
- }
- }
-
- // Emojis in the remaining blocks of the Basic Multilingual
- // Plane (BMP), in the Supplementary Multilingual Plane (SMP),
- // and in the Supplementary Ideographic Plane (SIP), are all 1
- // or 2 columns wide when unicode-width is used, and always 2
- // columns wide otherwise. This includes all of our favorite
- // emojis such as 😊.
- for ch in '\u{FF}'..'\u{2FFFF}' {
- if is_emoji(ch) {
- let desc = format!("{:?} U+{:04X}", ch, ch as u32);
-
- #[cfg(feature = "unicode")]
- assert!(ch.width().unwrap() <= 2, "char: {desc}");
-
- #[cfg(not(feature = "unicode"))]
- assert_eq!(ch_width(ch), 1, "char: {desc}");
- }
- }
-
- // The remaining planes contain almost no assigned code points
- // and thus also no emojis.
- }
-
- #[test]
- #[cfg(feature = "unicode")]
- fn display_width_works() {
- assert_eq!("Café Plain".len(), 11); // “é” is two bytes
- assert_eq!(display_width("Café Plain"), 10);
- }
-
- #[test]
- #[cfg(feature = "unicode")]
- fn display_width_narrow_emojis() {
- assert_eq!(display_width("⁉"), 1);
- }
-
- #[test]
- #[cfg(feature = "unicode")]
- fn display_width_narrow_emojis_variant_selector() {
- assert_eq!(display_width("⁉\u{fe0f}"), 1);
- }
-
- #[test]
- #[cfg(feature = "unicode")]
- fn display_width_emojis() {
- assert_eq!(display_width("😂😭🥺🤣✨😍🙏🥰😊🔥"), 20);
- }
-}
diff --git a/vendor/clap_builder/src/output/textwrap/mod.rs b/vendor/clap_builder/src/output/textwrap/mod.rs
deleted file mode 100644
index fe8139f..0000000
--- a/vendor/clap_builder/src/output/textwrap/mod.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-//! Fork of `textwrap` crate
-//!
-//! Benefits of forking:
-//! - Pull in only what we need rather than relying on the compiler to remove what we don't need
-//! - `LineWrapper` is able to incrementally wrap which will help with `StyledStr
-
-pub(crate) mod core;
-#[cfg(feature = "wrap_help")]
-pub(crate) mod word_separators;
-#[cfg(feature = "wrap_help")]
-pub(crate) mod wrap_algorithms;
-
-#[cfg(feature = "wrap_help")]
-pub(crate) fn wrap(content: &str, hard_width: usize) -> String {
- let mut wrapper = wrap_algorithms::LineWrapper::new(hard_width);
- let mut total = Vec::new();
- for line in content.split_inclusive('\n') {
- wrapper.reset();
- let line = word_separators::find_words_ascii_space(line).collect::<Vec<_>>();
- total.extend(wrapper.wrap(line));
- }
- total.join("")
-}
-
-#[cfg(not(feature = "wrap_help"))]
-pub(crate) fn wrap(content: &str, _hard_width: usize) -> String {
- content.to_owned()
-}
-
-#[cfg(test)]
-#[cfg(feature = "wrap_help")]
-mod test {
- /// Compatibility shim to keep textwrap's tests
- fn wrap(content: &str, hard_width: usize) -> Vec<String> {
- super::wrap(content, hard_width)
- .trim_end()
- .split('\n')
- .map(|s| s.to_owned())
- .collect::<Vec<_>>()
- }
-
- #[test]
- fn no_wrap() {
- assert_eq!(wrap("foo", 10), vec!["foo"]);
- }
-
- #[test]
- fn wrap_simple() {
- assert_eq!(wrap("foo bar baz", 5), vec!["foo", "bar", "baz"]);
- }
-
- #[test]
- fn to_be_or_not() {
- assert_eq!(
- wrap("To be, or not to be, that is the question.", 10),
- vec!["To be, or", "not to be,", "that is", "the", "question."]
- );
- }
-
- #[test]
- fn multiple_words_on_first_line() {
- assert_eq!(wrap("foo bar baz", 10), vec!["foo bar", "baz"]);
- }
-
- #[test]
- fn long_word() {
- assert_eq!(wrap("foo", 0), vec!["foo"]);
- }
-
- #[test]
- fn long_words() {
- assert_eq!(wrap("foo bar", 0), vec!["foo", "bar"]);
- }
-
- #[test]
- fn max_width() {
- assert_eq!(wrap("foo bar", usize::MAX), vec!["foo bar"]);
-
- let text = "Hello there! This is some English text. \
- It should not be wrapped given the extents below.";
- assert_eq!(wrap(text, usize::MAX), vec![text]);
- }
-
- #[test]
- fn leading_whitespace() {
- assert_eq!(wrap(" foo bar", 6), vec![" foo", " bar"]);
- }
-
- #[test]
- fn leading_whitespace_empty_first_line() {
- // If there is no space for the first word, the first line
- // will be empty. This is because the string is split into
- // words like [" ", "foobar ", "baz"], which puts "foobar " on
- // the second line. We never output trailing whitespace
- assert_eq!(wrap(" foobar baz", 6), vec!["", " foobar", " baz"]);
- }
-
- #[test]
- fn trailing_whitespace() {
- // Whitespace is only significant inside a line. After a line
- // gets too long and is broken, the first word starts in
- // column zero and is not indented.
- assert_eq!(wrap("foo bar baz ", 5), vec!["foo", "bar", "baz"]);
- }
-
- #[test]
- fn issue_99() {
- // We did not reset the in_whitespace flag correctly and did
- // not handle single-character words after a line break.
- assert_eq!(
- wrap("aaabbbccc x yyyzzzwww", 9),
- vec!["aaabbbccc", "x", "yyyzzzwww"]
- );
- }
-
- #[test]
- fn issue_129() {
- // The dash is an em-dash which takes up four bytes. We used
- // to panic since we tried to index into the character.
- assert_eq!(wrap("x – x", 1), vec!["x", "–", "x"]);
- }
-}
diff --git a/vendor/clap_builder/src/output/textwrap/word_separators.rs b/vendor/clap_builder/src/output/textwrap/word_separators.rs
deleted file mode 100644
index cb8250b..0000000
--- a/vendor/clap_builder/src/output/textwrap/word_separators.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-pub(crate) fn find_words_ascii_space(line: &str) -> impl Iterator<Item = &'_ str> + '_ {
- let mut start = 0;
- let mut in_whitespace = false;
- let mut char_indices = line.char_indices();
-
- std::iter::from_fn(move || {
- for (idx, ch) in char_indices.by_ref() {
- let next_whitespace = ch == ' ';
- if in_whitespace && !next_whitespace {
- let word = &line[start..idx];
- start = idx;
- in_whitespace = next_whitespace;
- return Some(word);
- }
-
- in_whitespace = next_whitespace;
- }
-
- if start < line.len() {
- let word = &line[start..];
- start = line.len();
- return Some(word);
- }
-
- None
- })
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- macro_rules! test_find_words {
- ($ascii_name:ident,
- $([ $line:expr, $ascii_words:expr ]),+) => {
- #[test]
- fn $ascii_name() {
- $(
- let expected_words: Vec<&str> = $ascii_words.to_vec();
- let actual_words = find_words_ascii_space($line)
- .collect::<Vec<_>>();
- assert_eq!(actual_words, expected_words, "Line: {:?}", $line);
- )+
- }
- };
- }
-
- test_find_words!(ascii_space_empty, ["", []]);
-
- test_find_words!(ascii_single_word, ["foo", ["foo"]]);
-
- test_find_words!(ascii_two_words, ["foo bar", ["foo ", "bar"]]);
-
- test_find_words!(
- ascii_multiple_words,
- ["foo bar", ["foo ", "bar"]],
- ["x y z", ["x ", "y ", "z"]]
- );
-
- test_find_words!(ascii_only_whitespace, [" ", [" "]], [" ", [" "]]);
-
- test_find_words!(
- ascii_inter_word_whitespace,
- ["foo bar", ["foo ", "bar"]]
- );
-
- test_find_words!(ascii_trailing_whitespace, ["foo ", ["foo "]]);
-
- test_find_words!(ascii_leading_whitespace, [" foo", [" ", "foo"]]);
-
- test_find_words!(
- ascii_multi_column_char,
- ["\u{1f920}", ["\u{1f920}"]] // cowboy emoji 🤠
- );
-
- test_find_words!(
- ascii_hyphens,
- ["foo-bar", ["foo-bar"]],
- ["foo- bar", ["foo- ", "bar"]],
- ["foo - bar", ["foo ", "- ", "bar"]],
- ["foo -bar", ["foo ", "-bar"]]
- );
-
- test_find_words!(ascii_newline, ["foo\nbar", ["foo\nbar"]]);
-
- test_find_words!(ascii_tab, ["foo\tbar", ["foo\tbar"]]);
-
- test_find_words!(
- ascii_non_breaking_space,
- ["foo\u{00A0}bar", ["foo\u{00A0}bar"]]
- );
-}
diff --git a/vendor/clap_builder/src/output/textwrap/wrap_algorithms.rs b/vendor/clap_builder/src/output/textwrap/wrap_algorithms.rs
deleted file mode 100644
index 34b4fd2..0000000
--- a/vendor/clap_builder/src/output/textwrap/wrap_algorithms.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use super::core::display_width;
-
-#[derive(Debug)]
-pub(crate) struct LineWrapper<'w> {
- hard_width: usize,
- line_width: usize,
- carryover: Option<&'w str>,
-}
-
-impl<'w> LineWrapper<'w> {
- pub(crate) fn new(hard_width: usize) -> Self {
- Self {
- hard_width,
- line_width: 0,
- carryover: None,
- }
- }
-
- pub(crate) fn reset(&mut self) {
- self.line_width = 0;
- self.carryover = None;
- }
-
- pub(crate) fn wrap(&mut self, mut words: Vec<&'w str>) -> Vec<&'w str> {
- if self.carryover.is_none() {
- if let Some(word) = words.first() {
- if word.trim().is_empty() {
- self.carryover = Some(*word);
- } else {
- self.carryover = Some("");
- }
- }
- }
-
- let mut i = 0;
- while i < words.len() {
- let word = &words[i];
- let trimmed = word.trim_end();
- let word_width = display_width(trimmed);
- let trimmed_delta = word.len() - trimmed.len();
- if i != 0 && self.hard_width < self.line_width + word_width {
- if 0 < i {
- let last = i - 1;
- let trimmed = words[last].trim_end();
- words[last] = trimmed;
- }
-
- self.line_width = 0;
- words.insert(i, "\n");
- i += 1;
- if let Some(carryover) = self.carryover {
- words.insert(i, carryover);
- self.line_width += carryover.len();
- i += 1;
- }
- }
- self.line_width += word_width + trimmed_delta;
-
- i += 1;
- }
- words
- }
-}