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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Access the clipboard.
use window_clipboard::mime::{AllowedMimeTypes, AsMimeTypes};

use crate::command::{self, Command};
use crate::futures::MaybeSend;

use std::fmt;

/// A clipboard action to be performed by some [`Command`].
///
/// [`Command`]: crate::Command
pub enum Action<T> {
    /// Read the clipboard and produce `T` with the result.
    Read(Box<dyn Fn(Option<String>) -> T>),

    /// Write the given contents to the clipboard.
    Write(String),

    /// Write the given contents to the clipboard.
    WriteData(Box<dyn AsMimeTypes + Send + Sync + 'static>),

    #[allow(clippy::type_complexity)]
    /// Read the clipboard and produce `T` with the result.
    ReadData(Vec<String>, Box<dyn Fn(Option<(Vec<u8>, String)>) -> T>),

    /// Read the clipboard and produce `T` with the result.
    ReadPrimary(Box<dyn Fn(Option<String>) -> T>),

    /// Write the given contents to the clipboard.
    WritePrimary(String),

    /// Write the given contents to the clipboard.
    WritePrimaryData(Box<dyn AsMimeTypes + Send + Sync + 'static>),

    #[allow(clippy::type_complexity)]
    /// Read the clipboard and produce `T` with the result.
    ReadPrimaryData(Vec<String>, Box<dyn Fn(Option<(Vec<u8>, String)>) -> T>),
}

impl<T> Action<T> {
    /// Maps the output of a clipboard [`Action`] using the provided closure.
    pub fn map<A>(
        self,
        f: impl Fn(T) -> A + 'static + MaybeSend + Sync,
    ) -> Action<A>
    where
        T: 'static,
    {
        match self {
            Self::Read(o) => Action::Read(Box::new(move |s| f(o(s)))),
            Self::Write(content) => Action::Write(content),
            Self::WriteData(content) => Action::WriteData(content),
            Self::ReadData(a, o) => {
                Action::ReadData(a, Box::new(move |s| f(o(s))))
            }
            Self::ReadPrimary(o) => {
                Action::ReadPrimary(Box::new(move |s| f(o(s))))
            }
            Self::WritePrimary(content) => Action::WritePrimary(content),
            Self::WritePrimaryData(content) => {
                Action::WritePrimaryData(content)
            }
            Self::ReadPrimaryData(a, o) => {
                Action::ReadPrimaryData(a, Box::new(move |s| f(o(s))))
            }
        }
    }
}

impl<T> fmt::Debug for Action<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Read(_) => write!(f, "Action::Read"),
            Self::Write(_) => write!(f, "Action::Write"),
            Self::WriteData(_) => write!(f, "Action::WriteData"),
            Self::ReadData(_, _) => write!(f, "Action::ReadData"),
            Self::ReadPrimary(_) => write!(f, "Action::ReadPrimary"),
            Self::WritePrimary(_) => write!(f, "Action::WritePrimary"),
            Self::WritePrimaryData(_) => write!(f, "Action::WritePrimaryData"),
            Self::ReadPrimaryData(_, _) => write!(f, "Action::ReadPrimaryData"),
        }
    }
}

/// Read the current contents of the clipboard.
pub fn read<Message>(
    f: impl Fn(Option<String>) -> Message + 'static,
) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::Read(Box::new(f))))
}

/// Write the given contents to the clipboard.
pub fn write<Message>(contents: String) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::Write(contents)))
}

/// Read the current contents of primary.
pub fn read_primary<Message>(
    f: impl Fn(Option<String>) -> Message + 'static,
) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::ReadPrimary(Box::new(
        f,
    ))))
}

/// Write the given contents to primary.
pub fn write_primary<Message>(contents: String) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::WritePrimary(contents)))
}

/// Read the current contents of the clipboard.
pub fn read_data<T: AllowedMimeTypes + Send + Sync + 'static, Message>(
    f: impl Fn(Option<T>) -> Message + 'static,
) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::ReadData(
        T::allowed().into(),
        Box::new(move |d| f(d.and_then(|d| T::try_from(d).ok()))),
    )))
}

/// Write the given contents to the clipboard.
pub fn write_data<Message>(
    contents: impl AsMimeTypes + std::marker::Sync + std::marker::Send + 'static,
) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::WriteData(Box::new(
        contents,
    ))))
}

/// Read the current contents of the clipboard.
pub fn read_primary_data<
    T: AllowedMimeTypes + Send + Sync + 'static,
    Message,
>(
    f: impl Fn(Option<T>) -> Message + 'static,
) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::ReadPrimaryData(
        T::allowed().into(),
        Box::new(move |d| f(d.and_then(|d| T::try_from(d).ok()))),
    )))
}

/// Write the given contents to the clipboard.
pub fn write_primary_data<Message>(
    contents: impl AsMimeTypes + std::marker::Sync + std::marker::Send + 'static,
) -> Command<Message> {
    Command::single(command::Action::Clipboard(Action::WritePrimaryData(
        Box::new(contents),
    )))
}