now_command.rs

 1use std::sync::atomic::AtomicBool;
 2use std::sync::Arc;
 3
 4use anyhow::Result;
 5use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandOutputSection};
 6use chrono::{DateTime, Local};
 7use gpui::{AppContext, Task, WeakView};
 8use language::LspAdapterDelegate;
 9use ui::{prelude::*, ButtonLike, ElevationIndex};
10use workspace::Workspace;
11
12pub(crate) struct NowSlashCommand;
13
14impl SlashCommand for NowSlashCommand {
15    fn name(&self) -> String {
16        "now".into()
17    }
18
19    fn description(&self) -> String {
20        "insert the current date and time".into()
21    }
22
23    fn menu_text(&self) -> String {
24        "Insert current date and time".into()
25    }
26
27    fn requires_argument(&self) -> bool {
28        false
29    }
30
31    fn complete_argument(
32        &self,
33        _query: String,
34        _cancel: Arc<AtomicBool>,
35        _workspace: Option<WeakView<Workspace>>,
36        _cx: &mut AppContext,
37    ) -> Task<Result<Vec<String>>> {
38        Task::ready(Ok(Vec::new()))
39    }
40
41    fn run(
42        self: Arc<Self>,
43        _argument: Option<&str>,
44        _workspace: WeakView<Workspace>,
45        _delegate: Arc<dyn LspAdapterDelegate>,
46        _cx: &mut WindowContext,
47    ) -> Task<Result<SlashCommandOutput>> {
48        let now = Local::now();
49        let text = format!("Today is {now}.", now = now.to_rfc3339());
50        let range = 0..text.len();
51
52        Task::ready(Ok(SlashCommandOutput {
53            text,
54            sections: vec![SlashCommandOutputSection {
55                range,
56                render_placeholder: Arc::new(move |id, unfold, _cx| {
57                    NowPlaceholder { id, unfold, now }.into_any_element()
58                }),
59            }],
60            run_commands_in_text: false,
61        }))
62    }
63}
64
65#[derive(IntoElement)]
66struct NowPlaceholder {
67    pub id: ElementId,
68    pub unfold: Arc<dyn Fn(&mut WindowContext)>,
69    pub now: DateTime<Local>,
70}
71
72impl RenderOnce for NowPlaceholder {
73    fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
74        let unfold = self.unfold;
75
76        ButtonLike::new(self.id)
77            .style(ButtonStyle::Filled)
78            .layer(ElevationIndex::ElevatedSurface)
79            .child(Icon::new(IconName::CountdownTimer))
80            .child(Label::new(self.now.to_rfc3339()))
81            .on_click(move |_, cx| unfold(cx))
82    }
83}