Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* switch focus to index after staging last file ([#1169](https://github.com/extrawurst/gitui/pull/1169))
* fix stashlist multi marking not updated after dropping ([#1207](https://github.com/extrawurst/gitui/pull/1207))
* exact matches have a higher priority and are placed to the top of the list when fuzzily finding files ([#1183](https://github.com/extrawurst/gitui/pull/1183))
* support horizontal scrolling in diff view ([#1017](https://github.com/extrawurst/gitui/issues/1017))

## [0.20.1] - 2021-01-26

Expand Down
1 change: 1 addition & 0 deletions src/components/blame_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ impl DrawableComponent for BlameFileComponent {
//
// https://github.com/fdehau/tui-rs/issues/448
table_state.selected().unwrap_or(0),
ui::Orientation::Vertical,
);

self.table_state.set(table_state);
Expand Down
3 changes: 2 additions & 1 deletion src/components/commitlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
keys::SharedKeyConfig,
strings::{self, symbol},
ui::style::{SharedTheme, Theme},
ui::{calc_scroll_top, draw_scrollbar},
ui::{calc_scroll_top, draw_scrollbar, Orientation},
};
use anyhow::Result;
use asyncgit::sync::{CommitId, Tags};
Expand Down Expand Up @@ -419,6 +419,7 @@ impl DrawableComponent for CommitList {
&self.theme,
self.count_total,
self.selection,
Orientation::Vertical,
);

Ok(())
Expand Down
65 changes: 61 additions & 4 deletions src/components/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use crate::{
keys::SharedKeyConfig,
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
string_utils::tabs_to_spaces,
string_utils::trim_offset,
strings, try_or_popup,
ui::style::SharedTheme,
ui::{draw_scrollbar, style::SharedTheme, Orientation},
};
use anyhow::Result;
use asyncgit::{
Expand Down Expand Up @@ -102,6 +103,7 @@ impl Selection {
pub struct DiffComponent {
repo: RepoPathRef,
diff: Option<FileDiff>,
longest_line: usize,
pending: bool,
selection: Selection,
selected_hunk: Option<usize>,
Expand All @@ -113,6 +115,7 @@ pub struct DiffComponent {
theme: SharedTheme,
key_config: SharedKeyConfig,
is_immutable: bool,
scrolled_right: usize,
}

impl DiffComponent {
Expand All @@ -131,13 +134,15 @@ impl DiffComponent {
pending: false,
selected_hunk: None,
diff: None,
longest_line: 0,
current_size: Cell::new((0, 0)),
selection: Selection::Single(0),
scroll: VerticalScroll::new(),
theme,
key_config,
is_immutable,
repo,
scrolled_right: 0,
}
}
///
Expand All @@ -155,10 +160,12 @@ impl DiffComponent {
pub fn clear(&mut self, pending: bool) {
self.current = Current::default();
self.diff = None;
self.longest_line = 0;
self.scroll.reset();
self.selection = Selection::Single(0);
self.selected_hunk = None;
self.pending = pending;
self.scrolled_right = 0;
}
///
pub fn update(
Expand All @@ -182,6 +189,24 @@ impl DiffComponent {

self.diff = Some(diff);

self.longest_line = self
.diff
.as_ref()
.map(|diff| {
diff.hunks
.iter()
.map(|hunk| {
hunk.lines
.iter()
.map(|line| line.content.len())
.max()
.unwrap_or(0)
})
.max()
.unwrap_or(0)
})
.unwrap_or(0);

if reset_selection {
self.scroll.reset();
self.selection = Selection::Single(0);
Expand Down Expand Up @@ -241,6 +266,11 @@ impl DiffComponent {
self.diff.as_ref().map_or(0, |diff| diff.lines)
}

fn max_scroll_right(&self) -> usize {
self.longest_line
.saturating_sub(self.current_size.get().0.into())
}

fn modify_selection(&mut self, direction: Direction) {
if self.diff.is_some() {
self.selection.modify(direction, self.lines_count());
Expand Down Expand Up @@ -379,6 +409,7 @@ impl DiffComponent {
hunk_selected,
i == hunk_len as usize - 1,
&self.theme,
self.scrolled_right,
));
lines_added += 1;
}
Expand All @@ -401,6 +432,7 @@ impl DiffComponent {
selected_hunk: bool,
end_of_hunk: bool,
theme: &SharedTheme,
scrolled_right: usize,
) -> Spans<'a> {
let style = theme.diff_hunk_marker(selected_hunk);

Expand All @@ -419,18 +451,22 @@ impl DiffComponent {
}
};

let content =
tabs_to_spaces(line.content.as_ref().to_string());
let content = trim_offset(&content, scrolled_right);

let filled = if selected {
// selected line
format!("{:w$}\n", line.content, w = width as usize)
format!("{:w$}\n", content, w = width as usize)
} else {
// weird eof missing eol line
format!("{}\n", line.content)
format!("{}\n", content)
};

Spans::from(vec![
left_side_of_line,
Span::styled(
Cow::from(tabs_to_spaces(filled)),
Cow::from(filled),
theme.diff_line(line.line_type, selected),
),
])
Expand Down Expand Up @@ -645,6 +681,17 @@ impl DrawableComponent for DiffComponent {

if self.focused() {
self.scroll.draw(f, r, &self.theme);

if self.scrolled_right != 0 {
draw_scrollbar(
f,
r,
&self.theme,
self.max_scroll_right(),
self.scrolled_right,
Orientation::Horizontal,
);
}
}

Ok(())
Expand Down Expand Up @@ -749,6 +796,16 @@ impl Component for DiffComponent {
} else if e == self.key_config.keys.page_down {
self.move_selection(ScrollType::PageDown);
Ok(EventState::Consumed)
} else if e == self.key_config.keys.move_right {
if self.scrolled_right < self.max_scroll_right() {
self.scrolled_right += 1;
}
Ok(EventState::Consumed)
} else if e == self.key_config.keys.move_left
&& self.scrolled_right > 0
{
self.scrolled_right -= 1;
Ok(EventState::Consumed)
} else if e == self.key_config.keys.stage_unstage_item
&& !self.is_immutable
{
Expand Down
3 changes: 2 additions & 1 deletion src/components/file_revlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
keys::SharedKeyConfig,
queue::{InternalEvent, NeedsUpdate, Queue},
strings,
ui::{draw_scrollbar, style::SharedTheme},
ui::{draw_scrollbar, style::SharedTheme, Orientation},
};
use anyhow::Result;
use asyncgit::{
Expand Down Expand Up @@ -410,6 +410,7 @@ impl FileRevlogComponent {
&self.theme,
self.count_total,
table_state.selected().unwrap_or(0),
Orientation::Vertical,
);

self.table_state.set(table_state);
Expand Down
1 change: 1 addition & 0 deletions src/components/syntax_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ impl DrawableComponent for SyntaxTextComponent {
state.height().saturating_sub(2),
)),
usize::from(state.scroll().y),
ui::Orientation::Vertical,
);
}

Expand Down
1 change: 1 addition & 0 deletions src/components/taglist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ impl DrawableComponent for TagListComponent {
&self.theme,
number_of_rows,
table_state.selected().unwrap_or(0),
ui::Orientation::Vertical,
);

self.table_state.set(table_state);
Expand Down
3 changes: 2 additions & 1 deletion src/components/utils/scroll_vertical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use tui::{backend::Backend, layout::Rect, Frame};

use crate::{
components::ScrollType,
ui::{draw_scrollbar, style::SharedTheme},
ui::{draw_scrollbar, style::SharedTheme, Orientation},
};

pub struct VerticalScroll {
Expand Down Expand Up @@ -95,6 +95,7 @@ impl VerticalScroll {
theme,
self.max_top.get(),
self.top.get(),
Orientation::Vertical,
);
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/string_utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;

///
pub fn trim_length_left(s: &str, width: usize) -> &str {
let len = s.len();
Expand All @@ -21,6 +24,22 @@ pub fn tabs_to_spaces(input: String) -> String {
}
}

/// This function will return a str slice which start at specified offset.
/// As src is a unicode str, start offset has to be calculated with each character.
pub fn trim_offset(src: &str, mut offset: usize) -> &str {
let mut start = 0;
for c in UnicodeSegmentation::graphemes(src, true) {
let w = c.width();
if w <= offset {
offset -= w;
start += c.len();
} else {
break;
}
}
&src[start..]
}

#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
Expand Down
2 changes: 1 addition & 1 deletion src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub mod style;
mod syntax_text;

use filetreelist::MoveSelection;
pub use scrollbar::draw_scrollbar;
pub use scrollbar::{draw_scrollbar, Orientation};
pub use scrolllist::{draw_list, draw_list_block};
pub use stateful_paragraph::{
ParagraphState, ScrollPos, StatefulParagraph,
Expand Down
18 changes: 1 addition & 17 deletions src/ui/reflow.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::string_utils::trim_offset;
use easy_cast::Cast;
use tui::text::StyledGrapheme;
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;

const NBSP: &str = "\u{00a0}";
Expand Down Expand Up @@ -233,22 +233,6 @@ impl<'a, 'b> LineComposer<'a> for LineTruncator<'a, 'b> {
}
}

/// This function will return a str slice which start at specified offset.
/// As src is a unicode str, start offset has to be calculated with each character.
fn trim_offset(src: &str, mut offset: usize) -> &str {
let mut start = 0;
for c in UnicodeSegmentation::graphemes(src, true) {
let w = c.width();
if w <= offset {
offset -= w;
start += c.len();
} else {
break;
}
}
&src[start..]
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
Loading