diff options
-rw-r--r-- | helix-term/src/commands.rs | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 65d286d9..6fb1c6a9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -98,6 +98,25 @@ impl<'a> Context<'a> { } } +enum Align { + Top, + Center, + Bottom, +} + +fn align_view(doc: &Document, view: &mut View, align: Align) { + let pos = doc.selection(view.id).cursor(); + let line = doc.text().char_to_line(pos); + + let relative = match align { + Align::Center => view.area.height as usize / 2, + Align::Top => 0, + Align::Bottom => view.area.height as usize, + }; + + view.first_line = line.saturating_sub(relative); +} + /// A command is a function that takes the current state and a count, and does a side-effect on the /// state (usually by creating and applying a transaction). pub type Command = fn(cx: &mut Context); @@ -616,6 +635,7 @@ fn _search(doc: &mut Document, view: &mut View, contents: &str, regex: &Regex, e let mat = regex .find_at(contents, start) .or_else(|| regex.find(contents)); + // TODO: message on wraparound if let Some(mat) = mat { let start = text.byte_to_char(mat.start()); let end = text.byte_to_char(mat.end()); @@ -630,9 +650,7 @@ fn _search(doc: &mut Document, view: &mut View, contents: &str, regex: &Regex, e // TODO: (first_match, regex) stuff in register? doc.set_selection(view.id, selection); - // TODO: extract this centering into a function to share with _goto? - let line = doc.text().char_to_line(head); - view.first_line = line.saturating_sub(view.area.height as usize / 2); + align_view(doc, view, Align::Center); }; } @@ -1243,8 +1261,7 @@ fn _goto( // TODO: convert inside server let new_pos = lsp_pos_to_pos(doc.text(), definition_pos, offset_encoding); doc.set_selection(view.id, Selection::point(new_pos)); - let line = doc.text().char_to_line(new_pos); - view.first_line = line.saturating_sub(view.area.height as usize / 2); + align_view(doc, view, Align::Center); } match locations.as_slice() { @@ -1946,7 +1963,6 @@ pub fn save(cx: &mut Context) { // Spawns an async task to actually do the saving. This way we prevent blocking. // TODO: handle save errors somehow? - // TODO: don't block tokio::spawn(cx.doc().save()); } @@ -2051,8 +2067,6 @@ pub fn hover(cx: &mut Context) { // TODO: factor out a doc.position_identifier() that returns lsp::TextDocumentPositionIdentifier - // TODO: blocking here is not ideal, make commands async fn? - // not like we can process additional input meanwhile though let pos = pos_to_lsp_pos( doc.text(), doc.selection(view.id).cursor(), @@ -2137,11 +2151,9 @@ pub fn jump_forward(cx: &mut Context) { if let Some((id, selection)) = view.jumps.forward(count) { view.doc = *id; let selection = selection.clone(); - let cursor = selection.cursor(); doc.set_selection(view.id, selection); - // TODO: extract this centering into a function to share with _goto? - let line = doc.text().char_to_line(cursor); - view.first_line = line.saturating_sub(view.area.height as usize / 2); + + align_view(doc, view, Align::Center); }; } @@ -2151,12 +2163,9 @@ pub fn jump_backward(cx: &mut Context) { if let Some((id, selection)) = view.jumps.backward(count) { view.doc = *id; - let selection = selection.clone(); - let cursor = selection.cursor(); - doc.set_selection(view.id, selection); - // TODO: extract this centering into a function to share with _goto? - let line = doc.text().char_to_line(cursor); - view.first_line = line.saturating_sub(view.area.height as usize / 2); + doc.set_selection(view.id, selection.clone()); + + align_view(doc, view, Align::Center); }; } @@ -2216,17 +2225,13 @@ pub fn view_mode(cx: &mut Context) { // bottom | 'b' => { let (view, doc) = cx.current(); - let pos = doc.selection(view.id).cursor(); - // TODO: extract this centering into a function to share with _goto? - let line = doc.text().char_to_line(pos); - let relative = match ch { - 'z' | 'c' => view.area.height as usize / 2, - 't' => 0, - 'b' => view.area.height as usize, + align_view(doc, view, match ch { + 'z' | 'c' => Align::Center, + 't' => Align::Top, + 'b' => Align::Bottom, _ => unreachable!() - }; - view.first_line = line.saturating_sub(relative); + }); } 'm' => { let (view, doc) = cx.current(); |