cosmic_files/
context_action.rs1use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7use crate::mime_app;
8use crate::spawn_detached::spawn_detached;
9
10#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
11pub enum ContextActionSelection {
12 #[default]
13 #[serde(alias = "any")]
14 Any,
15 #[serde(alias = "files")]
16 Files,
17 #[serde(alias = "folders")]
18 Folders,
19}
20
21#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
22#[serde(default)]
23pub struct ContextActionPreset {
24 pub name: String,
25 pub confirm: bool,
26 pub selection: ContextActionSelection,
27 pub steps: Vec<String>,
28}
29
30impl ContextActionPreset {
31 pub fn matches_selection(&self, selected: usize, selected_dir: usize) -> bool {
32 if selected == 0 {
33 return false;
34 }
35
36 match self.selection {
37 ContextActionSelection::Any => true,
38 ContextActionSelection::Files => selected_dir == 0,
39 ContextActionSelection::Folders => selected_dir == selected,
40 }
41 }
42
43 pub fn run(&self, paths: &[PathBuf]) {
44 if self.steps.is_empty() {
45 log::warn!("context action {:?} has no steps", self.name);
46 return;
47 }
48
49 for step in &self.steps {
50 let Some(commands) = mime_app::exec_to_command(step, &self.name, None, paths) else {
51 log::warn!(
52 "failed to parse context action {:?}: invalid Exec {:?}",
53 self.name,
54 step
55 );
56 return;
57 };
58
59 for mut command in commands {
60 if let Err(err) = spawn_detached(&mut command) {
61 log::warn!(
62 "failed to run context action {:?} step {:?}: {}",
63 self.name,
64 step,
65 err
66 );
67 return;
68 }
69 }
70 }
71 }
72}
73
74pub fn run(actions: &[ContextActionPreset], action: usize, paths: &[PathBuf]) {
75 if let Some(preset) = actions.get(action) {
76 preset.run(paths);
77 } else {
78 log::warn!("invalid context action index `{action}`");
79 }
80}