alfred_workflow/lib.rs
1//! This contains common abstractions for reuse in multiple workflows
2//!
3use alfred::{Item, json};
4use anyhow::{Error, anyhow};
5use rusqlite::Connection;
6use std::{fs, io::Write};
7
8/// Opens or creates if not exists an `SQLite` database.
9///
10/// # Arguments
11/// * `name` - The name of the workflow, which will create a dedicated sub-directory for.vec!
12/// * `f` - A lazily evaluated function that is called when the database is first created.
13///
14/// # Remarks
15/// `name` must be unique or it may conflict with other workflows.
16///
17/// # Errors
18///
19/// Will return `Err` if connection to database fails
20///
21/// # Examples
22///
23/// ```
24/// use anyhow::Error;
25/// use rusqlite::Connection;
26///
27/// fn main() -> Result<(), Error> {
28/// let conn = alfred_workflow::open_database_or_else("myworkflow", create_tables)?;
29/// Ok(())
30/// }
31///
32/// fn create_tables(conn: &Connection) -> Result<(), Error> {
33/// conn.execute(
34/// "CREATE TABLE IF NOT EXISTS config (
35/// key TEXT NOT NULL PRIMARY KEY,
36/// value TEXT NOT NULL
37/// );",
38/// [],
39/// )?;
40/// Ok(())
41/// }
42/// ```
43pub fn open_database_or_else<F>(name: &str, f: F) -> Result<Connection, Error>
44where
45 F: Fn(&Connection) -> Result<(), Error>,
46{
47 let conn: Connection;
48 let path = dirs::home_dir()
49 .ok_or_else(|| anyhow!("Impossible to get your home dir!"))?
50 .join(".alfred")
51 .join("workflows")
52 .join(name);
53
54 let db = path.join("db.sqlite3");
55 if db.exists() {
56 conn = Connection::open(&db)?;
57 } else {
58 fs::create_dir_all(path)?;
59 conn = Connection::open(&db)?;
60 f(&conn)?;
61 }
62 Ok(conn)
63}
64
65/// Writes Alfred items to the provided writer.
66///
67/// # Arguments
68/// * `writer` - the writer to writer iterms to.vec!
69/// * `items` - the Alfred items to be written.vec!
70///
71/// # Errors
72///
73/// Will return `Err` if items cannot be serialized to JSON.
74///
75/// # Examples
76/// ```
77/// use alfred::{json, Item};
78/// use std::{io, io::Write};
79/// use anyhow::Error;
80///
81/// fn main() -> Result<(), Error> {
82/// let item = alfred::ItemBuilder::new("settings")
83/// .subtitle("settings for the workflow")
84/// .into_item();
85/// alfred_workflow::write_items(io::stdout(), &[item])
86/// }
87/// ```
88pub fn write_items<W>(writer: W, items: &[Item]) -> Result<(), Error>
89where
90 W: Write,
91{
92 json::write_items(writer, items).map_err(|e| anyhow!("failed to write alfred items->json: {e}"))
93}