From fb98e4e2f558064d8df93e24812bc0a89c5c273f Mon Sep 17 00:00:00 2001 From: Gregory Date: Fri, 19 Jun 2020 20:22:49 -0400 Subject: [PATCH] Rely on a more robust entry parser | #9 --- Cargo.lock | 17 ++++++++++ Cargo.toml | 1 + src/common/desktop_entry.rs | 64 +++++++++++++++++++------------------ src/common/mime_types.rs | 7 ++-- src/common/mod.rs | 2 +- src/error.rs | 2 -- tests/cmus.desktop | 11 +++++++ tests/rust.vim | 5 +-- 8 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 tests/cmus.desktop diff --git a/Cargo.lock b/Cargo.lock index 1a184a2..01bc8ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index c627159..2725956 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/src/common/desktop_entry.rs b/src/common/desktop_entry.rs index 81595b4..16d0fd1 100644 --- a/src/common/desktop_entry.rs +++ b/src/common/desktop_entry.rs @@ -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 { - 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::>(); - 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::>(); + mimes.pop(); + entry.mimes = mimes; + } + b"Terminal" => entry.term = attr.value == b"true", _ => {} } } @@ -127,3 +118,14 @@ impl TryFrom 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(); + } +} diff --git a/src/common/mime_types.rs b/src/common/mime_types.rs index f872576..46c636b 100644 --- a/src/common/mime_types.rs +++ b/src/common/mime_types.rs @@ -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(()) } diff --git a/src/common/mod.rs b/src/common/mod.rs index 896b3f9..18957f8 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -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}; diff --git a/src/error.rs b/src/error.rs index 82f9ecd..0b70e67 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,5 @@ #[derive(Debug, thiserror::Error)] pub enum Error { - #[error(transparent)] - ParseEntry(#[from] pest::error::Error), #[error(transparent)] ParseApps(#[from] pest::error::Error), #[error(transparent)] diff --git a/tests/cmus.desktop b/tests/cmus.desktop new file mode 100644 index 0000000..16a324f --- /dev/null +++ b/tests/cmus.desktop @@ -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 diff --git a/tests/rust.vim b/tests/rust.vim index 16586b7..cd31bbf 100644 --- a/tests/rust.vim +++ b/tests/rust.vim @@ -1,2 +1,3 @@ -#!/bin/sh -bat "$@" +highlight CocRustChainingHint ctermfg=0 +hi link rustDerive SpecialComment +hi link rustDeriveTrait SpecialComment