Skip to content

Commit

Permalink
perf: only process visible lines (#135)
Browse files Browse the repository at this point in the history
* perf: only highlight visible lines

* fix: only process visible lines

* fix: handle vertical layout switch

Synchronize line offsets when switching layout mode.
  • Loading branch information
luckasRanarison authored Aug 8, 2024
1 parent 3448aa8 commit 6ff2691
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 54 deletions.
15 changes: 10 additions & 5 deletions src/actors/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::config::{
};
use crate::exec::ExecBuilder;

use super::console::{Output, PanelStatus, RegisterPanel};
use super::console::{Output, OutputKind, PanelStatus, RegisterPanel};
use super::watcher::{IgnorePath, WatchGlob};

#[cfg(not(test))]
Expand Down Expand Up @@ -265,7 +265,8 @@ impl CommandActor {
fn log_info(&self, log: String) {
let job_name = self.operator.name.clone();

self.console.do_send(Output::now(job_name, log, true));
self.console
.do_send(Output::now(job_name, log, OutputKind::Service));
}

fn log_debug(&self, log: String) {
Expand Down Expand Up @@ -353,7 +354,11 @@ impl CommandActor {
colors: task_colors.clone(),
});
}
console.do_send(Output::now(tab_name.to_owned(), line.clone(), false));
console.do_send(Output::now(
tab_name.to_owned(),
line,
OutputKind::Command,
));
}
OutputRedirection::File(path) => {
let path = task_pipe.regex.replace(&line, path);
Expand Down Expand Up @@ -383,11 +388,11 @@ impl CommandActor {

// append new line since strings from the buffer reader don't include it
line.push('\n');
file.write_all(line.clone().as_bytes()).unwrap();
file.write_all(line.as_bytes()).unwrap();
}
}
} else {
console.do_send(Output::now(op_name.clone(), line.clone(), false));
console.do_send(Output::now(op_name.clone(), line, OutputKind::Command));
}
}

Expand Down
132 changes: 90 additions & 42 deletions src/actors/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ impl AppMode {
}

pub struct Panel {
logs: Vec<(String, Style)>,
lines: u16,
logs: Vec<(String, OutputKind)>,
line_offsets: Vec<usize>,
shift: u16,
command: Addr<CommandActor>,
status: Option<ExitStatus>,
Expand All @@ -76,13 +76,22 @@ impl Panel {
pub fn new(command: Addr<CommandActor>, colors: Vec<ColorOption>) -> Self {
Self {
logs: Vec::default(),
lines: 0,
line_offsets: Vec::default(),
shift: 0,
command,
status: None,
colors,
}
}

pub fn sync_lines(&mut self, width: u16) {
self.line_offsets = self
.logs
.iter()
.enumerate()
.flat_map(|(i, l)| vec![i; wrapped_lines(&l.0, width)])
.collect();
}
}

pub struct ConsoleActor {
Expand Down Expand Up @@ -138,7 +147,8 @@ impl ConsoleActor {
if let Some(focused_panel) = self.panels.get_mut(&self.index) {
// maximum_scroll is the number of lines
// overflowing in the current focused panel
let maximum_scroll = focused_panel.lines - min(focused_panel.lines, log_height);
let lines = focused_panel.line_offsets.len() as u16;
let maximum_scroll = lines - min(lines, log_height);

// `focused_panel.shift` goes from 0 until maximum_scroll
focused_panel.shift = min(focused_panel.shift + shift, maximum_scroll);
Expand Down Expand Up @@ -201,23 +211,45 @@ impl ConsoleActor {
.draw(|f| {
let chunks = chunks(&self.mode, &self.layout_direction, f);
let logs = &focused_panel.logs;

let log_height = chunks[0].height;
let maximum_scroll = focused_panel.lines - min(focused_panel.lines, log_height);

let lines: Vec<Line> = logs
.iter()
.flat_map(|(str, base_style)| {
let colorizer = Colorizer::new(&focused_panel.colors, *base_style);
colorizer.patch_text(str)
let shift = focused_panel.shift as usize;
let line_offsets = &focused_panel.line_offsets;
let lines = line_offsets.len();
let log_height = chunks[0].height as usize;

let maximum_scroll = lines - min(lines, log_height);
let scroll_offset = maximum_scroll - min(maximum_scroll, shift);
let offset_end = min(lines, scroll_offset + log_height).wrapping_sub(1);

let line_start = line_offsets.get(scroll_offset).cloned().unwrap_or(0);
let line_end = line_offsets.get(offset_end).cloned().unwrap_or(0);

let wrap_offset = line_offsets
.get(..scroll_offset)
.map(|offsets| {
offsets
.iter()
.rev()
.take_while(|&line| *line == line_start)
.count()
})
.collect();
.unwrap_or(0);

let lines = logs
.get(line_start..=line_end)
.map(|logs| {
logs.iter()
.flat_map(|(s, kind)| {
Colorizer::new(&focused_panel.colors, kind.style())
.patch_text(s)
})
.collect::<Vec<_>>()
})
.unwrap_or_default();

let paragraph = Paragraph::new(lines).wrap(Wrap { trim: false });
let paragraph = Paragraph::new(lines)
.wrap(Wrap { trim: false })
.scroll((wrap_offset as u16, 0));

// scroll by default until the last line
let paragraph = paragraph
.scroll((maximum_scroll - min(maximum_scroll, focused_panel.shift), 0));
f.render_widget(paragraph, chunks[0]);

//Format titles
Expand Down Expand Up @@ -303,8 +335,18 @@ impl ConsoleActor {
}
}

pub fn resize_panels(&mut self, width: u16) {
for panel in self.panels.values_mut() {
panel.shift = 0;
panel.sync_lines(width)
}
}

pub fn switch_layout(&mut self) {
self.layout_direction = self.layout_direction.get_opposite_orientation();
let f = self.terminal.get_frame();
let chunks = chunks(&self.mode, &self.layout_direction, &f);
self.resize_panels(chunks[0].width);
}
pub fn switch_mode(&mut self) {
self.mode = self.mode.get_opposite_mode();
Expand Down Expand Up @@ -432,16 +474,7 @@ impl Handler<TermEvent> for ConsoleActor {
},
_ => {}
},
Event::Resize(width, _) => {
for panel in self.panels.values_mut() {
panel.shift = 0;
let new_lines = panel
.logs
.iter()
.fold(0, |agg, l| agg + wrapped_lines(&l.0, width));
panel.lines = new_lines;
}
}
Event::Resize(width, _) => self.resize_panels(width),
Event::Mouse(e) => match e.kind {
MouseEventKind::ScrollUp => {
self.up(1);
Expand All @@ -457,29 +490,44 @@ impl Handler<TermEvent> for ConsoleActor {
}
}

#[derive(Debug)]
pub enum OutputKind {
Service,
Command,
}

impl OutputKind {
fn style(&self) -> Style {
match self {
OutputKind::Service => Style::default().bg(Color::DarkGray),
OutputKind::Command => Style::default(),
}
}
}

#[derive(Message)]
#[rtype(result = "()")]
pub struct Output {
panel_name: String,
pub message: String,
service: bool,
kind: OutputKind,
timestamp: DateTime<Local>,
}

impl Output {
pub fn now(panel_name: String, message: String, service: bool) -> Self {
pub fn now(panel_name: String, message: String, kind: OutputKind) -> Self {
Self {
panel_name,
message,
service,
kind,
timestamp: Local::now(),
}
}
}

fn wrapped_lines(message: &String, width: u16) -> u16 {
fn wrapped_lines(message: &String, width: u16) -> usize {
let clean = strip_ansi_escapes::strip(message);
textwrap::wrap(str::from_utf8(&clean).unwrap(), width as usize).len() as u16
textwrap::wrap(str::from_utf8(&clean).unwrap(), width as usize).len()
}

// Replace the character that are max that MAX_CHARS with an ellipse ...
Expand All @@ -502,19 +550,19 @@ impl Handler<Output> for ConsoleActor {
type Result = ();

fn handle(&mut self, msg: Output, _: &mut Context<Self>) -> Self::Result {
let panel = self.panels.get_mut(&msg.panel_name).unwrap();
let style = match msg.service {
true => Style::default().bg(Color::DarkGray),
false => Style::default(),
};

let message = match self.timestamp {
true => format_message(&msg.message, &msg.timestamp),
false => msg.message,
};

let panel = self.panels.get_mut(&msg.panel_name).unwrap();
let width = self.terminal.get_frame().size().width;
panel.lines += wrapped_lines(&message, width);
panel.logs.push((message, style));
let line_count = wrapped_lines(&message, width);
let line_offset = panel.logs.len();

panel.line_offsets.extend(vec![line_offset; line_count]);
panel.logs.push((message, msg.kind));

self.draw();
}
}
Expand Down Expand Up @@ -558,7 +606,7 @@ impl Handler<PanelStatus> for ConsoleActor {

if let Some(message) = msg.status.map(|c| format!("Status: {:?}", c)) {
ctx.address()
.do_send(Output::now(msg.panel_name, message, true));
.do_send(Output::now(msg.panel_name, message, OutputKind::Service));
}

self.draw();
Expand Down
10 changes: 3 additions & 7 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use anyhow::{Ok, Result};
use subprocess::ExitStatus;

use crate::actors::command::{CommandActorsBuilder, WaitStatus};
use crate::actors::console::RegisterPanel;
use crate::actors::console::{OutputKind, RegisterPanel};
use crate::actors::watcher::WatchGlob;
use crate::args::Args;
use crate::config::{ConfigInner, RawConfig};
Expand Down Expand Up @@ -94,19 +94,15 @@ fn hello() {
.send(Output::now(
"test".to_string(),
"message".to_string(),
false,
OutputKind::Command,
))
.await?;

let commands = CommandActorsBuilder::new(config, console, watcher)
.build()
.await?;

let status = commands
.get("test")
.unwrap()
.send(WaitStatus)
.await?;
let status = commands.get("test").unwrap().send(WaitStatus).await?;
println!("status: {:?}", status);

Ok(())
Expand Down

0 comments on commit 6ff2691

Please sign in to comment.