proc_cli/commands/
kill.rs1use crate::core::{apply_filters, parse_targets, resolve_targets_excluding_self};
12use crate::error::{ProcError, Result};
13use crate::ui::Printer;
14use clap::Args;
15
16#[derive(Args, Debug)]
18pub struct KillCommand {
19 pub target: String,
21
22 #[arg(long, short = 'y')]
24 pub yes: bool,
25
26 #[arg(long)]
28 pub dry_run: bool,
29
30 #[arg(long, short = 'j')]
32 pub json: bool,
33
34 #[arg(long, short = 'v')]
36 pub verbose: bool,
37
38 #[arg(long, short = 'g')]
40 pub graceful: bool,
41
42 #[arg(long = "in", short = 'i', num_args = 0..=1, default_missing_value = ".")]
44 pub in_dir: Option<String>,
45
46 #[arg(long = "by", short = 'b')]
48 pub by_name: Option<String>,
49}
50
51impl KillCommand {
52 pub fn execute(&self) -> Result<()> {
54 let printer = Printer::from_flags(self.json, self.verbose);
55
56 let targets = parse_targets(&self.target);
59 let (mut processes, not_found) = resolve_targets_excluding_self(&targets);
60
61 if !not_found.is_empty() {
63 printer.warning(&format!("Not found: {}", not_found.join(", ")));
64 }
65
66 apply_filters(&mut processes, &self.in_dir, &self.by_name);
68
69 if processes.is_empty() {
70 return Err(ProcError::ProcessNotFound(self.target.clone()));
71 }
72
73 if self.dry_run {
75 printer.print_dry_run("kill", &processes);
76 return Ok(());
77 }
78
79 if !printer.ask_confirm("kill", &processes, self.yes)? {
81 return Ok(());
82 }
83
84 let mut killed = Vec::new();
86 let mut failed = Vec::new();
87
88 for proc in processes {
89 let result = if self.graceful {
90 proc.terminate()
91 } else {
92 proc.kill()
93 };
94
95 match result {
96 Ok(()) => killed.push(proc),
97 Err(e) => failed.push((proc, e.to_string())),
98 }
99 }
100
101 printer.print_action_result("kill", &killed, &failed)
102 }
103}