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.
|
||||
# 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]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
|
@ -285,6 +291,16 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
|
@ -393,6 +409,7 @@ dependencies = [
|
|||
"atty",
|
||||
"clap",
|
||||
"confy",
|
||||
"freedesktop_entry_parser",
|
||||
"itertools",
|
||||
"json",
|
||||
"mime",
|
||||
|
|
|
@ -24,6 +24,7 @@ atty = "0.2.14"
|
|||
confy = "0.4.0"
|
||||
serde = "1.0.111"
|
||||
xdg-mime = "0.3.2"
|
||||
freedesktop_entry_parser = "0.2.2"
|
||||
|
||||
[profile.release]
|
||||
opt-level=3
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{Error, Result};
|
||||
use mime::Mime;
|
||||
use pest::Parser;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
ffi::OsString,
|
||||
|
@ -9,8 +8,7 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, pest_derive::Parser, Default, PartialEq, Eq)]
|
||||
#[grammar = "common/ini.pest"]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub struct DesktopEntry {
|
||||
pub(crate) name: String,
|
||||
pub(crate) exec: String,
|
||||
|
@ -77,39 +75,32 @@ impl DesktopEntry {
|
|||
}
|
||||
|
||||
fn parse_file(path: &Path) -> Option<DesktopEntry> {
|
||||
let raw = std::fs::read_to_string(&path).ok()?;
|
||||
let file = DesktopEntry::parse(Rule::file, &raw).ok()?.next()?;
|
||||
let raw = std::fs::read(&path).ok()?;
|
||||
let parsed = freedesktop_entry_parser::parse_entry(&raw)
|
||||
.filter_map(Result::ok)
|
||||
.find(|s| s.title == b"Desktop Entry")?;
|
||||
|
||||
let mut entry = DesktopEntry::default();
|
||||
entry.file_name = path.file_name()?.to_owned();
|
||||
|
||||
let mut section = "";
|
||||
|
||||
for line in file.into_inner() {
|
||||
match line.as_rule() {
|
||||
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",
|
||||
_ => {}
|
||||
}
|
||||
for attr in parsed.attrs {
|
||||
match attr.name {
|
||||
b"Name" if entry.name == "" => {
|
||||
entry.name = String::from_utf8(attr.value.into()).ok()?;
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn from_path() -> Result<()> {
|
||||
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.type_(), "text");
|
||||
assert_eq!(MimeType::try_from("./tests/rust.vim")?.0, "text/plain");
|
||||
assert_eq!(
|
||||
MimeType::try_from("./tests/cat")?.0,
|
||||
"application/x-shellscript"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ mod handler;
|
|||
mod mime_types;
|
||||
|
||||
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 mime_types::{MimeOrExtension, MimeType};
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
ParseEntry(#[from] pest::error::Error<crate::common::EntryRule>),
|
||||
#[error(transparent)]
|
||||
ParseApps(#[from] pest::error::Error<crate::apps::MimeappsRule>),
|
||||
#[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
|
||||
bat "$@"
|
||||
highlight CocRustChainingHint ctermfg=0
|
||||
hi link rustDerive SpecialComment
|
||||
hi link rustDeriveTrait SpecialComment
|
||||
|
|
Loading…
Reference in a new issue