mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
Display current repository path in the top-right corner (#1387)
This commit is contained in:
parent
c7e54fa17d
commit
9c2d8c0e0d
3 changed files with 78 additions and 13 deletions
|
|
@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
* add `vendor-openssl` feature to allow building without vendored openssl [[@jirutka](https://github.com/jirutka)]
|
* add `vendor-openssl` feature to allow building without vendored openssl [[@jirutka](https://github.com/jirutka)]
|
||||||
* allow copying marked commits [[@remique](https://github.com/remique)] ([#1288](https://github.com/extrawurst/gitui/issues/1288))
|
* allow copying marked commits [[@remique](https://github.com/remique)] ([#1288](https://github.com/extrawurst/gitui/issues/1288))
|
||||||
* display tags and branches in the log view [[@alexmaco]](https://github.com/alexmaco)([#1371](https://github.com/extrawurst/gitui/pull/1371))
|
* display tags and branches in the log view [[@alexmaco]](https://github.com/alexmaco)([#1371](https://github.com/extrawurst/gitui/pull/1371))
|
||||||
|
* display current repository path in the top-right corner [[@alexmaco]](https://github.com/alexmaco)([#1387](https://github.com/extrawurst/gitui/pull/1387))
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
* remove insecure dependency `ansi_term` ([#1290](https://github.com/extrawurst/gitui/issues/1290))
|
* remove insecure dependency `ansi_term` ([#1290](https://github.com/extrawurst/gitui/issues/1290))
|
||||||
|
|
|
||||||
70
src/app.rs
70
src/app.rs
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
Action, InternalEvent, NeedsUpdate, Queue, StackablePopupOpen,
|
Action, InternalEvent, NeedsUpdate, Queue, StackablePopupOpen,
|
||||||
},
|
},
|
||||||
setup_popups,
|
setup_popups,
|
||||||
strings::{self, order},
|
strings::{self, ellipsis_trim_start, order},
|
||||||
tabs::{FilesTab, Revlog, StashList, Stashing, Status},
|
tabs::{FilesTab, Revlog, StashList, Stashing, Status},
|
||||||
ui::style::{SharedTheme, Theme},
|
ui::style::{SharedTheme, Theme},
|
||||||
AsyncAppNotification, AsyncNotification,
|
AsyncAppNotification, AsyncNotification,
|
||||||
|
|
@ -41,11 +41,14 @@ use std::{
|
||||||
};
|
};
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
layout::{Constraint, Direction, Layout, Margin, Rect},
|
layout::{
|
||||||
|
Alignment, Constraint, Direction, Layout, Margin, Rect,
|
||||||
|
},
|
||||||
text::{Span, Spans},
|
text::{Span, Spans},
|
||||||
widgets::{Block, Borders, Tabs},
|
widgets::{Block, Borders, Paragraph, Tabs},
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum QuitState {
|
pub enum QuitState {
|
||||||
|
|
@ -94,6 +97,7 @@ pub struct App {
|
||||||
input: Input,
|
input: Input,
|
||||||
popup_stack: PopupStack,
|
popup_stack: PopupStack,
|
||||||
options: SharedOptions,
|
options: SharedOptions,
|
||||||
|
repo_path_text: String,
|
||||||
|
|
||||||
// "Flags"
|
// "Flags"
|
||||||
requires_redraw: Cell<bool>,
|
requires_redraw: Cell<bool>,
|
||||||
|
|
@ -114,6 +118,9 @@ impl App {
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
log::trace!("open repo at: {:?}", &repo);
|
log::trace!("open repo at: {:?}", &repo);
|
||||||
|
|
||||||
|
let repo_path_text =
|
||||||
|
repo_work_dir(&repo.borrow()).unwrap_or_default();
|
||||||
|
|
||||||
let queue = Queue::new();
|
let queue = Queue::new();
|
||||||
let theme = Rc::new(theme);
|
let theme = Rc::new(theme);
|
||||||
let key_config = Rc::new(key_config);
|
let key_config = Rc::new(key_config);
|
||||||
|
|
@ -311,6 +318,7 @@ impl App {
|
||||||
requires_redraw: Cell::new(false),
|
requires_redraw: Cell::new(false),
|
||||||
file_to_open: None,
|
file_to_open: None,
|
||||||
repo,
|
repo,
|
||||||
|
repo_path_text,
|
||||||
popup_stack: PopupStack::default(),
|
popup_stack: PopupStack::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -339,7 +347,7 @@ impl App {
|
||||||
|
|
||||||
self.cmdbar.borrow().draw(f, chunks_main[2]);
|
self.cmdbar.borrow().draw(f, chunks_main[2]);
|
||||||
|
|
||||||
self.draw_tabs(f, chunks_main[0]);
|
self.draw_top_bar(f, chunks_main[0]);
|
||||||
|
|
||||||
//TODO: component property + a macro `fullscreen_popup_open!`
|
//TODO: component property + a macro `fullscreen_popup_open!`
|
||||||
// to make this scale better?
|
// to make this scale better?
|
||||||
|
|
@ -1104,23 +1112,47 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: make this dynamic
|
//TODO: make this dynamic
|
||||||
fn draw_tabs<B: Backend>(&self, f: &mut Frame<B>, r: Rect) {
|
fn draw_top_bar<B: Backend>(&self, f: &mut Frame<B>, r: Rect) {
|
||||||
|
const DIVIDER_PAD_SPACES: usize = 2;
|
||||||
|
const SIDE_PADS: usize = 2;
|
||||||
|
const MARGIN_LEFT_AND_RIGHT: usize = 2;
|
||||||
|
|
||||||
let r = r.inner(&Margin {
|
let r = r.inner(&Margin {
|
||||||
vertical: 0,
|
vertical: 0,
|
||||||
horizontal: 1,
|
horizontal: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
let tabs = [
|
let tab_labels = [
|
||||||
Span::raw(strings::tab_status(&self.key_config)),
|
Span::raw(strings::tab_status(&self.key_config)),
|
||||||
Span::raw(strings::tab_log(&self.key_config)),
|
Span::raw(strings::tab_log(&self.key_config)),
|
||||||
Span::raw(strings::tab_files(&self.key_config)),
|
Span::raw(strings::tab_files(&self.key_config)),
|
||||||
Span::raw(strings::tab_stashing(&self.key_config)),
|
Span::raw(strings::tab_stashing(&self.key_config)),
|
||||||
Span::raw(strings::tab_stashes(&self.key_config)),
|
Span::raw(strings::tab_stashes(&self.key_config)),
|
||||||
]
|
];
|
||||||
.iter()
|
let divider = strings::tab_divider(&self.key_config);
|
||||||
.cloned()
|
|
||||||
.map(Spans::from)
|
// heuristic, since tui doesn't provide a way to know
|
||||||
.collect();
|
// how much space is needed to draw a `Tabs`
|
||||||
|
let tabs_len: usize =
|
||||||
|
tab_labels.iter().map(Span::width).sum::<usize>()
|
||||||
|
+ tab_labels.len().saturating_sub(1)
|
||||||
|
* (divider.width() + DIVIDER_PAD_SPACES)
|
||||||
|
+ SIDE_PADS + MARGIN_LEFT_AND_RIGHT;
|
||||||
|
|
||||||
|
let left_right = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.constraints(vec![
|
||||||
|
Constraint::Length(
|
||||||
|
u16::try_from(tabs_len).unwrap_or(r.width),
|
||||||
|
),
|
||||||
|
Constraint::Min(0),
|
||||||
|
])
|
||||||
|
.split(r);
|
||||||
|
|
||||||
|
let table_area = r; // use entire area to allow drawing the horizontal separator line
|
||||||
|
let text_area = left_right[1];
|
||||||
|
|
||||||
|
let tabs = tab_labels.into_iter().map(Spans::from).collect();
|
||||||
|
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
Tabs::new(tabs)
|
Tabs::new(tabs)
|
||||||
|
|
@ -1131,9 +1163,21 @@ impl App {
|
||||||
)
|
)
|
||||||
.style(self.theme.tab(false))
|
.style(self.theme.tab(false))
|
||||||
.highlight_style(self.theme.tab(true))
|
.highlight_style(self.theme.tab(true))
|
||||||
.divider(strings::tab_divider(&self.key_config))
|
.divider(divider)
|
||||||
.select(self.tab),
|
.select(self.tab),
|
||||||
r,
|
table_area,
|
||||||
|
);
|
||||||
|
|
||||||
|
f.render_widget(
|
||||||
|
Paragraph::new(Spans::from(vec![Span::styled(
|
||||||
|
ellipsis_trim_start(
|
||||||
|
&self.repo_path_text,
|
||||||
|
text_area.width as usize,
|
||||||
|
),
|
||||||
|
self.theme.title(true),
|
||||||
|
)]))
|
||||||
|
.alignment(Alignment::Right),
|
||||||
|
text_area,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use asyncgit::sync::CommitId;
|
use asyncgit::sync::CommitId;
|
||||||
|
use unicode_truncate::UnicodeTruncateStr;
|
||||||
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
use crate::keys::SharedKeyConfig;
|
use crate::keys::SharedKeyConfig;
|
||||||
|
|
||||||
|
|
@ -34,6 +38,7 @@ pub mod symbol {
|
||||||
pub const FOLDER_ICON_COLLAPSED: &str = "\u{25b8}"; //▸
|
pub const FOLDER_ICON_COLLAPSED: &str = "\u{25b8}"; //▸
|
||||||
pub const FOLDER_ICON_EXPANDED: &str = "\u{25be}"; //▾
|
pub const FOLDER_ICON_EXPANDED: &str = "\u{25be}"; //▾
|
||||||
pub const EMPTY_STR: &str = "";
|
pub const EMPTY_STR: &str = "";
|
||||||
|
pub const ELLIPSIS: char = '\u{2026}'; // …
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title_branches() -> String {
|
pub fn title_branches() -> String {
|
||||||
|
|
@ -348,6 +353,21 @@ pub fn rename_branch_popup_msg(
|
||||||
"new branch name".to_string()
|
"new branch name".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ellipsis_trim_start(s: &str, width: usize) -> Cow<str> {
|
||||||
|
if s.width() <= width {
|
||||||
|
Cow::Borrowed(s)
|
||||||
|
} else {
|
||||||
|
Cow::Owned(format!(
|
||||||
|
"[{}]{}",
|
||||||
|
symbol::ELLIPSIS,
|
||||||
|
s.unicode_truncate_start(
|
||||||
|
width.saturating_sub(3 /* front indicator */)
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod commit {
|
pub mod commit {
|
||||||
use crate::keys::SharedKeyConfig;
|
use crate::keys::SharedKeyConfig;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue