Skip to content
Open
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
19 changes: 19 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum Action {
MoveRight,
ToggleDetail,
Refresh,
Delete,
}

pub struct App {
Expand Down Expand Up @@ -136,6 +137,7 @@ impl App {
Action::SelectDown => self.select(1),
Action::ToggleDetail => self.detail_open = !self.detail_open,
Action::Refresh | Action::MoveLeft | Action::MoveRight => {}
Action::Delete => { self.delete_current_card(); },
}
false
}
Expand Down Expand Up @@ -168,6 +170,23 @@ impl App {

Some((card_id, to_col_id))
}

pub fn delete_current_card(&mut self) -> Option<String> {
if self.board.columns.is_empty() {
return None;
}

self.clamp();

if self.board.columns[self.col].cards.is_empty() {
return None;
}

let card = self.board.columns[self.col].cards.remove(self.row);
self.clamp_row();

Some(card.id)
}
}

fn first_non_empty_column(board: &Board) -> Option<usize> {
Expand Down
23 changes: 22 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mod store_fs;
use app::{Action, App};

fn help_text() -> &'static str {
"h/l or ←/→ focus j/k or ↑/↓ select H/L move n new e edit Enter detail r refresh Esc close/quit q quit"
"h/l or ←/→ focus j/k or ↑/↓ select H/L move n new e edit d delete Enter detail r refresh Esc close/quit q quit"
}

fn action_from_key(code: KeyCode) -> Option<Action> {
Expand All @@ -51,6 +51,7 @@ fn action_from_key(code: KeyCode) -> Option<Action> {

KeyCode::Enter => Action::ToggleDetail,
KeyCode::Char('r') => Action::Refresh,
KeyCode::Char('d') => Action::Delete,

_ => return None,
})
Expand Down Expand Up @@ -253,6 +254,26 @@ fn run(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>) -> io::Result<()>
Err(e) => app.banner = Some(format!("Refresh failed: {e}")),
}
}
Action::Delete => {
if quitting {
continue;
}
if let Some(card_id) = selected_card_id(&app) {
app.apply(a);
if let Err(e) = provider.delete_card(&card_id) {
app.banner = Some(format!("Delete failed: {e}"));
if let Ok(board) = provider.load_board() {
app.board = board;
app.clamp();
}
} else {
app.banner = Some("Card deleted".to_string());
}
} else {
app.apply(a);
app.banner = Some("No card selected to delete".to_string());
}
}
_ => {
if app.apply(a) {
if move_rx.is_some() || !move_queue.is_empty() {
Expand Down
6 changes: 6 additions & 0 deletions src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ pub trait Provider {
msg: "edit_card not supported by current provider".to_string(),
})
}

fn delete_card(&mut self, _card_id: &str) -> Result<(), ProviderError> {
Err(ProviderError::Parse {
msg: "delete_card not supported by current provider".to_string(),
})
}
}

pub fn from_env() -> Box<dyn Provider> {
Expand Down
8 changes: 8 additions & 0 deletions src/provider_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ impl Provider for LocalProvider {
},
})
}
fn delete_card(&mut self, card_id: &str) -> Result<(), ProviderError> {
store_fs::delete_card(&self.root, card_id)
.map_err(|err| ProviderError::Io {
op: "delete_card".to_string(),
path: self.root.clone(),
source: err,
})
}
}

fn map_load_err(op: &str, root: &Path, err: io::Error) -> ProviderError {
Expand Down
12 changes: 12 additions & 0 deletions src/store_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ pub fn move_card(root: &Path, card_id: &str, to_col_id: &str) -> io::Result<()>
Ok(())
}

pub fn delete_card(root: &Path, card_id: &str) -> io::Result<()> {
let col_ids = list_columns(root)?;
let src = find_card_column(root, &col_ids, card_id)?
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "card not found"))?;

let dir = root.join("cols").join(&src);
fs::remove_file(dir.join(format!("{card_id}.md")))?;
order_remove(&dir.join("order.txt"), card_id)?;

Ok(())
}

pub fn create_card(root: &Path, to_col_id: &str) -> io::Result<String> {
let id = format!("CARD-{}", now_millis());
let dir = root.join("cols").join(to_col_id);
Expand Down