Rust · 2000 bytes Raw Blame History
1 //! garfieldctl - CLI control tool for garfield.
2
3 use anyhow::Result;
4 use clap::{Parser, Subcommand};
5 use garfield_ipc::{Command, Response};
6 use std::io::{BufRead, BufReader, Write};
7 use std::os::unix::net::UnixStream;
8 use std::path::PathBuf;
9
10 #[derive(Parser)]
11 #[command(name = "garfieldctl")]
12 #[command(about = "Control garfield file manager", long_about = None)]
13 struct Cli {
14 #[command(subcommand)]
15 command: Commands,
16 }
17
18 #[derive(Subcommand)]
19 enum Commands {
20 /// Open a directory in garfield.
21 Open {
22 /// Path to open.
23 path: PathBuf,
24 /// Open in new tab.
25 #[arg(short = 't', long)]
26 new_tab: bool,
27 },
28 /// Get the current directory.
29 CurrentDir,
30 /// Get garfield status.
31 Status,
32 /// Quit garfield.
33 Quit,
34 }
35
36 fn main() -> Result<()> {
37 let cli = Cli::parse();
38
39 let cmd = match cli.command {
40 Commands::Open { path, new_tab } => Command::Open {
41 path: path.to_string_lossy().to_string(),
42 new_tab,
43 },
44 Commands::CurrentDir => Command::CurrentDir,
45 Commands::Status => Command::Status,
46 Commands::Quit => Command::Quit,
47 };
48
49 let response = send_command(&cmd)?;
50
51 if response.success {
52 if let Some(data) = response.data {
53 println!("{}", serde_json::to_string_pretty(&data)?);
54 }
55 } else {
56 eprintln!("Error: {}", response.error.unwrap_or_default());
57 std::process::exit(1);
58 }
59
60 Ok(())
61 }
62
63 fn send_command(cmd: &Command) -> Result<Response> {
64 let socket_path = garfield_ipc::socket_path();
65 let mut stream = UnixStream::connect(&socket_path)?;
66
67 // Send command as JSON line
68 let json = serde_json::to_string(cmd)?;
69 writeln!(stream, "{}", json)?;
70 stream.flush()?;
71
72 // Read response
73 let mut reader = BufReader::new(stream);
74 let mut line = String::new();
75 reader.read_line(&mut line)?;
76
77 let response: Response = serde_json::from_str(&line)?;
78 Ok(response)
79 }
80