mirror of
https://github.com/chmln/handlr.git
synced 2024-11-14 21:49:27 +01:00
Rely on a more robust entry parser | #9
This commit is contained in:
parent
845aa5f213
commit
fb98e4e2f5
8 changed files with 71 additions and 38 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -1,5 +1,11 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
@ -285,6 +291,16 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "freedesktop_entry_parser"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e71e40cde9e00afcb8c5f4e3339f72dae1fb0b30f299d54b690ceb6ce11f3e3"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-zircon"
|
name = "fuchsia-zircon"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -393,6 +409,7 @@ dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"clap",
|
"clap",
|
||||||
"confy",
|
"confy",
|
||||||
|
"freedesktop_entry_parser",
|
||||||
"itertools",
|
"itertools",
|
||||||
"json",
|
"json",
|
||||||
"mime",
|
"mime",
|
||||||
|
|
|
@ -24,6 +24,7 @@ atty = "0.2.14"
|
||||||
confy = "0.4.0"
|
confy = "0.4.0"
|
||||||
serde = "1.0.111"
|
serde = "1.0.111"
|
||||||
xdg-mime = "0.3.2"
|
xdg-mime = "0.3.2"
|
||||||
|
freedesktop_entry_parser = "0.2.2"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level=3
|
opt-level=3
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use pest::Parser;
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
|
@ -9,8 +8,7 @@ use std::{
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, pest_derive::Parser, Default, PartialEq, Eq)]
|
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||||
#[grammar = "common/ini.pest"]
|
|
||||||
pub struct DesktopEntry {
|
pub struct DesktopEntry {
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
pub(crate) exec: String,
|
pub(crate) exec: String,
|
||||||
|
@ -77,39 +75,32 @@ impl DesktopEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_file(path: &Path) -> Option<DesktopEntry> {
|
fn parse_file(path: &Path) -> Option<DesktopEntry> {
|
||||||
let raw = std::fs::read_to_string(&path).ok()?;
|
let raw = std::fs::read(&path).ok()?;
|
||||||
let file = DesktopEntry::parse(Rule::file, &raw).ok()?.next()?;
|
let parsed = freedesktop_entry_parser::parse_entry(&raw)
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.find(|s| s.title == b"Desktop Entry")?;
|
||||||
|
|
||||||
let mut entry = DesktopEntry::default();
|
let mut entry = DesktopEntry::default();
|
||||||
entry.file_name = path.file_name()?.to_owned();
|
entry.file_name = path.file_name()?.to_owned();
|
||||||
|
|
||||||
let mut section = "";
|
for attr in parsed.attrs {
|
||||||
|
match attr.name {
|
||||||
for line in file.into_inner() {
|
b"Name" if entry.name == "" => {
|
||||||
match line.as_rule() {
|
entry.name = String::from_utf8(attr.value.into()).ok()?;
|
||||||
Rule::section => section = line.into_inner().as_str(),
|
|
||||||
Rule::property if section == "Desktop Entry" => {
|
|
||||||
let mut inner = line.into_inner(); // { name ~ "=" ~ value }
|
|
||||||
|
|
||||||
match inner.next()?.as_str() {
|
|
||||||
"Name" if entry.name == "" => {
|
|
||||||
entry.name = inner.next()?.as_str().into()
|
|
||||||
}
|
|
||||||
"Exec" => entry.exec = inner.next()?.as_str().into(),
|
|
||||||
"MimeType" => {
|
|
||||||
let mut mimes = inner
|
|
||||||
.next()?
|
|
||||||
.as_str()
|
|
||||||
.split(";")
|
|
||||||
.filter_map(|m| Mime::from_str(m).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
mimes.pop();
|
|
||||||
entry.mimes = mimes;
|
|
||||||
}
|
|
||||||
"Terminal" => entry.term = inner.next()?.as_str() == "true",
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
b"Exec" => {
|
||||||
|
entry.exec = String::from_utf8(attr.value.into()).ok()?
|
||||||
|
}
|
||||||
|
b"MimeType" => {
|
||||||
|
let mut mimes = String::from_utf8(attr.value.into())
|
||||||
|
.ok()?
|
||||||
|
.split(";")
|
||||||
|
.filter_map(|m| Mime::from_str(m).ok())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
mimes.pop();
|
||||||
|
entry.mimes = mimes;
|
||||||
|
}
|
||||||
|
b"Terminal" => entry.term = attr.value == b"true",
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,3 +118,14 @@ impl TryFrom<PathBuf> for DesktopEntry {
|
||||||
parse_file(&path).ok_or(Error::BadEntry(path))
|
parse_file(&path).ok_or(Error::BadEntry(path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn complex_exec() {
|
||||||
|
let path = PathBuf::from("tests/cmus.desktop");
|
||||||
|
parse_file(&*path).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -84,8 +84,11 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn from_path() -> Result<()> {
|
fn from_path() -> Result<()> {
|
||||||
assert_eq!(MimeType::try_from(".")?.0.essence_str(), "inode/directory");
|
assert_eq!(MimeType::try_from(".")?.0.essence_str(), "inode/directory");
|
||||||
assert_eq!(MimeType::try_from("./tests/cat")?.0.type_(), "text");
|
assert_eq!(MimeType::try_from("./tests/rust.vim")?.0, "text/plain");
|
||||||
assert_eq!(MimeType::try_from("./tests/rust.vim")?.0.type_(), "text");
|
assert_eq!(
|
||||||
|
MimeType::try_from("./tests/cat")?.0,
|
||||||
|
"application/x-shellscript"
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@ mod handler;
|
||||||
mod mime_types;
|
mod mime_types;
|
||||||
|
|
||||||
pub use self::db::autocomplete as db_autocomplete;
|
pub use self::db::autocomplete as db_autocomplete;
|
||||||
pub use desktop_entry::{DesktopEntry, Mode as ExecMode, Rule as EntryRule};
|
pub use desktop_entry::{DesktopEntry, Mode as ExecMode};
|
||||||
pub use handler::Handler;
|
pub use handler::Handler;
|
||||||
pub use mime_types::{MimeOrExtension, MimeType};
|
pub use mime_types::{MimeOrExtension, MimeType};
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
|
||||||
ParseEntry(#[from] pest::error::Error<crate::common::EntryRule>),
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ParseApps(#[from] pest::error::Error<crate::apps::MimeappsRule>),
|
ParseApps(#[from] pest::error::Error<crate::apps::MimeappsRule>),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
11
tests/cmus.desktop
Normal file
11
tests/cmus.desktop
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Encoding=UTF-8
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Display=true
|
||||||
|
Exec=bash -c "(! pgrep cmus && tilix -e cmus && tilix -a session-add-down -e cava); sleep 0.1 && cmus-remote -q %f"
|
||||||
|
Terminal=false
|
||||||
|
Name=cmus-remote
|
||||||
|
Comment=Music player cmus-remote control
|
||||||
|
NoDisplay=true
|
||||||
|
Icon=cmus
|
|
@ -1,2 +1,3 @@
|
||||||
#!/bin/sh
|
highlight CocRustChainingHint ctermfg=0
|
||||||
bat "$@"
|
hi link rustDerive SpecialComment
|
||||||
|
hi link rustDeriveTrait SpecialComment
|
||||||
|
|
Loading…
Reference in a new issue