1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! This contains common abstractions for reuse in multiple workflows
//!
use alfred::{json, Item};
use failure::{format_err, Error};
use rusqlite::Connection;
use std::{fs, io::Write};

/// Opens or creates if not exists an SQLite database.
///
/// # Arguments
/// * `name` - The name of the workflow, which will create a dedicated sub-directory for.vec!
/// * `f` - A lazily evaluated function that is called when the database is first created.
///
/// # Remarks
/// `name` must be unique or it may conflict with other workflows.
///
/// # Examples
///
/// ```
/// use failure::Error;
/// use rusqlite::Connection;
/// use rusqlite::NO_PARAMS;
///
/// fn main() -> Result<(), Error> {
///     let conn = alfred_workflow::open_database_or_else("myworkflow", create_tables)?;
///     Ok(())
/// }
///
/// fn create_tables(conn: &Connection) -> Result<(), Error> {
///     conn.execute(
///         "CREATE TABLE IF NOT EXISTS config (
///             key   TEXT NOT NULL PRIMARY KEY,
///             value TEXT NOT NULL
///         );",
///         NO_PARAMS,
///     )?;
///     Ok(())
/// }
/// ```
pub fn open_database_or_else<F>(name: &str, f: F) -> Result<Connection, Error>
where
    F: Fn(&Connection) -> Result<(), Error>,
{
    let conn: Connection;
    let path = dirs::home_dir()
        .ok_or_else(|| format_err!("Impossible to get your home dir!"))?
        .join(".alfred")
        .join("workflows")
        .join(name);

    let db = path.join("db.sqlite3");
    if !db.exists() {
        fs::create_dir_all(path)?;
        conn = Connection::open(&db)?;
        f(&conn)?
    } else {
        conn = Connection::open(&db)?
    }
    Ok(conn)
}

/// Writes Alfred items to the provided writer.
///
/// # Arguments
/// * `writer` - the writer to writer iterms to.vec!
/// * `items` - the Alfred items to be written.vec!
///
/// # Examples
/// ```
/// use alfred::{json, Item};
/// use std::{io, io::Write};
/// use failure::Error;
///
/// fn main() -> Result<(), Error> {
///     let item = alfred::ItemBuilder::new("settings")
///                .subtitle("settings for the workflow")
///                .into_item();
///      alfred_workflow::write_items(io::stdout(), &[item])
/// }
/// ```
pub fn write_items<W>(writer: W, items: &[Item]) -> Result<(), Error>
where
    W: Write,
{
    json::write_items(writer, &items[..])
        .map_err(|e| format_err!("failed to write alfred items->json: {}", e))
}