Show help menu

pull/3/head
Arijit Basu 3 years ago
parent 7beaec1763
commit 669151c70e
No known key found for this signature in database
GPG Key ID: 7D7BF809E7378863

@ -8,13 +8,13 @@ Example usage:
```bash
# Edit file
vim $(xplr)
vim "$(xplr)"
# Copy file(s)
cp $(xplr) $(xplr)
cp "$(xplr)" "$(xplr)/"
# Search and move file
mv $(fzf) $(xplr)
mv "$(fzf)" "$(xplr)/"
```

@ -254,6 +254,26 @@ pub struct DirectoryItemMetadata {
pub total: usize,
}
pub fn parse_help_menu<'a>(
kb: impl Iterator<Item = (&'a Key, &'a (String, Vec<Action>))>,
) -> Vec<(String, String)> {
let mut m = kb
.map(|(k, a)| {
(
a.0.clone(),
serde_yaml::to_string(k)
.unwrap()
.strip_prefix("---")
.unwrap_or_default()
.trim()
.to_string(),
)
})
.collect::<Vec<(String, String)>>();
m.sort();
m
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct App {
pub version: String,
@ -263,6 +283,7 @@ pub struct App {
pub selected_paths: HashSet<PathBuf>,
pub mode: Mode,
pub parsed_key_bindings: HashMap<Key, (String, Vec<Action>)>,
pub parsed_help_menu: Vec<(String, String)>,
pub show_hidden: bool,
pub call: Option<CommandConfig>,
pub result: Option<String>,
@ -289,6 +310,8 @@ impl App {
let parsed_key_bindings = config.key_bindings.clone().filtered(&mode);
let parsed_help_menu = parse_help_menu(parsed_key_bindings.iter());
Ok(Self {
version: VERSION.into(),
config: config.to_owned(),
@ -297,6 +320,7 @@ impl App {
selected_paths: selected_paths.to_owned(),
mode,
parsed_key_bindings,
parsed_help_menu,
show_hidden,
result: None,
call: None,
@ -526,8 +550,8 @@ impl App {
}
pub fn back(self) -> Result<Self, Error> {
let app = self.clone();
self.focus_path(&app.directory_buffer.pwd)
let pwd = self.directory_buffer.pwd.clone();
self.focus_path(&pwd)
}
pub fn select(self) -> Result<Self, Error> {
@ -541,10 +565,15 @@ impl App {
})
.unwrap_or_else(|| self.selected_paths.clone());
let mut app = self;
app.selected_paths = selected_paths;
app.mode = Mode::Select;
Ok(app)
Self::new(
&self.config,
&self.directory_buffer.pwd,
&self.saved_buffers,
&selected_paths,
Mode::Select,
self.show_hidden,
self.directory_buffer.focus,
)
}
pub fn toggle_selection(self) -> Result<Self, Error> {
@ -568,16 +597,34 @@ impl App {
Mode::Select
};
let mut app = self;
app.selected_paths = selected_paths;
app.mode = mode;
Ok(app)
Self::new(
&self.config,
&self.directory_buffer.pwd,
&self.saved_buffers,
&selected_paths,
mode,
self.show_hidden,
self.directory_buffer.focus,
)
}
pub fn enter_submode(self, submode: &String) -> Result<Self, Error> {
let mut app = self;
app.mode = Mode::ExploreSubmode(submode.clone());
Ok(app)
let mode = match self.mode {
Mode::Explore => Mode::ExploreSubmode(submode.clone()),
Mode::ExploreSubmode(_) => Mode::ExploreSubmode(submode.clone()),
Mode::Select => Mode::SelectSubmode(submode.clone()),
Mode::SelectSubmode(_) => Mode::SelectSubmode(submode.clone()),
};
Self::new(
&self.config,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
mode,
self.show_hidden,
self.directory_buffer.focus,
)
}
pub fn print_focused(self) -> Result<Self, Error> {

@ -1,5 +1,5 @@
use termion::event::Key as TermionKey;
use serde::{Deserialize, Serialize};
use termion::event::Key as TermionKey;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
@ -246,6 +246,12 @@ pub enum Key {
NotSupported,
}
impl std::fmt::Display for Key {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl Key {
pub fn from_termion_event(key: TermionKey) -> Self {
match key {

@ -48,7 +48,15 @@ fn main() -> Result<(), Error> {
let mut list_state = ListState::default();
term::enable_raw_mode().unwrap();
terminal.draw(|f| ui::draw(&app, &hb, f, &mut table_state, &mut list_state))?;
terminal.draw(|f| {
ui::draw(
&app,
&hb,
f,
&mut table_state,
&mut list_state,
)
})?;
let mut result = Ok(());
'outer: for key in keys {
@ -56,8 +64,15 @@ fn main() -> Result<(), Error> {
for action in actions.iter() {
app = match app.handle(action) {
Ok(mut a) => {
terminal
.draw(|f| ui::draw(&a, &hb, f, &mut table_state, &mut list_state))?;
terminal.draw(|f| {
ui::draw(
&a,
&hb,
f,
&mut table_state,
&mut list_state,
)
})?;
if let Some(result) = a.result.clone() {
term::disable_raw_mode().unwrap();
@ -89,7 +104,13 @@ fn main() -> Result<(), Error> {
terminal = Terminal::new(backend)?;
a = a.refresh()?;
terminal.draw(|f| {
ui::draw(&a, &hb, f, &mut table_state, &mut list_state)
ui::draw(
&a,
&hb,
f,
&mut table_state,
&mut list_state,
)
})?;
};

@ -102,7 +102,11 @@ pub fn draw<B: Backend>(
.focus
.map(app::DirectoryBuffer::relative_focus),
);
f.render_stateful_widget(table, chunks[0], table_state);
let left_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([TUIConstraint::Percentage(40), TUIConstraint::Percentage(60)].as_ref())
.split(chunks[1]);
let selected: Vec<ListItem> = app
.selected_paths
@ -120,5 +124,20 @@ pub fn draw<B: Backend>(
.borders(Borders::ALL)
.title(format!(" Selected ({}) ", selected_count)),
);
f.render_stateful_widget(selected_list, chunks[1], list_state);
// Help menu
let help_menu_rows: Vec<Row> = app
.parsed_help_menu
.clone()
.iter()
.map(|(h, k)| Row::new(vec![Cell::from(h.to_string()), Cell::from(k.to_string())]))
.collect();
let help_menu = Table::new(help_menu_rows)
.block(Block::default().borders(Borders::ALL).title(" Help "))
.widths(&[TUIConstraint::Percentage(40), TUIConstraint::Percentage(60)]);
f.render_stateful_widget(table, chunks[0], table_state);
f.render_stateful_widget(selected_list, left_chunks[0], list_state);
f.render_widget(help_menu, left_chunks[1]);
}

Loading…
Cancel
Save