Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and update dependencies #31

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
928 changes: 678 additions & 250 deletions Cargo.lock

Large diffs are not rendered by default.

25 changes: 8 additions & 17 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "mates"
version = "0.3.0"
authors = ["Markus Unterwaditzer <[email protected]>"]
version = "1.0.0"
authors = ["Markus Unterwaditzer <[email protected]>", "Shaleen Jain <[email protected]>"]
license = "MIT"
keywords = ["vdir", "vcard", "contacts", "addressbook"]
readme = "README.md"
Expand All @@ -11,22 +11,13 @@ documentation = "https://github.com/untitaker/mates.rs"
homepage = "https://github.com/untitaker/mates.rs"
repository = "https://github.com/untitaker/mates.rs"

[lib]
name = "mates"
path = "src/mates/lib.rs"

[[bin]]
name = "mates"
test = false
doc = false
edition = "2018"

[dependencies]
uuid = { version = "0.5", features = ["v4"] }
atomicwrites = "0.1"
atomicwrites = "0.3"
email = "0.0"
clap = "2.31"
vobject = "0.2"
cursive = "0.5"

[build-dependencies]
clap = "2.31"
clap = "3.1"
vobject = "0.7"
cursive = "0.17"
anyhow = "1.0"
6 changes: 2 additions & 4 deletions build.rs → build.rs.bak
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
extern crate clap;
extern crate mates;

use std::env;
use std::fs;

use clap::Shell;

#[path = "src/mates/app.rs"]
mod app;

fn main() {
let outdir = match env::var_os("OUT_DIR") {
None => return,
Some(outdir) => outdir,
};
fs::create_dir_all(&outdir).unwrap();

let mut app = app::app();
let mut app = mates::app();
app.gen_completions("mates", Shell::Bash, &outdir);
app.gen_completions("mates", Shell::Fish, &outdir);
app.gen_completions("mates", Shell::Zsh, &outdir);
Expand Down
4 changes: 0 additions & 4 deletions src/bin/mates.rs

This file was deleted.

192 changes: 192 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
use anyhow::Result;
use std::borrow::ToOwned;
use std::env;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::path;

use atomicwrites::{AllowOverwrite, AtomicFile};

use crate::editor;
use crate::utils;
use crate::utils::CustomPathExt;

#[inline]
fn get_pwd() -> path::PathBuf {
env::current_dir().ok().expect("Failed to get CWD")
}

#[inline]
fn get_envvar(key: &str) -> Option<String> {
match env::var(key) {
Ok(x) => Some(x),
Err(env::VarError::NotPresent) => None,
Err(env::VarError::NotUnicode(_)) => panic!("{} is not unicode.", key),
}
}

pub fn index_contact(index_path: &path::Path, contact: &utils::Contact) -> Result<()> {
let mut index_fp = fs::OpenOptions::new()
.append(true)
.write(true)
.open(&index_path)?;

let index_entry = utils::index_item_from_contact(contact)?;
index_fp.write_all(index_entry.as_bytes())?;
Ok(())
}

pub fn build_index(outfile: &path::Path, dir: &path::Path) -> Result<()> {
if !dir.is_dir() {
return Err(anyhow!("MATES_DIR must be a directory."));
};

let af = AtomicFile::new(&outfile, AllowOverwrite);
let mut errors = false;

af.write::<(), io::Error, _>(|outf| {
for entry in fs::read_dir(dir)? {
let entry = match entry {
Ok(x) => x,
Err(e) => {
println!("Error while listing directory: {}", e);
errors = true;
continue;
}
};

let pathbuf = entry.path();

if pathbuf.str_extension().unwrap_or("") != "vcf" || !pathbuf.is_file() {
continue;
};

let contact = match utils::Contact::from_file(&pathbuf) {
Ok(x) => x,
Err(e) => {
println!("Error while reading {}: {}", pathbuf.display(), e);
errors = true;
continue;
}
};

match utils::index_item_from_contact(&contact) {
Ok(index_string) => {
outf.write_all(index_string.as_bytes())?;
}
Err(e) => {
println!("Error while indexing {}: {}", pathbuf.display(), e);
errors = true;
continue;
}
};
}
Ok(())
})?;

if errors {
Err(anyhow!(
"Several errors happened while generating the index."
))
} else {
Ok(())
}
}

pub fn edit_contact(config: &Configuration, query: &str) -> Result<()> {
let results = if get_pwd().join(query).is_file() {
vec![path::PathBuf::from(query)]
} else {
utils::file_query(config, query)?.into_iter().collect()
};

if results.len() < 1 {
return Err(anyhow!("No such contact."));
} else if results.len() > 1 {
return Err(anyhow!("Ambiguous query."));
}

let fpath = &results[0];
editor::cli_main(fpath);

let fcontent = {
let mut fcontent = String::new();
let mut file = fs::File::open(fpath)?;
file.read_to_string(&mut fcontent)?;
fcontent
};

if (&fcontent[..]).trim().len() == 0 {
fs::remove_file(fpath)?;
return Err(anyhow!("Contact emptied, file removed."));
};

Ok(())
}

pub fn mutt_query(config: &Configuration, disable_first_line: bool, query: &str) -> Result<()> {
// For some reason mutt requires an empty line
// We need to ignore errors here, otherwise mutt's UI will glitch
if !disable_first_line {
println!();
}

if let Ok(items) = utils::index_query(config, query) {
for item in items {
if item.email.len() > 0 && item.name.len() > 0 {
println!("{}\t{}", item.email, item.name);
};
}
};
Ok(())
}

pub fn file_query(config: &Configuration, query: &str) -> Result<()> {
for path in utils::file_query(config, query)?.iter() {
println!("{}", path.display());
}
Ok(())
}

pub fn email_query(config: &Configuration, query: &str) -> Result<()> {
for item in utils::index_query(config, query)? {
if item.name.len() > 0 && item.email.len() > 0 {
println!("{} <{}>", item.name, item.email);
};
}
Ok(())
}

pub struct Configuration {
pub index_path: path::PathBuf,
pub vdir_path: path::PathBuf,
pub grep_cmd: String,
}

impl Configuration {
pub fn new() -> Result<Configuration, String> {
Ok(Configuration {
index_path: match get_envvar("MATES_INDEX") {
Some(x) => path::PathBuf::from(&x),
None => match get_envvar("HOME") {
Some(home) => get_pwd().join(&home).join(".mates_index"),
None => return Err("Unable to determine user's home directory.".to_owned()),
},
},
vdir_path: match get_envvar("MATES_DIR") {
Some(x) => path::PathBuf::from(&x),
None => {
return Err(
"MATES_DIR must be set to your vdir path (directory of vcf-files)."
.to_owned(),
)
}
},
grep_cmd: match get_envvar("MATES_GREP") {
Some(x) => x,
None => "grep -i".to_owned(),
},
})
}
}
44 changes: 23 additions & 21 deletions src/mates/editor/mod.rs → src/editor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use std::fs;
use std::io::{Read,Write};
use std::process;
use std::io::{Read, Write};
use std::path::Path;
use std::process;

use vobject;

use atomicwrites;

use cursive::Cursive;
use crate::cursive::CursiveExt;
use cursive::theme;
use cursive::theme::Color::*;
use cursive::theme::BaseColor::*;
use cursive::theme::Color::*;
use cursive::Cursive;
use cursive::With;

mod widgets;

Expand All @@ -29,33 +31,33 @@ pub fn cli_main<P: AsRef<Path>>(filename: P) {
process::exit(1);
}


let (editor, editor_view) = VcardEditor::new(vobj);

let mut siv = Cursive::new();
let mut siv = Cursive::default();
siv.add_fullscreen_layer(editor_view);

siv.set_theme(theme::Theme {
shadow: false,
borders: Some(theme::BorderStyle::Simple),
colors: theme::Palette {
background: Dark(Black),
shadow: Dark(Black),
view: Dark(Black),
primary: Dark(White),
secondary: Dark(White),
tertiary: Dark(White),
title_primary: Dark(White),
title_secondary: Dark(White),
highlight: Light(White),
highlight_inactive: Dark(Black),
}
borders: theme::BorderStyle::Simple,
palette: theme::Palette::default().with(|p| {
p.set_color("background", Dark(Black));
p.set_color("shadow", Dark(Black));
p.set_color("view", Dark(Black));
p.set_color("primary", Dark(White));
p.set_color("secondary", Dark(White));
p.set_color("tertiary", Dark(White));
p.set_color("title_primary", Dark(White));
p.set_color("title_secondary", Dark(White));
p.set_color("highlight", Light(White));
p.set_color("highlight_inactive", Dark(Black));
}),
});
siv.run();

vobj = editor.to_vobject(&mut siv);
drop(siv); // Necessary to be able to write text immediately afterwards
drop(siv); // Necessary to be able to write text immediately afterwards

let af = atomicwrites::AtomicFile::new(filename, atomicwrites::AllowOverwrite);
af.write(|mut f| f.write_all(vobject::write_component(&vobj).as_bytes())).unwrap();
af.write(|f| f.write_all(vobject::write_component(&vobj).as_bytes()))
.unwrap();
}
Loading