improv: Separate components & merge plugins binary with launcher service
This commit is contained in:
parent
43a4229ba7
commit
88acf0a74e
41 changed files with 219 additions and 152 deletions
46
Cargo.lock
generated
46
Cargo.lock
generated
|
|
@ -761,23 +761,21 @@ dependencies = [
|
||||||
name = "pop-launcher"
|
name = "pop-launcher"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"blocking",
|
||||||
"async-io",
|
|
||||||
"async-oneshot",
|
|
||||||
"async-trait",
|
|
||||||
"flume",
|
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"futures_codec",
|
"futures_codec",
|
||||||
"gen-z",
|
|
||||||
"regex",
|
|
||||||
"ron",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with",
|
"serde_with",
|
||||||
"slab",
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pop-launcher-bin"
|
||||||
|
version = "1.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"pop-launcher-plugins",
|
||||||
|
"pop-launcher-service",
|
||||||
"smol",
|
"smol",
|
||||||
"strsim",
|
|
||||||
"toml",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
@ -803,6 +801,32 @@ dependencies = [
|
||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pop-launcher-service"
|
||||||
|
version = "1.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-io",
|
||||||
|
"async-oneshot",
|
||||||
|
"async-trait",
|
||||||
|
"flume",
|
||||||
|
"futures-lite",
|
||||||
|
"futures_codec",
|
||||||
|
"gen-z",
|
||||||
|
"pop-launcher",
|
||||||
|
"regex",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with",
|
||||||
|
"slab",
|
||||||
|
"smol",
|
||||||
|
"strsim",
|
||||||
|
"toml",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
|
|
||||||
23
Cargo.toml
23
Cargo.toml
|
|
@ -2,29 +2,18 @@
|
||||||
name = "pop-launcher"
|
name = "pop-launcher"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
authors = ["Michael Aaron Murphy <mmstick@pm.me>"]
|
authors = ["Michael Aaron Murphy <mmstick@pm.me>"]
|
||||||
|
description = "Library for writing plugins and frontends for pop-launcher"
|
||||||
|
repository = "https://github.com/pop-os/launcher"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["plugins"]
|
members = ["bin", "plugins", "service"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
|
||||||
async-io = "1"
|
|
||||||
async-oneshot = "0.5"
|
|
||||||
async-trait = "0.1"
|
|
||||||
flume = "=0.10.7" # Restrict version to build with 1.47.0
|
|
||||||
futures_codec = "0.4"
|
|
||||||
futures-lite = "1"
|
|
||||||
regex = "1.5"
|
|
||||||
ron = "0.6"
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_with = "1"
|
serde_with = "1"
|
||||||
slab = "0.4"
|
futures-lite = "1"
|
||||||
smol = "1"
|
futures_codec = "0.4"
|
||||||
strsim = "0.10"
|
blocking = "1"
|
||||||
toml = "0.5"
|
|
||||||
tracing = "0.1"
|
|
||||||
tracing-subscriber = { version = "0.2", features = ["fmt"] }
|
|
||||||
gen-z = "0.1"
|
|
||||||
|
|
|
||||||
32
Makefile
32
Makefile
|
|
@ -12,8 +12,8 @@ endif
|
||||||
LAUNCHER_DIR = $(LIB_PATH)/pop-launcher
|
LAUNCHER_DIR = $(LIB_PATH)/pop-launcher
|
||||||
SCRIPTS_DIR = $(LAUNCHER_DIR)/scripts
|
SCRIPTS_DIR = $(LAUNCHER_DIR)/scripts
|
||||||
PLUGIN_DIR = $(LAUNCHER_DIR)/plugins
|
PLUGIN_DIR = $(LAUNCHER_DIR)/plugins
|
||||||
DEFAULT_PLUGINS_BIN = $(PLUGIN_DIR)/pop-launcher-plugins
|
|
||||||
BIN_DIR = $(BASE_PATH)/bin
|
BIN_DIR = $(BASE_PATH)/bin
|
||||||
|
BIN = $(BIN_DIR)/pop-launcher
|
||||||
|
|
||||||
PLUGINS=calc desktop_entries files find pop_shell pulse recent scripts terminal web
|
PLUGINS=calc desktop_entries files find pop_shell pulse recent scripts terminal web
|
||||||
|
|
||||||
|
|
@ -31,8 +31,7 @@ ifneq ($(VENDOR),0)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: extract-vendor
|
all: extract-vendor
|
||||||
cargo build -p pop-launcher-plugins $(ARGS)
|
cargo build -p pop-launcher-bin $(ARGS)
|
||||||
cargo build $(ARGS)
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cargo clean
|
cargo clean
|
||||||
|
|
@ -56,42 +55,41 @@ install:
|
||||||
for plugin in $(PLUGINS); do \
|
for plugin in $(PLUGINS); do \
|
||||||
dest=$(PLUGIN_DIR)/$${plugin}; \
|
dest=$(PLUGIN_DIR)/$${plugin}; \
|
||||||
mkdir -p $${dest}; \
|
mkdir -p $${dest}; \
|
||||||
install -Dm0644 plugins/src/plugins/$${plugin}/plugin.ron $${dest}/plugin.ron; \
|
install -Dm0644 plugins/src/$${plugin}/plugin.ron $${dest}/plugin.ron; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install -Dm0755 target/$(TARGET)/pop-launcher $(BIN_DIR)/pop-launcher
|
install -Dm0755 target/$(TARGET)/pop-launcher-bin $(BIN)
|
||||||
install -Dm0755 target/$(TARGET)/pop-launcher-plugins $(DEFAULT_PLUGINS_BIN)
|
|
||||||
|
|
||||||
# Pop Shell Windows plugin
|
# Pop Shell Windows plugin
|
||||||
ln -sf $(DEFAULT_PLUGINS_BIN) $(PLUGIN_DIR)/pop_shell/pop-shell
|
ln -sf $(BIN) $(PLUGIN_DIR)/pop_shell/pop-shell
|
||||||
|
|
||||||
# Desktop Entries plugin
|
# Desktop Entries plugin
|
||||||
ln -sf $(DEFAULT_PLUGINS_BIN) $(PLUGIN_DIR)/desktop_entries/desktop-entries
|
ln -sf $(BIN) $(PLUGIN_DIR)/desktop_entries/desktop-entries
|
||||||
|
|
||||||
# Find plugin
|
# Find plugin
|
||||||
ln -sf $(DEFAULT_PLUGINS_BIN) $(PLUGIN_DIR)/find/find
|
ln -sf $(BIN) $(PLUGIN_DIR)/find/find
|
||||||
|
|
||||||
# Scripts plugin
|
# Scripts plugin
|
||||||
ln -sf $(DEFAULT_PLUGINS_BIN) $(PLUGIN_DIR)/scripts/scripts
|
ln -sf $(BIN) $(PLUGIN_DIR)/scripts/scripts
|
||||||
|
|
||||||
# Calculator plugin
|
# Calculator plugin
|
||||||
install -Dm0755 plugins/src/plugins/calc/calc.js $(PLUGIN_DIR)/calc
|
install -Dm0755 plugins/src/calc/calc.js $(PLUGIN_DIR)/calc
|
||||||
install -Dm0644 plugins/src/plugins/calc/math.js $(PLUGIN_DIR)/calc
|
install -Dm0644 plugins/src/calc/math.js $(PLUGIN_DIR)/calc
|
||||||
|
|
||||||
# Files plugin
|
# Files plugin
|
||||||
install -Dm0755 plugins/src/plugins/files/files.js $(PLUGIN_DIR)/files
|
install -Dm0755 plugins/src/files/files.js $(PLUGIN_DIR)/files
|
||||||
|
|
||||||
# Recent plugin
|
# Recent plugin
|
||||||
install -Dm0755 plugins/src/plugins/recent/recent.js $(PLUGIN_DIR)/recent
|
install -Dm0755 plugins/src/recent/recent.js $(PLUGIN_DIR)/recent
|
||||||
|
|
||||||
# Pulse plugin
|
# Pulse plugin
|
||||||
install -Dm0755 plugins/src/plugins/pulse/pulse.js $(PLUGIN_DIR)/pulse
|
install -Dm0755 plugins/src/pulse/pulse.js $(PLUGIN_DIR)/pulse
|
||||||
|
|
||||||
# Terminal plugin
|
# Terminal plugin
|
||||||
install -Dm0755 plugins/src/plugins/terminal/terminal.js $(PLUGIN_DIR)/terminal
|
install -Dm0755 plugins/src/terminal/terminal.js $(PLUGIN_DIR)/terminal
|
||||||
|
|
||||||
# Web plugin
|
# Web plugin
|
||||||
install -Dm0755 plugins/src/plugins/web/web.js $(PLUGIN_DIR)/web
|
install -Dm0755 plugins/src/web/web.js $(PLUGIN_DIR)/web
|
||||||
|
|
||||||
# Scripts
|
# Scripts
|
||||||
mkdir -p $(SCRIPTS_DIR)
|
mkdir -p $(SCRIPTS_DIR)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Using IPC enables each plugin to isolate their data from other plugin processes
|
||||||
|
|
||||||
## Script Directories
|
## Script Directories
|
||||||
|
|
||||||
- User-local plugins: `~/.local/share/pop-shell/scripts`
|
- User-local scripts: `~/.local/share/pop-shell/scripts`
|
||||||
- System-wide install for system administrators: `/etc/pop-shell/scripts`
|
- System-wide install for system administrators: `/etc/pop-shell/scripts`
|
||||||
- Distribution packaging: `/usr/lib/pop-shell/scripts`
|
- Distribution packaging: `/usr/lib/pop-shell/scripts`
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ If you are writing a plugin, you should send these events to your stdout.
|
||||||
```rust
|
```rust
|
||||||
pub enum PluginResponse {
|
pub enum PluginResponse {
|
||||||
/// Append a new search item to the launcher
|
/// Append a new search item to the launcher
|
||||||
Append(SearchMeta),
|
Append(PluginSearchResult),
|
||||||
/// Clear all results in the launcher list
|
/// Clear all results in the launcher list
|
||||||
Clear,
|
Clear,
|
||||||
/// Close the launcher
|
/// Close the launcher
|
||||||
|
|
@ -81,14 +81,14 @@ pub enum PluginResponse {
|
||||||
|
|
||||||
#### JSON Equivalent
|
#### JSON Equivalent
|
||||||
|
|
||||||
- `{ "Append": SearchMeta }`,
|
- `{ "Append": PluginSearchResult }`,
|
||||||
- `"Clear"`,
|
- `"Clear"`,
|
||||||
- `"Close"`,
|
- `"Close"`,
|
||||||
- `{ "DesktopEntry": string }`
|
- `{ "DesktopEntry": string }`
|
||||||
- `{ "Fill": string }`
|
- `{ "Fill": string }`
|
||||||
- `"Finished"`
|
- `"Finished"`
|
||||||
|
|
||||||
Where `SearchMeta` is:
|
Where `PluginSearchResult` is:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
{
|
{
|
||||||
|
|
|
||||||
14
bin/Cargo.toml
Normal file
14
bin/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "pop-launcher-bin"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
pop-launcher-plugins = { path = "../plugins" }
|
||||||
|
pop-launcher-service = { path = "../service" }
|
||||||
|
smol = "1"
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = "0.2"
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
mod plugins;
|
use pop_launcher_plugins as plugins;
|
||||||
|
use pop_launcher_service::Service;
|
||||||
use smol::block_on;
|
use smol::block_on;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
|
@ -13,7 +13,12 @@ fn main() {
|
||||||
|
|
||||||
if let Some(plugin) = std::env::args().next() {
|
if let Some(plugin) = std::env::args().next() {
|
||||||
let start = plugin.rfind('/').map(|v| v + 1).unwrap_or(0);
|
let start = plugin.rfind('/').map(|v| v + 1).unwrap_or(0);
|
||||||
match &plugin.as_str()[start..] {
|
let cmd = &plugin.as_str()[start..];
|
||||||
|
match cmd {
|
||||||
|
"pop-launcher" => {
|
||||||
|
let stdout = io::stdout();
|
||||||
|
block_on(Service::new(stdout.lock()).exec())
|
||||||
|
},
|
||||||
"desktop-entries" => block_on(plugins::desktop_entries::main()),
|
"desktop-entries" => block_on(plugins::desktop_entries::main()),
|
||||||
"pop-shell" => block_on(plugins::pop_shell::main()),
|
"pop-shell" => block_on(plugins::pop_shell::main()),
|
||||||
"find" => block_on(plugins::find::main()),
|
"find" => block_on(plugins::find::main()),
|
||||||
8
debian/pop-launcher.links
vendored
8
debian/pop-launcher.links
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
/usr/lib/pop-launcher/plugins/pop-launcher-plugins /usr/lib/pop-launcher/plugins/desktop_entries/desktop-entries
|
/usr/bin/pop-launcher /usr/lib/pop-launcher/plugins/desktop_entries/desktop-entries
|
||||||
/usr/lib/pop-launcher/plugins/pop-launcher-plugins /usr/lib/pop-launcher/plugins/find/find
|
/usr/bin/pop-launcher /usr/lib/pop-launcher/plugins/find/find
|
||||||
/usr/lib/pop-launcher/plugins/pop-launcher-plugins /usr/lib/pop-launcher/plugins/pop_shell/pop-shell
|
/usr/bin/pop-launcher /usr/lib/pop-launcher/plugins/pop_shell/pop-shell
|
||||||
/usr/lib/pop-launcher/plugins/pop-launcher-plugins /usr/lib/pop-launcher/plugins/scripts/scripts
|
/usr/bin/pop-launcher /usr/lib/pop-launcher/plugins/scripts/scripts
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ name = "pop-launcher-plugins"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
authors = ["Michael Aaron Murphy <mmstick@pm.me>"]
|
authors = ["Michael Aaron Murphy <mmstick@pm.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
flume = "0.10"
|
flume = "0.10"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter as DesktopIter, PathSource};
|
use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter as DesktopIter, PathSource};
|
||||||
use futures_lite::{AsyncWrite, StreamExt};
|
use futures_lite::{AsyncWrite, StreamExt};
|
||||||
use pop_launcher::*;
|
use pop_launcher::*;
|
||||||
use pop_launcher_plugins::*;
|
use crate::*;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
@ -172,7 +172,7 @@ impl<W: AsyncWrite + Unpin> DesktopEntryPlugin<W> {
|
||||||
|| strsim::damerau_levenshtein(&*query, &*search_interest) < 3;
|
|| strsim::damerau_levenshtein(&*query, &*search_interest) < 3;
|
||||||
|
|
||||||
if append {
|
if append {
|
||||||
let response = PluginResponse::Append(SearchMeta {
|
let response = PluginResponse::Append(PluginSearchResult {
|
||||||
id: id as u32,
|
id: id as u32,
|
||||||
name: entry.name.clone(),
|
name: entry.name.clone(),
|
||||||
description: format!("{} - {}", path_string(&entry.src), entry.description),
|
description: format!("{} - {}", path_string(&entry.src), entry.description),
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use futures_lite::*;
|
use futures_lite::*;
|
||||||
use pop_launcher::*;
|
use pop_launcher::*;
|
||||||
use pop_launcher_plugins::send;
|
use crate::send;
|
||||||
use smol::process::{ChildStdout, Command, Stdio};
|
use smol::process::{ChildStdout, Command, Stdio};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
@ -121,7 +121,7 @@ impl SearchContext {
|
||||||
|
|
||||||
let path = PathBuf::from(line);
|
let path = PathBuf::from(line);
|
||||||
|
|
||||||
let response = PluginResponse::Append(SearchMeta {
|
let response = PluginResponse::Append(PluginSearchResult {
|
||||||
id,
|
id,
|
||||||
description,
|
description,
|
||||||
name,
|
name,
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
pub mod desktop_entries;
|
||||||
|
pub mod find;
|
||||||
|
pub mod pop_shell;
|
||||||
|
pub mod scripts;
|
||||||
|
|
||||||
use futures_lite::{AsyncWrite, AsyncWriteExt};
|
use futures_lite::{AsyncWrite, AsyncWriteExt};
|
||||||
|
|
||||||
use pop_launcher::PluginResponse;
|
use pop_launcher::PluginResponse;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
pub mod desktop_entries;
|
|
||||||
pub mod find;
|
|
||||||
pub mod pop_shell;
|
|
||||||
pub mod scripts;
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use futures_lite::{AsyncWrite, AsyncWriteExt, StreamExt};
|
use futures_lite::{AsyncWrite, AsyncWriteExt, StreamExt};
|
||||||
use pop_launcher::*;
|
use pop_launcher::*;
|
||||||
use pop_launcher_plugins::*;
|
use crate::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
|
@ -106,7 +106,7 @@ impl<W: AsyncWrite + Unpin> App<W> {
|
||||||
|
|
||||||
send(
|
send(
|
||||||
&mut self.tx,
|
&mut self.tx,
|
||||||
PluginResponse::Append(SearchMeta {
|
PluginResponse::Append(PluginSearchResult {
|
||||||
id: id as u32,
|
id: id as u32,
|
||||||
name: item.name.clone(),
|
name: item.name.clone(),
|
||||||
description: item.description.clone(),
|
description: item.description.clone(),
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use pop_launcher::*;
|
use pop_launcher::*;
|
||||||
use pop_launcher_plugins::*;
|
use crate::*;
|
||||||
|
|
||||||
use flume::Sender;
|
use flume::Sender;
|
||||||
use futures_lite::{AsyncBufReadExt, StreamExt};
|
use futures_lite::{AsyncBufReadExt, StreamExt};
|
||||||
|
|
@ -114,7 +114,7 @@ impl App {
|
||||||
if should_include {
|
if should_include {
|
||||||
send(
|
send(
|
||||||
out,
|
out,
|
||||||
PluginResponse::Append(SearchMeta {
|
PluginResponse::Append(PluginSearchResult {
|
||||||
id: id as u32,
|
id: id as u32,
|
||||||
name: script.name.clone(),
|
name: script.name.clone(),
|
||||||
description: script.description.clone(),
|
description: script.description.clone(),
|
||||||
27
service/Cargo.toml
Normal file
27
service/Cargo.toml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
[package]
|
||||||
|
name = "pop-launcher-service"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
async-io = "1"
|
||||||
|
async-oneshot = "0.5"
|
||||||
|
async-trait = "0.1"
|
||||||
|
flume = "=0.10.7" # Restrict version to build with 1.47.0
|
||||||
|
futures_codec = "0.4"
|
||||||
|
futures-lite = "1"
|
||||||
|
regex = "1.5"
|
||||||
|
ron = "0.6"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
serde_with = "1"
|
||||||
|
slab = "0.4"
|
||||||
|
smol = "1"
|
||||||
|
strsim = "0.10"
|
||||||
|
toml = "0.5"
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.2", features = ["fmt"] }
|
||||||
|
gen-z = "0.1"
|
||||||
|
pop-launcher = { path = "../" }
|
||||||
|
|
@ -1,12 +1,30 @@
|
||||||
use crate::*;
|
mod plugins;
|
||||||
|
|
||||||
|
use pop_launcher::*;
|
||||||
|
use crate::plugins::*;
|
||||||
|
|
||||||
use flume::{unbounded, Receiver, Sender};
|
use flume::{unbounded, Receiver, Sender};
|
||||||
use futures_lite::{future, StreamExt};
|
use futures_lite::{future, StreamExt};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
pub type PluginKey = usize;
|
||||||
|
|
||||||
|
pub enum Event {
|
||||||
|
Request(Request),
|
||||||
|
Response((PluginKey, PluginResponse)),
|
||||||
|
PluginExit(PluginKey),
|
||||||
|
Help(async_oneshot::Sender<Slab<PluginHelp>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginHelp {
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub help: Option<String>,
|
||||||
|
}
|
||||||
pub struct Service<O> {
|
pub struct Service<O> {
|
||||||
active_search: Vec<(PluginKey, SearchMeta)>,
|
active_search: Vec<(PluginKey, PluginSearchResult)>,
|
||||||
awaiting_results: usize,
|
awaiting_results: usize,
|
||||||
last_query: String,
|
last_query: String,
|
||||||
output: O,
|
output: O,
|
||||||
|
|
@ -172,7 +190,7 @@ impl<O: Write> Service<O> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append(&mut self, plugin: PluginKey, append: SearchMeta) {
|
fn append(&mut self, plugin: PluginKey, append: PluginSearchResult) {
|
||||||
self.active_search.push((plugin, append));
|
self.active_search.push((plugin, append));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,7 +321,7 @@ impl<O: Write> Service<O> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// From a given position ID, fetch the search result and its associated plugin
|
/// From a given position ID, fetch the search result and its associated plugin
|
||||||
fn search_result(&mut self, id: usize) -> Option<(&mut PluginConnector, &mut SearchMeta)> {
|
fn search_result(&mut self, id: usize) -> Option<(&mut PluginConnector, &mut PluginSearchResult)> {
|
||||||
let &mut Self {
|
let &mut Self {
|
||||||
ref mut active_search,
|
ref mut active_search,
|
||||||
ref mut plugins,
|
ref mut plugins,
|
||||||
|
|
@ -334,7 +352,7 @@ impl<O: Write> Service<O> {
|
||||||
*no_sort = false;
|
*no_sort = false;
|
||||||
} else {
|
} else {
|
||||||
active_search.sort_by(|a, b| {
|
active_search.sort_by(|a, b| {
|
||||||
fn calculate_weight(meta: &SearchMeta, query: &str) -> usize {
|
fn calculate_weight(meta: &PluginSearchResult, query: &str) -> usize {
|
||||||
let mut weight = 0;
|
let mut weight = 0;
|
||||||
|
|
||||||
let name = meta.name.to_ascii_lowercase();
|
let name = meta.name.to_ascii_lowercase();
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{Event, IconSource, Plugin, PluginConfig, PluginQuery, PluginResponse, SearchMeta};
|
use crate::*;
|
||||||
|
use pop_launcher::*;
|
||||||
use flume::Sender;
|
use flume::Sender;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
@ -19,13 +19,6 @@ pub const CONFIG: PluginConfig = PluginConfig {
|
||||||
},
|
},
|
||||||
icon: Some(IconSource::Name(Cow::Borrowed("system-help-symbolic"))),
|
icon: Some(IconSource::Name(Cow::Borrowed("system-help-symbolic"))),
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PluginHelp {
|
|
||||||
pub name: String,
|
|
||||||
pub description: String,
|
|
||||||
pub help: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct HelpPlugin {
|
pub struct HelpPlugin {
|
||||||
pub details: Slab<PluginHelp>,
|
pub details: Slab<PluginHelp>,
|
||||||
pub internal: Sender<Event>,
|
pub internal: Sender<Event>,
|
||||||
|
|
@ -78,7 +71,7 @@ impl Plugin for HelpPlugin {
|
||||||
if detail.help.is_some() {
|
if detail.help.is_some() {
|
||||||
let _ = self
|
let _ = self
|
||||||
.tx
|
.tx
|
||||||
.send_async(PluginResponse::Append(SearchMeta {
|
.send_async(PluginResponse::Append(PluginSearchResult {
|
||||||
id: id as u32,
|
id: id as u32,
|
||||||
name: detail.name.clone(),
|
name: detail.name.clone(),
|
||||||
description: detail.description.clone(),
|
description: detail.description.clone(),
|
||||||
|
|
@ -4,9 +4,9 @@ pub mod help;
|
||||||
|
|
||||||
pub use self::config::{PluginBinary, PluginConfig, PluginQuery};
|
pub use self::config::{PluginBinary, PluginConfig, PluginQuery};
|
||||||
pub use self::external::ExternalPlugin;
|
pub use self::external::ExternalPlugin;
|
||||||
pub use self::help::{HelpPlugin, PluginHelp};
|
pub use self::help::HelpPlugin;
|
||||||
|
|
||||||
use crate::Request;
|
use crate::{PluginHelp, Request};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use flume::{Receiver, Sender};
|
use flume::{Receiver, Sender};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use futures_codec::{FramedRead, LinesCodec};
|
use futures_codec::{FramedRead, LinesCodec};
|
||||||
use futures_lite::{AsyncRead, Stream, StreamExt};
|
use futures_lite::{AsyncRead, Stream, StreamExt};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use smol::Unblock;
|
use blocking::Unblock;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
/// stdin with AsyncRead support
|
/// stdin with AsyncRead support
|
||||||
|
|
|
||||||
117
src/lib.rs
117
src/lib.rs
|
|
@ -1,115 +1,124 @@
|
||||||
mod codec;
|
mod codec;
|
||||||
mod plugins;
|
|
||||||
mod service;
|
|
||||||
|
|
||||||
pub use self::codec::*;
|
pub use self::codec::*;
|
||||||
pub use self::plugins::*;
|
|
||||||
pub use self::service::Service;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use slab::Slab;
|
|
||||||
use std::{borrow::Cow, path::PathBuf};
|
use std::{borrow::Cow, path::PathBuf};
|
||||||
|
|
||||||
pub type PluginKey = usize;
|
/// u32 value defining the generation of an indice.
|
||||||
pub type Generation = u32;
|
pub type Generation = u32;
|
||||||
pub type Indice = u32;
|
|
||||||
|
|
||||||
pub enum Event {
|
/// u32 value defining the indice of a slot.
|
||||||
Request(Request),
|
pub type Indice = u32;
|
||||||
Response((PluginKey, PluginResponse)),
|
|
||||||
PluginExit(PluginKey),
|
|
||||||
Help(async_oneshot::Sender<Slab<PluginHelp>>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub enum IconSource {
|
pub enum IconSource {
|
||||||
// Locate by name or path
|
// Locate by name or path.
|
||||||
Name(Cow<'static, str>),
|
Name(Cow<'static, str>),
|
||||||
// Icon is a mime type
|
// Icon is a mime type.
|
||||||
Mime(Cow<'static, str>),
|
Mime(Cow<'static, str>),
|
||||||
// Window Entity ID
|
// Window Entity ID.
|
||||||
Window((Generation, Indice)),
|
Window((Generation, Indice)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Launcher frontends shall send these requests to the launcher service.
|
/// Sent from a plugin to the launcher service.
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub enum PluginResponse {
|
||||||
|
/// Append a new search item to the launcher.
|
||||||
|
Append(PluginSearchResult),
|
||||||
|
/// Clear all results in the launcher list.
|
||||||
|
Clear,
|
||||||
|
/// Close the launcher.
|
||||||
|
Close,
|
||||||
|
// Notifies that a .desktop entry should be launched by the frontend.
|
||||||
|
DesktopEntry(PathBuf),
|
||||||
|
/// Update the text in the launcher.
|
||||||
|
Fill(String),
|
||||||
|
/// Indicoates that a plugin is finished with its queries.
|
||||||
|
Finished,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Search information from a plugin to be sorted and filtered by the launcher service.
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
pub struct PluginSearchResult {
|
||||||
|
/// Numeric identifier tracked by the plugin.
|
||||||
|
pub id: Indice,
|
||||||
|
/// The name / title.
|
||||||
|
pub name: String,
|
||||||
|
/// The description / subtitle.
|
||||||
|
pub description: String,
|
||||||
|
/// Extra words to match when sorting and filtering.
|
||||||
|
pub keywords: Option<Vec<String>>,
|
||||||
|
/// Icon to display in the frontend.
|
||||||
|
pub icon: Option<IconSource>,
|
||||||
|
/// Command that is executed by this result, used for sorting and filtering.
|
||||||
|
pub exec: Option<String>,
|
||||||
|
/// Designates that this search item refers to a window.
|
||||||
|
pub window: Option<(Generation, Indice)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sent to the input pipe of the launcher service, and disseminated to its plugins.
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
/// Activate on the selected item
|
/// Activate on the selected item.
|
||||||
Activate(Indice),
|
Activate(Indice),
|
||||||
/// Perform a tab completion from the selected item
|
/// Perform a tab completion from the selected item.
|
||||||
Complete(Indice),
|
Complete(Indice),
|
||||||
/// Request to end the service
|
/// Request to end the service.
|
||||||
Exit,
|
Exit,
|
||||||
/// Requests to cancel any active searches
|
/// Requests to cancel any active searches.
|
||||||
Interrupt,
|
Interrupt,
|
||||||
/// Request to close the selected item
|
/// Request to close the selected item.
|
||||||
Quit(Indice),
|
Quit(Indice),
|
||||||
/// Perform a search in our database
|
/// Perform a search in our database.
|
||||||
Search(String),
|
Search(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Launcher frontends shall react to these responses from the launcher service.
|
/// Sent from the launcher service to a frontend.
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub enum Response {
|
pub enum Response {
|
||||||
// An operation was performed and the frontend may choose to exit its process.
|
// An operation was performed and the frontend may choose to exit its process.
|
||||||
Close,
|
Close,
|
||||||
// Notifies that a .desktop entry should be launched by the frontend
|
// Notifies that a .desktop entry should be launched by the frontend.
|
||||||
DesktopEntry(PathBuf),
|
DesktopEntry(PathBuf),
|
||||||
// The frontend should clear its search results and display a new list
|
// The frontend should clear its search results and display a new list.
|
||||||
Update(Vec<SearchResult>),
|
Update(Vec<SearchResult>),
|
||||||
// An item was selected that resulted in a need to autofill the launcher
|
// An item was selected that resulted in a need to autofill the launcher.
|
||||||
Fill(String),
|
Fill(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
pub enum PluginResponse {
|
|
||||||
/// Append a new search item to the launcher
|
|
||||||
Append(SearchMeta),
|
|
||||||
/// Clear all results in the launcher list
|
|
||||||
Clear,
|
|
||||||
/// Close the launcher
|
|
||||||
Close,
|
|
||||||
// Notifies that a .desktop entry should be launched by the frontend
|
|
||||||
DesktopEntry(PathBuf),
|
|
||||||
/// Update the text in the launcher
|
|
||||||
Fill(String),
|
|
||||||
/// Indicoates that a plugin is finished with its queries
|
|
||||||
Finished,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
|
||||||
pub struct SearchMeta {
|
|
||||||
pub id: Indice,
|
|
||||||
pub name: String,
|
|
||||||
pub description: String,
|
|
||||||
pub keywords: Option<Vec<String>>,
|
|
||||||
pub icon: Option<IconSource>,
|
|
||||||
pub exec: Option<String>,
|
|
||||||
pub window: Option<(Generation, Indice)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialized response to launcher frontend about a search result.
|
/// Serialized response to launcher frontend about a search result.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SearchResult {
|
pub struct SearchResult {
|
||||||
|
/// Numeric identifier tracked by the plugin.
|
||||||
pub id: Indice,
|
pub id: Indice,
|
||||||
|
/// The name / title.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// The description / subtitle.
|
||||||
pub description: String,
|
pub description: String,
|
||||||
|
|
||||||
#[serde(
|
#[serde(
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
with = "::serde_with::rust::unwrap_or_skip"
|
with = "::serde_with::rust::unwrap_or_skip"
|
||||||
)]
|
)]
|
||||||
|
/// Icon to display in the frontend for this item
|
||||||
pub icon: Option<IconSource>,
|
pub icon: Option<IconSource>,
|
||||||
|
|
||||||
#[serde(
|
#[serde(
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
with = "::serde_with::rust::unwrap_or_skip"
|
with = "::serde_with::rust::unwrap_or_skip"
|
||||||
)]
|
)]
|
||||||
|
/// Icon to display in the frontend for this plugin
|
||||||
pub category_icon: Option<IconSource>,
|
pub category_icon: Option<IconSource>,
|
||||||
|
|
||||||
#[serde(
|
#[serde(
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
with = "::serde_with::rust::unwrap_or_skip"
|
with = "::serde_with::rust::unwrap_or_skip"
|
||||||
)]
|
)]
|
||||||
|
/// Designates that this search item refers to a window.
|
||||||
pub window: Option<(Generation, Indice)>,
|
pub window: Option<(Generation, Indice)>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -1,12 +0,0 @@
|
||||||
use pop_launcher::Service;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
tracing_subscriber::fmt()
|
|
||||||
.with_writer(io::stderr)
|
|
||||||
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
|
||||||
.init();
|
|
||||||
|
|
||||||
let stdout = io::stdout();
|
|
||||||
smol::block_on(Service::new(stdout.lock()).exec());
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue