start maildir work

This commit is contained in:
Michael Zhang 2021-03-20 03:22:28 -05:00
parent f906e5203b
commit 680c9c9ebc
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
7 changed files with 93 additions and 20 deletions

26
Cargo.lock generated
View file

@ -32,9 +32,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.38"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
[[package]]
name = "archery"
@ -1481,9 +1481,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.89"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "538c092e5586f4cdd7dd8078c4a79220e3e168880218124dcbce860f0ea938c6"
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
[[package]]
name = "libgit2-sys"
@ -1860,6 +1860,16 @@ dependencies = [
"webpki-roots",
]
[[package]]
name = "panorama-maildir"
version = "0.1.0"
dependencies = [
"anyhow",
"futures 0.3.13",
"tempfile",
"tokio 1.3.0",
]
[[package]]
name = "panorama-smtp"
version = "0.1.0"
@ -2486,9 +2496,9 @@ dependencies = [
[[package]]
name = "siphasher"
version = "0.3.3"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
[[package]]
name = "sized-chunks"
@ -2939,9 +2949,9 @@ checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "vec-arena"
version = "1.0.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"
checksum = "34b2f665b594b07095e3ac3f718e13c2197143416fae4c5706cffb7b1af8d7f1"
[[package]]
name = "vec_map"

View file

@ -9,10 +9,14 @@ readme = "README.md"
license = "GPL-3.0-or-later"
[workspace]
members = ["imap", "smtp"]
members = [
"imap",
"smtp",
"maildir",
]
[dependencies]
anyhow = "1.0.38"
anyhow = "1.0.39"
async-trait = "0.1.48"
cfg-if = "1.0.0"
chrono = "0.4.19"

11
maildir/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "panorama-maildir"
version = "0.1.0"
authors = ["Michael Zhang <mail@mzhang.io>"]
edition = "2018"
[dependencies]
anyhow = "1.0.39"
futures = "0.3.13"
tempfile = "3.2.0"
tokio = { version = "1.3.0", features = ["full"] }

50
maildir/src/lib.rs Normal file
View file

@ -0,0 +1,50 @@
use std::path::{Path, PathBuf};
use tokio::fs::{File, self};
use anyhow::Result;
use tempfile::NamedTempFile;
pub struct Maildir {
path: PathBuf,
}
impl Maildir {
// TODO: should this double as create (aka create tmp cur new if they don't exist)?
pub async fn open(path: impl AsRef<Path>) -> Result<Self> {
Ok(Maildir {
path: path.as_ref().to_path_buf(),
})
}
/// Stores a new message into the `new` directory
// TODO: maybe have a streaming option?
pub async fn store(&self) -> Result<()> {
let unique_name = "hellosu";
let tmp_file = self.tmp_dir().join(unique_name);
{
let mut file = File::create(&tmp_file).await?;
}
let new_file = self.new_dir().join(unique_name);
fs::rename(tmp_file, new_file).await?;
Ok(())
}
/// Returns the path to the `tmp` subdirectory
#[inline]
pub fn tmp_dir(&self) -> PathBuf {
self.path.join("tmp")
}
/// Returns the path to the `new` subdirectory
#[inline]
pub fn new_dir(&self) -> PathBuf {
self.path.join("new")
}
/// Returns the path to the `cur` subdirectory
#[inline]
pub fn cur_dir(&self) -> PathBuf {
self.path.join("cur")
}
}

View file

@ -10,11 +10,11 @@ pub struct ColonPrompt {
}
impl ColonPrompt {
pub fn init(term: TermType) -> Self {
let s = term.size().unwrap();
term.set_cursor(1, s.height - 1);
term.show_cursor();
ColonPrompt::default()
pub fn init(term: TermType) -> Result<Self> {
let s = term.size()?;
term.set_cursor(1, s.height - 1)?;
term.show_cursor()?;
Ok(ColonPrompt::default())
}
}

View file

@ -41,7 +41,7 @@ impl HandlesInput for BaseInputHandler {
KeyCode::Char('j') => self.1.store(1, Ordering::Relaxed),
KeyCode::Char('k') => self.1.store(-1, Ordering::Relaxed),
KeyCode::Char(':') => {
let colon_prompt = Box::new(ColonPrompt::init(term));
let colon_prompt = Box::new(ColonPrompt::init(term)?);
return Ok(InputResult::Push(colon_prompt));
}
_ => {}

View file

@ -286,16 +286,14 @@ pub async fn run_ui(
// handle states in the state stack
// although this is written in a for loop, every case except one should break
let mut should_pop = false;
for input_state in input_states.iter_mut().rev() {
if let Some(input_state) = input_states.last_mut() {
match input_state.handle_key(&mut term, evt)? {
InputResult::Ok => break,
InputResult::Ok => {},
InputResult::Push(state) => {
input_states.push(state);
break;
}
InputResult::Pop => {
should_pop = true;
break;
}
}
}