ltrait_source_desktop/lib.rs
1//! # Example Usage
2//! ```rust
3//! # use ltrait::{color_eyre::Result, Launcher, filter::ClosureFilter};
4//! # use std::time::Duration;
5//! #
6//! # struct DummyUI;
7//! #
8//! # impl<'a> ltrait::UI<'a> for DummyUI {
9//! # type Context = ();
10//! #
11//! # async fn run<Cushion: 'a + Send>(
12//! # &self,
13//! # _: ltrait::launcher::batcher::Batcher<'a, Cushion, Self::Context>,
14//! # ) -> Result<Option<Cushion>> {
15//! # unimplemented!()
16//! # }
17//! # }
18//! #
19//! # fn main() -> Result<()> {
20//! #
21//! use ltrait_source_desktop::{default_paths, DesktopEntry};
22//!
23//! let launcher = Launcher::default()
24//! .set_ui(DummyUI, |c| unimplemented!())
25//! .add_raw_source(
26//! ltrait_source_desktop::new(default_paths())?,
27//! )
28//! .add_raw_filter(ClosureFilter::new(|d: &DesktopEntry, _| {
29//! !d.entry.no_display() && d.entry.exec().is_some()
30//! }));
31//! #
32//! # Ok(()) }
33//! ```
34
35use ltrait::{source::Source, tokio_stream};
36use std::path::PathBuf;
37
38pub use freedesktop_desktop_entry::default_paths;
39
40pub mod icon;
41
42#[derive(Debug, thiserror::Error)]
43pub enum DesktopError {
44 // Stringは名前
45 #[error("Failed to find icon of {0}")]
46 NoIcon(String),
47 #[error("Failed to open file: {0}")]
48 OpenFile(#[source] std::io::Error),
49 #[error("Failed to decode the image: {0}")]
50 ImageDecode(#[source] image::ImageError),
51}
52
53#[derive(Debug, Clone)]
54pub struct DesktopEntry {
55 pub entry: freedesktop_desktop_entry::DesktopEntry,
56}
57
58impl DesktopEntry {
59 pub fn icon(&self) -> Option<PathBuf> {
60 self.entry.icon().and_then(|n| icon::lookup(n).ok())
61 }
62}
63
64// 楽をするためにfreedesktop_desktop_entryを使っているからStreamではなく、性能を最大限に活かしきれていない
65pub fn new(paths: impl Iterator<Item = PathBuf>) -> Result<Source<DesktopEntry>, DesktopError> {
66 use freedesktop_desktop_entry::Iter;
67 let entries = Iter::new(paths)
68 .entries::<String>(None)
69 .map(|e| DesktopEntry { entry: e });
70
71 Ok(Box::pin(tokio_stream::iter(entries)))
72}