Skip to content

Commit

Permalink
confirmation prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
cartercanedy committed Sep 27, 2024
1 parent eae34fb commit a6b58fa
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 47 deletions.
28 changes: 15 additions & 13 deletions core/src/inner.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::{Command, ListNode, Tab};
use ego_tree::{NodeMut, Tree};
use include_dir::{include_dir, Dir};
use serde::Deserialize;
use std::{
fs::File,
io::{BufRead, BufReader, Read},
os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
rc::Rc
};

use crate::{Command, ListNode, Tab};
use ego_tree::{NodeMut, Tree};
use include_dir::{include_dir, Dir};
use serde::Deserialize;
use tempdir::TempDir;

const TAB_DATA: Dir = include_dir!("$CARGO_MANIFEST_DIR/tabs");
Expand Down Expand Up @@ -35,12 +37,12 @@ pub fn get_tabs(validate: bool) -> Vec<Tab> {
},
directory,
)| {
let mut tree = Tree::new(ListNode {
let mut tree = Tree::new(Rc::new(ListNode {
name: "root".to_string(),
description: String::new(),
command: Command::None,
task_list: String::new(),
});
}));
let mut root = tree.root_mut();
create_directory(data, &mut root, &directory, validate);
Tab {
Expand Down Expand Up @@ -164,28 +166,28 @@ fn filter_entries(entries: &mut Vec<Entry>) {

fn create_directory(
data: Vec<Entry>,
node: &mut NodeMut<ListNode>,
node: &mut NodeMut<Rc<ListNode>>,
command_dir: &Path,
validate: bool,
) {
for entry in data {
match entry.entry_type {
EntryType::Entries(entries) => {
let mut node = node.append(ListNode {
let mut node = node.append(Rc::new(ListNode {
name: entry.name,
description: entry.description,
command: Command::None,
task_list: String::new(),
});
}));
create_directory(entries, &mut node, command_dir, validate);
}
EntryType::Command(command) => {
node.append(ListNode {
node.append(Rc::new(ListNode {
name: entry.name,
description: entry.description,
command: Command::Raw(command),
task_list: String::new(),
});
}));
}
EntryType::Script(script) => {
let script = command_dir.join(script);
Expand All @@ -194,7 +196,7 @@ fn create_directory(
}

if let Some((executable, args)) = get_shebang(&script, validate) {
node.append(ListNode {
node.append(Rc::new(ListNode {
name: entry.name,
description: entry.description,
command: Command::LocalFile {
Expand All @@ -203,7 +205,7 @@ fn create_directory(
file: script,
},
task_list: entry.task_list,
});
}));
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod inner;

use std::rc::Rc;

use ego_tree::Tree;
use std::path::PathBuf;

Expand All @@ -20,7 +22,7 @@ pub enum Command {
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct Tab {
pub name: String,
pub tree: Tree<ListNode>,
pub tree: Tree<Rc<ListNode>>,
pub multi_selectable: bool,
}

Expand Down
103 changes: 103 additions & 0 deletions tui/src/confirmation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::borrow::Cow;

use crate::{
float::FloatContent,
hint::Shortcut
};

use ratatui::{prelude::*, widgets::{Block, Borders, Clear, List}};
use crossterm::event::{KeyCode, KeyEvent};

pub enum ConfirmStatus {
Confirm,
Abort,
None
}

pub struct ConfirmPrompt {
pub names: Box<[String]>,
pub status: ConfirmStatus,
scroll: usize,
}

impl ConfirmPrompt {
pub fn new(names: &[&str]) -> Self {
let names = names
.iter()
.zip(1..)
.map(|(name, n)| format!("{n}. {name}"))
.collect();

Self {
names,
status: ConfirmStatus::None,
scroll: 0
}
}

pub fn scroll_down(&mut self) {
if self.scroll < self.names.len() {
self.scroll += 1;
}
}

pub fn scroll_up(&mut self) {
if self.scroll > 0 {
self.scroll -= 1;
}
}
}

impl FloatContent for ConfirmPrompt {
fn draw(&mut self, frame: &mut Frame, area: Rect) {
let block = Block::default()
.borders(Borders::ALL)
.title("Confirm selections")
.title_alignment(ratatui::layout::Alignment::Center)
.title_style(Style::default().reversed())
.style(Style::default());

// Draw the Block first
frame.render_widget(block.clone(), area);

let inner_area = block.inner(area);

let paths_text = self.names
.iter()
.skip(self.scroll)
.map(|p| Line::from(Span::from(Cow::<'_, str>::Borrowed(p))).style(Style::default().bold()))
.collect::<Text>();

frame.render_widget(Clear, inner_area);
frame.render_widget(List::new(paths_text), inner_area);
}

fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
use KeyCode::*;
self.status = match key.code {
Char('y') | Char('Y') => ConfirmStatus::Confirm,
Char('n') | Char('N') | Esc => ConfirmStatus::Abort,
_ => ConfirmStatus::None
};

false
}

fn is_finished(&self) -> bool {
use ConfirmStatus::*;
match self.status {
Confirm | Abort => true,
None => false
}
}

fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) {
(
"Confirmation prompt",
Box::new([
Shortcut::new("Continue", ["Y", "y"]),
Shortcut::new("Abort", ["N", "n"])
])
)
}
}
8 changes: 4 additions & 4 deletions tui/src/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ pub trait FloatContent {
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>);
}

pub struct Float {
content: Box<dyn FloatContent>,
pub struct Float<Content: FloatContent + ?Sized> {
pub content: Box<Content>,
width_percent: u16,
height_percent: u16,
}

impl Float {
pub fn new(content: Box<dyn FloatContent>, width_percent: u16, height_percent: u16) -> Self {
impl<Content: FloatContent + ?Sized> Float<Content> {
pub fn new(content: Box<Content>, width_percent: u16, height_percent: u16) -> Self {
Self {
content,
width_percent,
Expand Down
1 change: 1 addition & 0 deletions tui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod float;
mod floating_text;
mod hint;
mod running_command;
mod confirmation;
pub mod state;
mod theme;

Expand Down
Loading

0 comments on commit a6b58fa

Please sign in to comment.