flake_edit/app/commands/
remove.rs1use crate::change::{Change, ChangeId};
10use crate::edit::{FlakeEdit, sorted_input_ids};
11use crate::tui;
12
13use super::super::editor::Editor;
14use super::super::state::AppState;
15use super::{Error, Result, apply_change};
16
17pub fn remove(
18 editor: &Editor,
19 flake_edit: &mut FlakeEdit,
20 state: &AppState,
21 id: Option<String>,
22) -> Result<()> {
23 let change = if let Some(id) = id {
24 Change::Remove {
25 ids: vec![
26 ChangeId::parse(&id).map_err(|source| Error::InvalidInputId {
27 id: id.clone(),
28 source,
29 })?,
30 ],
31 }
32 } else if state.interactive {
33 let inputs = flake_edit.list();
34 let mut removable: Vec<String> = Vec::new();
35 for input_id in sorted_input_ids(inputs) {
36 let input = &inputs[input_id];
37 removable.push(input_id.clone());
38 for follows in input.follows() {
39 if let crate::input::Follows::Indirect { path, target } = follows {
40 let target_str = match target {
41 Some(t) => t.to_string(),
42 None => "\"\"".to_string(),
43 };
44 removable.push(format!("{}.{} => {}", input_id, path, target_str));
45 }
46 }
47 }
48 if removable.is_empty() {
49 return Err(Error::NoInputs);
50 }
51
52 let tui_app = tui::App::remove("Remove", editor.text(), removable);
53 let Some(tui::AppResult::Change(tui_change)) = tui::run(tui_app)? else {
54 return Ok(());
55 };
56
57 if let Change::Remove { ids } = tui_change {
59 let stripped_ids: Vec<_> = ids
60 .iter()
61 .filter_map(|id| {
62 let s = id.to_string();
63 let stripped = s.split(" => ").next().unwrap_or(&s);
64 ChangeId::parse(stripped).ok()
65 })
66 .collect();
67 Change::Remove { ids: stripped_ids }
68 } else {
69 tui_change
70 }
71 } else {
72 return Err(Error::NoId);
73 };
74
75 apply_change(editor, flake_edit, state, change)
76}