mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
cmd help grouping and long desc
This commit is contained in:
parent
f2336d32e1
commit
ed5668c4c8
7 changed files with 141 additions and 15 deletions
|
|
@ -273,6 +273,7 @@ impl App {
|
|||
res.push(
|
||||
CommandInfo::new(
|
||||
strings::CMD_STATUS_FOCUS_UNSTAGED,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
main_cmds_available
|
||||
&& focus_on_stage
|
||||
|
|
@ -283,6 +284,7 @@ impl App {
|
|||
res.push(
|
||||
CommandInfo::new(
|
||||
strings::CMD_STATUS_FOCUS_STAGED,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
main_cmds_available
|
||||
&& !focus_on_stage
|
||||
|
|
@ -295,11 +297,13 @@ impl App {
|
|||
let focus_on_diff = self.focus == Focus::Diff;
|
||||
res.push(CommandInfo::new(
|
||||
strings::CMD_STATUS_LEFT,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
main_cmds_available && focus_on_diff,
|
||||
));
|
||||
res.push(CommandInfo::new(
|
||||
strings::CMD_STATUS_RIGHT,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
main_cmds_available && !focus_on_diff,
|
||||
));
|
||||
|
|
@ -308,6 +312,7 @@ impl App {
|
|||
res.push(
|
||||
CommandInfo::new(
|
||||
strings::CMD_STATUS_QUIT,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
main_cmds_available,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -178,17 +178,20 @@ impl Component for ChangesComponent {
|
|||
if self.is_working_dir {
|
||||
out.push(CommandInfo::new(
|
||||
strings::CMD_STATUS_STAGE,
|
||||
strings::CMD_GROUP_CHANGES,
|
||||
some_selection,
|
||||
self.focused,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::CMD_STATUS_RESET,
|
||||
strings::CMD_GROUP_CHANGES,
|
||||
some_selection,
|
||||
self.focused,
|
||||
));
|
||||
} else {
|
||||
out.push(CommandInfo::new(
|
||||
strings::CMD_STATUS_UNSTAGE,
|
||||
strings::CMD_GROUP_CHANGES,
|
||||
some_selection,
|
||||
self.focused,
|
||||
));
|
||||
|
|
@ -196,6 +199,7 @@ impl Component for ChangesComponent {
|
|||
|
||||
out.push(CommandInfo::new(
|
||||
strings::CMD_SCROLL,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
self.items.len() > 1,
|
||||
self.focused,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ pub struct CommandInfo {
|
|||
///
|
||||
pub name: String,
|
||||
///
|
||||
pub group: String,
|
||||
///
|
||||
pub desc: String,
|
||||
///
|
||||
// pub keys:
|
||||
/// available but not active in the context
|
||||
pub enabled: bool,
|
||||
|
|
@ -16,9 +20,16 @@ pub struct CommandInfo {
|
|||
|
||||
impl CommandInfo {
|
||||
///
|
||||
pub fn new(name: &str, enabled: bool, available: bool) -> Self {
|
||||
pub fn new(
|
||||
name: &str,
|
||||
group: &str,
|
||||
enabled: bool,
|
||||
available: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
group: group.to_string(),
|
||||
desc: String::default(),
|
||||
enabled,
|
||||
quick_bar: true,
|
||||
available,
|
||||
|
|
@ -32,6 +43,12 @@ impl CommandInfo {
|
|||
res
|
||||
}
|
||||
///
|
||||
pub fn desc(self, txt: &str) -> Self {
|
||||
let mut res = self;
|
||||
res.desc = txt.to_string();
|
||||
res
|
||||
}
|
||||
///
|
||||
pub fn hidden(self) -> Self {
|
||||
let mut res = self;
|
||||
res.quick_bar = false;
|
||||
|
|
|
|||
|
|
@ -55,16 +55,19 @@ impl Component for CommitComponent {
|
|||
) -> CommandBlocking {
|
||||
out.push(CommandInfo::new(
|
||||
strings::COMMIT_CMD_OPEN,
|
||||
strings::CMD_GROUP_COMMIT,
|
||||
!self.stage_empty,
|
||||
!self.visible,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::COMMIT_CMD_ENTER,
|
||||
strings::CMD_GROUP_COMMIT,
|
||||
self.can_commit(),
|
||||
self.visible,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::COMMIT_CMD_CLOSE,
|
||||
strings::CMD_GROUP_COMMIT,
|
||||
true,
|
||||
self.visible,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ impl Component for DiffComponent {
|
|||
) -> CommandBlocking {
|
||||
out.push(CommandInfo::new(
|
||||
strings::CMD_SCROLL,
|
||||
strings::CMD_GROUP_DIFF,
|
||||
self.can_scroll(),
|
||||
self.focused,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@ use super::{
|
|||
DrawableComponent, EventUpdate,
|
||||
};
|
||||
use crate::{keys, strings, ui};
|
||||
use asyncgit::hash;
|
||||
use crossterm::event::Event;
|
||||
use std::borrow::Cow;
|
||||
use itertools::Itertools;
|
||||
use std::{borrow::Cow, cmp, convert::TryFrom};
|
||||
use tui::{
|
||||
backend::Backend,
|
||||
layout::{Alignment, Rect},
|
||||
style::{Color, Style},
|
||||
widgets::{Block, Borders, Paragraph, Text, Widget},
|
||||
Frame,
|
||||
};
|
||||
|
|
@ -16,21 +19,22 @@ use tui::{
|
|||
pub struct HelpComponent {
|
||||
cmds: Vec<CommandInfo>,
|
||||
visible: bool,
|
||||
selection: u16,
|
||||
}
|
||||
|
||||
impl DrawableComponent for HelpComponent {
|
||||
fn draw<B: Backend>(&self, f: &mut Frame<B>, _rect: Rect) {
|
||||
if self.visible {
|
||||
let txt = self
|
||||
.cmds
|
||||
.iter()
|
||||
.map(|e| {
|
||||
let mut out = String::new();
|
||||
e.print(&mut out);
|
||||
out.push('\n');
|
||||
Text::Raw(Cow::from(out))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let (txt, selected_line) = self.get_text();
|
||||
|
||||
let height = 24;
|
||||
let scroll_threshold = height / 3;
|
||||
|
||||
let scroll = if selected_line > scroll_threshold {
|
||||
self.selection - scroll_threshold
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
ui::Clear::new(
|
||||
Paragraph::new(txt.iter())
|
||||
|
|
@ -39,9 +43,13 @@ impl DrawableComponent for HelpComponent {
|
|||
.title(strings::HELP_TITLE)
|
||||
.borders(Borders::ALL),
|
||||
)
|
||||
.scroll(scroll)
|
||||
.alignment(Alignment::Left),
|
||||
)
|
||||
.render(f, ui::centered_rect_absolute(60, 20, f.size()));
|
||||
.render(
|
||||
f,
|
||||
ui::centered_rect_absolute(65, height, f.size()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,14 +67,24 @@ impl Component for HelpComponent {
|
|||
out.push(
|
||||
CommandInfo::new(
|
||||
strings::CMD_STATUS_HELP,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
!self.visible,
|
||||
)
|
||||
.desc("open this help screen")
|
||||
.order(99),
|
||||
);
|
||||
|
||||
out.push(CommandInfo::new(
|
||||
strings::CMD_SCROLL,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
self.visible,
|
||||
));
|
||||
|
||||
out.push(CommandInfo::new(
|
||||
strings::COMMIT_CMD_CLOSE,
|
||||
strings::CMD_GROUP_GENERAL,
|
||||
true,
|
||||
self.visible,
|
||||
));
|
||||
|
|
@ -77,8 +95,11 @@ impl Component for HelpComponent {
|
|||
fn event(&mut self, ev: Event) -> Option<EventUpdate> {
|
||||
if self.visible {
|
||||
if let Event::Key(e) = ev {
|
||||
if let keys::EXIT_POPUP = e {
|
||||
self.hide();
|
||||
match e {
|
||||
keys::EXIT_POPUP => self.hide(),
|
||||
keys::MOVE_DOWN => self.move_selection(true),
|
||||
keys::MOVE_UP => self.move_selection(false),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,5 +129,75 @@ impl HelpComponent {
|
|||
///
|
||||
pub fn set_cmds(&mut self, cmds: Vec<CommandInfo>) {
|
||||
self.cmds = cmds;
|
||||
self.cmds.sort_by_key(|e| hash(&e.group));
|
||||
}
|
||||
|
||||
fn move_selection(&mut self, inc: bool) {
|
||||
let mut new_selection = self.selection;
|
||||
|
||||
new_selection = if inc {
|
||||
new_selection.saturating_add(1)
|
||||
} else {
|
||||
new_selection.saturating_sub(1)
|
||||
};
|
||||
new_selection = cmp::max(new_selection, 0);
|
||||
|
||||
if let Ok(max) = u16::try_from(self.cmds.len() - 1) {
|
||||
self.selection = cmp::min(new_selection, max);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_text<'a>(&self) -> (Vec<Text<'a>>, u16) {
|
||||
let mut txt = Vec::new();
|
||||
|
||||
let mut processed = 0_u16;
|
||||
let mut selected_line = 0_u16;
|
||||
|
||||
for (key, group) in
|
||||
&self.cmds.iter().group_by(|e| e.group.clone())
|
||||
{
|
||||
txt.push(Text::Styled(
|
||||
Cow::from(format!(" {}\n", key)),
|
||||
Style::default().fg(Color::Black).bg(Color::Gray),
|
||||
));
|
||||
|
||||
txt.extend(
|
||||
group
|
||||
.into_iter()
|
||||
.map(|e| {
|
||||
let is_selected = self.selection == processed;
|
||||
if is_selected {
|
||||
selected_line = processed;
|
||||
}
|
||||
processed += 1;
|
||||
|
||||
let mut out = String::from(if is_selected {
|
||||
">"
|
||||
} else {
|
||||
" "
|
||||
});
|
||||
|
||||
e.print(&mut out);
|
||||
out.push('\n');
|
||||
|
||||
if is_selected {
|
||||
out.push_str(
|
||||
format!(" {}\n", e.desc).as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
let style = if is_selected {
|
||||
Style::default().fg(Color::Yellow)
|
||||
} else {
|
||||
Style::default()
|
||||
};
|
||||
|
||||
Text::Styled(Cow::from(out), style)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
|
||||
(txt, selected_line)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ pub static TITLE_INDEX: &str = "Staged Changes [2]";
|
|||
pub static TAB_STATUS: &str = "Status";
|
||||
pub static TAB_DIVIDER: &str = " | ";
|
||||
|
||||
pub static CMD_GROUP_GENERAL: &str = "General";
|
||||
pub static CMD_GROUP_DIFF: &str = "Diff";
|
||||
pub static CMD_GROUP_CHANGES: &str = "Changes";
|
||||
pub static CMD_GROUP_COMMIT: &str = "Commit";
|
||||
|
||||
pub static CMD_STATUS_FOCUS_UNSTAGED: &str = "Unstaged [1]";
|
||||
pub static CMD_STATUS_FOCUS_STAGED: &str = "Staged [2]";
|
||||
pub static CMD_STATUS_STAGE: &str = "Stage File [enter]";
|
||||
|
|
|
|||
Loading…
Reference in a new issue