#![warn(missing_docs)]
extern crate rustc_serialize;
pub mod json;
pub mod xml;
pub mod env;
use std::borrow::Cow;
use std::collections::HashMap;
pub use self::xml::XMLWriter;
#[derive(PartialEq,Eq,Clone)]
pub struct Item<'a> {
pub title: Cow<'a, str>,
pub subtitle: Option<Cow<'a, str>>,
pub icon: Option<Icon<'a>>,
pub uid: Option<Cow<'a, str>>,
pub arg: Option<Cow<'a, str>>,
pub type_: ItemType,
pub valid: bool,
pub autocomplete: Option<Cow<'a, str>>,
pub text_copy: Option<Cow<'a, str>>,
pub text_large_type: Option<Cow<'a, str>>,
pub quicklook_url: Option<Cow<'a, str>>,
pub modifiers: HashMap<Modifier, ModifierData<'a>>
}
impl<'a> Item<'a> {
pub fn new<S: Into<Cow<'a, str>>>(title: S) -> Item<'a> {
Item {
title: title.into(),
subtitle: None,
icon: None,
uid: None,
arg: None,
type_: ItemType::Default,
valid: true,
autocomplete: None,
text_copy: None,
text_large_type: None,
quicklook_url: None,
modifiers: HashMap::new()
}
}
}
#[derive(Clone)]
pub struct ItemBuilder<'a> {
item: Item<'a>
}
impl<'a> ItemBuilder<'a> {
pub fn new<S: Into<Cow<'a, str>>>(title: S) -> ItemBuilder<'a> {
ItemBuilder {
item: Item::new(title)
}
}
pub fn into_item(self) -> Item<'a> {
self.item
}
}
impl<'a> ItemBuilder<'a> {
pub fn title<S: Into<Cow<'a, str>>>(mut self, title: S) -> ItemBuilder<'a> {
self.set_title(title);
self
}
pub fn subtitle<S: Into<Cow<'a, str>>>(mut self, subtitle: S) -> ItemBuilder<'a> {
self.set_subtitle(subtitle);
self
}
pub fn subtitle_mod<S: Into<Cow<'a, str>>>(mut self, modifier: Modifier, subtitle: S)
-> ItemBuilder<'a> {
self.set_subtitle_mod(modifier, subtitle);
self
}
pub fn icon_path<S: Into<Cow<'a, str>>>(mut self, path: S) -> ItemBuilder<'a> {
self.set_icon_path(path);
self
}
pub fn icon_file<S: Into<Cow<'a, str>>>(mut self, path: S) -> ItemBuilder<'a> {
self.set_icon_file(path);
self
}
pub fn icon_filetype<S: Into<Cow<'a, str>>>(mut self, filetype: S) -> ItemBuilder<'a> {
self.set_icon_filetype(filetype);
self
}
pub fn uid<S: Into<Cow<'a, str>>>(mut self, uid: S) -> ItemBuilder<'a> {
self.set_uid(uid);
self
}
pub fn arg<S: Into<Cow<'a, str>>>(mut self, arg: S) -> ItemBuilder<'a> {
self.set_arg(arg);
self
}
pub fn arg_mod<S: Into<Cow<'a, str>>>(mut self, modifier: Modifier, arg: S)
-> ItemBuilder<'a> {
self.set_arg_mod(modifier, arg);
self
}
pub fn type_(mut self, type_: ItemType) -> ItemBuilder<'a> {
self.set_type(type_);
self
}
pub fn valid(mut self, valid: bool) -> ItemBuilder<'a> {
self.set_valid(valid);
self
}
pub fn valid_mod(mut self, modifier: Modifier, valid: bool) -> ItemBuilder<'a> {
self.set_valid_mod(modifier, valid);
self
}
pub fn modifier<S: Into<Cow<'a, str>>, S2: Into<Cow<'a, str>>>(mut self,
modifier: Modifier,
subtitle: Option<S>,
arg: Option<S2>,
valid: bool)
-> ItemBuilder<'a> {
self.set_modifier(modifier, subtitle, arg, valid);
self
}
pub fn autocomplete<S: Into<Cow<'a, str>>>(mut self, autocomplete: S) -> ItemBuilder<'a> {
self.set_autocomplete(autocomplete);
self
}
pub fn text_copy<S: Into<Cow<'a, str>>>(mut self, text: S) -> ItemBuilder<'a> {
self.set_text_copy(text);
self
}
pub fn text_large_type<S: Into<Cow<'a, str>>>(mut self, text: S) -> ItemBuilder<'a> {
self.set_text_large_type(text);
self
}
pub fn quicklook_url<S: Into<Cow<'a, str>>>(mut self, url: S) -> ItemBuilder<'a> {
self.set_quicklook_url(url);
self
}
}
impl<'a> ItemBuilder<'a> {
pub fn set_title<S: Into<Cow<'a, str>>>(&mut self, title: S) {
self.item.title = title.into();
}
pub fn set_subtitle<S: Into<Cow<'a, str>>>(&mut self, subtitle: S) {
self.item.subtitle = Some(subtitle.into());
}
pub fn unset_subtitle(&mut self) {
self.item.subtitle = None;
}
pub fn set_subtitle_mod<S: Into<Cow<'a, str>>>(&mut self, modifier: Modifier, subtitle: S) {
self.data_for_modifier(modifier).subtitle = Some(subtitle.into());
}
pub fn unset_subtitle_mod(&mut self, modifier: Modifier) {
use std::collections::hash_map::Entry;
if let Entry::Occupied(mut entry) = self.item.modifiers.entry(modifier) {
entry.get_mut().subtitle = None;
if entry.get().is_empty() {
entry.remove();
}
}
}
pub fn clear_subtitle(&mut self) {
self.item.subtitle = None;
for &modifier in ALL_MODIFIERS {
self.unset_subtitle_mod(modifier);
}
}
pub fn set_icon_path<S: Into<Cow<'a, str>>>(&mut self, path: S) {
self.item.icon = Some(Icon::Path(path.into()));
}
pub fn set_icon_file<S: Into<Cow<'a, str>>>(&mut self, path: S) {
self.item.icon = Some(Icon::File(path.into()));
}
pub fn set_icon_filetype<S: Into<Cow<'a, str>>>(&mut self, filetype: S) {
self.item.icon = Some(Icon::FileType(filetype.into()));
}
pub fn unset_icon(&mut self) {
self.item.icon = None;
}
pub fn set_uid<S: Into<Cow<'a, str>>>(&mut self, uid: S) {
self.item.uid = Some(uid.into());
}
pub fn unset_uid(&mut self) {
self.item.uid = None;
}
pub fn set_arg<S: Into<Cow<'a, str>>>(&mut self, arg: S) {
self.item.arg = Some(arg.into());
}
pub fn unset_arg(&mut self) {
self.item.arg = None;
}
pub fn set_arg_mod<S: Into<Cow<'a, str>>>(&mut self, modifier: Modifier, arg: S) {
self.data_for_modifier(modifier).arg = Some(arg.into());
}
pub fn unset_arg_mod(&mut self, modifier: Modifier) {
use std::collections::hash_map::Entry;
if let Entry::Occupied(mut entry) = self.item.modifiers.entry(modifier) {
entry.get_mut().arg = None;
if entry.get().is_empty() {
entry.remove();
}
}
}
pub fn clear_arg(&mut self) {
self.item.arg = None;
for &modifier in ALL_MODIFIERS {
self.unset_arg_mod(modifier);
}
}
pub fn set_type(&mut self, type_: ItemType) {
self.item.type_ = type_;
}
pub fn set_valid(&mut self, valid: bool) {
self.item.valid = valid;
}
pub fn set_valid_mod(&mut self, modifier: Modifier, valid: bool) {
self.data_for_modifier(modifier).valid = Some(valid);
}
pub fn unset_valid_mod(&mut self, modifier: Modifier) {
use std::collections::hash_map::Entry;
if let Entry::Occupied(mut entry) = self.item.modifiers.entry(modifier) {
entry.get_mut().valid = None;
if entry.get().is_empty() {
entry.remove();
}
}
}
pub fn clear_valid(&mut self) {
self.item.valid = true;
for &modifier in ALL_MODIFIERS {
self.unset_valid_mod(modifier);
}
}
pub fn set_autocomplete<S: Into<Cow<'a, str>>>(&mut self, autocomplete: S) {
self.item.autocomplete = Some(autocomplete.into());
}
pub fn unset_autocomplete(&mut self) {
self.item.autocomplete = None;
}
pub fn set_modifier<S: Into<Cow<'a, str>>, S2: Into<Cow<'a, str>>>(&mut self,
modifier: Modifier,
subtitle: Option<S>,
arg: Option<S2>,
valid: bool) {
let data = ModifierData {
subtitle: subtitle.map(Into::into),
arg: arg.map(Into::into),
valid: Some(valid)
};
self.item.modifiers.insert(modifier, data);
}
pub fn unset_modifier(&mut self, modifier: Modifier) {
self.item.modifiers.remove(&modifier);
}
pub fn set_text_copy<S: Into<Cow<'a, str>>>(&mut self, text: S) {
self.item.text_copy = Some(text.into());
}
pub fn unset_text_copy(&mut self) {
self.item.text_copy = None;
}
pub fn set_text_large_type<S: Into<Cow<'a, str>>>(&mut self, text: S) {
self.item.text_large_type = Some(text.into());
}
pub fn unset_text_large_type(&mut self) {
self.item.text_large_type = None;
}
pub fn set_quicklook_url<S: Into<Cow<'a, str>>>(&mut self, url: S) {
self.item.quicklook_url = Some(url.into());
}
pub fn unset_quicklook_url(&mut self) {
self.item.quicklook_url = None;
}
fn data_for_modifier(&mut self, modifier: Modifier) -> &mut ModifierData<'a> {
self.item.modifiers.entry(modifier).or_insert(Default::default())
}
}
#[derive(Clone,Copy,Debug,Hash,PartialEq,Eq)]
pub enum Modifier {
Command,
Option,
Control,
Shift,
Fn
}
const ALL_MODIFIERS: &'static [Modifier] = &[Modifier::Command, Modifier::Option,
Modifier::Control, Modifier::Shift, Modifier::Fn];
#[derive(Clone,Debug,PartialEq,Eq,Default)]
pub struct ModifierData<'a> {
pub subtitle: Option<Cow<'a, str>>,
pub arg: Option<Cow<'a, str>>,
pub valid: Option<bool>
}
impl<'a> ModifierData<'a> {
fn is_empty(&self) -> bool {
self.subtitle.is_none() && self.arg.is_none() && self.valid.is_none()
}
}
#[derive(PartialEq,Eq,Clone)]
pub enum Icon<'a> {
Path(Cow<'a, str>),
File(Cow<'a, str>),
FileType(Cow<'a, str>)
}
#[derive(PartialEq,Eq,Clone,Copy)]
pub enum ItemType {
Default,
File,
FileSkipCheck
}