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

Fix bar-less text output #659

Merged
merged 15 commits into from
Nov 15, 2024
Merged

Fix bar-less text output #659

merged 15 commits into from
Nov 15, 2024

Conversation

spoutn1k
Copy link
Contributor

@spoutn1k spoutn1k commented Sep 26, 2024

This is my attempt at fixing #447.

The code in draw_to_term is a bit of mess, with double definitions, complex branching, and I tried cleaning it up. I introduce a LineType enum to differentiate between text, bars and empty lines. The variables names have been renamed to reflect better what they represent. Some code has been shuffled around. Tests pass and I ran examples at random with no issues.

A sample program to understand what this PR wants to fix:

static LOREM_SMALL: &str = "Lorem ipsum dolor sit amet.";
static LOREM_BIG: &str= "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec viverra massa. Nunc nisl lectus,
auctor in lorem eu, maximus elementum est.";

fn generate_logs(manager: &indicatif::MultiProgress, i: u32) {
    if i % 20 == 0 {
        let _ = manager.println(LOREM_BIG);
    } else if i % 10 == 0 {
        let _ = manager.println(LOREM_SMALL);
    }
}

fn main() {
    let display_manager = indicatif::MultiProgress::new();
    let bar = display_manager.add(indicatif::ProgressBar::new(100));

    for i in 0..100 {
        generate_logs(&display_manager, i);
        std::thread::sleep(std::time::Duration::from_millis(10));
    }

    for i in 0..100 {
        bar.inc(1);
        generate_logs(&display_manager, i);
        std::thread::sleep(std::time::Duration::from_millis(100));
    }
}

This is the output of the above before the PR:
asciicast

Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

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

Thanks for trying to improve this code. Especially because this is pretty gnarly code, it would be good to split these changes into smaller commits that make minimal (logical) changes -- for example, might introduce the LineType enum while representing only the types of lines that are currently in lines, and then later introduce the other variants.

src/draw_target.rs Show resolved Hide resolved
Comment on lines 405 to 406
.filter(|l| matches!(l, LineType::Text(_)))
.map(|l| String::from(l.as_ref())),
Copy link
Member

Choose a reason for hiding this comment

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

Suggest we use filter_map() instead of filter().map(). Also prefer to_owned() instead of String::from() here.

@@ -456,15 +461,60 @@ impl RateLimiter {

const MAX_BURST: u8 = 20;

#[derive(Debug, Clone, PartialEq)]
Copy link
Member

Choose a reason for hiding this comment

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

We have a top-down order here, this should move down below any types that rely on it (DrawState at least).

@@ -473,21 +523,25 @@ pub(crate) struct DrawState {

impl DrawState {
fn draw_to_term(
&mut self,
&self,
Copy link
Member

Choose a reason for hiding this comment

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

Why does this happen?

@spoutn1k
Copy link
Contributor Author

spoutn1k commented Oct 7, 2024

Thank you for taking the time to review this. My tests omitted the --all-features flag and it shows. It did not help that this PR is the result of a caffeine overdose and subsequent insomnia. Comments duly noted this PR will either be force pushed or a new one will be opened with working tests and better commits. Thanks again !

@djc
Copy link
Member

djc commented Oct 7, 2024

Thanks! Force pushing is fine IME.

@spoutn1k
Copy link
Contributor Author

// Keep the cursor on the right terminal side
// So that next user writes/prints will happen on the next line
last_line_filler = term_width.saturating_sub(line_width);

I think my main issue stems here. For wrapping lines, this calculation is not accurate. However the concept itself seems strange to me. Why fill the line with whitespace and expect the terminal to wrap instead of moving the cursor down when needed ? This means when resizing the terminal the formatting will fall apart.

Any objections to me investigating changing this behaviour ?

@spoutn1k spoutn1k force-pushed the linetype-enum branch 2 times, most recently from 506bb01 to 1b29cf0 Compare October 10, 2024 18:55
@spoutn1k
Copy link
Contributor Author

spoutn1k commented Oct 10, 2024

The new commit passes all the tests but two, and that is because the filler is not only printed when needed (removing one variable definition). On my machine:

---- multi_progress_many_bars stdout ----
thread 'multi_progress_many_bars' panicked at tests/render.rs:1230:5:
assertion failed: `(left == right)`
                                                                                                                                                                                 
Diff < left / right > :
[...]
 Str("")
 NewLine
 Str("⠁ 2")
>Str("") <---------------------------------- Those useless prints are avoided
 Flush

@djc
Copy link
Member

djc commented Oct 11, 2024

I think my main issue stems here. For wrapping lines, this calculation is not accurate. However the concept itself seems strange to me. Why fill the line with whitespace and expect the terminal to wrap instead of moving the cursor down when needed ? This means when resizing the terminal the formatting will fall apart.

Any objections to me investigating changing this behaviour ?

I never have objections to other people investigating things. 😄 Suggest reading git blame to figure out why this change was made, pretty sure it wasn't just for funsies.

@djc
Copy link
Member

djc commented Oct 11, 2024

The new commit passes all the tests but two, and that is because the filler is not only printed when needed (removing one variable definition).

Removing the empty writes from the test seems fine to me.

@spoutn1k
Copy link
Contributor Author

Suggest reading git blame to figure out why this change was made, pretty sure it wasn't just for funsies.

I believe this is working in tandem with this check:

if idx != 0 {
term.write_line("")?;
}

This means that for everyline line other than the first one, a newline is added. The first is expected to wrap automatically due to the filler set in my previous comment.

@spoutn1k
Copy link
Contributor Author

spoutn1k commented Oct 11, 2024

This effectively fixes #447. I deeply want to keep going, because there is a lot of further refactoring that can be done, and the current solution of padding the last line will break any resizing. This is, for future reference, the watermark to go back to if the PR spins out of control

@spoutn1k
Copy link
Contributor Author

In a rare moment of lucidity I will not change the line padding in this PR. It is now ready for review again @djc !

src/draw_target.rs Outdated Show resolved Hide resolved
@spoutn1k spoutn1k force-pushed the linetype-enum branch 3 times, most recently from 62a7eea to 1433812 Compare November 11, 2024 16:10
Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

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

Thanks, this is a lot easier to review!

src/draw_target.rs Outdated Show resolved Hide resolved
src/draw_target.rs Outdated Show resolved Hide resolved
tests/render.rs Show resolved Hide resolved
src/draw_target.rs Outdated Show resolved Hide resolved
src/draw_target.rs Outdated Show resolved Hide resolved
src/draw_target.rs Outdated Show resolved Hide resolved
src/draw_target.rs Show resolved Hide resolved
src/draw_target.rs Outdated Show resolved Hide resolved
tests/render.rs Outdated Show resolved Hide resolved
@spoutn1k
Copy link
Contributor Author

Resolved most of the comments. For the separate commits, I am very sorry but I do not have infinite time to alter commits of code that gets optimized out in the full PR. I do not think it alters readability either.

@djc djc merged commit 632989d into console-rs:main Nov 15, 2024
10 checks passed
@djc
Copy link
Member

djc commented Nov 15, 2024

Alright, thanks for all your work on this!

@spoutn1k
Copy link
Contributor Author

Thank you, it was a pleasure, I just am travelling a lot at the moment. Cheers !

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