1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-27 12:23:46 +03:00

implement new pane trait methods for copy and quickselect overlays

This commit is contained in:
Wez Furlong 2022-08-27 06:19:12 -07:00
parent f03dc68f96
commit d492eef700
3 changed files with 232 additions and 10 deletions

View File

@ -223,6 +223,10 @@ impl Line {
.replace(Arc::downgrade(&appdata));
}
pub fn clear_appdata(&self) {
self.appdata.lock().unwrap().take();
}
/// Retrieve the appdata for the line, if any.
/// This may return None in the case where the underlying data has
/// been released: Line only stores a Weak reference to it.

View File

@ -1023,16 +1023,126 @@ impl Pane for CopyOverlay {
self.delegate.get_changed_since(lines, seqno)
}
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
todo!();
}
fn for_each_logical_line_in_stable_range_mut(
&self,
lines: Range<StableRowIndex>,
for_line: &mut dyn ForEachPaneLogicalLine,
) {
todo!();
self.delegate
.for_each_logical_line_in_stable_range_mut(lines, for_line);
}
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
// Take care to access self.delegate methods here before we get into
// calling into its own with_lines_mut to avoid a runtime
// borrow erro!
let mut renderer = self.render.borrow_mut();
if self.delegate.get_current_seqno() > renderer.last_result_seqno {
renderer.update_search();
}
renderer.check_for_resize();
let dims = self.get_dimensions();
let search_row = renderer.compute_search_row();
struct OverlayLines<'a> {
with_lines: &'a mut dyn WithPaneLines,
dims: RenderableDimensions,
search_row: StableRowIndex,
renderer: &'a mut CopyRenderable,
}
self.delegate.with_lines_mut(
lines,
&mut OverlayLines {
with_lines,
dims,
search_row,
renderer: &mut *renderer,
},
);
impl<'a> WithPaneLines for OverlayLines<'a> {
fn with_lines_mut(&mut self, first_row: StableRowIndex, lines: &mut [&mut Line]) {
let mut overlay_lines = vec![];
let config = config::configuration();
let colors = &config.resolved_palette;
for (idx, line) in lines.iter_mut().enumerate() {
let mut line: Line = line.clone();
let stable_idx = idx as StableRowIndex + first_row;
self.renderer.dirty_results.remove(stable_idx);
if stable_idx == self.search_row
&& (self.renderer.editing_search || !self.renderer.pattern.is_empty())
{
// Replace with search UI
let rev = CellAttributes::default().set_reverse(true).clone();
line.fill_range(0..self.dims.cols, &Cell::new(' ', rev.clone()), SEQ_ZERO);
let mode = &match self.renderer.pattern {
Pattern::CaseSensitiveString(_) => "case-sensitive",
Pattern::CaseInSensitiveString(_) => "ignore-case",
Pattern::Regex(_) => "regex",
};
line.overlay_text_with_attribute(
0,
&format!(
"Search: {} ({}/{} matches. {})",
*self.renderer.pattern,
self.renderer.result_pos.map(|x| x + 1).unwrap_or(0),
self.renderer.results.len(),
mode
),
rev,
SEQ_ZERO,
);
self.renderer.last_bar_pos = Some(self.search_row);
line.clear_appdata();
} else if let Some(matches) = self.renderer.by_line.get(&stable_idx) {
for m in matches {
// highlight
for cell_idx in m.range.clone() {
if let Some(cell) =
line.cells_mut_for_attr_changes_only().get_mut(cell_idx)
{
if Some(m.result_index) == self.renderer.result_pos {
cell.attrs_mut()
.set_background(
colors
.copy_mode_active_highlight_bg
.unwrap_or(AnsiColor::Yellow.into()),
)
.set_foreground(
colors
.copy_mode_active_highlight_fg
.unwrap_or(AnsiColor::Black.into()),
)
.set_reverse(false);
} else {
cell.attrs_mut()
.set_background(
colors
.copy_mode_inactive_highlight_bg
.unwrap_or(AnsiColor::Fuchsia.into()),
)
.set_foreground(
colors
.copy_mode_inactive_highlight_fg
.unwrap_or(AnsiColor::Black.into()),
)
.set_reverse(false);
}
}
}
}
line.clear_appdata();
}
overlay_lines.push(line);
}
let mut overlay_refs: Vec<&mut Line> = overlay_lines.iter_mut().collect();
self.with_lines.with_lines_mut(first_row, &mut overlay_refs);
}
}
}
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {

View File

@ -452,16 +452,124 @@ impl Pane for QuickSelectOverlay {
dirty.intersection_with_range(lines)
}
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
todo!();
}
fn for_each_logical_line_in_stable_range_mut(
&self,
lines: Range<StableRowIndex>,
for_line: &mut dyn ForEachPaneLogicalLine,
) {
todo!();
self.delegate
.for_each_logical_line_in_stable_range_mut(lines, for_line);
}
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
let mut renderer = self.renderer.borrow_mut();
// Take care to access self.delegate methods here before we get into
// calling into its own with_lines_mut to avoid a runtime
// borrow erro!
renderer.check_for_resize();
let dims = self.get_dimensions();
let search_row = renderer.compute_search_row();
struct OverlayLines<'a> {
with_lines: &'a mut dyn WithPaneLines,
dims: RenderableDimensions,
search_row: StableRowIndex,
renderer: &'a mut QuickSelectRenderable,
}
self.delegate.with_lines_mut(
lines,
&mut OverlayLines {
with_lines,
dims,
search_row,
renderer: &mut *renderer,
},
);
impl<'a> WithPaneLines for OverlayLines<'a> {
fn with_lines_mut(&mut self, first_row: StableRowIndex, lines: &mut [&mut Line]) {
let mut overlay_lines = vec![];
let colors = self.renderer.config.resolved_palette.clone();
// Process the lines; for the search row we want to render instead
// the search UI.
// For rows with search results, we want to highlight the matching ranges
for (idx, line) in lines.iter_mut().enumerate() {
let mut line: Line = line.clone();
let stable_idx = idx as StableRowIndex + first_row;
self.renderer.dirty_results.remove(stable_idx);
if stable_idx == self.search_row {
// Replace with search UI
let rev = CellAttributes::default().set_reverse(true).clone();
line.fill_range(0..self.dims.cols, &Cell::new(' ', rev.clone()), SEQ_ZERO);
line.overlay_text_with_attribute(
0,
&format!(
"Select: {} (type highlighted prefix to {}, uppercase pastes, ESC to cancel)",
self.renderer.selection,
if self.renderer.args.label.is_empty() {
"copy"
} else {
&self.renderer.args.label
},
),
rev,
SEQ_ZERO,
);
self.renderer.last_bar_pos = Some(self.search_row);
line.clear_appdata();
} else if let Some(matches) = self.renderer.by_line.get(&stable_idx) {
for m in matches {
// highlight
for cell_idx in m.range.clone() {
if let Some(cell) =
line.cells_mut_for_attr_changes_only().get_mut(cell_idx)
{
cell.attrs_mut()
.set_background(
colors
.quick_select_match_bg
.unwrap_or(AnsiColor::Black.into()),
)
.set_foreground(
colors
.quick_select_match_fg
.unwrap_or(AnsiColor::Green.into()),
)
.set_reverse(false);
}
}
for (idx, c) in m.label.chars().enumerate() {
let mut attr = line
.get_cell(idx)
.map(|cell| cell.attrs().clone())
.unwrap_or_else(|| CellAttributes::default());
attr.set_background(
colors
.quick_select_label_bg
.unwrap_or(AnsiColor::Black.into()),
)
.set_foreground(
colors
.quick_select_label_fg
.unwrap_or(AnsiColor::Olive.into()),
)
.set_reverse(false);
line.set_cell(m.range.start + idx, Cell::new(c, attr), SEQ_ZERO);
}
}
line.clear_appdata();
}
overlay_lines.push(line);
}
let mut overlay_refs: Vec<&mut Line> = overlay_lines.iter_mut().collect();
self.with_lines.with_lines_mut(first_row, &mut overlay_refs);
}
}
}
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {