Skip to main content

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}