tmux_interface/options/pane/ctl/
pane_options_ctl.rs

1use crate::{
2    Error, GetPaneOption, GetPaneOptionTr, PaneOptions, RemainOnExit, SetPaneOption,
3    SetPaneOptionTr, SetPaneOptions, SetPaneOptionsTr, ShowOptions, Switch, Tmux, TmuxCommand,
4    TmuxOutput,
5};
6use std::borrow::Cow;
7use std::str::FromStr;
8
9//oneline
10//multiline
11
12// Output:
13// * random (got buffer, need recognize fields)
14//      * Form
15//          * long (`option_name value`)
16//          * short (`value`), single option get/parse (otherwise there is no chance to assign)
17//
18// * expected (got buffer, need to extract some fields)
19//      * Form
20//          * long (`option_name value`)
21//          * short (`value`), single option get/parse (otherwise there is no chance to assign)
22//
23
24// get
25// * get single one
26// * get all for object
27//
28// set
29// * set single one
30//      * set value
31//      * toggle (on/off {default}/off) if no value specified
32
33// FIXME: proper Error in return
34//
35//
36// PaneOption::backspace() -> Result<Self::Backspace(String), Error>
37//  GetPaneOption::backspace()
38//  ParsePaneOption::from_str()
39//
40// PaneOption::set().backspace() -> Result<(), Error> {
41//  SetPaneOption::backspace()
42//  Output
43// }
44
45// XXX: rename PaneOptionCtl?
46// trait top level options, then server session window pane
47pub struct PaneOptionsCtl<'a> {
48    // TODO: comment/doc
49    //
50    // function used for executing the given option get/set command
51    //
52    // ```
53    // let tmux = Tmux::new();
54    // ```
55    pub invoker: &'a dyn Fn(TmuxCommand<'a>) -> Result<TmuxOutput, Error>,
56    pub target: Option<Cow<'a, str>>,
57}
58
59impl<'a> Default for PaneOptionsCtl<'a> {
60    fn default() -> Self {
61        Self {
62            invoker: &|cmd| Tmux::with_command(cmd).output(),
63            target: None,
64        }
65    }
66}
67
68impl<'a> PaneOptionsCtl<'a> {
69    pub fn new<S>(
70        target: Option<S>,
71        invoker: &'a dyn Fn(TmuxCommand<'a>) -> Result<TmuxOutput, Error>,
72    ) -> Self
73    where
74        S: Into<Cow<'a, str>>,
75    {
76        PaneOptionsCtl {
77            invoker,
78            target: target.map(|s| s.into()),
79        }
80    }
81
82    pub fn with_target<S>(target: Option<S>) -> Self
83    where
84        S: Into<Cow<'a, str>>,
85    {
86        PaneOptionsCtl {
87            target: target.map(|s| s.into()),
88            ..Default::default()
89        }
90    }
91
92    pub fn with_invoker(invoker: &'a dyn Fn(TmuxCommand<'a>) -> Result<TmuxOutput, Error>) -> Self {
93        Self {
94            invoker,
95            ..Default::default()
96        }
97    }
98
99    pub fn target(&self) -> Option<Cow<'a, str>> {
100        self.target.to_owned()
101    }
102
103    pub fn invoker(&self) -> &'a dyn Fn(TmuxCommand<'a>) -> Result<TmuxOutput, Error> {
104        self.invoker
105    }
106
107    pub fn get_all(&self) -> Result<PaneOptions<'a>, Error> {
108        Self::get_all_ext(self.target(), self.invoker())
109    }
110
111    pub fn get_all_ext(
112        target: Option<Cow<'a, str>>,
113        invoke: &'a dyn Fn(TmuxCommand<'a>) -> Result<TmuxOutput, Error>,
114    ) -> Result<PaneOptions<'a>, Error> {
115        let cmd = ShowOptions::new().pane();
116        let cmd = match target {
117            Some(target) => cmd.target(target),
118            None => cmd,
119        };
120        let cmd = cmd.build();
121        let output = invoke(cmd)?.to_string();
122        PaneOptions::from_str(&output)
123    }
124
125    pub fn set_all(&self, pane_options: PaneOptions<'a>) -> Result<TmuxOutput, Error> {
126        Self::set_all_ext(self.target(), self.invoker(), pane_options)
127    }
128
129    pub fn set_all_ext(
130        target: Option<Cow<'a, str>>,
131        invoke: &'a dyn Fn(TmuxCommand<'a>) -> Result<TmuxOutput, Error>,
132        pane_options: PaneOptions<'a>,
133    ) -> Result<TmuxOutput, Error> {
134        let cmds = SetPaneOptions::new();
135
136        #[cfg(feature = "tmux_3_0")]
137        let cmds = cmds.allow_rename(target.clone(), pane_options.allow_rename);
138        #[cfg(feature = "tmux_3_0")]
139        let cmds = cmds.alternate_screen(target.clone(), pane_options.alternate_screen);
140        #[cfg(feature = "tmux_3_0")]
141        let cmds = cmds.remain_on_exit(target.clone(), pane_options.remain_on_exit);
142        #[cfg(feature = "tmux_3_0")]
143        let cmds = cmds.window_active_style(target.clone(), pane_options.window_active_style);
144        #[cfg(feature = "tmux_3_0")]
145        let cmds = cmds.window_style(target.clone(), pane_options.window_style);
146        #[cfg(feature = "tmux_3_2")]
147        let cmds = cmds.synchronize_panes(target.clone(), pane_options.synchronize_panes);
148        // #[cfg(feature = "tmux_3_0")]
149        // let pane_options = pane_options.user_options();
150        // `@USER_OPTION`
151
152        let cmd = TmuxCommand::with_cmds(cmds.build());
153
154        invoke(cmd)
155    }
156
157    // get and parse single line option
158    pub fn get<T: std::str::FromStr>(&self, cmd: TmuxCommand<'a>) -> Result<Option<T>, Error> {
159        Ok((self.invoker)(cmd)?.to_string().trim().parse::<T>().ok())
160    }
161
162    pub fn set(&self, cmd: TmuxCommand<'a>) -> Result<TmuxOutput, Error> {
163        (self.invoker)(cmd)
164    }
165
166    // FIXME: full array support
167    // Tmux binary
168    //
169    // 1. multiple binary call
170    // tmux set -s command-alias[0] value0
171    // tmux set -s command-alias[1] value1
172    // tmux set -s command-alias[2] value2
173    //
174    // 2. single binary call
175    // tmux set -s command-alias[0] value0 ; set -s command-alias[1] ; set -s command-alias[2]
176    //
177    // Control Mode
178    //
179    // 1. multiple control mode commands
180    // set -s command-alias[0] value0
181    // set -s command-alias[1] value1
182    // set -s command-alias[2] value2
183    //
184    // 2. single control mode command
185    // set -s command-alias[0] value0 ; set -s command-alias[1] ; set -s command-alias[2]
186    //
187    pub fn get_array(&self, get_option_cmd: TmuxCommand<'a>) -> Result<Option<Vec<String>>, Error> {
188        let output = (self.invoker)(get_option_cmd)?;
189        let v: Vec<String> = output
190            .to_string()
191            .lines()
192            .map(|s| s.trim().into())
193            .collect();
194        let result = match v.is_empty() {
195            true => None,
196            false => Some(v),
197        };
198        Ok(result)
199    }
200
201    /// tmux ^3.0:
202    /// ```text
203    /// allow-rename [on | off]
204    /// ```
205    #[cfg(feature = "tmux_3_0")]
206    pub fn get_allow_rename(&self) -> Result<Option<Switch>, Error> {
207        self.get(GetPaneOption::allow_rename(self.target.clone()))
208    }
209
210    /// tmux ^3.0:
211    /// ```text
212    /// allow-rename [on | off]
213    /// ```
214    #[cfg(feature = "tmux_3_0")]
215    pub fn set_allow_rename<S: Into<Cow<'a, str>>>(
216        &self,
217        allow_rename: Option<Switch>,
218    ) -> Result<TmuxOutput, Error> {
219        self.set(SetPaneOption::allow_rename(
220            self.target.clone(),
221            allow_rename,
222        ))
223    }
224
225    /// tmux ^3.0:
226    /// ```text
227    /// alternate-screen [on | off]
228    /// ```
229    #[cfg(feature = "tmux_3_0")]
230    pub fn get_alternate_screen(&self) -> Result<Option<Switch>, Error> {
231        self.get(GetPaneOption::alternate_screen(self.target.clone()))
232    }
233
234    /// tmux ^3.0:
235    /// ```text
236    /// alternate-screen [on | off]
237    /// ```
238    #[cfg(feature = "tmux_3_0")]
239    pub fn set_alternate_screen<S: Into<Cow<'a, str>>>(
240        &self,
241        alternate_screen: Option<Switch>,
242    ) -> Result<TmuxOutput, Error> {
243        self.set(SetPaneOption::alternate_screen(
244            self.target.clone(),
245            alternate_screen,
246        ))
247    }
248
249    /// tmux ^3.2:
250    /// ```text
251    /// remain-on-exit [on | off | failed]
252    /// ```
253    ///
254    /// tmux ^3.0:
255    /// ```text
256    /// remain-on-exit [on | off]
257    /// ```
258    #[cfg(feature = "tmux_3_0")]
259    pub fn get_remain_on_exit(&self) -> Result<Option<RemainOnExit>, Error> {
260        self.get(GetPaneOption::remain_on_exit(self.target.clone()))
261    }
262
263    /// tmux ^3.2:
264    /// ```text
265    /// remain-on-exit [on | off | failed]
266    /// ```
267    ///
268    /// tmux ^3.0:
269    /// ```text
270    /// remain-on-exit [on | off]
271    /// ```
272    #[cfg(feature = "tmux_3_0")]
273    pub fn set_remain_on_exit<S: Into<Cow<'a, str>>>(
274        &self,
275        remain_on_exit: Option<RemainOnExit>,
276    ) -> Result<TmuxOutput, Error> {
277        self.set(SetPaneOption::remain_on_exit(
278            self.target.clone(),
279            remain_on_exit,
280        ))
281    }
282
283    /// tmux ^3.0:
284    /// ```text
285    /// window-active-style style
286    /// ```
287    #[cfg(feature = "tmux_3_0")]
288    pub fn get_window_active_style(&self) -> Result<Option<String>, Error> {
289        self.get(GetPaneOption::window_active_style(self.target.clone()))
290    }
291
292    /// tmux ^3.0:
293    /// ```text
294    /// window-active-style style
295    /// ```
296    #[cfg(feature = "tmux_3_0")]
297    pub fn set_window_active_style<S: Into<Cow<'a, str>>>(
298        &self,
299        window_active_style: Option<Cow<'a, str>>,
300    ) -> Result<TmuxOutput, Error> {
301        self.set(SetPaneOption::window_active_style(
302            self.target.clone(),
303            window_active_style,
304        ))
305    }
306
307    /// tmux ^3.0:
308    /// ```text
309    /// window-style style
310    /// ```
311    #[cfg(feature = "tmux_3_0")]
312    pub fn get_window_style(&self) -> Result<Option<String>, Error> {
313        self.get(GetPaneOption::window_style(self.target.clone()))
314    }
315
316    /// tmux ^3.0:
317    /// ```text
318    /// window-style style
319    /// ```
320    #[cfg(feature = "tmux_3_0")]
321    pub fn set_window_style<S: Into<Cow<'a, str>>>(
322        &self,
323        window_style: Option<Cow<'a, str>>,
324    ) -> Result<TmuxOutput, Error> {
325        self.set(SetPaneOption::window_style(
326            self.target.clone(),
327            window_style,
328        ))
329    }
330
331    /// tmux ^3.2:
332    /// ```text
333    /// synchronize-panes [on | off]
334    /// ```
335    #[cfg(feature = "tmux_3_2")]
336    pub fn get_synchronize_panes(&self) -> Result<Option<Switch>, Error> {
337        self.get(GetPaneOption::synchronize_panes(self.target.clone()))
338    }
339
340    /// tmux ^3.2:
341    /// ```text
342    /// synchronize-panes [on | off]
343    /// ```
344    #[cfg(feature = "tmux_3_2")]
345    pub fn set_synchronize_panes(
346        &self,
347        synchronize_panes: Option<Switch>,
348    ) -> Result<TmuxOutput, Error> {
349        self.set(SetPaneOption::synchronize_panes(
350            self.target.clone(),
351            synchronize_panes,
352        ))
353    }
354}