Skip to main content

tab_command/service/main/
close_tabs.rs

1use std::time::Duration;
2
3use tab_api::tab::normalize_name;
4use tokio::time;
5
6use crate::{
7    message::main::MainRecv, message::main::MainShutdown, prelude::*, state::tabs::ActiveTabsState,
8    utils::await_state,
9};
10
11pub struct MainCloseTabsService {
12    _run: Lifeline,
13}
14
15impl Service for MainCloseTabsService {
16    type Bus = MainBus;
17    type Lifeline = anyhow::Result<Self>;
18
19    fn spawn(bus: &Self::Bus) -> Self::Lifeline {
20        let mut rx = bus.rx::<MainRecv>()?;
21        let mut rx_active = bus.rx::<Option<ActiveTabsState>>()?.into_inner();
22
23        let mut tx_request = bus.tx::<Request>()?;
24        let mut tx_shutdown = bus.tx::<MainShutdown>()?;
25
26        let _run = Self::try_task("run", async move {
27            while let Some(msg) = rx.recv().await {
28                if let MainRecv::CloseTabs(tabs) = msg {
29                    let state = await_state(&mut rx_active).await?;
30                    let exit_code = Self::close_tabs(tabs, state, &mut tx_request).await?;
31
32                    time::delay_for(Duration::from_millis(5)).await;
33                    tx_shutdown.send(MainShutdown(exit_code)).await?;
34                    break;
35                }
36            }
37
38            Ok(())
39        });
40
41        Ok(Self { _run })
42    }
43}
44
45impl MainCloseTabsService {
46    async fn close_tabs(
47        tabs: Vec<String>,
48        state: ActiveTabsState,
49        tx_websocket: &mut impl Sender<Request>,
50    ) -> anyhow::Result<i32> {
51        if tabs.is_empty() {
52            if let Ok(tab) = std::env::var("TAB_ID") {
53                eprintln!(
54                    "Closing current tab: {}",
55                    std::env::var("TAB").unwrap_or("".to_string())
56                );
57
58                let id = tab.parse()?;
59                tx_websocket.send(Request::CloseTab(id)).await?;
60            } else {
61                eprintln!("No arguments or current tab were detected.");
62                return Ok(1);
63            }
64
65            return Ok(0);
66        }
67
68        let running_tabs = state.into_name_set();
69
70        for tab in tabs {
71            let name = normalize_name(tab.as_str());
72
73            if !running_tabs.contains(&name) {
74                eprintln!("Tab not running: {}", name);
75                continue;
76            }
77
78            eprintln!("Closing tab: {}", name);
79
80            let tab = state.find_name(name.as_str()).unwrap();
81            tx_websocket.send(Request::CloseTab(tab.id)).await?;
82        }
83
84        Ok(0)
85    }
86}