mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
copy mode: move by semantic zone, select by zone
Allows the following assignment actions; I was just over-using z for no real reason, I'm not suggesting that these are good assignments. ``` -- move the cursor backwards to the start of the current zone, or -- to the prior zone if already at the start { key = 'z', mods = 'NONE', action = act.CopyMode 'MoveBackwardSemanticZone' }, -- move the cursor forwards to the start of the next zone { key = 'Z', mods = 'NONE', action = act.CopyMode 'MoveForwardSemanticZone' }, -- start selecting by zone: both the start point and the cursor -- position will be expanded to the containing zone and the union -- of those two will be used for the selection { key = 'z', mods = 'CTRL', action = act.CopyMode { SetSelectionMode = 'SemanticZone' }, }, -- like MoveBackwardSemanticZone by only considers zones of the -- specified type { key = 'z', mods = 'ALT', action = act.CopyMode { MoveBackwardZoneOfType ='Output' }}, -- like MoveForwardSemanticZone by only considers zones of the -- specified type { key = 'Z', mods = 'ALT', action = act.CopyMode { MoveForwardZoneOfType ='Output' }}, ``` refs: https://github.com/wez/wezterm/issues/2346
This commit is contained in:
parent
33866dad70
commit
1df1f166ca
@ -9,6 +9,7 @@ use std::path::PathBuf;
|
||||
use wezterm_dynamic::{FromDynamic, ToDynamic};
|
||||
use wezterm_input_types::{KeyCode, Modifiers};
|
||||
use wezterm_term::input::MouseButton;
|
||||
use wezterm_term::SemanticType;
|
||||
|
||||
#[derive(Default, Debug, Clone, FromDynamic, ToDynamic, PartialEq, Eq)]
|
||||
pub struct LauncherActionArgs {
|
||||
@ -496,6 +497,10 @@ pub enum CopyModeAssignment {
|
||||
ClearPattern,
|
||||
EditPattern,
|
||||
AcceptPattern,
|
||||
MoveBackwardSemanticZone,
|
||||
MoveForwardSemanticZone,
|
||||
MoveBackwardZoneOfType(SemanticType),
|
||||
MoveForwardZoneOfType(SemanticType),
|
||||
}
|
||||
|
||||
pub type KeyTable = HashMap<(KeyCode, Modifiers), KeyTableEntry>;
|
||||
|
@ -147,7 +147,7 @@ macro_rules! bitfield {
|
||||
/// Input (that the user typed) and Prompt (effectively, "chrome" provided
|
||||
/// by the shell or application that the user is interacting with.
|
||||
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromDynamic, ToDynamic)]
|
||||
#[repr(u16)]
|
||||
pub enum SemanticType {
|
||||
Output = 0,
|
||||
|
@ -22,8 +22,8 @@ use unicode_segmentation::*;
|
||||
use url::Url;
|
||||
use wezterm_term::color::ColorPalette;
|
||||
use wezterm_term::{
|
||||
unicode_column_width, Clipboard, KeyCode, KeyModifiers, Line, MouseEvent, StableRowIndex,
|
||||
TerminalSize,
|
||||
unicode_column_width, Clipboard, KeyCode, KeyModifiers, Line, MouseEvent, SemanticType,
|
||||
StableRowIndex, TerminalSize,
|
||||
};
|
||||
use window::{KeyCode as WKeyCode, Modifiers, WindowOps};
|
||||
|
||||
@ -352,35 +352,47 @@ impl CopyRenderable {
|
||||
|
||||
fn select_to_cursor_pos(&mut self) {
|
||||
self.clamp_cursor_to_scrollback();
|
||||
if let Some(start) = self.start {
|
||||
let cursor_is_above_start = self.cursor.y < start.y;
|
||||
let start = if self.selection_mode == SelectionMode::Line {
|
||||
SelectionCoordinate::x_y(
|
||||
if cursor_is_above_start {
|
||||
usize::max_value()
|
||||
} else {
|
||||
0
|
||||
},
|
||||
start.y,
|
||||
)
|
||||
} else {
|
||||
SelectionCoordinate {
|
||||
x: start.x,
|
||||
y: start.y,
|
||||
}
|
||||
};
|
||||
if let Some(sel_start) = self.start {
|
||||
let cursor = SelectionCoordinate::x_y(self.cursor.x, self.cursor.y);
|
||||
|
||||
let end = if self.selection_mode == SelectionMode::Line {
|
||||
SelectionCoordinate::x_y(
|
||||
if cursor_is_above_start {
|
||||
0
|
||||
} else {
|
||||
usize::max_value()
|
||||
},
|
||||
self.cursor.y,
|
||||
)
|
||||
} else {
|
||||
SelectionCoordinate::x_y(self.cursor.x, self.cursor.y)
|
||||
let (start, end) = match self.selection_mode {
|
||||
SelectionMode::Line => {
|
||||
let cursor_is_above_start = self.cursor.y < sel_start.y;
|
||||
|
||||
let start = SelectionCoordinate::x_y(
|
||||
if cursor_is_above_start {
|
||||
usize::max_value()
|
||||
} else {
|
||||
0
|
||||
},
|
||||
sel_start.y,
|
||||
);
|
||||
let end = SelectionCoordinate::x_y(
|
||||
if cursor_is_above_start {
|
||||
0
|
||||
} else {
|
||||
usize::max_value()
|
||||
},
|
||||
self.cursor.y,
|
||||
);
|
||||
(start, end)
|
||||
}
|
||||
SelectionMode::SemanticZone => {
|
||||
let zone_range = SelectionRange::zone_around(cursor, &*self.delegate);
|
||||
let start_zone = SelectionRange::zone_around(sel_start, &*self.delegate);
|
||||
|
||||
let range = zone_range.extend_with(start_zone);
|
||||
|
||||
(range.start, range.end)
|
||||
}
|
||||
_ => {
|
||||
let start = SelectionCoordinate {
|
||||
x: sel_start.x,
|
||||
y: sel_start.y,
|
||||
};
|
||||
let end = cursor;
|
||||
(start, end)
|
||||
}
|
||||
};
|
||||
|
||||
self.adjust_selection(start, SelectionRange { start, end });
|
||||
@ -764,6 +776,52 @@ impl CopyRenderable {
|
||||
self.select_to_cursor_pos();
|
||||
}
|
||||
|
||||
fn move_by_zone(&mut self, mut delta: isize, zone_type: Option<SemanticType>) {
|
||||
if delta == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let zones = self
|
||||
.delegate
|
||||
.get_semantic_zones()
|
||||
.unwrap_or_else(|_| vec![]);
|
||||
let mut idx = match zones.binary_search_by(|zone| {
|
||||
if zone.start_y == self.cursor.y {
|
||||
zone.start_x.cmp(&self.cursor.x)
|
||||
} else if zone.start_y < self.cursor.y {
|
||||
std::cmp::Ordering::Less
|
||||
} else {
|
||||
std::cmp::Ordering::Greater
|
||||
}
|
||||
}) {
|
||||
Ok(idx) | Err(idx) => idx,
|
||||
};
|
||||
|
||||
let step = if delta > 0 { 1 } else { -1 };
|
||||
|
||||
while delta != 0 {
|
||||
if step > 0 {
|
||||
idx = idx.saturating_add(1);
|
||||
} else {
|
||||
idx = idx.saturating_sub(1);
|
||||
}
|
||||
let zone = match zones.get(idx) {
|
||||
Some(z) => z,
|
||||
None => return,
|
||||
};
|
||||
if let Some(zone_type) = &zone_type {
|
||||
if zone.semantic_type != *zone_type {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
delta = delta.saturating_sub(step);
|
||||
|
||||
self.cursor.x = zone.start_x;
|
||||
self.cursor.y = zone.start_y;
|
||||
}
|
||||
self.select_to_cursor_pos();
|
||||
}
|
||||
|
||||
fn set_selection_mode(&mut self, mode: &Option<SelectionMode>) {
|
||||
match mode {
|
||||
None => {
|
||||
@ -878,6 +936,10 @@ impl Pane for CopyOverlay {
|
||||
EditPattern => render.edit_pattern(),
|
||||
AcceptPattern => render.accept_pattern(),
|
||||
SetSelectionMode(mode) => render.set_selection_mode(mode),
|
||||
MoveBackwardSemanticZone => render.move_by_zone(-1, None),
|
||||
MoveForwardSemanticZone => render.move_by_zone(1, None),
|
||||
MoveBackwardZoneOfType(zone_type) => render.move_by_zone(-1, Some(*zone_type)),
|
||||
MoveForwardZoneOfType(zone_type) => render.move_by_zone(1, Some(*zone_type)),
|
||||
}
|
||||
true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user