Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utility function ansi::slice_ansi_str #206

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

remi-dupre
Copy link

@remi-dupre remi-dupre commented Feb 7, 2024

Hi!

While working on a bug of indicatif (cf. console-rs/indicatif#627), I needed an ANSI-aware slicing method. I think it made more sense to add it in this crate.

/// Slice a `&str` in terms of text width. This means that only the text
/// columns strictly between `start` and `stop` will be kept.
///
/// If a multi-columns character overlaps with the end of the interval it will
/// not be included. In such a case, the result will be less than `end - start`
/// columns wide.
///
/// If non-empty head and tail are specified, they are inserted between the
/// ANSI symbols from truncated bounds and the slice.
///
/// This ensures that escape codes are not screwed up in the process.
pub fn slice_str<'a>(s: &'a str, head: &str, bounds: Range<usize>, tail: &str) -> Cow<'a, str> {
    ...
}

I made this quite similar to truncate_str, which enables code reuse 😊

I also suggested a non-allocating implementation for measure_text_width 🤷

I also took my chance and suggested an non-allocating version of
measure_text_width.
@remi-dupre remi-dupre marked this pull request as ready for review February 7, 2024 18:24
@remi-dupre remi-dupre force-pushed the ansi-slice branch 3 times, most recently from 3811bcc to 3324138 Compare February 7, 2024 21:52
@@ -56,7 +56,7 @@ pub fn terminal_size(out: &Term) -> Option<(u16, u16)> {
#[allow(clippy::useless_conversion)]
libc::ioctl(out.as_raw_fd(), libc::TIOCGWINSZ.into(), &mut winsize);
if winsize.ws_row > 0 && winsize.ws_col > 0 {
Some((winsize.ws_row as u16, winsize.ws_col as u16))
Some((winsize.ws_row, winsize.ws_col))
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just a random (new?) clippy lint : these are already u16 🤷

Comment on lines +71 to +75
AnsiCodeIterator::new(s)
.filter(|(_, is_ansi)| !is_ansi)
.map(|(sub, _)| str_width(sub))
.sum()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to the MR, but while implementing a less optimized draft of my fix I thought this could spare a few allocs. This is probably not something to care about so I wouldn't mind if you want to revert this for the sake of simplification.

@remi-dupre remi-dupre force-pushed the ansi-slice branch 3 times, most recently from 19d8f2d to 0f33b85 Compare February 7, 2024 23:23
This new implementation also has the benefit of allocating at most once.
@remi-dupre remi-dupre changed the title Add function ansi::slice_ansi_str Add utility function ansi::slice_ansi_str Feb 8, 2024
@djc
Copy link
Member

djc commented Feb 10, 2024

Can you avoid let .. else in order to pass the MSRV tests?

@remi-dupre
Copy link
Author

Indeed, that should be good now 👍

@remi-dupre
Copy link
Author

remi-dupre commented Feb 12, 2024

And format is also a recent-is feature, on it 😬

I'll try to build on 1.56, it didn't work last time I tried it because it fails to resolve regex = "=1.10.3" 😞

EDIT : Ok, got it

@remi-dupre
Copy link
Author

Should be good, make test runs with rust 1.56 on my machine 👍

@djc djc requested a review from mitsuhiko February 12, 2024 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants