1use std::str::FromStr;
4
5use async_std::process::Command;
6use nom::{character::complete::char, combinator::all_consuming, sequence::tuple};
7use serde::{Deserialize, Serialize};
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 = tuple((quoted_nonempty_string, char(':'), quoted_string));
50
51 let (_, (session_name, _, last_session_name)) =
52 all_consuming(parser)(input).map_err(|e| map_add_intent(desc, intent, e))?;
53
54 Ok(Client {
55 session_name: session_name.to_string(),
56 last_session_name: last_session_name.to_string(),
57 })
58 }
59}
60
61pub async fn current() -> Result<Client> {
71 let args = vec![
72 "display-message",
73 "-p",
74 "-F",
75 "'#{client_session}':'#{client_last_session}'",
76 ];
77
78 let output = Command::new("tmux").args(&args).output().await?;
79 let buffer = String::from_utf8(output.stdout)?;
80
81 Client::from_str(buffer.trim_end())
82}
83
84pub fn display_message(message: &str) {
90 let args = vec!["display-message", message];
91
92 std::process::Command::new("tmux")
93 .args(&args)
94 .output()
95 .expect("Cannot communicate with Tmux for displaying message");
96}
97
98pub 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}