imrpove drun

This commit is contained in:
Alexander Mohr 2025-04-08 23:35:57 +02:00
parent ff22c0c9c6
commit 8ebefeffe6
6 changed files with 336 additions and 71 deletions

195
Cargo.lock generated
View file

@ -117,6 +117,17 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.4.0"
@ -138,6 +149,12 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.0"
@ -176,7 +193,7 @@ version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae50b5510d86cf96ac2370e66d8dc960882f3df179d6a5a1e52bd94a1416c0f7"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"cairo-sys-rs",
"glib",
"libc",
@ -199,7 +216,7 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"log",
"polling",
"rustix",
@ -213,7 +230,7 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10929724661d1c43856fd87c7a127ae944ec55579134fb485e4136fb6a46fdcb"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"polling",
"rustix",
"slab",
@ -257,6 +274,22 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags 1.3.2",
"clap_lex 0.2.4",
"indexmap 1.9.3",
"strsim 0.10.0",
"termcolor",
"textwrap",
"yaml-rust",
]
[[package]]
name = "clap"
version = "4.5.35"
@ -275,8 +308,8 @@ checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
"clap_lex 0.7.4",
"strsim 0.11.1",
]
[[package]]
@ -291,6 +324,15 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
@ -462,6 +504,16 @@ dependencies = [
"rustc_version",
]
[[package]]
name = "freedesktop-file-parser"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6059d3997cc694ec3e9a378db855866233ef7edfeafd85afcb2239fd130e6e6b"
dependencies = [
"thiserror 2.0.12",
"xdgkit",
]
[[package]]
name = "futures-channel"
version = "0.3.31"
@ -655,7 +707,7 @@ version = "0.20.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707b819af8059ee5395a2de9f2317d87a53dbad8846a2f089f0bb44703f37686"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"futures-channel",
"futures-core",
"futures-executor",
@ -785,7 +837,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aec4fd3226bb6aa8dda5370142e14a4d15f00bba99bfb355b6ef7bb49d100758"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"gdk4",
"glib",
"glib-sys",
@ -838,6 +890,12 @@ dependencies = [
"system-deps",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.15.2"
@ -850,6 +908,15 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.4.0"
@ -898,6 +965,16 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.9.0"
@ -905,7 +982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.15.2",
]
[[package]]
@ -965,6 +1042,12 @@ version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
@ -1076,7 +1159,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925"
dependencies = [
"bitflags",
"bitflags 2.9.0",
]
[[package]]
@ -1094,6 +1177,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "os_str_bytes"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]]
name = "pango"
version = "0.20.9"
@ -1192,7 +1281,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"hermit-abi 0.4.0",
"pin-project-lite",
"rustix",
"tracing",
@ -1256,6 +1345,16 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-xml"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0452695941410a58c8ce4391707ba9bad26a247173bd9886a05a5e8a8babec75"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "quick-xml"
version = "0.37.4"
@ -1339,7 +1438,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys",
@ -1443,7 +1542,7 @@ version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"bytemuck",
"calloop 0.13.0",
"calloop-wayland-source",
@ -1475,6 +1574,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
@ -1535,6 +1640,21 @@ version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
[[package]]
name = "thiserror"
version = "1.0.69"
@ -1575,6 +1695,12 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "tini"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e004df4c5f0805eb5f55883204a514cfa43a6d924741be29e871753a53d5565a"
[[package]]
name = "tokio"
version = "1.44.2"
@ -1629,7 +1755,7 @@ version = "0.22.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
dependencies = [
"indexmap",
"indexmap 2.9.0",
"serde",
"serde_spanned",
"toml_datetime",
@ -1708,7 +1834,7 @@ version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"rustix",
"wayland-backend",
"wayland-scanner",
@ -1720,7 +1846,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"cursor-icon",
"wayland-backend",
]
@ -1742,7 +1868,7 @@ version = "0.32.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"wayland-backend",
"wayland-client",
"wayland-scanner",
@ -1754,7 +1880,7 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2"
dependencies = [
"bitflags",
"bitflags 2.9.0",
"wayland-backend",
"wayland-client",
"wayland-protocols",
@ -1768,7 +1894,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
dependencies = [
"proc-macro2",
"quick-xml",
"quick-xml 0.37.4",
"quote",
]
@ -1797,6 +1923,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@ -1953,9 +2088,10 @@ version = "0.1.0"
dependencies = [
"anyhow",
"calloop 0.14.2",
"clap",
"clap 4.5.35",
"crossbeam",
"env_logger",
"freedesktop-file-parser",
"gdk4",
"gtk4",
"gtk4-layer-shell",
@ -1982,6 +2118,18 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61"
[[package]]
name = "xdgkit"
version = "3.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeac9c0125f3c131c6a2898d2a9f25c11b7954c3ff644a018cb9e06fa92919b"
dependencies = [
"clap 3.2.25",
"quick-xml 0.21.0",
"serde",
"tini",
]
[[package]]
name = "xkbcommon"
version = "0.7.0"
@ -2008,6 +2156,15 @@ version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "zerocopy"
version = "0.7.35"

View file

@ -27,3 +27,4 @@ smithay-client-toolkit = { version = "0.19.2", features = ["calloop"]}
calloop = "0.14.2"
crossbeam = "0.8.4"
libc = "0.2.171"
freedesktop-file-parser = "0.1.0"

View file

@ -37,7 +37,7 @@ impl FromStr for Mode {
}
#[derive(Parser, Debug, Deserialize, Serialize)]
#[clap(about = "Ravi is a wofi clone written in rust, it aims to be a drop in replacement")]
#[clap(about = "Worf is a wofi clone written in rust, it aims to be a drop in replacement")]
pub struct Args {
/// Forks the menu so you can close the terminal
#[clap(short = 'f', long = "fork")]

View file

@ -1,8 +1,9 @@
use freedesktop_file_parser::DesktopFile;
use gtk4::prelude::*;
use gtk4::{IconLookupFlags, IconTheme, TextDirection};
use home::home_dir;
use ini::configparser::ini::Ini;
use log::{info, warn};
use log::{debug, info, warn};
use regex::Regex;
use std::collections::HashMap;
use std::path::Path;
@ -46,23 +47,25 @@ pub fn default_icon() -> String {
}
fn fetch_icon_from_desktop_file(icon_name: &str) -> Option<String> {
find_desktop_files().into_iter().find_map(|desktop_file| {
desktop_file
.get("Desktop Entry")
.filter(|desktop_entry| {
desktop_entry
.get("Exec")
.and_then(|opt| opt.as_ref())
.is_some_and(|exec| exec.to_lowercase().contains(icon_name))
})
.map(|desktop_entry| {
desktop_entry
.get("Icon")
.and_then(|opt| opt.as_ref())
.map(ToOwned::to_owned)
.unwrap_or_default()
})
})
// find_desktop_files().into_iter().find_map(|desktop_file| {
// desktop_file
// .get("Desktop Entry")
// .filter(|desktop_entry| {
// desktop_entry
// .get("Exec")
// .and_then(|opt| opt.as_ref())
// .is_some_and(|exec| exec.to_lowercase().contains(icon_name))
// })
// .map(|desktop_entry| {
// desktop_entry
// .get("Icon")
// .and_then(|opt| opt.as_ref())
// .map(ToOwned::to_owned)
// .unwrap_or_default()
// })
// })
//todo
None
}
fn fetch_icon_from_theme(icon_name: &str) -> Option<String> {
@ -135,8 +138,11 @@ fn find_file_case_insensitive(folder: &Path, file_name: &Regex) -> Option<Vec<Pa
})
}
pub(crate) fn find_desktop_files() -> Vec<HashMap<String, HashMap<String, Option<String>>>> {
let mut paths = vec![PathBuf::from("/usr/share/applications")];
pub(crate) fn find_desktop_files() -> Vec<DesktopFile> {
let mut paths = vec![
PathBuf::from("/usr/share/applications"),
PathBuf::from("/usr/local/share/applications"),
];
if let Some(home) = home_dir() {
paths.push(home.join(".local/share/applications"));
@ -150,8 +156,10 @@ pub(crate) fn find_desktop_files() -> Vec<HashMap<String, HashMap<String, Option
})
.flat_map(|desktop_files| {
desktop_files.into_iter().filter_map(|desktop_file| {
let mut conf = Ini::new();
conf.load(desktop_file.as_path().to_str().unwrap()).ok()
debug!("loading desktop file {:?}", desktop_file);
fs::read_to_string(desktop_file)
.ok()
.and_then(|content| freedesktop_file_parser::parse(&content).ok())
})
})
.collect();

View file

@ -50,7 +50,7 @@ pub fn show(config: Config, elements: Vec<EntryElement>) -> anyhow::Result<(i32)
);
// No need for application_id unless you want portal support
let app = Application::builder().application_id("ravi").build();
let app = Application::builder().application_id("worf").build();
let (sender, receiver) = channel::bounded(1);
app.connect_activate(move |app| {
@ -185,7 +185,7 @@ fn setup_key_event_handler(
let key_controller = EventControllerKey::new();
key_controller.connect_key_pressed(move |_, key_value, _, _| {
match key_value {
Key::Escape => exit(1),
Key::Escape => exit(1), // todo better way to do this?
Key::Return => {
for s in &inner_box.selected_children() {
// let element : &Option<&EntryElement> = &elements.get(s.index() as usize);

View file

@ -12,14 +12,16 @@ use gtk4::prelude::{
FlowBoxChildExt, GtkWindowExt, ListBoxRowExt, NativeExt, ObjectExt, SurfaceExt, WidgetExt,
};
use gtk4_layer_shell::LayerShell;
use log::{debug, warn};
use merge::Merge;
use std::collections::HashMap;
use std::ops::Deref;
use std::os::unix::process::CommandExt;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::sync::Arc;
use std::thread::sleep;
use std::{fs, time};
use std::{env, fs, time};
mod args;
mod config;
@ -80,43 +82,139 @@ fn main() -> anyhow::Result<()> {
Ok(())
}
fn get_locale_variants() -> Vec<String> {
let locale = env::var("LC_ALL")
.or_else(|_| env::var("LC_MESSAGES"))
.or_else(|_| env::var("LANG"))
.unwrap_or_else(|_| "c".to_string());
let lang = locale.split('.').next().unwrap_or(&locale).to_lowercase();
let mut variants = vec![];
if let Some((lang_part, region)) = lang.split_once('_') {
variants.push(format!("{}_{region}", lang_part)); // en_us
variants.push(lang_part.to_string()); // en
} else {
variants.push(lang.clone()); // e.g. "fr"
}
variants
}
fn extract_desktop_fields(
category: &str,
//keys: Vec<String>,
desktop_map: &HashMap<String, HashMap<String, Option<String>>>,
) -> HashMap<String, String> {
let mut result: HashMap<String, String> = HashMap::new();
let category_map = desktop_map.get(category);
if category_map.is_none() {
debug!("No desktop map for category {category}, map data: {desktop_map:?}");
return result;
}
let keys_needed = ["name", "exec", "icon"];
let locale_variants = get_locale_variants();
for (map_key, map_value) in category_map.unwrap() {
for key in keys_needed {
if result.contains_key(key) || map_value.is_none() {
continue;
}
let (k, v) = locale_variants
.iter()
.find(|locale| {
let localized_key = format!("{}[{}]", key, locale);
key == localized_key
})
.map(|_| (Some(key), map_value))
.unwrap_or_else(|| {
if key == map_key {
(Some(key), map_value)
} else {
(None, &None)
}
});
if let Some(k) = k {
if let Some(v) = v {
result.insert(k.to_owned(), v.clone());
}
}
}
if result.len() == keys_needed.len() {
break;
}
}
result
}
fn drun(mut config: Config) -> anyhow::Result<()> {
let mut entries: Vec<EntryElement> = Vec::new();
for file in &find_desktop_files() {
if let Some(desktop_entry) = file.get("desktop entry") {
let icon = desktop_entry
.get("icon")
.and_then(|x| x.as_ref().map(|x| x.to_owned()));
let Some(exec) = desktop_entry.get("exec").and_then(|x| x.as_ref().cloned()) else {
continue;
};
let n = get_locale_variants()
.iter()
.filter_map(|local| file.entry.name.variants.get(local))
.next()
.map(|name| name.deref().clone())
.or_else(|| Some(&file.entry.name.default));
if let Some((cmd, _)) = exec.split_once(' ') {
if !PathBuf::from(cmd).exists() {
continue;
}
}
debug!("{n:?}")
let name = desktop_entry
.get("name")
.and_then(|x| x.as_ref().map(|x| x.to_owned()));
if let Some(name) = name {
entries.push({
EntryElement {
label: name,
icon_path: icon,
action: Some(exec),
sub_elements: None,
}
})
}
}
// let desktop = Some("desktop entry");
// let locale =
// env::var("LC_ALL")
// .or_else(|_| env::var("LC_MESSAGES"))
// .or_else(|_| env::var("LANG"))
// .unwrap_or_else(|_| "en_US.UTF-8".to_string()).split_once(".").map(|(k,_)| k.to_owned().to_lowercase());
//
//
//
//
// if let Some(desktop_entry) = file.get("desktop entry") {
// let icon = desktop_entry
// .get("icon")
// .and_then(|x| x.as_ref().map(|x| x.to_owned()));
//
//
// let Some(exec) = desktop_entry.get("exec")
//
//
//
// .and_then(|x| x.as_ref()) else {
// warn!("Skipping desktop file {file:#?}");
// continue;
// };
//
// if let Some((cmd, _)) = exec.split_once(' ') {
// if !PathBuf::from(cmd).exists() {
// continue;
// }
// }
//
// let name = desktop_entry
// .get("name")
// .and_then(|x| x.as_ref().map(|x| x.to_owned()));
//
// if let Some(name) = name {
// entries.push({
// EntryElement {
// label: name,
// icon_path: icon,
// action: Some(exec.clone()),
// sub_elements: None,
// }
// })
// }
// }
}
entries.sort_by(|l, r| l.label.cmp(&r.label));
if config.prompt.is_none() {
config.prompt = Some("drun".to_owned());
}
// todo ues a arc instead of cloning the config
let selected_index = gui::show(config.clone(), entries.clone())?;
entries.get(selected_index as usize).map(|e| {
@ -130,6 +228,7 @@ fn drun(mut config: Config) -> anyhow::Result<()> {
fn spawn_fork(cmd: &str) {
// todo fork this for real
// todo probably remove arguments?
// Unix-like systems (Linux, macOS)
let _ = Command::new(cmd)
.stdin(Stdio::null()) // Disconnect stdin