1use std::str::FromStr;
4
5use nom::{character::complete::char, combinator::all_consuming, Parser};
6use serde::{Deserialize, Serialize};
7use smol::process::Command;
8
9use crate::{
10 error::{map_add_intent, Error},
11 parse::{quoted_nonempty_string, quoted_string},
12 Result,
13};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Client {
18 pub session_name: String,
20 pub last_session_name: String,
22}
23
24impl FromStr for Client {
25 type Err = Error;
26
27 fn from_str(input: &str) -> std::result::Result<Self, Self::Err> {
47 let desc = "Client";
48 let intent = "'#{client_session}':'#{client_last_session}'";
49 let parser = (quoted_nonempty_string, char(':'), quoted_string);
50
51 let (_, (session_name, _, last_session_name)) = all_consuming(parser)
52 .parse(input)
53 .map_err(|e| map_add_intent(desc, intent, e))?;
54
55 Ok(Client {
56 session_name: session_name.to_string(),
57 last_session_name: last_session_name.to_string(),
58 })
59 }
60}
61
62pub async fn current() -> Result<Client> {
72 let args = vec![
73 "display-message",
74 "-p",
75 "-F",
76 "'#{client_session}':'#{client_last_session}'",
77 ];
78
79 let output = Command::new("tmux").args(&args).output().await?;
80 let buffer = String::from_utf8(output.stdout)?;
81
82 Client::from_str(buffer.trim_end())
83}
84
85pub fn display_message(message: &str) {
91 let args = vec!["display-message", message];
92
93 std::process::Command::new("tmux")
94 .args(&args)
95 .output()
96 .expect("Cannot communicate with Tmux for displaying message");
97}
98
99pub async fn switch_client(session_name: &str) -> Result<()> {
101 let exact_session_name = format!("={session_name}");
102 let args = vec!["switch-client", "-t", &exact_session_name];
103
104 Command::new("tmux")
105 .args(&args)
106 .output()
107 .await
108 .expect("Cannot communicate with Tmux for switching the client");
109
110 Ok(())
111}