feat(cmd): unify jump-to-edge and fix viewport scrolling
Replaces separate jump-to-edge commands with a unified `JumpToEdge` command. Simplifies the command registry using a macro and updates `ScrollRows` to use a shared `viewport_effects` helper for consistent scrolling behavior. This fixes a bug where viewport scrolling was based on a hardcoded constant (20) instead of the actual visible row count. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-31B-it-GGUF:UD-Q5_K_XL)
This commit is contained in:
@ -313,75 +313,32 @@ impl Cmd for MoveSelection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unified jump-to-edge: jump to first/last row or column.
|
||||||
|
/// `is_row` selects the axis; `end` selects first (false) or last (true).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct JumpToFirstRow {
|
pub struct JumpToEdge {
|
||||||
pub col: usize,
|
pub cursor: CursorState,
|
||||||
|
pub is_row: bool,
|
||||||
|
pub end: bool,
|
||||||
|
pub cmd_name: &'static str,
|
||||||
}
|
}
|
||||||
impl Cmd for JumpToFirstRow {
|
impl Cmd for JumpToEdge {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"jump-first-row"
|
self.cmd_name
|
||||||
}
|
}
|
||||||
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
||||||
vec![
|
let (nr, nc) = if self.is_row {
|
||||||
Box::new(effect::SetSelected(0, self.col)),
|
let r = if self.end { self.cursor.row_count.saturating_sub(1) } else { 0 };
|
||||||
Box::new(effect::SetRowOffset(0)),
|
(r, self.cursor.col)
|
||||||
]
|
} else {
|
||||||
}
|
let c = if self.end { self.cursor.col_count.saturating_sub(1) } else { 0 };
|
||||||
}
|
(self.cursor.row, c)
|
||||||
|
};
|
||||||
#[derive(Debug)]
|
viewport_effects(
|
||||||
pub struct JumpToLastRow {
|
nr, nc,
|
||||||
pub col: usize,
|
self.cursor.row_offset, self.cursor.col_offset,
|
||||||
pub row_count: usize,
|
self.cursor.visible_rows, self.cursor.visible_cols,
|
||||||
pub row_offset: usize,
|
)
|
||||||
}
|
|
||||||
impl Cmd for JumpToLastRow {
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"jump-last-row"
|
|
||||||
}
|
|
||||||
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
|
||||||
let last = self.row_count.saturating_sub(1);
|
|
||||||
let mut effects: Vec<Box<dyn Effect>> = vec![Box::new(effect::SetSelected(last, self.col))];
|
|
||||||
if last >= self.row_offset + 20 {
|
|
||||||
effects.push(Box::new(effect::SetRowOffset(last.saturating_sub(19))));
|
|
||||||
}
|
|
||||||
effects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct JumpToFirstCol {
|
|
||||||
pub row: usize,
|
|
||||||
}
|
|
||||||
impl Cmd for JumpToFirstCol {
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"jump-first-col"
|
|
||||||
}
|
|
||||||
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
|
||||||
vec![
|
|
||||||
Box::new(effect::SetSelected(self.row, 0)),
|
|
||||||
Box::new(effect::SetColOffset(0)),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct JumpToLastCol {
|
|
||||||
pub row: usize,
|
|
||||||
pub col_count: usize,
|
|
||||||
pub col_offset: usize,
|
|
||||||
}
|
|
||||||
impl Cmd for JumpToLastCol {
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"jump-last-col"
|
|
||||||
}
|
|
||||||
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
|
||||||
let last = self.col_count.saturating_sub(1);
|
|
||||||
let mut effects: Vec<Box<dyn Effect>> = vec![Box::new(effect::SetSelected(self.row, last))];
|
|
||||||
if last >= self.col_offset + 8 {
|
|
||||||
effects.push(Box::new(effect::SetColOffset(last.saturating_sub(7))));
|
|
||||||
}
|
|
||||||
effects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,19 +354,14 @@ impl Cmd for ScrollRows {
|
|||||||
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
fn execute(&self, _ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
|
||||||
let row_max = self.cursor.row_count.saturating_sub(1) as i32;
|
let row_max = self.cursor.row_count.saturating_sub(1) as i32;
|
||||||
let nr = (self.cursor.row as i32 + self.delta).clamp(0, row_max) as usize;
|
let nr = (self.cursor.row as i32 + self.delta).clamp(0, row_max) as usize;
|
||||||
let mut effects: Vec<Box<dyn Effect>> =
|
viewport_effects(
|
||||||
vec![Box::new(effect::SetSelected(nr, self.cursor.col))];
|
nr,
|
||||||
let mut row_offset = self.cursor.row_offset;
|
self.cursor.col,
|
||||||
if nr < row_offset {
|
self.cursor.row_offset,
|
||||||
row_offset = nr;
|
self.cursor.col_offset,
|
||||||
}
|
self.cursor.visible_rows,
|
||||||
if nr >= row_offset + 20 {
|
self.cursor.visible_cols,
|
||||||
row_offset = nr.saturating_sub(19);
|
)
|
||||||
}
|
|
||||||
if row_offset != self.cursor.row_offset {
|
|
||||||
effects.push(Box::new(effect::SetRowOffset(row_offset)));
|
|
||||||
}
|
|
||||||
effects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2549,58 +2501,20 @@ pub fn default_registry() -> CmdRegistry {
|
|||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
r.register(
|
// Jump-to-edge commands: first/last row/col
|
||||||
&JumpToFirstRow { col: 0 },
|
macro_rules! reg_jump {
|
||||||
|_| Ok(Box::new(JumpToFirstRow { col: 0 })),
|
($r:expr, $is_row:expr, $end:expr, $name:expr) => {
|
||||||
|_, ctx| {
|
$r.register(
|
||||||
Ok(Box::new(JumpToFirstRow {
|
&JumpToEdge { cursor: CursorState::default(), is_row: $is_row, end: $end, cmd_name: $name },
|
||||||
col: ctx.selected.1,
|
|_| Ok(Box::new(JumpToEdge { cursor: CursorState::default(), is_row: $is_row, end: $end, cmd_name: $name })),
|
||||||
}))
|
|_, ctx| Ok(Box::new(JumpToEdge { cursor: CursorState::from_ctx(ctx), is_row: $is_row, end: $end, cmd_name: $name })),
|
||||||
},
|
);
|
||||||
);
|
};
|
||||||
r.register(
|
}
|
||||||
&JumpToLastRow { col: 0, row_count: 0, row_offset: 0 },
|
reg_jump!(r, true, false, "jump-first-row");
|
||||||
|_| {
|
reg_jump!(r, true, true, "jump-last-row");
|
||||||
Ok(Box::new(JumpToLastRow {
|
reg_jump!(r, false, false, "jump-first-col");
|
||||||
col: 0,
|
reg_jump!(r, false, true, "jump-last-col");
|
||||||
row_count: 0,
|
|
||||||
row_offset: 0,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
|_, ctx| {
|
|
||||||
Ok(Box::new(JumpToLastRow {
|
|
||||||
col: ctx.selected.1,
|
|
||||||
row_count: ctx.row_count,
|
|
||||||
row_offset: ctx.row_offset,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
r.register(
|
|
||||||
&JumpToFirstCol { row: 0 },
|
|
||||||
|_| Ok(Box::new(JumpToFirstCol { row: 0 })),
|
|
||||||
|_, ctx| {
|
|
||||||
Ok(Box::new(JumpToFirstCol {
|
|
||||||
row: ctx.selected.0,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
r.register(
|
|
||||||
&JumpToLastCol { row: 0, col_count: 0, col_offset: 0 },
|
|
||||||
|_| {
|
|
||||||
Ok(Box::new(JumpToLastCol {
|
|
||||||
row: 0,
|
|
||||||
col_count: 0,
|
|
||||||
col_offset: 0,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
|_, ctx| {
|
|
||||||
Ok(Box::new(JumpToLastCol {
|
|
||||||
row: ctx.selected.0,
|
|
||||||
col_count: ctx.col_count,
|
|
||||||
col_offset: ctx.col_offset,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
r.register(
|
r.register(
|
||||||
&ScrollRows { delta: 0, cursor: CursorState::default() },
|
&ScrollRows { delta: 0, cursor: CursorState::default() },
|
||||||
|args| {
|
|args| {
|
||||||
|
|||||||
Reference in New Issue
Block a user