Accept file URIs via stdin instead
This commit is contained in:
parent
90f2a2db1d
commit
c9db5a6b7d
18
README.md
18
README.md
|
@ -9,7 +9,7 @@ software.
|
||||||
|
|
||||||
AUR package: `dfmd-git`
|
AUR package: `dfmd-git`
|
||||||
|
|
||||||
If some other handler takes precedence over this one, try copying the DBus
|
If some other handler takes precedence over this one, try copying the D-Bus
|
||||||
service file into your user directory. Also make sure no other service is
|
service file into your user directory. Also make sure no other service is
|
||||||
running while executing `dfmd`.
|
running while executing `dfmd`.
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ cp /usr/share/dbus-1/services/sh.natty.FileManager1.service "$XDG_DATA_HOME/dbus
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- DBus
|
- D-Bus
|
||||||
- xdg-open as the default handler
|
- xdg-open as the default handler
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
@ -42,20 +42,20 @@ cargo build --release
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Use the DFMD_*_PROGRAM environment variables. `%ARGS%` is substituted with a
|
Use the DFMD_*_PROGRAM environment variables. Filenames are provided via stdin,
|
||||||
list of input files.
|
one per line.
|
||||||
|
|
||||||
### Default handler programs
|
### Default handler programs
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
DFMD_FOLDER_PROGRAM="echo %ARGS% | xargs -n1 xdg-open"
|
DFMD_FOLDER_PROGRAM="xargs -r -n1 xdg-open"
|
||||||
DFMD_ITEMS_PROGRAM="echo %ARGS% | xargs -d ' ' -r -n1 dirname | xargs -n1 xdg-open"
|
DFMD_ITEMS_PROGRAM="xargs -r -n1 dirname | xargs -n1 xdg-open"
|
||||||
DFMD_PROPERTIES_PROGRAM="echo %ARGS% | xargs -n1 xdg-open"
|
DFMD_PROPERTIES_PROGRAM="xargs -r -n1 xdg-open"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Autostart
|
## Autostart
|
||||||
|
|
||||||
Create a DBus service in
|
Create a D-Bus service in
|
||||||
`$XDG_DATA_HOME/dbus-1/services/org.freedesktop.FileManager1.service`.
|
`$XDG_DATA_HOME/dbus-1/services/org.freedesktop.FileManager1.service`.
|
||||||
|
|
||||||
(The default directory for `XDG_DATA_HOME` is `$HOME/.local/share/`)
|
(The default directory for `XDG_DATA_HOME` is `$HOME/.local/share/`)
|
||||||
|
@ -76,5 +76,5 @@ can be overridden using `env`:
|
||||||
```
|
```
|
||||||
[D-BUS Service]
|
[D-BUS Service]
|
||||||
Name=org.freedesktop.FileManager1
|
Name=org.freedesktop.FileManager1
|
||||||
Exec=env DFMD_ITEMS_PROGRAM="echo %ARGS% | xargs -d ' ' -r -n1 dirname | xargs -n1 notify-send 'File opened'" /usr/bin/dfmd
|
Exec=env DFMD_ITEMS_PROGRAM="xargs -r -n1 dirname | xargs -n1 notify-send 'File opened'" /usr/bin/dfmd
|
||||||
```
|
```
|
||||||
|
|
85
src/main.rs
85
src/main.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::{env, future::pending};
|
use std::{env, future::pending, process::Stdio};
|
||||||
|
|
||||||
use tokio::process;
|
use tokio::{io::AsyncWriteExt, process};
|
||||||
use tracing::{error, Level};
|
use tracing::{error, Level};
|
||||||
use zbus::ConnectionBuilder;
|
use zbus::ConnectionBuilder;
|
||||||
use zbus_macros::dbus_interface;
|
use zbus_macros::dbus_interface;
|
||||||
|
@ -14,47 +14,78 @@ struct FileManager {
|
||||||
#[dbus_interface(name = "org.freedesktop.FileManager1")]
|
#[dbus_interface(name = "org.freedesktop.FileManager1")]
|
||||||
impl FileManager {
|
impl FileManager {
|
||||||
async fn show_folders(&self, ref uris: Vec<String>, _startup_id: &str) {
|
async fn show_folders(&self, ref uris: Vec<String>, _startup_id: &str) {
|
||||||
process::Command::new("sh")
|
let Ok(mut proc) = process::Command::new("sh")
|
||||||
.args([
|
.args(["-c", &self.show_folder_program])
|
||||||
"-c",
|
.stdin(Stdio::piped())
|
||||||
&self.show_folder_program.replace("%ARGS%", &uris.join(" ")),
|
|
||||||
])
|
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Failed to run file manager: {}", e);
|
error!("Failed to run file manager: {}", e);
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.ok();
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = uris.join("\n");
|
||||||
|
let Some(mut stdin) = proc.stdin.take() else {
|
||||||
|
error!("No process stdin!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = stdin.write_all(data.as_bytes()).await {
|
||||||
|
error!("Write error: {}", e)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn show_items(&self, uris: Vec<String>, _startup_id: &str) {
|
async fn show_items(&self, uris: Vec<String>, _startup_id: &str) {
|
||||||
process::Command::new("sh")
|
let Ok(mut proc) = process::Command::new("sh")
|
||||||
.args([
|
.args(["-c", &self.show_items_program])
|
||||||
"-c",
|
.stdin(Stdio::piped())
|
||||||
&self.show_items_program.replace("%ARGS%", &uris.join(" ")),
|
|
||||||
])
|
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Failed to run file manager: {}", e);
|
error!("Failed to run file manager: {}", e);
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.ok();
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = uris.join("\n");
|
||||||
|
let Some(mut stdin) = proc.stdin.take() else {
|
||||||
|
error!("No process stdin!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = stdin.write_all(data.as_bytes()).await {
|
||||||
|
error!("Write error: {}", e)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn show_item_properties(&self, ref uris: Vec<String>, _startup_id: &str) {
|
async fn show_item_properties(&self, ref uris: Vec<String>, _startup_id: &str) {
|
||||||
process::Command::new("sh")
|
let Ok(mut proc) = process::Command::new("sh")
|
||||||
.args([
|
.args(["-c", &self.show_properties_program])
|
||||||
"-c",
|
.stdin(Stdio::piped())
|
||||||
&self
|
|
||||||
.show_properties_program
|
|
||||||
.replace("%ARGS%", &uris.join(" ")),
|
|
||||||
])
|
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Failed to run file manager: {}", e);
|
error!("Failed to run file manager: {}", e);
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.ok();
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = uris.join("\n");
|
||||||
|
let Some(mut stdin) = proc.stdin.take() else {
|
||||||
|
error!("No process stdin!");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = stdin.write_all(data.as_bytes()).await {
|
||||||
|
error!("Write error: {}", e)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,15 +95,15 @@ async fn main() -> eyre::Result<()> {
|
||||||
|
|
||||||
let show_folder_program = env::var("DFMD_FOLDER_PROGRAM")
|
let show_folder_program = env::var("DFMD_FOLDER_PROGRAM")
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap_or_else(|| r#"echo %ARGS% | xargs -n1 xdg-open"#.to_string());
|
.unwrap_or_else(|| r#"xargs -r -n1 xdg-open"#.to_string());
|
||||||
|
|
||||||
let show_items_program = env::var("DFMD_ITEMS_PROGRAM").ok().unwrap_or_else(|| {
|
let show_items_program = env::var("DFMD_ITEMS_PROGRAM")
|
||||||
r#"echo %ARGS% | xargs -d ' ' -r -n1 dirname | xargs -n1 xdg-open"#.to_string()
|
.ok()
|
||||||
});
|
.unwrap_or_else(|| r#"xargs -r -n1 dirname | xargs -n1 xdg-open"#.to_string());
|
||||||
|
|
||||||
let show_properties_program = env::var("DFMD_PROPERTIES_PROGRAM")
|
let show_properties_program = env::var("DFMD_PROPERTIES_PROGRAM")
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap_or_else(|| r#"echo %ARGS% | xargs -n1 xdg-open"#.to_string());
|
.unwrap_or_else(|| r#"xargs -r -n1 xdg-open"#.to_string());
|
||||||
|
|
||||||
let _conn = ConnectionBuilder::session()?
|
let _conn = ConnectionBuilder::session()?
|
||||||
.name("org.freedesktop.FileManager1")?
|
.name("org.freedesktop.FileManager1")?
|
||||||
|
|
Loading…
Reference in New Issue