diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/indenter | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/indenter')
-rw-r--r-- | vendor/indenter/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/indenter/CHANGELOG.md | 31 | ||||
-rw-r--r-- | vendor/indenter/Cargo.lock | 5 | ||||
-rw-r--r-- | vendor/indenter/Cargo.toml | 70 | ||||
-rw-r--r-- | vendor/indenter/README.md | 113 | ||||
-rw-r--r-- | vendor/indenter/examples/usage.rs | 12 | ||||
-rw-r--r-- | vendor/indenter/src/lib.rs | 542 |
7 files changed, 774 insertions, 0 deletions
diff --git a/vendor/indenter/.cargo-checksum.json b/vendor/indenter/.cargo-checksum.json new file mode 100644 index 000000000..569f4a23c --- /dev/null +++ b/vendor/indenter/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"488d07e32f0882080938c8baae0af55ea58937d816f4c4c12f294f057238b064","Cargo.lock":"3df02f6a248110ecf9527ce2ae8c3c91acc295277bd2d0745d9d1d3aa622754f","Cargo.toml":"1ee8d05e19dffa8cd49dc9f7288a30b00d598d3240a06a24298e845e9854541b","README.md":"8f9fff9b73b1205590cb57eba24c1b6e79424cea82c30eccc072d07472062cf7","examples/usage.rs":"5bb66ce0078a6cd1dded6f49122fa96c8f0842c4d6631827299ebf575dfff49d","src/lib.rs":"3e504c87e794adaa522153e350ba1cec7e4671fdb4b71309800b9bdeb6a94400"},"package":"ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"}
\ No newline at end of file diff --git a/vendor/indenter/CHANGELOG.md b/vendor/indenter/CHANGELOG.md new file mode 100644 index 000000000..3d8a3c634 --- /dev/null +++ b/vendor/indenter/CHANGELOG.md @@ -0,0 +1,31 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +<!-- next-header --> + +## [Unreleased] - ReleaseDate + +## [0.3.3] - 2021-02-22 +### Added +- Implement new code dedenting / indenting formatter by cecton + +## [0.3.2] - 2021-01-04 +### Fixed +- Changed indentation logic to better support trailing newlines and improve + overall formatting consistency + +## [0.3.1] - 2020-12-21 +### Added +- `with_str` helper method for indenting with static strings +### Changed +- Relaxed `Sized` bound on inner writers + + +<!-- next-url --> +[Unreleased]: https://github.com/yaahc/indenter/compare/v0.3.3...HEAD +[0.3.3]: https://github.com/yaahc/indenter/compare/v0.3.2...v0.3.3 +[0.3.2]: https://github.com/yaahc/indenter/compare/v0.3.1...v0.3.2 +[0.3.1]: https://github.com/yaahc/indenter/releases/tag/v0.3.1 diff --git a/vendor/indenter/Cargo.lock b/vendor/indenter/Cargo.lock new file mode 100644 index 000000000..e4e4181ff --- /dev/null +++ b/vendor/indenter/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "indenter" +version = "0.3.3" diff --git a/vendor/indenter/Cargo.toml b/vendor/indenter/Cargo.toml new file mode 100644 index 000000000..6afb65425 --- /dev/null +++ b/vendor/indenter/Cargo.toml @@ -0,0 +1,70 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "indenter" +version = "0.3.3" +authors = ["Jane Lusby <jlusby@yaah.dev>"] +description = "A formatter wrapper that indents the text, designed for error display impls\n" +homepage = "https://github.com/yaahc/indenter" +documentation = "https://docs.rs/indenter" +readme = "README.md" +keywords = ["display", "fmt", "Formatter", "error"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/yaahc/indenter" +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.release] +no-dev-version = true + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +replace = "{{version}}" +search = "Unreleased" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "src/lib.rs" +replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]" +search = "#!\\[doc\\(html_root_url.*" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "...{{tag_name}}" +search = "\\.\\.\\.HEAD" + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +replace = "{{date}}" +search = "ReleaseDate" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "<!-- next-header -->\n\n## [Unreleased] - ReleaseDate" +search = "<!-- next-header -->" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "<!-- next-url -->\n[Unreleased]: https://github.com/yaahc/{{crate_name}}/compare/{{tag_name}}...HEAD" +search = "<!-- next-url -->" + +[dependencies] + +[features] +default = [] +std = [] diff --git a/vendor/indenter/README.md b/vendor/indenter/README.md new file mode 100644 index 000000000..98bce3c4c --- /dev/null +++ b/vendor/indenter/README.md @@ -0,0 +1,113 @@ +## indenter + +[![Build Status][actions-badge]][actions-url] +[![Latest Version][version-badge]][version-url] +[![Rust Documentation][docs-badge]][docs-url] + +[actions-badge]: https://github.com/yaahc/indenter/workflows/Continuous%20integration/badge.svg +[actions-url]: https://github.com/yaahc/indenter/actions?query=workflow%3A%22Continuous+integration%22 +[version-badge]: https://img.shields.io/crates/v/indenter.svg +[version-url]: https://crates.io/crates/indenter +[docs-badge]: https://img.shields.io/badge/docs-latest-blue.svg +[docs-url]: https://docs.rs/indenter + +A few wrappers for the `fmt::Write` objects that efficiently appends and remove +common indentation after every newline + +## Setup + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +indenter = "0.2" +``` + +## Examples + +## Indentation only + +This type is intended primarily for writing error reporters that gracefully +format error messages that span multiple lines. + +```rust +use std::error::Error; +use std::fmt::{self, Write}; +use indenter::indented; + +struct ErrorReporter<'a>(&'a dyn Error); + +impl fmt::Debug for ErrorReporter<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut source = Some(self.0); + let mut i = 0; + + while let Some(error) = source { + writeln!(f)?; + write!(indented(f).ind(i), "{}", error)?; + + source = error.source(); + i += 1; + } + + Ok(()) + } +} +``` + +## "Dedenting" (removing common leading indendation) + +This type is intended primarily for formatting source code. For example, when +generating code. + +This type requires the feature `std`. + +```rust +use std::error::Error; +use core::fmt::{self, Write}; +use indenter::CodeFormatter; + +let mut output = String::new(); +let mut f = CodeFormatter::new(&mut output, " "); + +write!( + f, + r#" + Hello + World + "#, +); + +assert_eq!(output, "Hello\n World\n"); + +let mut output = String::new(); +let mut f = CodeFormatter::new(&mut output, " "); + +// it can also indent... +f.indent(2); + +write!( + f, + r#" + Hello + World + "#, +); + +assert_eq!(output, " Hello\n World\n"); +``` + +#### License + +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> + +<br> + +<sub> +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. +</sub> diff --git a/vendor/indenter/examples/usage.rs b/vendor/indenter/examples/usage.rs new file mode 100644 index 000000000..3432fccc3 --- /dev/null +++ b/vendor/indenter/examples/usage.rs @@ -0,0 +1,12 @@ +use indenter::indented; +use std::fmt::Write; + +fn main() { + let input = "verify\nthis"; + let mut output = String::new(); + + indented(&mut output).ind(12).write_str(input).unwrap(); + + println!("Before:\n{}\n", input); + println!("After:\n{}", output); +} diff --git a/vendor/indenter/src/lib.rs b/vendor/indenter/src/lib.rs new file mode 100644 index 000000000..f9b73ba7a --- /dev/null +++ b/vendor/indenter/src/lib.rs @@ -0,0 +1,542 @@ +//! A few wrappers for the `fmt::Write` objects that efficiently appends and remove +//! common indentation after every newline +//! +//! # Setup +//! +//! Add this to your `Cargo.toml`: +//! +//! ```toml +//! [dependencies] +//! indenter = "0.2" +//! ``` +//! +//! # Examples +//! +//! ## Indentation only +//! +//! This type is intended primarily for writing error reporters that gracefully +//! format error messages that span multiple lines. +//! +//! ```rust +//! use std::error::Error; +//! use core::fmt::{self, Write}; +//! use indenter::indented; +//! +//! struct ErrorReporter<'a>(&'a dyn Error); +//! +//! impl fmt::Debug for ErrorReporter<'_> { +//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +//! let mut source = Some(self.0); +//! let mut i = 0; +//! +//! while let Some(error) = source { +//! writeln!(f)?; +//! write!(indented(f).ind(i), "{}", error)?; +//! +//! source = error.source(); +//! i += 1; +//! } +//! +//! Ok(()) +//! } +//! } +//! ``` +//! +//! ## "Dedenting" (removing common leading indendation) +//! +//! This type is intended primarily for formatting source code. For example, when +//! generating code. +//! +//! This type requires the feature `std`. +//! +//! ```rust +//! # #[cfg(feature = "std")] +//! # fn main() { +//! use std::error::Error; +//! use core::fmt::{self, Write}; +//! use indenter::CodeFormatter; +//! +//! let mut output = String::new(); +//! let mut f = CodeFormatter::new(&mut output, " "); +//! +//! write!( +//! f, +//! r#" +//! Hello +//! World +//! "#, +//! ); +//! +//! assert_eq!(output, "Hello\n World\n"); +//! +//! let mut output = String::new(); +//! let mut f = CodeFormatter::new(&mut output, " "); +//! +//! // it can also indent... +//! f.indent(2); +//! +//! write!( +//! f, +//! r#" +//! Hello +//! World +//! "#, +//! ); +//! +//! assert_eq!(output, " Hello\n World\n"); +//! # } +//! # #[cfg(not(feature = "std"))] +//! # fn main() { +//! # } +//! ``` +#![cfg_attr(not(feature = "std"), no_std)] +#![doc(html_root_url = "https://docs.rs/indenter/0.3.3")] +#![warn( + missing_debug_implementations, + missing_docs, + missing_doc_code_examples, + rust_2018_idioms, + unreachable_pub, + bad_style, + const_err, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + private_in_public, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true +)] +use core::fmt; + +/// The set of supported formats for indentation +#[allow(missing_debug_implementations)] +pub enum Format<'a> { + /// Insert uniform indentation before every line + /// + /// This format takes a static string as input and inserts it after every newline + Uniform { + /// The string to insert as indentation + indentation: &'static str, + }, + /// Inserts a number before the first line + /// + /// This format hard codes the indentation level to match the indentation from + /// `core::backtrace::Backtrace` + Numbered { + /// The index to insert before the first line of output + ind: usize, + }, + /// A custom indenter which is executed after every newline + /// + /// Custom indenters are passed the current line number and the buffer to be written to as args + Custom { + /// The custom indenter + inserter: &'a mut Inserter, + }, +} + +/// Helper struct for efficiently indenting multi line display implementations +/// +/// # Explanation +/// +/// This type will never allocate a string to handle inserting indentation. It instead leverages +/// the `write_str` function that serves as the foundation of the `core::fmt::Write` trait. This +/// lets it intercept each piece of output as its being written to the output buffer. It then +/// splits on newlines giving slices into the original string. Finally we alternate writing these +/// lines and the specified indentation to the output buffer. +#[allow(missing_debug_implementations)] +pub struct Indented<'a, D: ?Sized> { + inner: &'a mut D, + needs_indent: bool, + format: Format<'a>, +} + +/// A callback for `Format::Custom` used to insert indenation after a new line +/// +/// The first argument is the line number within the output, starting from 0 +pub type Inserter = dyn FnMut(usize, &mut dyn fmt::Write) -> fmt::Result; + +impl Format<'_> { + fn insert_indentation(&mut self, line: usize, f: &mut dyn fmt::Write) -> fmt::Result { + match self { + Format::Uniform { indentation } => write!(f, "{}", indentation), + Format::Numbered { ind } => { + if line == 0 { + write!(f, "{: >4}: ", ind) + } else { + write!(f, " ") + } + } + Format::Custom { inserter } => inserter(line, f), + } + } +} + +impl<'a, D> Indented<'a, D> { + /// Sets the format to `Format::Numbered` with the provided index + pub fn ind(self, ind: usize) -> Self { + self.with_format(Format::Numbered { ind }) + } + + /// Sets the format to `Format::Uniform` with the provided static string + pub fn with_str(self, indentation: &'static str) -> Self { + self.with_format(Format::Uniform { indentation }) + } + + /// Construct an indenter with a user defined format + pub fn with_format(mut self, format: Format<'a>) -> Self { + self.format = format; + self + } +} + +impl<T> fmt::Write for Indented<'_, T> +where + T: fmt::Write + ?Sized, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + for (ind, line) in s.split('\n').enumerate() { + if ind > 0 { + self.inner.write_char('\n')?; + self.needs_indent = true; + } + + if self.needs_indent { + // Don't render the line unless its actually got text on it + if line.is_empty() { + continue; + } + + self.format.insert_indentation(ind, &mut self.inner)?; + self.needs_indent = false; + } + + self.inner.write_fmt(format_args!("{}", line))?; + } + + Ok(()) + } +} + +/// Helper function for creating a default indenter +pub fn indented<D: ?Sized>(f: &mut D) -> Indented<'_, D> { + Indented { + inner: f, + needs_indent: true, + format: Format::Uniform { + indentation: " ", + }, + } +} + +/// Helper struct for efficiently dedent and indent multi line display implementations +/// +/// # Explanation +/// +/// This type allocates a string once to get the formatted result and then uses the internal +/// formatter efficiently to: first dedent the output, then re-indent to the desired level. +#[cfg(feature = "std")] +#[allow(missing_debug_implementations)] +pub struct CodeFormatter<'a, T> { + f: &'a mut T, + level: u32, + indentation: String, +} + +#[cfg(feature = "std")] +impl<'a, T: fmt::Write> fmt::Write for CodeFormatter<'a, T> { + fn write_str(&mut self, input: &str) -> fmt::Result { + let input = match input.chars().next() { + Some('\n') => &input[1..], + _ => return self.f.write_str(input), + }; + + let min = input + .split('\n') + .map(|line| line.chars().take_while(char::is_ascii_whitespace).count()) + .filter(|count| *count > 0) + .min() + .unwrap_or_default(); + + let input = input.trim_end_matches(|c| char::is_ascii_whitespace(&c)); + + for line in input.split('\n') { + if line.len().saturating_sub(min) > 0 { + for _ in 0..self.level { + self.f.write_str(&self.indentation)?; + } + } + + if line.len() >= min { + self.f.write_str(&line[min..])?; + } else { + self.f.write_str(&line)?; + } + self.f.write_char('\n')?; + } + + Ok(()) + } + + fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { + self.write_str(&args.to_string()) + } +} + +#[cfg(feature = "std")] +impl<'a, T: fmt::Write> CodeFormatter<'a, T> { + /// Wrap the formatter `f`, use `indentation` as base string indentation and return a new + /// formatter that implements `std::fmt::Write` that can be used with the macro `write!()` + pub fn new<S: Into<String>>(f: &'a mut T, indentation: S) -> Self { + Self { + f, + level: 0, + indentation: indentation.into(), + } + } + + /// Set the indentation level to a specific value + pub fn set_level(&mut self, level: u32) { + self.level = level; + } + + /// Increase the indentation level by `inc` + pub fn indent(&mut self, inc: u32) { + self.level = self.level.saturating_add(inc); + } + + /// Decrease the indentation level by `inc` + pub fn dedent(&mut self, inc: u32) { + self.level = self.level.saturating_sub(inc); + } +} + +#[cfg(test)] +mod tests { + extern crate alloc; + + use super::*; + use alloc::string::String; + use core::fmt::Write as _; + + #[test] + fn one_digit() { + let input = "verify\nthis"; + let expected = " 2: verify\n this"; + let mut output = String::new(); + + indented(&mut output).ind(2).write_str(input).unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn two_digits() { + let input = "verify\nthis"; + let expected = " 12: verify\n this"; + let mut output = String::new(); + + indented(&mut output).ind(12).write_str(input).unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn no_digits() { + let input = "verify\nthis"; + let expected = " verify\n this"; + let mut output = String::new(); + + indented(&mut output).write_str(input).unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn with_str() { + let input = "verify\nthis"; + let expected = "...verify\n...this"; + let mut output = String::new(); + + indented(&mut output) + .with_str("...") + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn dyn_write() { + let input = "verify\nthis"; + let expected = " verify\n this"; + let mut output = String::new(); + let writer: &mut dyn core::fmt::Write = &mut output; + + indented(writer).write_str(input).unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn nice_api() { + let input = "verify\nthis"; + let expected = " 1: verify\n this"; + let output = &mut String::new(); + let n = 1; + + write!( + indented(output).with_format(Format::Custom { + inserter: &mut move |line_no, f| { + if line_no == 0 { + write!(f, "{: >4}: ", n) + } else { + write!(f, " ") + } + } + }), + "{}", + input + ) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn nice_api_2() { + let input = "verify\nthis"; + let expected = " verify\n this"; + let output = &mut String::new(); + + write!( + indented(output).with_format(Format::Uniform { indentation: " " }), + "{}", + input + ) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn trailing_newlines() { + let input = "verify\nthis\n"; + let expected = " verify\n this\n"; + let output = &mut String::new(); + + write!(indented(output).with_str(" "), "{}", input).unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn several_interpolations() { + let input = "verify\nthis\n"; + let expected = " verify\n this\n and verify\n this\n"; + let output = &mut String::new(); + + write!(indented(output).with_str(" "), "{} and {}", input, input).unwrap(); + + assert_eq!(expected, output); + } +} + +#[cfg(all(test, feature = "std"))] +mod tests_std { + use super::*; + use core::fmt::Write as _; + + #[test] + fn dedent() { + let mut s = String::new(); + let mut f = CodeFormatter::new(&mut s, " "); + write!( + f, + r#" + struct Foo; + + impl Foo {{ + fn foo() {{ + todo!() + }} + }} + "#, + ) + .unwrap(); + assert_eq!( + s, + "struct Foo;\n\nimpl Foo {\n fn foo() {\n todo!()\n }\n}\n" + ); + + let mut s = String::new(); + let mut f = CodeFormatter::new(&mut s, " "); + write!( + f, + r#" + struct Foo; + + impl Foo {{ + fn foo() {{ + todo!() + }} + }}"#, + ) + .unwrap(); + assert_eq!( + s, + "struct Foo;\n\nimpl Foo {\n fn foo() {\n todo!()\n }\n}\n" + ); + } + + #[test] + fn indent() { + let mut s = String::new(); + let mut f = CodeFormatter::new(&mut s, " "); + f.indent(1); + write!( + f, + r#" + struct Foo; + + impl Foo {{ + fn foo() {{ + todo!() + }} + }} + "#, + ) + .unwrap(); + assert_eq!(s, " struct Foo;\n\n impl Foo {\n fn foo() {\n todo!()\n }\n }\n"); + } + + #[test] + fn inline() { + let mut s = String::new(); + let mut f = CodeFormatter::new(&mut s, " "); + write!( + f, + r#"struct Foo; + fn foo() {{ + }}"#, + ) + .unwrap(); + assert_eq!(s, "struct Foo;\n fn foo() {\n }"); + } + + #[test] + fn split_prefix() { + let mut s = String::new(); + let mut f = CodeFormatter::new(&mut s, " "); + writeln!(f).unwrap(); + assert_eq!(s, "\n"); + } +} |