refactor: name configurable viewport scroll steps accurately
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
- [x] diff view: automatically detect changes and update the view when relevant bookmarks move change ids (regards bookmark-based diff view; i.e., user selected at least one bookmark in the before/after picker)
|
- [x] diff view: automatically detect changes and update the view when relevant bookmarks move change ids (regards bookmark-based diff view; i.e., user selected at least one bookmark in the before/after picker)
|
||||||
- [x] action to scroll viewport without having to move the cursor (like vim's `ctrl+e|u`).
|
- [x] action to scroll viewport without having to move the cursor (like vim's `ctrl+e|u`).
|
||||||
- [x] scroll viewport action (`ctrl+u|d`) scroll distance should be configurable.
|
- [x] scroll viewport action (`ctrl+u|d`) scroll distance should be configurable.
|
||||||
|
- [ ] file picker file search should also be fuzzy (we should be able to use the same fuzzy implemented for diff view search, i believe)
|
||||||
- [ ] diff view: labels are currently attached also when scrolling the view port horizontally (such that e.g. a function name is not fully visible in the viewport), which is good, but it currently attaches at that line, thus pushing down the function by one line, which causes a one-line jump when scrolling horizontally.
|
- [ ] diff view: labels are currently attached also when scrolling the view port horizontally (such that e.g. a function name is not fully visible in the viewport), which is good, but it currently attaches at that line, thus pushing down the function by one line, which causes a one-line jump when scrolling horizontally.
|
||||||
- we should in this case attach the label above the function instead of on the same line that it's defined such that it's not pushed down.
|
- we should in this case attach the label above the function instead of on the same line that it's defined such that it's not pushed down.
|
||||||
- [ ] diff view: github integration (code review) - add comments on a pr, add review comments at specific lines of files, request changes, approve pr, etc.
|
- [ ] diff view: github integration (code review) - add comments on a pr, add review comments at specific lines of files, request changes, approve pr, etc.
|
||||||
|
|||||||
+17
-6
@@ -5,18 +5,29 @@ Vamp.configure do |config|
|
|||||||
"python" => true,
|
"python" => true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# fallback tab spaces
|
||||||
|
config.tab_spaces = 4
|
||||||
|
|
||||||
|
# language specific tab spaces
|
||||||
|
config.language_tab_spaces.merge!(
|
||||||
|
"rust" => 4,
|
||||||
|
"ruby" => 2,
|
||||||
|
"makefile" => nil,
|
||||||
|
)
|
||||||
|
|
||||||
# 0 (default): scroll only at viewport edges
|
# 0 (default): scroll only at viewport edges
|
||||||
# nil: center; oversized integer margins also center
|
# nil: center; oversized integer margins also center
|
||||||
config.scroll_distance = 7
|
config.scroll_distance = 7
|
||||||
|
config.scroll_step_lines = 3
|
||||||
|
|
||||||
config.highlight_trailing_whitespace = true
|
config.highlight_trailing_whitespace = true
|
||||||
|
|
||||||
config.whitespace_scope = "leading" # or "all" (default)
|
#config.whitespace_scope = "leading" # or "all" (default)
|
||||||
config.whitespace_characters = {
|
#config.whitespace_characters = {
|
||||||
" " => "·",
|
# " " => "·",
|
||||||
"\t" => "→",
|
# "\t" => "→",
|
||||||
"\n" => "↵",
|
# "\n" => "↵",
|
||||||
}
|
#}
|
||||||
|
|
||||||
# "bar" (default), "symbols", "line_numbers", "none"
|
# "bar" (default), "symbols", "line_numbers", "none"
|
||||||
config.git_gutter = "bar"
|
config.git_gutter = "bar"
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ Resolution exposes its projected comparison through the same active DiffState an
|
|||||||
|
|
||||||
`Editor::scroll_distance()` supplies the session-wide optional edge margin. The TUI applies it to document/diff visual rows and unwrapped text columns, and retains independent picker offsets across navigation frames. Picker windows exclude their fixed chrome and align whole multi-row entries. File projections carry a monotonic viewport revision, so catalog/filter/expansion changes invalidate picker identity without hashing the entire catalog on every redraw. Metadata-only status changes do not move the viewport. Explicit LSP/wrap-toggle anchors and detached wheel views retain precedence.
|
`Editor::scroll_distance()` supplies the session-wide optional edge margin. The TUI applies it to document/diff visual rows and unwrapped text columns, and retains independent picker offsets across navigation frames. Picker windows exclude their fixed chrome and align whole multi-row entries. File projections carry a monotonic viewport revision, so catalog/filter/expansion changes invalidate picker identity without hashing the entire catalog on every redraw. Metadata-only status changes do not move the viewport. Explicit LSP/wrap-toggle anchors and detached wheel views retain precedence.
|
||||||
|
|
||||||
Keyboard viewport actions queue per-view row and half-page counts without moving carets. `Editor::take_viewport_scroll(height)` resolves half-page counts using the session-wide `scroll_half_page_lines` preference, or half the focused viewport when unset, and saturates multiplication before the frontend clamps movement to content bounds. Ordinary, diff, and conflict-history rendering share this resolution.
|
Keyboard viewport actions queue per-view row and configured-step counts without moving carets. `Editor::take_viewport_scroll(height)` resolves step counts using the session-wide `scroll_step_lines` preference, or half the focused viewport when unset, and saturates multiplication before the frontend clamps movement to content bounds. Ordinary, diff, and conflict-history rendering share this resolution.
|
||||||
|
|
||||||
Mouse wheel input uses the last rendered document/panel rectangles for hit-testing. Document offsets and explorer scroll state remain frontend-owned; three-row wheel steps never become document cursor motions. Manual document views persist until logical caret-reveal, caret/selection, mode, revision, or buffer changes; offscreen primary and browsing-selection cursors are not placed. Hover wheel input reuses the existing editor-owned popup scrolling.
|
Mouse wheel input uses the last rendered document/panel rectangles for hit-testing. Document offsets and explorer scroll state remain frontend-owned; three-row wheel steps never become document cursor motions. Manual document views persist until logical caret-reveal, caret/selection, mode, revision, or buffer changes; offscreen primary and browsing-selection cursors are not placed. Hover wheel input reuses the existing editor-owned popup scrolling.
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Vamp.configure do |config|
|
|||||||
config.git_blame = true # false disables current-line attribution
|
config.git_blame = true # false disables current-line attribution
|
||||||
config.git_gutter = "bar" # or "symbols", "line_numbers", "none"
|
config.git_gutter = "bar" # or "symbols", "line_numbers", "none"
|
||||||
config.scroll_distance = 0 # nonnegative edge distance, or nil to center
|
config.scroll_distance = 0 # nonnegative edge distance, or nil to center
|
||||||
config.scroll_half_page_lines = nil # Ctrl+u/d: half viewport, or a positive screen-row count
|
config.scroll_step_lines = nil # Ctrl+u/d: half viewport, or a positive screen-row count
|
||||||
config.highlight_trailing_whitespace = false # true marks line-end whitespace in red
|
config.highlight_trailing_whitespace = false # true marks line-end whitespace in red
|
||||||
config.whitespace_characters = {} # opt in: { " " => "·", "\t" => "→", "\n" => "↵" }
|
config.whitespace_characters = {} # opt in: { " " => "·", "\t" => "→", "\n" => "↵" }
|
||||||
config.whitespace_scope = "all" # or "leading" for indentation only
|
config.whitespace_scope = "all" # or "leading" for indentation only
|
||||||
@@ -58,7 +58,7 @@ Plugin paths resolve relative to the config file, not the shell's working direct
|
|||||||
|
|
||||||
The setting applies to ordinary and historical buffers, split/unified diff panes, file pickers and explorers, command/buffer palettes, completion lists, and revision selectors. Wrapped text measures visual rows, not source lines; picker distances use result rows, excluding borders, search fields, and help. Manual mouse-wheel scrolling remains detached until keyboard navigation resumes. Only `nil` or integers from `0` through the platform's Rust `usize` maximum (`18446744073709551615` on 64-bit systems) are accepted; other values reject the configuration.
|
The setting applies to ordinary and historical buffers, split/unified diff panes, file pickers and explorers, command/buffer palettes, completion lists, and revision selectors. Wrapped text measures visual rows, not source lines; picker distances use result rows, excluding borders, search fields, and help. Manual mouse-wheel scrolling remains detached until keyboard navigation resumes. Only `nil` or integers from `0` through the platform's Rust `usize` maximum (`18446744073709551615` on 64-bit systems) are accepted; other values reject the configuration.
|
||||||
|
|
||||||
`config.scroll_half_page_lines` controls Normal/Visual Ctrl+u/Ctrl+d (`core.scroll_half_up` / `core.scroll_half_down`). The default `nil` scrolls half the focused text viewport, rounded down with a minimum of one screen row. A positive integer, such as `config.scroll_half_page_lines = 3`, fixes the distance in screen rows, including wrapped continuations and diff display rows. Counts multiply that distance; `2` then Ctrl+d scrolls six rows with this example. This session-wide setting applies to ordinary, historical, diff, and conflict text panes without moving carets or selections. It does not change the cursor-edge margin, one-row scroll actions, mouse wheel, or picker navigation. Only `nil` or integers from `1` through the platform's Rust `usize` maximum are accepted; other values reject the configuration. Distances and count multiplication saturate at Rust's `isize` limit before the viewport clamps to content bounds.
|
`config.scroll_step_lines` controls Normal/Visual Ctrl+u/Ctrl+d (`core.scroll_step_up` / `core.scroll_step_down`). The default `nil` scrolls half the focused text viewport, rounded down with a minimum of one screen row. A positive integer, such as `config.scroll_step_lines = 3`, fixes the distance in screen rows, including wrapped continuations and diff display rows. Counts multiply that distance; `2` then Ctrl+d scrolls six rows with this example. This session-wide setting applies to ordinary, historical, diff, and conflict text panes without moving carets or selections. It does not change the cursor-edge margin, one-row scroll actions, mouse wheel, or picker navigation. Only `nil` or integers from `1` through the platform's Rust `usize` maximum are accepted; other values reject the configuration. Distances and count multiplication saturate at Rust's `isize` limit before the viewport clamps to content bounds.
|
||||||
|
|
||||||
`config.highlight_trailing_whitespace` defaults to `false`. Set it to `true` to give trailing whitespace a red background in ordinary and historical buffers and both sides of split/unified diffs, including wrapped and horizontally scrolled text. Spaces, expanded tab cells, and Unicode whitespace at the end of a source line are highlighted; whitespace-only lines are included, but empty lines and padding beyond the text are not. Wrapping does not make interior whitespace trailing. Search, selections, and secondary carets retain their background precedence; diagnostic underlines remain visible. This changes display only, not file contents. Only literal Ruby booleans are accepted; other values reject the configuration.
|
`config.highlight_trailing_whitespace` defaults to `false`. Set it to `true` to give trailing whitespace a red background in ordinary and historical buffers and both sides of split/unified diffs, including wrapped and horizontally scrolled text. Spaces, expanded tab cells, and Unicode whitespace at the end of a source line are highlighted; whitespace-only lines are included, but empty lines and padding beyond the text are not. Wrapping does not make interior whitespace trailing. Search, selections, and secondary carets retain their background precedence; diagnostic underlines remain visible. This changes display only, not file contents. Only literal Ruby booleans are accepted; other values reject the configuration.
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ Normal `C` / `D` / `Y` change/delete/copy the cursor-to-line-end suffix through
|
|||||||
|
|
||||||
`f<char>` / `F<char>` seeks forward/backward on the current line in Normal and Visual, with counts such as `2fx`. Rebind `config.core.seek_forward` / `config.core.seek_backward` to a single key or leader sequence; the action then waits for a literal target character. For example, `config.bind "s", config.core.seek_forward` makes `2sx` seek the second following `x`. Pass `mode: config.modes.visual` to install a Visual route. These native-only actions do not have Ex commands.
|
`f<char>` / `F<char>` seeks forward/backward on the current line in Normal and Visual, with counts such as `2fx`. Rebind `config.core.seek_forward` / `config.core.seek_backward` to a single key or leader sequence; the action then waits for a literal target character. For example, `config.bind "s", config.core.seek_forward` makes `2sx` seek the second following `x`. Pass `mode: config.modes.visual` to install a Visual route. These native-only actions do not have Ex commands.
|
||||||
|
|
||||||
Normal and Visual Ctrl+u/Ctrl+d invoke `config.core.scroll_half_up` / `config.core.scroll_half_down` without moving carets or selection endpoints. Counts multiply the configured `scroll_half_page_lines` distance (half a viewport by default). Bind `config.core.scroll_up` / `config.core.scroll_down` for one screen row per count, for example `config.bind "ctrl+e", config.core.scroll_down` to replace clone-below in Normal. Pass `mode: config.modes.visual` to rebind Visual too. These actions work in ordinary and diff text panes, use wrapped screen rows, and have no Ex commands. Cursor navigation or editing resumes caret following.
|
Normal and Visual Ctrl+u/Ctrl+d invoke `config.core.scroll_step_up` / `config.core.scroll_step_down` without moving carets or selection endpoints. Counts multiply the configured `scroll_step_lines` distance (half a viewport by default). Bind `config.core.scroll_up` / `config.core.scroll_down` for one screen row per count, for example `config.bind "ctrl+e", config.core.scroll_down` to replace clone-below in Normal. Pass `mode: config.modes.visual` to rebind Visual too. These actions work in ordinary and diff text panes, use wrapped screen rows, and have no Ex commands. Cursor navigation or editing resumes caret following.
|
||||||
|
|
||||||
## Action reference
|
## Action reference
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ Normal and Visual Ctrl+u/Ctrl+d invoke `config.core.scroll_half_up` / `config.co
|
|||||||
| Normal, Visual | `file_picker`, `file_explorer` |
|
| Normal, Visual | `file_picker`, `file_explorer` |
|
||||||
| Normal, Visual | `document_start`, `document_end`, `go_to_line` |
|
| Normal, Visual | `document_start`, `document_end`, `go_to_line` |
|
||||||
| Normal, Visual | `seek_forward`, `seek_backward` |
|
| Normal, Visual | `seek_forward`, `seek_backward` |
|
||||||
| Normal, Visual | `scroll_up`, `scroll_down`, `scroll_half_up`, `scroll_half_down` |
|
| Normal, Visual | `scroll_up`, `scroll_down`, `scroll_step_up`, `scroll_step_down` |
|
||||||
| Normal, Insert, Visual | `line_start`, `line_end` |
|
| Normal, Insert, Visual | `line_start`, `line_end` |
|
||||||
| Normal, Insert, Visual, Tree | `left`, `right` |
|
| Normal, Insert, Visual, Tree | `left`, `right` |
|
||||||
| Normal, Insert, Visual, Selection, Tree | `down`, `up` |
|
| Normal, Insert, Visual, Selection, Tree | `down`, `up` |
|
||||||
|
|||||||
+1
-1
@@ -76,7 +76,7 @@ Diff styling checks cover independent snapshot language/shebang/injection detect
|
|||||||
|
|
||||||
- Undo uses full-buffer snapshots and movement scans the current line. This favors straightforward correctness over large-file performance.
|
- Undo uses full-buffer snapshots and movement scans the current line. This favors straightforward correctness over large-file performance.
|
||||||
- Rapid-wheel verification must replay bursts against the running editor and measure arrival at the final viewport after input stops, not just individual frame duration. Cheap frames can still accumulate a visible backlog if each queued report requires its own redraw.
|
- Rapid-wheel verification must replay bursts against the running editor and measure arrival at the final viewport after input stops, not just individual frame duration. Cheap frames can still accumulate a visible backlog if each queued report requires its own redraw.
|
||||||
- Keyboard viewport scrolling coalesces up to 64 consecutive inputs for the same resolved scroll action into one redraw. Reversals, changes between row/half-page scrolling, and cursor motions end the batch so boundary clamping and caret reveal happen before the next action. Burst checks must include direction changes at the start/end of the buffer, not just throughput.
|
- Keyboard viewport scrolling coalesces up to 64 consecutive inputs for the same resolved scroll action into one redraw. Reversals, changes between row/configured-step scrolling, and cursor motions end the batch so boundary clamping and caret reveal happen before the next action. Burst checks must include direction changes at the start/end of the buffer, not just throughput.
|
||||||
- PTY throughput alone cannot prove terminal presentation stays smooth: capture the editor and terminal while the user reproduces a pause. Synchronized-output commands must not reach the terminal during frame computation, even when individual frames and queued-input catch-up appear fast.
|
- PTY throughput alone cannot prove terminal presentation stays smooth: capture the editor and terminal while the user reproduces a pause. Synchronized-output commands must not reach the terminal during frame computation, even when individual frames and queued-input catch-up appear fast.
|
||||||
- Annotation coordinate validation fast-paths ASCII grapheme lengths using byte lengths with CRLF pair accounting, retaining Unicode segmentation for non-ASCII text. Validation remains atomic and still checks every token; large Unicode buffers or diagnostic batches can require foreground work.
|
- Annotation coordinate validation fast-paths ASCII grapheme lengths using byte lengths with CRLF pair accounting, retaining Unicode segmentation for non-ASCII text. Validation remains atomic and still checks every token; large Unicode buffers or diagnostic batches can require foreground work.
|
||||||
- Legacy synchronous plugin invocation may pause input for up to 500 ms before a host timeout. Async plugins opt into background replies; pending requests and transport queues are bounded. Config/plugin startup has a 2-second deadline per host. Buffer context/document snapshots must fit within a 4 MiB JSON frame; a too-large frame disables that plugin, not editing.
|
- Legacy synchronous plugin invocation may pause input for up to 500 ms before a host timeout. Async plugins opt into background replies; pending requests and transport queues are bounded. Config/plugin startup has a 2-second deadline per host. Buffer context/document snapshots must fit within a 4 MiB JSON frame; a too-large frame disables that plugin, not editing.
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ Indicators refresh asynchronously. Typing and undo/redo retain the last complete
|
|||||||
| Normal, Visual | `<line>g` jumps immediately to that one-based source line at first nonblank (`42g`); clamps at EOF and extends Visual selections |
|
| Normal, Visual | `<line>g` jumps immediately to that one-based source line at first nonblank (`42g`); clamps at EOF and extends Visual selections |
|
||||||
| Normal | Ctrl+o goes to an older jump location; Ctrl+i/Tab goes forward; counts select multiple locations |
|
| Normal | Ctrl+o goes to an older jump location; Ctrl+i/Tab goes forward; counts select multiple locations |
|
||||||
| Normal, Visual | Decimal prefixes repeat cursor/word/search motions: `5j`, `3k`, `2w`, `4e`, `2n`; Esc cancels a pending count |
|
| Normal, Visual | Decimal prefixes repeat cursor/word/search motions: `5j`, `3k`, `2w`, `4e`, `2n`; Esc cancels a pending count |
|
||||||
| Normal, Visual | Ctrl+u/Ctrl+d scroll up/down without moving carets or selections; half a viewport by default, configurable with `config.scroll_half_page_lines`; counts multiply the distance |
|
| Normal, Visual | Ctrl+u/Ctrl+d scroll up/down without moving carets or selections; half a viewport by default, configurable with `config.scroll_step_lines`; counts multiply the distance |
|
||||||
| Normal | `J` (Shift+j) joins each targeted line with the next line |
|
| Normal | `J` (Shift+j) joins each targeted line with the next line |
|
||||||
| Normal | `x`/Delete delete; `u` undo; `U` (Shift+u) redo; `:` enter command mode |
|
| Normal | `x`/Delete delete; `u` undo; `U` (Shift+u) redo; `:` enter command mode |
|
||||||
| Normal | `yy` copies whole lines without moving; `dd` deletes them; `cc` changes them and enters Insert; counts work (`3yy`, `2dd`, `2cc`) |
|
| Normal | `yy` copies whole lines without moving; `dd` deletes them; `cc` changes them and enters Insert; counts work (`3yy`, `2dd`, `2cc`) |
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ Vamp.configure do |config|
|
|||||||
config.clipboard_mode = "system" # "separate" keeps ordinary y/d/c/p/P internal
|
config.clipboard_mode = "system" # "separate" keeps ordinary y/d/c/p/P internal
|
||||||
config.git_blame = true # false disables current-line inline blame
|
config.git_blame = true # false disables current-line inline blame
|
||||||
config.scroll_distance = 0 # nonnegative edge distance, or nil to center
|
config.scroll_distance = 0 # nonnegative edge distance, or nil to center
|
||||||
config.scroll_half_page_lines = nil # Ctrl+u/d: half viewport, or a positive screen-row count
|
config.scroll_step_lines = nil # Ctrl+u/d: half viewport, or a positive screen-row count
|
||||||
config.highlight_trailing_whitespace = false # true marks line-end whitespace in red
|
config.highlight_trailing_whitespace = false # true marks line-end whitespace in red
|
||||||
config.whitespace_characters = {} # opt in: { " " => "·", "\t" => "→", "\n" => "↵" }
|
config.whitespace_characters = {} # opt in: { " " => "·", "\t" => "→", "\n" => "↵" }
|
||||||
config.whitespace_scope = "all" # or "leading" for indentation only; newline markers remain independent
|
config.whitespace_scope = "all" # or "leading" for indentation only; newline markers remain independent
|
||||||
|
|||||||
+24
-24
@@ -644,13 +644,13 @@ core_actions![
|
|||||||
&[Mode::Normal, Mode::Visual]
|
&[Mode::Normal, Mode::Visual]
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"core.scroll_half_up",
|
"core.scroll_step_up",
|
||||||
Action::ScrollHalfUp,
|
Action::ScrollStepUp,
|
||||||
&[Mode::Normal, Mode::Visual]
|
&[Mode::Normal, Mode::Visual]
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"core.scroll_half_down",
|
"core.scroll_step_down",
|
||||||
Action::ScrollHalfDown,
|
Action::ScrollStepDown,
|
||||||
&[Mode::Normal, Mode::Visual]
|
&[Mode::Normal, Mode::Visual]
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@@ -1342,8 +1342,8 @@ fn default_bindings() -> HashMap<Mode, HashMap<Input, Binding>> {
|
|||||||
for (key, action) in [
|
for (key, action) in [
|
||||||
(Input::Ctrl('k'), CloneAbove),
|
(Input::Ctrl('k'), CloneAbove),
|
||||||
(Input::Ctrl('e'), CloneBelow),
|
(Input::Ctrl('e'), CloneBelow),
|
||||||
(Input::Ctrl('u'), ScrollHalfUp),
|
(Input::Ctrl('u'), ScrollStepUp),
|
||||||
(Input::Ctrl('d'), ScrollHalfDown),
|
(Input::Ctrl('d'), ScrollStepDown),
|
||||||
(Input::Escape, Normal),
|
(Input::Escape, Normal),
|
||||||
] {
|
] {
|
||||||
bindings
|
bindings
|
||||||
@@ -2009,7 +2009,7 @@ pub struct Editor {
|
|||||||
popup: PopupConfig,
|
popup: PopupConfig,
|
||||||
labels: BTreeMap<String, String>,
|
labels: BTreeMap<String, String>,
|
||||||
scroll_distance: Option<usize>,
|
scroll_distance: Option<usize>,
|
||||||
scroll_half_page_lines: Option<NonZeroUsize>,
|
scroll_step_lines: Option<NonZeroUsize>,
|
||||||
highlight_trailing_whitespace: bool,
|
highlight_trailing_whitespace: bool,
|
||||||
whitespace_characters: BTreeMap<char, char>,
|
whitespace_characters: BTreeMap<char, char>,
|
||||||
whitespace_scope: WhitespaceScope,
|
whitespace_scope: WhitespaceScope,
|
||||||
@@ -2120,7 +2120,7 @@ impl Editor {
|
|||||||
popup: PopupConfig::default(),
|
popup: PopupConfig::default(),
|
||||||
labels: BTreeMap::new(),
|
labels: BTreeMap::new(),
|
||||||
scroll_distance: Some(0),
|
scroll_distance: Some(0),
|
||||||
scroll_half_page_lines: None,
|
scroll_step_lines: None,
|
||||||
highlight_trailing_whitespace: false,
|
highlight_trailing_whitespace: false,
|
||||||
whitespace_characters: BTreeMap::new(),
|
whitespace_characters: BTreeMap::new(),
|
||||||
whitespace_scope: WhitespaceScope::All,
|
whitespace_scope: WhitespaceScope::All,
|
||||||
@@ -4118,8 +4118,8 @@ impl Editor {
|
|||||||
self.scroll_distance = distance;
|
self.scroll_distance = distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_scroll_half_page_lines(&mut self, lines: Option<NonZeroUsize>) {
|
pub(crate) fn set_scroll_step_lines(&mut self, lines: Option<NonZeroUsize>) {
|
||||||
self.scroll_half_page_lines = lines;
|
self.scroll_step_lines = lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn highlight_trailing_whitespace(&self) -> bool {
|
pub(crate) fn highlight_trailing_whitespace(&self) -> bool {
|
||||||
@@ -4465,8 +4465,8 @@ impl Editor {
|
|||||||
| Action::Up
|
| Action::Up
|
||||||
| Action::ScrollUp
|
| Action::ScrollUp
|
||||||
| Action::ScrollDown
|
| Action::ScrollDown
|
||||||
| Action::ScrollHalfUp
|
| Action::ScrollStepUp
|
||||||
| Action::ScrollHalfDown
|
| Action::ScrollStepDown
|
||||||
| Action::LineStart
|
| Action::LineStart
|
||||||
| Action::LineEnd
|
| Action::LineEnd
|
||||||
| Action::DocumentStart
|
| Action::DocumentStart
|
||||||
@@ -4487,8 +4487,8 @@ impl Editor {
|
|||||||
Binding::Action(
|
Binding::Action(
|
||||||
action @ (Action::ScrollUp
|
action @ (Action::ScrollUp
|
||||||
| Action::ScrollDown
|
| Action::ScrollDown
|
||||||
| Action::ScrollHalfUp
|
| Action::ScrollStepUp
|
||||||
| Action::ScrollHalfDown),
|
| Action::ScrollStepDown),
|
||||||
) => Some(action.entry().name),
|
) => Some(action.entry().name),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -5834,12 +5834,12 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn take_viewport_scroll(&self, height: usize) -> isize {
|
pub(crate) fn take_viewport_scroll(&self, height: usize) -> isize {
|
||||||
let (rows, halves) = self.active.view.viewport_scroll.take();
|
let (rows, steps) = self.active.view.viewport_scroll.take();
|
||||||
let lines = self
|
let lines = self
|
||||||
.scroll_half_page_lines
|
.scroll_step_lines
|
||||||
.map_or((height / 2).max(1), NonZeroUsize::get);
|
.map_or((height / 2).max(1), NonZeroUsize::get);
|
||||||
let lines = isize::try_from(lines).unwrap_or(isize::MAX);
|
let lines = isize::try_from(lines).unwrap_or(isize::MAX);
|
||||||
rows.saturating_add(halves.saturating_mul(lines))
|
rows.saturating_add(steps.saturating_mul(lines))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reveal_caret(&mut self) {
|
fn reveal_caret(&mut self) {
|
||||||
@@ -8305,22 +8305,22 @@ impl Editor {
|
|||||||
Action::JumpForward => self.traverse_jumps(true, count),
|
Action::JumpForward => self.traverse_jumps(true, count),
|
||||||
Action::ScrollUp
|
Action::ScrollUp
|
||||||
| Action::ScrollDown
|
| Action::ScrollDown
|
||||||
| Action::ScrollHalfUp
|
| Action::ScrollStepUp
|
||||||
| Action::ScrollHalfDown => {
|
| Action::ScrollStepDown => {
|
||||||
if self.document_actions_available() {
|
if self.document_actions_available() {
|
||||||
let amount = isize::try_from(count).unwrap_or(isize::MAX);
|
let amount = isize::try_from(count).unwrap_or(isize::MAX);
|
||||||
let amount = if matches!(action, Action::ScrollUp | Action::ScrollHalfUp) {
|
let amount = if matches!(action, Action::ScrollUp | Action::ScrollStepUp) {
|
||||||
-amount
|
-amount
|
||||||
} else {
|
} else {
|
||||||
amount
|
amount
|
||||||
};
|
};
|
||||||
let (mut rows, mut halves) = self.active.view.viewport_scroll.get();
|
let (mut rows, mut steps) = self.active.view.viewport_scroll.get();
|
||||||
if matches!(action, Action::ScrollHalfUp | Action::ScrollHalfDown) {
|
if matches!(action, Action::ScrollStepUp | Action::ScrollStepDown) {
|
||||||
halves = halves.saturating_add(amount);
|
steps = steps.saturating_add(amount);
|
||||||
} else {
|
} else {
|
||||||
rows = rows.saturating_add(amount);
|
rows = rows.saturating_add(amount);
|
||||||
}
|
}
|
||||||
self.active.view.viewport_scroll.set((rows, halves));
|
self.active.view.viewport_scroll.set((rows, steps));
|
||||||
if let Some(diff) = self.interaction_diff_mut() {
|
if let Some(diff) = self.interaction_diff_mut() {
|
||||||
diff.follow_caret = false;
|
diff.follow_caret = false;
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-10
@@ -46,7 +46,7 @@ pub struct Config {
|
|||||||
pub popup: PopupConfig,
|
pub popup: PopupConfig,
|
||||||
pub labels: BTreeMap<String, String>,
|
pub labels: BTreeMap<String, String>,
|
||||||
pub scroll_distance: Option<usize>,
|
pub scroll_distance: Option<usize>,
|
||||||
pub scroll_half_page_lines: Option<NonZeroUsize>,
|
pub scroll_step_lines: Option<NonZeroUsize>,
|
||||||
pub highlight_trailing_whitespace: bool,
|
pub highlight_trailing_whitespace: bool,
|
||||||
pub whitespace_characters: BTreeMap<char, char>,
|
pub whitespace_characters: BTreeMap<char, char>,
|
||||||
pub whitespace_scope: crate::editor::WhitespaceScope,
|
pub whitespace_scope: crate::editor::WhitespaceScope,
|
||||||
@@ -98,7 +98,7 @@ impl Default for Config {
|
|||||||
popup: PopupConfig::default(),
|
popup: PopupConfig::default(),
|
||||||
labels: BTreeMap::new(),
|
labels: BTreeMap::new(),
|
||||||
scroll_distance: Some(0),
|
scroll_distance: Some(0),
|
||||||
scroll_half_page_lines: None,
|
scroll_step_lines: None,
|
||||||
highlight_trailing_whitespace: false,
|
highlight_trailing_whitespace: false,
|
||||||
whitespace_characters: BTreeMap::new(),
|
whitespace_characters: BTreeMap::new(),
|
||||||
whitespace_scope: crate::editor::WhitespaceScope::All,
|
whitespace_scope: crate::editor::WhitespaceScope::All,
|
||||||
@@ -137,7 +137,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
|
|||||||
popup,
|
popup,
|
||||||
labels,
|
labels,
|
||||||
scroll_distance,
|
scroll_distance,
|
||||||
scroll_half_page_lines,
|
scroll_step_lines,
|
||||||
highlight_trailing_whitespace,
|
highlight_trailing_whitespace,
|
||||||
whitespace_characters,
|
whitespace_characters,
|
||||||
whitespace_scope,
|
whitespace_scope,
|
||||||
@@ -177,7 +177,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
|
|||||||
config.popup = popup;
|
config.popup = popup;
|
||||||
config.labels = labels;
|
config.labels = labels;
|
||||||
config.scroll_distance = scroll_distance;
|
config.scroll_distance = scroll_distance;
|
||||||
config.scroll_half_page_lines = scroll_half_page_lines;
|
config.scroll_step_lines = scroll_step_lines;
|
||||||
config.highlight_trailing_whitespace = highlight_trailing_whitespace;
|
config.highlight_trailing_whitespace = highlight_trailing_whitespace;
|
||||||
config.whitespace_characters = whitespace_characters;
|
config.whitespace_characters = whitespace_characters;
|
||||||
config.whitespace_scope = whitespace_scope;
|
config.whitespace_scope = whitespace_scope;
|
||||||
@@ -516,7 +516,7 @@ struct ConfigFrame {
|
|||||||
labels: BTreeMap<String, String>,
|
labels: BTreeMap<String, String>,
|
||||||
#[serde(deserialize_with = "scroll_distance")]
|
#[serde(deserialize_with = "scroll_distance")]
|
||||||
scroll_distance: Option<usize>,
|
scroll_distance: Option<usize>,
|
||||||
scroll_half_page_lines: Option<NonZeroUsize>,
|
scroll_step_lines: Option<NonZeroUsize>,
|
||||||
highlight_trailing_whitespace: bool,
|
highlight_trailing_whitespace: bool,
|
||||||
#[serde(deserialize_with = "whitespace_characters")]
|
#[serde(deserialize_with = "whitespace_characters")]
|
||||||
whitespace_characters: BTreeMap<char, char>,
|
whitespace_characters: BTreeMap<char, char>,
|
||||||
@@ -1935,7 +1935,7 @@ end
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn config_scroll_half_page_lines_controls_counted_scrolling_and_rejects_invalid_values() {
|
fn config_scroll_step_lines_controls_counted_scrolling_and_rejects_invalid_values() {
|
||||||
let fixture = Fixture::new();
|
let fixture = Fixture::new();
|
||||||
for (value, expected) in [
|
for (value, expected) in [
|
||||||
("nil", 30),
|
("nil", 30),
|
||||||
@@ -1945,17 +1945,31 @@ end
|
|||||||
] {
|
] {
|
||||||
let path = fixture.file(
|
let path = fixture.file(
|
||||||
"config.rb",
|
"config.rb",
|
||||||
&format!("Vamp.configure {{ |config| config.scroll_half_page_lines = {value} }}"),
|
&format!(
|
||||||
|
"Vamp.configure do |config|
|
||||||
|
config.scroll_step_lines = {value}
|
||||||
|
config.bind \"alt+j\", config.core.scroll_step_down
|
||||||
|
config.bind \"alt+k\", config.core.scroll_step_up
|
||||||
|
end"
|
||||||
|
),
|
||||||
);
|
);
|
||||||
let mut session =
|
let mut session =
|
||||||
crate::session::EditorSession::open(None, vec![], Some(&path)).unwrap();
|
crate::session::EditorSession::open(None, vec![], Some(&path)).unwrap();
|
||||||
session.handle(crate::editor::Input::Char('3'));
|
session.handle(crate::editor::Input::Char('3'));
|
||||||
session.handle(crate::editor::Input::Ctrl('d'));
|
session.handle(crate::editor::Input::Alt('j'));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
session.editor().take_viewport_scroll(20),
|
session.editor().take_viewport_scroll(20),
|
||||||
expected,
|
expected,
|
||||||
"{value}"
|
"{value}"
|
||||||
);
|
);
|
||||||
|
session.handle(crate::editor::Input::Char('3'));
|
||||||
|
session.handle(crate::editor::Input::Alt('k'));
|
||||||
|
let up = if expected == isize::MAX {
|
||||||
|
isize::MIN
|
||||||
|
} else {
|
||||||
|
-expected
|
||||||
|
};
|
||||||
|
assert_eq!(session.editor().take_viewport_scroll(20), up, "{value}");
|
||||||
}
|
}
|
||||||
for value in [
|
for value in [
|
||||||
"0",
|
"0",
|
||||||
@@ -1968,11 +1982,11 @@ end
|
|||||||
] {
|
] {
|
||||||
let path = fixture.file(
|
let path = fixture.file(
|
||||||
"config.rb",
|
"config.rb",
|
||||||
&format!("Vamp.configure {{ |config| config.scroll_half_page_lines = {value} }}"),
|
&format!("Vamp.configure {{ |config| config.scroll_step_lines = {value} }}"),
|
||||||
);
|
);
|
||||||
let error = load_config(&path).unwrap_err();
|
let error = load_config(&path).unwrap_err();
|
||||||
assert!(
|
assert!(
|
||||||
error.contains("scroll_half_page_lines") && error.contains("must be"),
|
error.contains("scroll_step_lines") && error.contains("must be"),
|
||||||
"{value}: {error}"
|
"{value}: {error}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -145,7 +145,7 @@ module Vamp
|
|||||||
@popup = PopupConfig.new
|
@popup = PopupConfig.new
|
||||||
@labels = {}
|
@labels = {}
|
||||||
@scroll_distance = 0
|
@scroll_distance = 0
|
||||||
@scroll_half_page_lines = nil
|
@scroll_step_lines = nil
|
||||||
@highlight_trailing_whitespace = false
|
@highlight_trailing_whitespace = false
|
||||||
@whitespace_characters = {}
|
@whitespace_characters = {}
|
||||||
@whitespace_scope = "all"
|
@whitespace_scope = "all"
|
||||||
@@ -232,8 +232,8 @@ module Vamp
|
|||||||
|
|
||||||
# @param lines [Integer, nil] positive screen rows, or nil for half the viewport
|
# @param lines [Integer, nil] positive screen rows, or nil for half the viewport
|
||||||
# @return [Integer, nil]
|
# @return [Integer, nil]
|
||||||
def scroll_half_page_lines=(lines)
|
def scroll_step_lines=(lines)
|
||||||
@scroll_half_page_lines = lines.nil? ? nil : diff_line_count!(lines, "scroll_half_page_lines", 1)
|
@scroll_step_lines = lines.nil? ? nil : diff_line_count!(lines, "scroll_step_lines", 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param enabled [Boolean]
|
# @param enabled [Boolean]
|
||||||
@@ -350,7 +350,7 @@ module Vamp
|
|||||||
"git_blame" => @git_blame,
|
"git_blame" => @git_blame,
|
||||||
"git_gutter" => @git_gutter,
|
"git_gutter" => @git_gutter,
|
||||||
"scroll_distance" => @scroll_distance,
|
"scroll_distance" => @scroll_distance,
|
||||||
"scroll_half_page_lines" => @scroll_half_page_lines,
|
"scroll_step_lines" => @scroll_step_lines,
|
||||||
"highlight_trailing_whitespace" => @highlight_trailing_whitespace,
|
"highlight_trailing_whitespace" => @highlight_trailing_whitespace,
|
||||||
"whitespace_characters" => @whitespace_characters,
|
"whitespace_characters" => @whitespace_characters,
|
||||||
"whitespace_scope" => @whitespace_scope,
|
"whitespace_scope" => @whitespace_scope,
|
||||||
|
|||||||
+1
-1
@@ -512,7 +512,7 @@ impl EditorSession {
|
|||||||
editor.set_git_blame(config.git_blame);
|
editor.set_git_blame(config.git_blame);
|
||||||
editor.set_gutter_style(config.git_gutter);
|
editor.set_gutter_style(config.git_gutter);
|
||||||
editor.set_scroll_distance(config.scroll_distance);
|
editor.set_scroll_distance(config.scroll_distance);
|
||||||
editor.set_scroll_half_page_lines(config.scroll_half_page_lines);
|
editor.set_scroll_step_lines(config.scroll_step_lines);
|
||||||
editor.set_highlight_trailing_whitespace(config.highlight_trailing_whitespace);
|
editor.set_highlight_trailing_whitespace(config.highlight_trailing_whitespace);
|
||||||
editor.set_whitespace_characters(config.whitespace_characters);
|
editor.set_whitespace_characters(config.whitespace_characters);
|
||||||
editor.set_whitespace_scope(config.whitespace_scope);
|
editor.set_whitespace_scope(config.whitespace_scope);
|
||||||
|
|||||||
+1
-1
@@ -12617,7 +12617,7 @@ end
|
|||||||
editor.handle(Input::Ctrl('u'));
|
editor.handle(Input::Ctrl('u'));
|
||||||
render(&mut terminal, &mut views, &mut editor);
|
render(&mut terminal, &mut views, &mut editor);
|
||||||
assert_eq!(offset(&views), initial);
|
assert_eq!(offset(&views), initial);
|
||||||
editor.set_scroll_half_page_lines(std::num::NonZeroUsize::new(3));
|
editor.set_scroll_step_lines(std::num::NonZeroUsize::new(3));
|
||||||
editor.handle(Input::Char('2'));
|
editor.handle(Input::Char('2'));
|
||||||
editor.handle(Input::Ctrl('d'));
|
editor.handle(Input::Ctrl('d'));
|
||||||
render(&mut terminal, &mut views, &mut editor);
|
render(&mut terminal, &mut views, &mut editor);
|
||||||
|
|||||||
Reference in New Issue
Block a user