1use std::{fmt::Display, path::PathBuf};
2
3use once_cell::sync::OnceCell;
4use url::Url;
5
6use crate::{attribute::Attribute, plugins, repo_url::RepoUrl, spec::Spec, tmux, utils};
7
8pub struct Plugin {
9 spec: Spec,
10 path: OnceCell<PathBuf>,
13}
14
15impl Plugin {
16 pub fn url(&self) -> Url {
17 self.spec.url().into()
18 }
19
20 pub fn repo_url(&self) -> &RepoUrl {
21 self.spec.url()
22 }
23
24 pub fn name(&self) -> &str {
25 self.spec
26 .attributes()
27 .get(&Attribute::Alias)
28 .unwrap_or_else(|| self.spec.name())
29 }
30
31 pub fn is_installed(&self) -> bool {
32 self.path().exists()
33 }
34
35 pub fn path(&self) -> &PathBuf {
36 self.path
37 .get_or_init(|| tmux::get_plugins_dir().join(self.name()))
38 }
39
40 pub fn branch(&self) -> Option<&str> {
41 self.spec.branch()
42 }
43
44 pub fn parallel(&self) -> bool {
45 self.spec
46 .attributes()
47 .get(&Attribute::Parallel)
48 .and_then(|s| utils::parse_bool(s))
49 .unwrap_or_else(plugins::do_parallel)
50 }
51}
52
53impl From<Spec> for Plugin {
54 fn from(spec: Spec) -> Self {
55 Plugin {
56 spec,
57 path: OnceCell::new(),
58 }
59 }
60}
61
62impl Display for Plugin {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(f, "{} ({}", self.name(), self.repo_url())?;
65 if let Some(branch) = self.branch() {
66 write!(f, "#{branch}")?;
67 };
68 write!(f, ")")
69 }
70}