Implement pager filter through EmbedGrid
Parse pager filter output as an EmbedGrid instead of the old ansi parser module.pull/144/head
parent
733de5a5fb
commit
22fb2ed46c
|
@ -40,6 +40,7 @@ pub struct Pager {
|
||||||
initialised: bool,
|
initialised: bool,
|
||||||
show_scrollbar: bool,
|
show_scrollbar: bool,
|
||||||
content: CellBuffer,
|
content: CellBuffer,
|
||||||
|
raw: bool,
|
||||||
text_lines: Vec<String>,
|
text_lines: Vec<String>,
|
||||||
line_breaker: LineBreakText,
|
line_breaker: LineBreakText,
|
||||||
movement: Option<PageMovement>,
|
movement: Option<PageMovement>,
|
||||||
|
@ -110,7 +111,7 @@ impl Pager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_string(
|
pub fn from_string(
|
||||||
mut text: String,
|
text: String,
|
||||||
context: Option<&Context>,
|
context: Option<&Context>,
|
||||||
cursor_pos: Option<usize>,
|
cursor_pos: Option<usize>,
|
||||||
mut width: Option<usize>,
|
mut width: Option<usize>,
|
||||||
|
@ -153,25 +154,22 @@ impl Pager {
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("Failed to start pager filter process");
|
.expect("Failed to start pager filter process");
|
||||||
{
|
let stdin = filter_child.stdin.as_mut().expect("failed to open stdin");
|
||||||
let stdin = filter_child.stdin.as_mut().expect("failed to open stdin");
|
stdin
|
||||||
stdin
|
.write_all(text.as_bytes())
|
||||||
.write_all(text.as_bytes())
|
.expect("Failed to write to stdin");
|
||||||
.expect("Failed to write to stdin");
|
let out = filter_child
|
||||||
}
|
.wait_with_output()
|
||||||
|
.expect("Failed to wait on filter")
|
||||||
|
.stdout;
|
||||||
|
let mut dev_null = std::fs::File::open("/dev/null").ok()?;
|
||||||
|
let mut embedded = crate::terminal::embed::EmbedGrid::new();
|
||||||
|
embedded.set_terminal_size((80, 20));
|
||||||
|
|
||||||
text = String::from_utf8_lossy(
|
for b in out {
|
||||||
&filter_child
|
embedded.process_byte(&mut dev_null, b);
|
||||||
.wait_with_output()
|
|
||||||
.expect("Failed to wait on filter")
|
|
||||||
.stdout,
|
|
||||||
)
|
|
||||||
.to_string();
|
|
||||||
if text.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
crate::terminal::ansi::ansi_to_cellbuffer(&text)
|
|
||||||
}
|
}
|
||||||
|
Some(std::mem::replace(embedded.buffer_mut(), Default::default()))
|
||||||
}) {
|
}) {
|
||||||
return Pager::from_buf(content, cursor_pos);
|
return Pager::from_buf(content, cursor_pos);
|
||||||
}
|
}
|
||||||
|
@ -186,6 +184,7 @@ impl Pager {
|
||||||
initialised: false,
|
initialised: false,
|
||||||
dirty: true,
|
dirty: true,
|
||||||
id: ComponentId::new_v4(),
|
id: ComponentId::new_v4(),
|
||||||
|
raw: false,
|
||||||
colors,
|
colors,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -200,7 +199,8 @@ impl Pager {
|
||||||
width,
|
width,
|
||||||
dirty: true,
|
dirty: true,
|
||||||
content,
|
content,
|
||||||
initialised: true,
|
raw: true,
|
||||||
|
initialised: false,
|
||||||
id: ComponentId::new_v4(),
|
id: ComponentId::new_v4(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -219,41 +219,44 @@ impl Pager {
|
||||||
if width < self.minimum_width {
|
if width < self.minimum_width {
|
||||||
width = self.minimum_width;
|
width = self.minimum_width;
|
||||||
}
|
}
|
||||||
if self.line_breaker.width() != Some(width.saturating_sub(4)) {
|
if !self.raw {
|
||||||
let line_breaker = LineBreakText::new(
|
if self.line_breaker.width() != Some(width.saturating_sub(4)) {
|
||||||
self.text.clone(),
|
let line_breaker = LineBreakText::new(
|
||||||
self.reflow,
|
self.text.clone(),
|
||||||
Some(width.saturating_sub(4)),
|
self.reflow,
|
||||||
);
|
Some(width.saturating_sub(4)),
|
||||||
|
|
||||||
self.line_breaker = line_breaker;
|
|
||||||
self.text_lines.clear();
|
|
||||||
};
|
|
||||||
self.height = self.text_lines.len();
|
|
||||||
self.width = width;
|
|
||||||
if let Some(ref mut search) = self.search {
|
|
||||||
use melib::text_processing::search::KMP;
|
|
||||||
search.positions.clear();
|
|
||||||
for (y, l) in self.text_lines.iter().enumerate() {
|
|
||||||
search.positions.extend(
|
|
||||||
l.kmp_search(&search.pattern)
|
|
||||||
.into_iter()
|
|
||||||
.map(|offset| (y, offset)),
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
if let Some(pos) = search.positions.get(search.cursor) {
|
self.line_breaker = line_breaker;
|
||||||
if self.cursor.1 > pos.0 || self.cursor.1 + height!(area) < pos.0 {
|
self.text_lines.clear();
|
||||||
self.cursor.1 = pos.0.saturating_sub(3);
|
};
|
||||||
|
self.height = self.text_lines.len();
|
||||||
|
self.width = width;
|
||||||
|
if let Some(ref mut search) = self.search {
|
||||||
|
use melib::text_processing::search::KMP;
|
||||||
|
search.positions.clear();
|
||||||
|
for (y, l) in self.text_lines.iter().enumerate() {
|
||||||
|
search.positions.extend(
|
||||||
|
l.kmp_search(&search.pattern)
|
||||||
|
.into_iter()
|
||||||
|
.map(|offset| (y, offset)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(pos) = search.positions.get(search.cursor) {
|
||||||
|
if self.cursor.1 > pos.0 || self.cursor.1 + height!(area) < pos.0 {
|
||||||
|
self.cursor.1 = pos.0.saturating_sub(3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.draw_lines_up_to(
|
||||||
|
grid,
|
||||||
|
area,
|
||||||
|
context,
|
||||||
|
self.cursor.1 + Self::PAGES_AHEAD_TO_RENDER_NO * height!(area),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.draw_lines_up_to(
|
|
||||||
grid,
|
|
||||||
area,
|
|
||||||
context,
|
|
||||||
self.cursor.1 + Self::PAGES_AHEAD_TO_RENDER_NO * height!(area),
|
|
||||||
);
|
|
||||||
self.draw_page(grid, area, context);
|
self.draw_page(grid, area, context);
|
||||||
|
|
||||||
self.initialised = true;
|
self.initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,6 +296,28 @@ impl Pager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_page(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
fn draw_page(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||||
|
if self.raw {
|
||||||
|
copy_area(
|
||||||
|
grid,
|
||||||
|
&self.content,
|
||||||
|
area,
|
||||||
|
(
|
||||||
|
(
|
||||||
|
std::cmp::min(
|
||||||
|
self.cursor.0.saturating_sub(width!(area)),
|
||||||
|
self.content.size().0.saturating_sub(width!(area)),
|
||||||
|
),
|
||||||
|
std::cmp::min(
|
||||||
|
self.cursor.1.saturating_sub(height!(area)),
|
||||||
|
self.content.size().1.saturating_sub(height!(area)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pos_dec(self.content.size(), (1, 1)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let (mut upper_left, bottom_right) = area;
|
let (mut upper_left, bottom_right) = area;
|
||||||
for l in self
|
for l in self
|
||||||
.text_lines
|
.text_lines
|
||||||
|
|
Loading…
Reference in New Issue