Skip to content

Add Go to line feature for the blame view #2262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add input validation to Go to line popup
Add a context struct for the go to line popup to keep the max line
number allowed

Add support for negative values for the go to line popup input (go to
the -n-th to last line)

Make the go to line input box red when invalid values are provided

Add an error message to the Go to line popup when invalid values are
used

Allow arbitrarily large values in the Go to line input box
  • Loading branch information
andrea-berling authored and extrawurst committed Sep 17, 2024
commit 4855ca6b677e24f6c75dbcc0dca9f1ce262b8b51
4 changes: 2 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,8 +675,8 @@ impl App {
StackablePopupOpen::CompareCommits(param) => {
self.compare_commits_popup.open(param)?;
}
StackablePopupOpen::GotoLine => {
self.goto_line_popup.open();
StackablePopupOpen::GotoLine(param) => {
self.goto_line_popup.open(param);
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/popups/blame_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ use ratatui::{
};
use std::path::Path;

use super::{goto_line::GotoLineContext, GotoLineOpen};

static NO_COMMIT_ID: &str = "0000000";
static NO_AUTHOR: &str = "<no author>";
static MIN_AUTHOR_WIDTH: usize = 3;
Expand Down Expand Up @@ -333,7 +335,11 @@ impl Component for BlameFilePopup {
self.hide_stacked(true);
self.visible = true;
self.queue.push(InternalEvent::OpenPopup(
StackablePopupOpen::GotoLine,
StackablePopupOpen::GotoLine(GotoLineOpen {
context: GotoLineContext {
max_line: self.get_max_line_number(),
},
}),
));
}

Expand Down
80 changes: 62 additions & 18 deletions src/popups/goto_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{

use ratatui::{
layout::Rect,
style::{Color, Style},
widgets::{Block, Clear, Paragraph},
Frame,
};
Expand All @@ -19,27 +20,44 @@ use anyhow::Result;

use crossterm::event::{Event, KeyCode};

#[derive(Debug)]
pub struct GotoLineContext {
pub max_line: usize,
}

#[derive(Debug)]
pub struct GotoLineOpen {
pub context: GotoLineContext,
}

pub struct GotoLinePopup {
visible: bool,
line: String,
input: String,
line_number: usize,
key_config: SharedKeyConfig,
queue: Queue,
theme: SharedTheme,
invalid_input: bool,
context: GotoLineContext,
}

impl GotoLinePopup {
pub fn new(env: &Environment) -> Self {
Self {
visible: false,
line: String::new(),
input: String::new(),
key_config: env.key_config.clone(),
queue: env.queue.clone(),
theme: env.theme.clone(),
invalid_input: false,
context: GotoLineContext { max_line: 0 },
line_number: 0,
}
}

pub fn open(&mut self) {
pub fn open(&mut self, open: GotoLineOpen) {
self.visible = true;
self.context = open.context;
}
}

Expand All @@ -63,41 +81,67 @@ impl Component for GotoLinePopup {
if let Event::Key(key) = event {
if key_match(key, self.key_config.keys.exit_popup) {
self.visible = false;
self.line.clear();
self.input.clear();
self.queue.push(InternalEvent::PopupStackPop);
} else if let KeyCode::Char(c) = key.code {
if c.is_ascii_digit() {
// I'd assume it's unusual for people to blame
// files with milions of lines
if self.line.len() < 6 {
self.line.push(c);
}
if c.is_ascii_digit() || c == '-' {
self.input.push(c);
}
} else if key.code == KeyCode::Backspace {
self.line.pop();
self.input.pop();
} else if key_match(key, self.key_config.keys.enter) {
self.visible = false;
if !self.line.is_empty() {
if self.invalid_input {
self.queue.push(InternalEvent::ShowErrorMsg(
format!("Invalid input: only numbers between -{0} and {0} (included) are allowed",self.context.max_line))
,
);
} else if !self.input.is_empty() {
self.queue.push(InternalEvent::GotoLine(
self.line.parse::<usize>()?,
self.line_number,
));
}
self.queue.push(InternalEvent::PopupStackPop);
self.line.clear();
self.input.clear();
self.invalid_input = false;
}
}
match self.input.parse::<isize>() {
Ok(input) => {
if input.unsigned_abs() > self.context.max_line {
self.invalid_input = true;
} else {
self.invalid_input = false;
self.line_number = if input > 0 {
input.unsigned_abs()
} else {
self.context.max_line
- input.unsigned_abs()
}
}
}
Err(_) => {
if !self.input.is_empty() {
self.invalid_input = true;
}
}
return Ok(EventState::Consumed);
}
return Ok(EventState::Consumed);
}

Ok(EventState::NotConsumed)
}
}

impl DrawableComponent for GotoLinePopup {
fn draw(&self, f: &mut Frame, area: Rect) -> Result<()> {
if self.is_visible() {
let input = Paragraph::new(self.line.as_str())
.style(self.theme.text(true, false))
let style = if self.invalid_input {
Style::default().fg(Color::Red)
} else {
self.theme.text(true, false)
};
let input = Paragraph::new(self.input.as_str())
.style(style)
.block(Block::bordered().title("Go to Line"));

let input_area = ui::centered_rect_absolute(15, 3, area);
Expand Down
2 changes: 1 addition & 1 deletion src/popups/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub use externaleditor::ExternalEditorPopup;
pub use fetch::FetchPopup;
pub use file_revlog::{FileRevOpen, FileRevlogPopup};
pub use fuzzy_find::FuzzyFindPopup;
pub use goto_line::GotoLinePopup;
pub use goto_line::{GotoLineOpen, GotoLinePopup};
pub use help::HelpPopup;
pub use inspect_commit::{InspectCommitOpen, InspectCommitPopup};
pub use log_search::LogSearchPopupPopup;
Expand Down
4 changes: 2 additions & 2 deletions src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
components::FuzzyFinderTarget,
popups::{
AppOption, BlameFileOpen, FileRevOpen, FileTreeOpen,
InspectCommitOpen,
GotoLineOpen, InspectCommitOpen,
},
tabs::StashingOptions,
};
Expand Down Expand Up @@ -69,7 +69,7 @@ pub enum StackablePopupOpen {
///
CompareCommits(InspectCommitOpen),
///
GotoLine,
GotoLine(GotoLineOpen),
}

pub enum AppTabs {
Expand Down