Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ required-features = ["terminal_size"]
all-features = true

[features]
default = ["unicode-linebreak", "unicode-width", "smawk"]
default = ["std", "unicode-linebreak", "unicode-width", "smawk"]
std = []

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(fuzzing)"] }
Expand Down
6 changes: 5 additions & 1 deletion src/columns.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
//! Functionality for wrapping text into columns.

extern crate alloc;

use crate::core::display_width;
use crate::{wrap, Options};

use alloc::{string::String, vec::Vec, vec};

/// Wrap text into columns with a given total width.
///
/// The `left_gap`, `middle_gap` and `right_gap` arguments specify the
Expand Down Expand Up @@ -81,7 +85,7 @@ where
.saturating_sub(display_width(right_gap))
.saturating_sub(display_width(middle_gap) * (columns - 1));

let column_width = std::cmp::max(inner_width / columns, 1);
let column_width = core::cmp::max(inner_width / columns, 1);
options.width = column_width;
let last_column_padding = " ".repeat(inner_width % column_width);
let wrapped_lines = wrap(text, options);
Expand Down
12 changes: 8 additions & 4 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@
//! the functionality here is not sufficient or if you have ideas for
//! improving it. We would love to hear from you!

extern crate alloc;

use alloc::{vec::Vec, format};

/// The CSI or “Control Sequence Introducer” introduces an ANSI escape
/// sequence. This is typically used for colored text and will be
/// ignored when computing the text width.
const CSI: (char, char) = ('\x1b', '[');
/// The final bytes of an ANSI escape sequence must be in this range.
const ANSI_FINAL_BYTE: std::ops::RangeInclusive<char> = '\x40'..='\x7e';
const ANSI_FINAL_BYTE: core::ops::RangeInclusive<char> = '\x40'..='\x7e';

/// Skip ANSI escape sequences.
///
Expand Down Expand Up @@ -218,7 +222,7 @@ pub fn display_width(text: &str) -> usize {
/// For wrapping purposes, the precise content of the word, the
/// whitespace, and the penalty is irrelevant. All we need to know is
/// the displayed width of each part, which this trait provides.
pub trait Fragment: std::fmt::Debug {
pub trait Fragment: core::fmt::Debug {
/// Displayed width of word represented by this fragment.
fn width(&self) -> f64;

Expand Down Expand Up @@ -247,7 +251,7 @@ pub struct Word<'a> {
pub width: usize,
}

impl std::ops::Deref for Word<'_> {
impl core::ops::Deref for Word<'_> {
type Target = str;

fn deref(&self) -> &Self::Target {
Expand Down Expand Up @@ -288,7 +292,7 @@ impl<'a> Word<'a> {
let mut offset = 0;
let mut width = 0;

std::iter::from_fn(move || {
core::iter::from_fn(move || {
while let Some((idx, ch)) = char_indices.next() {
if skip_ansi_escape_sequence(ch, &mut char_indices.by_ref().map(|(_, ch)| ch)) {
continue;
Expand Down
6 changes: 5 additions & 1 deletion src/fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

use crate::{wrap, wrap_algorithms, Options, WordSeparator};

extern crate alloc;

use alloc::{string::String, vec::Vec};

/// Fill a line of text at a given width.
///
/// The result is a [`String`], complete with newlines between each
Expand Down Expand Up @@ -145,7 +149,7 @@ pub fn fill_inplace(text: &mut String, width: usize) {
offset += line.len() + 1;
}

let mut bytes = std::mem::take(text).into_bytes();
let mut bytes = core::mem::take(text).into_bytes();
for idx in indices {
bytes[idx] = b'\n';
}
Expand Down
2 changes: 1 addition & 1 deletion src/fuzzing.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Fuzzing helpers.

use super::Options;
use std::borrow::Cow;
use core::borrow::Cow;

/// Exposed for fuzzing so we can check the slow path is correct.
pub fn fill_slow_path<'a>(text: &str, options: Options<'_>) -> String {
Expand Down
4 changes: 4 additions & 0 deletions src/indentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
//! The functions here can be used to uniformly indent or dedent
//! (unindent) word wrapped lines of text.

extern crate alloc;

use alloc::string::String;

/// Indent each line by the given prefix.
///
/// # Examples
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![allow(clippy::redundant_field_names)]
#![no_std]

// Make `cargo test` execute the README doctests.
#[cfg(doctest)]
Expand Down
7 changes: 5 additions & 2 deletions src/line_ending.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Line ending detection and conversion.

use std::fmt::Debug;
extern crate alloc;

use core::fmt::Debug;
use alloc::{vec::Vec, vec};

/// Supported line endings. Like in the Rust standard library, two line
/// endings are supported: `\r\n` and `\n`
Expand Down Expand Up @@ -53,7 +56,7 @@ impl<'a> Iterator for NonEmptyLines<'a> {
if self.0.is_empty() {
None
} else {
let line = std::mem::take(&mut self.0);
let line = core::mem::take(&mut self.0);
Some((line, None))
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/refill.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
//! Functionality for unfilling and refilling text.
extern crate alloc;

use crate::core::display_width;
use crate::line_ending::NonEmptyLines;
use crate::{fill, LineEnding, Options};
use alloc::string::String;

/// Unpack a paragraph of already-wrapped text.
///
Expand Down Expand Up @@ -64,7 +67,7 @@ pub fn unfill(text: &str) -> (String, Options<'_>) {

let mut options = Options::new(0);
for (idx, line) in text.lines().enumerate() {
options.width = std::cmp::max(options.width, display_width(line));
options.width = core::cmp::max(options.width, display_width(line));
let without_prefix = line.trim_start_matches(prefix_chars);
let prefix = &line[..line.len() - without_prefix.len()];

Expand Down
9 changes: 6 additions & 3 deletions src/word_separators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#[cfg(feature = "unicode-linebreak")]
use crate::core::skip_ansi_escape_sequence;
use crate::core::Word;
use alloc::{boxed::Box, string::String, vec::Vec, vec};

extern crate alloc;

/// Describes where words occur in a line of text.
///
Expand Down Expand Up @@ -193,7 +196,7 @@ fn find_words_ascii_space<'a>(line: &'a str) -> Box<dyn Iterator<Item = Word<'a>
let mut in_whitespace = false;
let mut char_indices = line.char_indices();

Box::new(std::iter::from_fn(move || {
Box::new(core::iter::from_fn(move || {
for (idx, ch) in char_indices.by_ref() {
if in_whitespace && ch != ' ' {
let word = Word::from(&line[start..idx]);
Expand Down Expand Up @@ -249,7 +252,7 @@ fn find_words_unicode_break_properties<'a>(
// the original string.
let mut last_stripped_idx = 0;
let mut char_indices = line.char_indices();
let mut idx_map = std::iter::from_fn(move || match char_indices.next() {
let mut idx_map = core::iter::from_fn(move || match char_indices.next() {
Some((orig_idx, ch)) => {
let stripped_idx = last_stripped_idx;
if !skip_ansi_escape_sequence(ch, &mut char_indices.by_ref().map(|(_, ch)| ch)) {
Expand Down Expand Up @@ -285,7 +288,7 @@ fn find_words_unicode_break_properties<'a>(
opportunities.next_back();

let mut start = 0;
Box::new(std::iter::from_fn(move || {
Box::new(core::iter::from_fn(move || {
for (idx, _) in opportunities.by_ref() {
if let Some((orig_idx, _)) = idx_map.find(|&(_, stripped_idx)| stripped_idx == idx) {
let word = Word::from(&line[start..orig_idx]);
Expand Down
5 changes: 4 additions & 1 deletion src/word_splitters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
//! across lines. The [`WordSplitter`] enum defines this
//! functionality.

extern crate alloc;

use crate::core::{display_width, Word};
use alloc::{vec::Vec, vec};

/// The `WordSplitter` enum describes where words can be split.
///
Expand Down Expand Up @@ -176,7 +179,7 @@ where
words.into_iter().flat_map(move |word| {
let mut prev = 0;
let mut split_points = word_splitter.split_points(&word).into_iter();
std::iter::from_fn(move || {
core::iter::from_fn(move || {
if let Some(idx) = split_points.next() {
let need_hyphen = !word[..idx].ends_with('-');
let w = Word {
Expand Down
12 changes: 9 additions & 3 deletions src/wrap.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
//! Functions for wrapping text.

use std::borrow::Cow;
use alloc::{
borrow::{Cow, ToOwned},
format, vec,
vec::Vec,
};

extern crate alloc;

use crate::core::{break_words, display_width, Word};
use crate::word_splitters::split_words;
Expand Down Expand Up @@ -627,7 +633,7 @@ mod tests {
fn borrowed_lines() {
// Lines that end with an extra hyphen are owned, the final
// line is borrowed.
use std::borrow::Cow::{Borrowed, Owned};
use alloc::borrow::Cow::{Borrowed, Owned};
let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap();
let options = Options::new(10).word_splitter(WordSplitter::Hyphenation(dictionary));
let lines = wrap("Internationalization", &options);
Expand Down Expand Up @@ -700,7 +706,7 @@ mod tests {

#[test]
fn preserve_trailing_space_borrows_spaces() {
use std::borrow::Cow::Owned;
use alloc::borrow::Cow::Owned;
let lines = wrap(
"foo bar baz",
Options::new(10).preserve_trailing_space(true),
Expand Down
9 changes: 6 additions & 3 deletions src/wrap_algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
//! While both algorithms run in linear time, the first-fit algorithm
//! is about 4 times faster than the optimal-fit algorithm.

extern crate alloc;

#[cfg(feature = "smawk")]
mod optimal_fit;
#[cfg(feature = "smawk")]
pub use optimal_fit::{wrap_optimal_fit, OverflowError, Penalties};

use crate::core::{Fragment, Word};
use alloc::vec::Vec;

/// Describes how to wrap words into lines.
///
Expand Down Expand Up @@ -372,7 +375,7 @@ mod tests {

#[test]
fn wrap_string_longer_than_f64() {
let words = vec![
let words = alloc::vec![
Word(1e307),
Word(2e307),
Word(3e307),
Expand All @@ -385,14 +388,14 @@ mod tests {
assert_eq!(
wrap_first_fit(&words, &[15e307]),
&[
vec![
alloc::vec![
Word(1e307),
Word(2e307),
Word(3e307),
Word(4e307),
Word(5e307)
],
vec![Word(6e307)]
alloc::vec![Word(6e307)]
]
);
}
Expand Down
11 changes: 7 additions & 4 deletions src/wrap_algorithms/optimal_fit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::cell::RefCell;
extern crate alloc;

use core::cell::RefCell;
use alloc::{vec::Vec, vec};

use crate::core::Fragment;

Expand Down Expand Up @@ -185,13 +188,13 @@ impl LineNumbers {
#[derive(Debug, PartialEq, Eq)]
pub struct OverflowError;

impl std::fmt::Display for OverflowError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl core::fmt::Display for OverflowError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "wrap_optimal_fit cost computation overflowed")
}
}

impl std::error::Error for OverflowError {}
impl core::error::Error for OverflowError {}

/// Wrap abstract fragments into lines with an optimal-fit algorithm.
///
Expand Down
Loading