1use std::fmt;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use slug::slugify;
5use crate::snippets::file_type::FileType;
6#[derive(Debug, Serialize, Deserialize, Clone)]
11pub struct Meta {
12 pub name: String,
14 pub description: String,
16 pub tags: Vec<String>,
18 pub language: FileType,
20 pub created: DateTime<Utc>,
22 pub modified: DateTime<Utc>,
24 #[serde(default = "Visibility::default")]
26 pub visibility: Visibility,
27}
28
29impl Meta {
30 pub fn new(
34 name: String,
35 description: String,
36 tags: Vec<String>,
37 language: FileType,
38 visibility: Option<Visibility>) -> Self {
39 Self {
40 name,
41 description,
42 tags,
43 language,
44 created: Utc::now(),
45 modified: Utc::now(),
46 visibility: visibility.unwrap_or_default(),
47 }
48 }
49 pub fn get_content_extension(&self) -> String {
51 self.language.extension().to_string()
52 }
53 pub fn get_slug(&self) -> String {
55 slugify(self.name.as_str())
56 }
57}
58
59
60
61
62impl Default for Visibility {
63 fn default() -> Self {
64 Visibility::Private
65 }
66}
67
68#[derive(Debug, Serialize, Deserialize, Clone)]
72#[serde(rename_all = "lowercase")]
73pub enum Visibility {
74 Private,
76 Public,
78 Archived,
80}
81
82impl From<&str> for Visibility {
83 fn from(s: &str) -> Self {
87 match s {
88 "private" => Visibility::Private,
89 "public" => Visibility::Public,
90 "archived" => Visibility::Archived,
91 _ => Visibility::Private,
92 }
93 }
94}
95#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct Snippet {
100 pub meta: Meta,
102 pub content: String,
104}
105
106impl Snippet {
107 pub fn new(meta: Meta, content: String) -> Self {
109 Self { meta, content }
110 }
111
112 pub fn to_json(&self) -> String {
113 serde_json::to_string(self)
114 .unwrap_or_else(|_| "{\"type\":\"Other\",\"message\":\"Serialization failed\"}".to_string())
115 }
116
117}
118
119
120#[cfg(feature = "ansi")]
121use colored::*;
122
123impl fmt::Display for Meta {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 #[cfg(feature = "ansi")]
126 {
127 writeln!(f, "{}: {}", "Name".bold().cyan(), self.name)?;
128 writeln!(f, "{}: {}", "Description".bold().cyan(), self.description)?;
129 writeln!(f, "{}: {}", "Tags".bold().cyan(), self.tags.join(", "))?;
130 writeln!(f, "{}: {}", "Language".bold().cyan(), self.language)?;
131 writeln!(f, "{}: {}", "Created".bold().cyan(), self.created)?;
132 writeln!(f, "{}: {}", "Modified".bold().cyan(), self.modified)?;
133 writeln!(f, "{}: {}", "Visibility".bold().cyan(), format!("{:?}", self.visibility))?;
134 Ok(())
135 }
136
137 #[cfg(not(feature = "ansi"))]
138 {
139 writeln!(f, "Name: {}", self.name)?;
140 writeln!(f, "Description: {}", self.description)?;
141 writeln!(f, "Tags: {}", self.tags.join(", "))?;
142 writeln!(f, "Language: {}", self.language)?;
143 writeln!(f, "Created: {}", self.created)?;
144 writeln!(f, "Modified: {}", self.modified)?;
145 writeln!(f, "Visibility: {:?}", self.visibility)?;
146 Ok(())
147 }
148 }
149}
150
151
152impl fmt::Display for Snippet {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 #[cfg(feature = "ansi")]
155 {
156 writeln!(f, "{}\n", self.meta)?;
157 writeln!(f, "{}\n{}", "Content:".bold().green(), self.content)
158 }
159
160 #[cfg(not(feature = "ansi"))]
161 {
162 writeln!(f, "{}\n", self.meta)?;
163 writeln!(f, "Content:\n{}", self.content)
164 }
165 }
166}