tmux_lib/
window_id.rs

1//! Window Id.
2
3use std::str::FromStr;
4
5use nom::{
6    character::complete::{char, digit1},
7    combinator::all_consuming,
8    sequence::preceded,
9    IResult,
10};
11use serde::{Deserialize, Serialize};
12
13use crate::error::{map_add_intent, Error};
14
15/// The id of a Tmux window.
16///
17/// This wraps the raw tmux representation (`@41`).
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct WindowId(String);
20
21impl FromStr for WindowId {
22    type Err = Error;
23
24    /// Parse into WindowId. The `&str` must start with '@' followed by a
25    /// `u16`.
26    fn from_str(input: &str) -> std::result::Result<Self, Self::Err> {
27        let desc = "WindowId";
28        let intent = "#{window_id}";
29
30        let (_, window_id) =
31            all_consuming(parse::window_id)(input).map_err(|e| map_add_intent(desc, intent, e))?;
32
33        Ok(window_id)
34    }
35}
36
37impl WindowId {
38    /// Extract a string slice containing the raw representation.
39    pub fn as_str(&self) -> &str {
40        &self.0
41    }
42}
43
44pub(crate) mod parse {
45    use super::*;
46
47    pub(crate) fn window_id(input: &str) -> IResult<&str, WindowId> {
48        let (input, digit) = preceded(char('@'), digit1)(input)?;
49        let id = format!("@{digit}");
50        Ok((input, WindowId(id)))
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_parse_window_id_fn() {
60        let actual = parse::window_id("@43");
61        let expected = Ok(("", WindowId("@43".into())));
62        assert_eq!(actual, expected);
63
64        let actual = parse::window_id("@4");
65        let expected = Ok(("", WindowId("@4".into())));
66        assert_eq!(actual, expected);
67    }
68
69    #[test]
70    fn test_parse_window_id_struct() {
71        let actual = WindowId::from_str("@43");
72        assert!(actual.is_ok());
73        assert_eq!(actual.unwrap(), WindowId("@43".into()));
74
75        let actual = WindowId::from_str("4:38");
76        assert!(matches!(
77            actual,
78            Err(Error::ParseError {
79                desc: "WindowId",
80                intent: "#{window_id}",
81                err: _
82            })
83        ));
84    }
85}