Add some documentation

This commit is contained in:
Michael Zhang 2021-02-14 06:27:13 -06:00
parent 371d6fb356
commit e980c597f1
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
6 changed files with 54 additions and 22 deletions

2
Justfile Normal file
View file

@ -0,0 +1,2 @@
doc:
cargo doc --document-private-items

View file

@ -1,3 +1,7 @@
//! Module for setting up config files and watchers.
//!
//! One of the primary goals of panorama is to be able to always hot-reload configuration files.
use std::fs::File; use std::fs::File;
use std::sync::mpsc::{self, Receiver}; use std::sync::mpsc::{self, Receiver};
use std::time::Duration; use std::time::Duration;
@ -9,14 +13,22 @@ use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use tokio::sync::watch; use tokio::sync::watch;
use xdg::BaseDirectories; use xdg::BaseDirectories;
/// Alias for a MailConfig receiver.
pub type ConfigWatcher = watch::Receiver<Option<MailConfig>>; pub type ConfigWatcher = watch::Receiver<Option<MailConfig>>;
/// Configuration
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
pub struct MailConfig { pub struct MailConfig {
/// Host of the IMAP server (needs to be hostname for TLS)
pub server: String, pub server: String,
/// Port of the IMAP server
pub port: u16, pub port: u16,
/// Username for authenticating to IMAP
pub username: String, pub username: String,
/// Password for authenticating to IMAP
pub password: String, pub password: String,
} }
@ -46,6 +58,10 @@ async fn read_config(path: impl AsRef<Path>) -> Result<MailConfig> {
Ok(config) Ok(config)
} }
/// The inner loop of the watcher, which is responsible for taking events received by the watcher
/// and trying to parse and return the config.
///
/// This exists so all errors are able to be caught in one go.
async fn watcher_loop( async fn watcher_loop(
fs_events: Receiver<DebouncedEvent>, fs_events: Receiver<DebouncedEvent>,
config_tx: watch::Sender<Option<MailConfig>>, config_tx: watch::Sender<Option<MailConfig>>,
@ -67,6 +83,8 @@ async fn watcher_loop(
Ok(()) Ok(())
} }
/// Start the entire config watcher system, and return a [ConfigWatcher][self::ConfigWatcher],
/// which is a cloneable receiver of config update events.
pub fn spawn_config_watcher() -> Result<ConfigWatcher> { pub fn spawn_config_watcher() -> Result<ConfigWatcher> {
let (_watcher, config_rx) = start_watcher()?; let (_watcher, config_rx) = start_watcher()?;
let (config_tx, config_update) = watch::channel(None); let (config_tx, config_update) = watch::channel(None);

20
src/lib.rs Normal file
View file

@ -0,0 +1,20 @@
//! Panorama
//! ===
#![deny(missing_docs)]
#[macro_use]
extern crate anyhow;
#[macro_use]
extern crate crossterm;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde;
pub mod config;
pub mod mail;
pub mod ui;
/// A cloneable type that allows sending an exit-"signal" to stop the application.
pub type ExitSender = tokio::sync::oneshot::Sender<()>;

View file

@ -1,3 +1,5 @@
//! Mail
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Display; use std::fmt::Display;
use std::sync::Arc; use std::sync::Arc;
@ -24,8 +26,12 @@ use tokio_util::codec::{Decoder, LinesCodec, LinesCodecError};
use crate::config::{MailConfig, ConfigWatcher}; use crate::config::{MailConfig, ConfigWatcher};
/// Command sent to the mail thread by something else (i.e. UI)
pub enum MailCommand { pub enum MailCommand {
/// Refresh the list
Refresh, Refresh,
/// Send a raw command
Raw(Command), Raw(Command),
} }

View file

@ -1,16 +1,3 @@
#[macro_use]
extern crate anyhow;
#[macro_use]
extern crate crossterm;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde;
mod config;
mod mail;
mod ui;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
@ -20,10 +7,7 @@ use futures::future::TryFutureExt;
use structopt::StructOpt; use structopt::StructOpt;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use xdg::BaseDirectories; use xdg::BaseDirectories;
use panorama::config::{spawn_config_watcher, MailConfig};
use crate::config::{spawn_config_watcher, MailConfig};
type ExitSender = oneshot::Sender<()>;
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
#[structopt(author, about)] #[structopt(author, about)]
@ -48,7 +32,6 @@ async fn main() -> Result<()> {
let xdg = BaseDirectories::new()?; let xdg = BaseDirectories::new()?;
let config_update = spawn_config_watcher()?; let config_update = spawn_config_watcher()?;
let config = MailConfig::default();
// let config: MailConfig = { // let config: MailConfig = {
// let config_path = opt // let config_path = opt
// .config_path // .config_path
@ -74,10 +57,6 @@ async fn main() -> Result<()> {
Ok(()) Ok(())
} }
fn report_err(err: anyhow::Error) {
error!("error: {:?}", err);
}
fn setup_logger(opt: &Opt) -> Result<()> { fn setup_logger(opt: &Opt) -> Result<()> {
let mut fern = fern::Dispatch::new() let mut fern = fern::Dispatch::new()
.format(|out, message, record| { .format(|out, message, record| {
@ -98,3 +77,7 @@ fn setup_logger(opt: &Opt) -> Result<()> {
fern.apply()?; fern.apply()?;
Ok(()) Ok(())
} }
fn report_err(err: anyhow::Error) {
log::error!("error: {:?}", err);
}

View file

@ -1,3 +1,5 @@
//! UI
mod table; mod table;
use std::io::Write; use std::io::Write;
@ -23,6 +25,7 @@ const FRAME: Duration = Duration::from_millis(20);
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Rect(u16, u16, u16, u16); pub struct Rect(u16, u16, u16, u16);
/// UI entrypoint.
pub async fn run_ui(mut w: impl Write, exit: ExitSender) -> Result<()> { pub async fn run_ui(mut w: impl Write, exit: ExitSender) -> Result<()> {
execute!(w, cursor::Hide, terminal::EnterAlternateScreen)?; execute!(w, cursor::Hide, terminal::EnterAlternateScreen)?;
terminal::enable_raw_mode()?; terminal::enable_raw_mode()?;