Remove ui crate
Merge ui crate with root crate. In preparation for uploading `meli` as a separate crate on crates.io. Workspace crates will need to be published as well and having a separate `ui` crate and binary perhaps doesn't make sense anymore.memfd
parent
6fcc792b83
commit
8b6ea8de9a
|
@ -236,15 +236,6 @@ dependencies = [
|
|||
"libdbus-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debug_printer"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"melib 0.4.1",
|
||||
"ui 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "1.0.5"
|
||||
|
@ -743,13 +734,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "meli"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linkify 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"melib 0.4.1",
|
||||
"nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify-rust 3.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rmp 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rmp-serde 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rmpv 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ui 0.4.1",
|
||||
"smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"text_processing 0.4.1",
|
||||
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xdg-utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1839,37 +1850,6 @@ name = "try-lock"
|
|||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ui"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linkify 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"melib 0.4.1",
|
||||
"nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify-rust 3.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rmp 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rmp-serde 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rmpv 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"text_processing 0.4.1",
|
||||
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xdg-utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
|
|
35
Cargo.toml
35
Cargo.toml
|
@ -14,21 +14,44 @@ crossbeam = "0.7.2"
|
|||
signal-hook = "0.1.12"
|
||||
signal-hook-registry = "1.2.0"
|
||||
nix = "0.16.1"
|
||||
melib = { path = "melib", version = "*" }
|
||||
ui = { path = "ui", version = "*" }
|
||||
melib = { path = "melib", version = "0.4.1" }
|
||||
|
||||
serde = "1.0.71"
|
||||
serde_derive = "1.0.71"
|
||||
serde_json = "1.0"
|
||||
toml = "0.5.3"
|
||||
fnv = "1.0.3" # >:c
|
||||
linkify = "0.3.1" # >:c
|
||||
xdg-utils = "0.3.0"
|
||||
nom = "3.2.0"
|
||||
notify = "4.0.1" # >:c
|
||||
notify-rust = "^3" # >:c
|
||||
termion = "1.5.1"
|
||||
bincode = "1.2.0"
|
||||
uuid = { version = "0.7.4", features = ["serde", "v4"] }
|
||||
unicode-segmentation = "1.2.1" # >:c
|
||||
text_processing = { path = "text_processing", version = "0.4.1" }
|
||||
libc = {version = "0.2.59", features = ["extra_traits",]}
|
||||
rusqlite = {version = "0.20.0", optional =true }
|
||||
rmp = "^0.8"
|
||||
rmpv = { version = "^0.4.2", features=["with-serde",] }
|
||||
rmp-serde = "^0.14.0"
|
||||
smallvec = { version = "1.1.0", features = ["serde", ] }
|
||||
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
debug = false
|
||||
|
||||
[workspace]
|
||||
members = ["melib", "ui", "debug_printer", "testing", "text_processing"]
|
||||
members = ["melib", "testing", "text_processing"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
notmuch = ["melib/notmuch_backend", "ui/notmuch"]
|
||||
default = ["sqlite3"]
|
||||
notmuch = ["melib/notmuch_backend", ]
|
||||
jmap = ["melib/jmap_backend",]
|
||||
sqlite3 = ["rusqlite"]
|
||||
|
||||
# Print tracing logs as meli runs in stderr
|
||||
# enable for debug tracing logs: build with --features=debug-tracing
|
||||
debug-tracing = ["melib/debug-tracing", "ui/debug-tracing"]
|
||||
debug-tracing = ["melib/debug-tracing", ]
|
||||
|
|
11
Makefile
11
Makefile
|
@ -46,17 +46,18 @@ GREEN ?= `[ -z $${NO_COLOR+x} ] && tput setaf 2 || echo ""`
|
|||
help:
|
||||
@echo "For a quick start, build and install locally:\n ${BOLD}${GREEN}PREFIX=~/.local make install${ANSI_RESET}\n"
|
||||
@echo "Available subcommands:"
|
||||
@echo " - ${BOLD}install${ANSI_RESET} (installs binary and documentation)"
|
||||
@echo " - ${BOLD}meli${ANSI_RESET} (builds meli with optimizations in \$$CARGO_TARGET_DIR)"
|
||||
@echo " - ${BOLD}install${ANSI_RESET} (installs binary in \$$BINDIR and documentation to \$$MANDIR)"
|
||||
@echo " - ${BOLD}uninstall${ANSI_RESET}"
|
||||
@echo "Secondary subcommands:"
|
||||
@echo " - ${BOLD}clean${ANSI_RESET} (cleans build artifacts)"
|
||||
@echo " - ${BOLD}check-deps${ANSI_RESET} (checks dependencies)"
|
||||
@echo " - ${BOLD}install-bin${ANSI_RESET} (installs binary to BINDIR)"
|
||||
@echo " - ${BOLD}install-doc${ANSI_RESET} (installs manpages to MANDIR)"
|
||||
@echo " - ${BOLD}install-bin${ANSI_RESET} (installs binary to \$$BINDIR)"
|
||||
@echo " - ${BOLD}install-doc${ANSI_RESET} (installs manpages to \$$MANDIR)"
|
||||
@echo " - ${BOLD}help${ANSI_RESET} (prints this information)"
|
||||
|
||||
@echo " - ${BOLD}dist${ANSI_RESET} (creates release tarball named meli-"${VERSION}".tar.gz)"
|
||||
@echo " - ${BOLD}deb-dist${ANSI_RESET} (builds debian package)"
|
||||
@echo " - ${BOLD}dist${ANSI_RESET} (creates release tarball named meli-"${VERSION}".tar.gz in this directory)"
|
||||
@echo " - ${BOLD}deb-dist${ANSI_RESET} (builds debian package in the parent directory)"
|
||||
@echo " - ${BOLD}distclean${ANSI_RESET} (cleans distribution build artifacts)"
|
||||
@echo "\nENVIRONMENT variables of interest:"
|
||||
@echo "* PREFIX = ${UNDERLINE}${PREFIX}${ANSI_RESET}"
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
[package]
|
||||
name = "debug_printer"
|
||||
version = "0.0.1" #:version
|
||||
authors = ["Manos Pitsidianakis <el13635@mail.ntua.gr>"]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "debugprinter"
|
||||
crate-type = ["dylib"]
|
||||
path = "src/lib.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
libc = {version = "0.2.55", features = ["extra_traits",] }
|
||||
melib = { path = "../melib", version = "*" }
|
||||
ui = { path = "../ui", version = "*" }
|
|
@ -1,44 +0,0 @@
|
|||
extern crate libc;
|
||||
extern crate melib;
|
||||
|
||||
use melib::Envelope;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn print_envelope(ptr: *const Envelope) -> *const c_char {
|
||||
unsafe {
|
||||
assert!(!ptr.is_null(), "Null pointer in print_envelope");
|
||||
//println!("got addr {}", p as u64);
|
||||
//unsafe { CString::new("blah".to_string()).unwrap().as_ptr() }
|
||||
let s = CString::new(format!("{:?}", *ptr)).unwrap();
|
||||
drop(ptr);
|
||||
let p = s.as_ptr();
|
||||
std::mem::forget(s);
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get_empty_envelope() -> *mut Envelope {
|
||||
let mut ret = Envelope::default();
|
||||
let ptr = std::ptr::NonNull::new(&mut ret as *mut Envelope)
|
||||
.expect("Envelope::default() has a NULL pointer?");
|
||||
|
||||
let ptr = ptr.as_ptr();
|
||||
std::mem::forget(ret);
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn destroy_cstring(ptr: *mut c_char) {
|
||||
unsafe {
|
||||
let slice = CString::from_raw(ptr);
|
||||
drop(slice);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn envelope_size() -> libc::size_t {
|
||||
std::mem::size_of::<Envelope>()
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2019 Manos Pitsidianakis
|
||||
*
|
||||
|
|
83
src/bin.rs
83
src/bin.rs
|
@ -21,24 +21,74 @@
|
|||
|
||||
//!
|
||||
//! This crate contains the frontend stuff of the application. The application entry way on
|
||||
//! `src/bin.rs` creates an event loop and passes input to the `ui` module.
|
||||
//! `src/bin.rs` creates an event loop and passes input to a thread.
|
||||
//!
|
||||
//! The mail handling stuff is done in the `melib` crate which includes all backend needs. The
|
||||
//! split is done to theoretically be able to create different frontends with the same innards.
|
||||
//!
|
||||
|
||||
use std::alloc::System;
|
||||
use std::collections::VecDeque;
|
||||
use std::path::{Path, PathBuf};
|
||||
extern crate notify_rust;
|
||||
extern crate text_processing;
|
||||
use text_processing::*;
|
||||
extern crate xdg_utils;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate linkify;
|
||||
extern crate uuid;
|
||||
|
||||
extern crate fnv;
|
||||
extern crate termion;
|
||||
|
||||
#[macro_use]
|
||||
extern crate nom;
|
||||
|
||||
extern crate serde_json;
|
||||
extern crate smallvec;
|
||||
|
||||
#[global_allocator]
|
||||
static GLOBAL: System = System;
|
||||
|
||||
// Re export to put crates in the documentation's start page.
|
||||
pub use melib;
|
||||
pub use ui;
|
||||
|
||||
#[macro_use]
|
||||
extern crate melib;
|
||||
use melib::*;
|
||||
use ui::*;
|
||||
|
||||
mod unix;
|
||||
use unix::*;
|
||||
|
||||
#[macro_use]
|
||||
pub mod types;
|
||||
use crate::types::*;
|
||||
|
||||
#[macro_use]
|
||||
pub mod terminal;
|
||||
use crate::terminal::*;
|
||||
|
||||
#[macro_use]
|
||||
pub mod execute;
|
||||
use crate::execute::*;
|
||||
|
||||
pub mod state;
|
||||
use crate::state::*;
|
||||
|
||||
pub mod components;
|
||||
use crate::components::*;
|
||||
|
||||
#[macro_use]
|
||||
pub mod conf;
|
||||
use crate::conf::*;
|
||||
|
||||
pub mod workers;
|
||||
use crate::workers::*;
|
||||
|
||||
#[cfg(feature = "sqlite3")]
|
||||
pub mod sqlite3;
|
||||
|
||||
pub mod cache;
|
||||
pub mod mailcap;
|
||||
pub mod plugins;
|
||||
|
||||
use nix;
|
||||
use std::os::raw::c_int;
|
||||
|
@ -152,15 +202,12 @@ fn run_app() -> Result<()> {
|
|||
args.version = true;
|
||||
}
|
||||
"--print-loaded-themes" => {
|
||||
let s = ui::conf::FileSettings::new()?;
|
||||
let s = conf::FileSettings::new()?;
|
||||
print!("{}", s.terminal.themes.to_string());
|
||||
return Ok(());
|
||||
}
|
||||
"--print-default-theme" => {
|
||||
print!(
|
||||
"{}",
|
||||
ui::conf::Theme::default().key_to_string("dark", false)
|
||||
);
|
||||
print!("{}", conf::Theme::default().key_to_string("dark", false));
|
||||
return Ok(());
|
||||
}
|
||||
e => match prev {
|
||||
|
@ -215,7 +262,7 @@ fn run_app() -> Result<()> {
|
|||
};
|
||||
|
||||
if let Some(config_path) = args.test_config.as_ref() {
|
||||
ui::conf::FileSettings::validate(config_path)?;
|
||||
conf::FileSettings::validate(config_path)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -235,7 +282,7 @@ fn run_app() -> Result<()> {
|
|||
if config_path.exists() {
|
||||
return Err(MeliError::new(format!("File `{}` already exists.\nMaybe you meant to specify another path with --create-config=PATH", config_path.display())));
|
||||
}
|
||||
ui::conf::create_config_file(&config_path)?;
|
||||
conf::create_config_file(&config_path)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -268,19 +315,17 @@ fn run_app() -> Result<()> {
|
|||
let status_bar = Box::new(StatusBar::new(window));
|
||||
state.register_component(status_bar);
|
||||
|
||||
let xdg_notifications = Box::new(ui::components::notifications::XDGNotifications::new());
|
||||
let xdg_notifications = Box::new(components::notifications::XDGNotifications::new());
|
||||
state.register_component(xdg_notifications);
|
||||
state.register_component(Box::new(
|
||||
ui::components::notifications::NotificationFilter {},
|
||||
));
|
||||
state.register_component(Box::new(components::notifications::NotificationFilter {}));
|
||||
|
||||
/* Keep track of the input mode. See ui::UIMode for details */
|
||||
/* Keep track of the input mode. See UIMode for details */
|
||||
'main: loop {
|
||||
state.render();
|
||||
|
||||
'inner: loop {
|
||||
/* Check if any components have sent reply events to State. */
|
||||
let events: ui::smallvec::SmallVec<[UIEvent; 8]> = state.context.replies();
|
||||
let events: smallvec::SmallVec<[UIEvent; 8]> = state.context.replies();
|
||||
for e in events {
|
||||
state.rcv_event(e);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Search queries.
|
||||
*/
|
||||
use melib::parsec::*;
|
||||
use melib::UnixTimestamp;
|
||||
use melib::{
|
||||
|
@ -27,6 +29,7 @@ use melib::{
|
|||
thread::{SortField, SortOrder},
|
||||
Result,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
pub use query_parser::query;
|
||||
|
@ -334,7 +337,6 @@ pub mod query_parser {
|
|||
|
||||
pub fn query_to_imap(q: &Query) -> String {
|
||||
fn rec(q: &Query, s: &mut String) {
|
||||
use crate::sqlite3::escape_double_quote;
|
||||
match q {
|
||||
Subject(t) => {
|
||||
s.push_str(" SUBJECT \"");
|
||||
|
@ -440,3 +442,12 @@ pub fn imap_search(
|
|||
panic!("Could not downcast ImapType backend. BUG");
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn escape_double_quote(w: &str) -> Cow<str> {
|
||||
if w.contains('"') {
|
||||
Cow::from(w.replace('"', "\"\""))
|
||||
} else {
|
||||
Cow::from(w)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -19,10 +19,10 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Components are ways to handle application data. They can draw on the terminal and receive events, but also do other stuff as well. (For example, see the `notifications` module.)
|
||||
|
||||
See the `Component` Trait for more details.
|
||||
/*! Components visual and logical separations of application interfaces.
|
||||
*
|
||||
* They can draw on the terminal and receive events, but also do other stuff as well. (For example, see the `notifications` module.)
|
||||
* See the `Component` Trait for more details.
|
||||
*/
|
||||
|
||||
use super::*;
|
||||
|
@ -32,9 +32,6 @@ pub use crate::mail::*;
|
|||
|
||||
pub mod notifications;
|
||||
|
||||
pub mod indexer;
|
||||
pub use self::indexer::*;
|
||||
|
||||
pub mod utilities;
|
||||
pub use self::utilities::*;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -74,6 +74,7 @@ pub(super) struct EntryStrings {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Creates a comma separated list `String` out of an `Address` iterable.
|
||||
macro_rules! address_list {
|
||||
(($name:expr) as comma_sep_list) => {{
|
||||
let mut ret: String =
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2019 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2020 Manos Pitsidianakis
|
||||
*
|
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Configuration logic and `config.toml` interfaces. */
|
||||
|
||||
extern crate bincode;
|
||||
extern crate serde;
|
||||
extern crate toml;
|
||||
|
@ -637,7 +639,7 @@ pub fn create_config_file(p: &Path) -> Result<()> {
|
|||
.create_new(true)
|
||||
.open(p)
|
||||
.expect("Could not create config file.");
|
||||
file.write_all(include_bytes!("../../sample-config"))
|
||||
file.write_all(include_bytes!("../sample-config"))
|
||||
.expect("Could not write to config file.");
|
||||
println!("Written example configuration to {}", p.display());
|
||||
let metadata = file.metadata()?;
|
||||
|
@ -649,6 +651,7 @@ pub fn create_config_file(p: &Path) -> Result<()> {
|
|||
}
|
||||
|
||||
mod pp {
|
||||
//! Preprocess configuration files by unfolding `include` macros.
|
||||
use melib::{
|
||||
error::{MeliError, Result},
|
||||
parsec::*,
|
||||
|
@ -656,6 +659,7 @@ mod pp {
|
|||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Try to parse line into a path to be included.
|
||||
fn include_directive<'a>() -> impl Parser<'a, Option<&'a str>> {
|
||||
move |input: &'a str| {
|
||||
enum State {
|
||||
|
@ -712,6 +716,7 @@ mod pp {
|
|||
}
|
||||
}
|
||||
|
||||
/// Expands `include` macros in path.
|
||||
fn pp_helper(path: &Path, level: u8) -> Result<String> {
|
||||
if level > 7 {
|
||||
return Err(MeliError::new(format!("Maximum recursion limit reached while unfolding include directives in {}. Have you included a config file within itself?", path.display())));
|
||||
|
@ -752,6 +757,8 @@ mod pp {
|
|||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Expands `include` macros in configuration file and other configuration files (eg. themes)
|
||||
/// in the filesystem.
|
||||
pub fn pp<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
let p_buf: PathBuf = if path.as_ref().is_relative() {
|
||||
path.as_ref().canonicalize()?
|
|
@ -1106,10 +1106,9 @@ impl Account {
|
|||
#[cfg(not(feature = "sqlite3"))]
|
||||
{
|
||||
let mut ret = SmallVec::new();
|
||||
let envelopes = self.collection.envelopes.clone().read();
|
||||
let envelopes = envelopes.unwrap();
|
||||
let envelopes = self.collection.envelopes.read().unwrap();
|
||||
|
||||
for env_hash in self.folders[folder_hash].as_result()?.envelopes {
|
||||
for &env_hash in &self.folders[&folder_hash].as_result()?.envelopes {
|
||||
let envelope = &envelopes[&env_hash];
|
||||
if envelope.subject().contains(&search_term) {
|
||||
ret.push(env_hash);
|
||||
|
@ -1127,7 +1126,7 @@ impl Account {
|
|||
ret.push(env_hash);
|
||||
}
|
||||
}
|
||||
ret
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Configuration for composing email.
|
||||
use super::default_vals::{false_val, none, true_val};
|
||||
|
||||
/// Settings for writing and sending new e-mail
|
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Settings for the pager function.
|
||||
|
||||
use super::default_vals::*;
|
||||
use super::deserializers::*;
|
||||
use melib::ToggleFlag;
|
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! E-mail tag configuration and {de,}serializing.
|
||||
|
||||
use crate::terminal::Color;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::collections::{hash_map::DefaultHasher, HashMap, HashSet};
|
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Settings for terminal display
|
||||
|
||||
use super::deserializers::non_empty_string;
|
||||
use super::Theme;
|
||||
use super::ToggleFlag;
|
|
@ -19,6 +19,15 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Application themes.
|
||||
//!
|
||||
//! * An attribute is a triple of foreground color, background color and terminal attribute `ThemeValue`s.
|
||||
//! * A `ThemeValue<T>` is either an actual value or the key name of another value to which it depends. The value is either `Color` or `Attr`.
|
||||
//! * `ThemeAttributeInner` is an attribute triplet.
|
||||
//! * `ThemeAttribute` is an attribute triplet with the links resolved.
|
||||
//!
|
||||
//! On startup a [DFS](https://en.wikipedia.org/wiki/Depth-first_search) is performed to see if there are any cycles in the link graph.
|
||||
|
||||
use crate::terminal::{Attr, Color};
|
||||
use crate::Context;
|
||||
use melib::{MeliError, Result};
|
||||
|
@ -187,6 +196,7 @@ const DEFAULT_KEYS: &'static [&'static str] = &[
|
|||
"mail.listing.thread_snooze_flag",
|
||||
];
|
||||
|
||||
/// `ThemeAttributeInner` but with the links resolved.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Default, Copy, Serialize, Deserialize)]
|
||||
pub struct ThemeAttribute {
|
||||
pub fg: Color,
|
||||
|
@ -194,6 +204,7 @@ pub struct ThemeAttribute {
|
|||
pub attrs: Attr,
|
||||
}
|
||||
|
||||
/// Holds {fore,back}ground color and terminal attribute values.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct ThemeAttributeInner {
|
||||
#[serde(default)]
|
||||
|
@ -205,6 +216,7 @@ pub struct ThemeAttributeInner {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Holds either an actual value or refers to the key name of the attribute that holds the value.
|
||||
pub enum ThemeValue<T> {
|
||||
Value(T),
|
||||
Link(Cow<'static, str>),
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -19,7 +19,7 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! A parser module for user commands passed through the Ex mode.
|
||||
/*! A parser module for user commands passed through the Execute mode.
|
||||
*/
|
||||
use melib::backends::FolderOperation;
|
||||
pub use melib::thread::{SortField, SortOrder};
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2019 Manos Pitsidianakis
|
||||
*
|
|
@ -18,6 +18,9 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Find mailcap entries to execute attachments.
|
||||
*/
|
||||
use crate::split_command;
|
||||
use crate::state::Context;
|
||||
use crate::types::{create_temp_file, ForkType, UIEvent};
|
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Plugins are executed by meli and communication is done by `messagepack` IPC.
|
||||
*/
|
||||
use melib::error::{MeliError, Result};
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
|
@ -19,9 +19,10 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Use an sqlite3 database for fast searching.
|
||||
*/
|
||||
use smallvec::SmallVec;
|
||||
use crate::cache::query;
|
||||
use crate::cache::Query::{self, *};
|
||||
use crate::cache::{escape_double_quote, query, Query::{self, *}};
|
||||
use crate::melib::parsec::Parser;
|
||||
use melib::{
|
||||
backends::MailBackend,
|
||||
|
@ -31,20 +32,10 @@ use melib::{
|
|||
MeliError, Result, ERROR,
|
||||
};
|
||||
use rusqlite::{params, Connection};
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn escape_double_quote(w: &str) -> Cow<str> {
|
||||
if w.contains('"') {
|
||||
Cow::from(w.replace('"', "\"\""))
|
||||
} else {
|
||||
Cow::from(w)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn db_path() -> Result<PathBuf> {
|
||||
let data_dir =
|
||||
xdg::BaseDirectories::with_prefix("meli").map_err(|e| MeliError::new(e.to_string()))?;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -641,6 +641,7 @@ impl State {
|
|||
}
|
||||
}
|
||||
AccountAction(ref account_name, ReIndex) => {
|
||||
#[cfg(feature = "sqlite3")]
|
||||
match crate::sqlite3::index(&mut self.context, account_name) {
|
||||
Ok(()) => {
|
||||
self.context.replies.push_back(UIEvent::Notification(
|
||||
|
@ -657,6 +658,15 @@ impl State {
|
|||
));
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "sqlite3"))]
|
||||
{
|
||||
self.context.replies.push_back(UIEvent::Notification(
|
||||
None,
|
||||
"Message index rebuild failed: meli is not built with sqlite3 support."
|
||||
.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
}
|
||||
}
|
||||
v => {
|
||||
self.rcv_event(UIEvent::Action(v));
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -18,6 +18,9 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Terminal grid cells, keys, colors, etc.
|
||||
*/
|
||||
extern crate serde;
|
||||
use self::serde::de::Visitor;
|
||||
use self::serde::{de, Deserialize, Deserializer};
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -36,6 +36,9 @@ use termion::color::{AnsiValue, Rgb as TermionRgb};
|
|||
|
||||
/// In a scroll region up and down cursor movements shift the region vertically. The new lines are
|
||||
/// empty.
|
||||
///
|
||||
/// See `CellBuffer::scroll_up` and `CellBuffer::scroll_down` for an explanation of how `xterm`
|
||||
/// scrolling works.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct ScrollRegion {
|
||||
pub top: usize,
|
||||
|
@ -56,7 +59,9 @@ pub struct CellBuffer {
|
|||
cols: usize,
|
||||
rows: usize,
|
||||
buf: Vec<Cell>,
|
||||
/// ASCII-only flag.
|
||||
pub ascii_drawing: bool,
|
||||
/// If printing to this buffer and we run out of space, expand it.
|
||||
growable: bool,
|
||||
}
|
||||
|
||||
|
@ -170,7 +175,7 @@ impl CellBuffer {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
/// ```no_run
|
||||
///
|
||||
/// let mut term = Terminal::new().unwrap();
|
||||
///
|
||||
|
@ -188,7 +193,7 @@ impl CellBuffer {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
/// ```no_run
|
||||
///
|
||||
/// let mut term = Terminal::new().unwrap();
|
||||
///
|
||||
|
@ -427,6 +432,8 @@ impl fmt::Display for CellBuffer {
|
|||
pub struct Cell {
|
||||
ch: char,
|
||||
|
||||
/// Set a `Cell` as empty when a previous cell spans multiple columns and it would
|
||||
/// "overflow" to this cell.
|
||||
empty: bool,
|
||||
fg: Color,
|
||||
bg: Color,
|
||||
|
@ -440,8 +447,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let cell = Cell::new('x', Color::Default, Color::Green, Attr::Default);
|
||||
/// assert_eq!(cell.ch(), 'x');
|
||||
/// assert_eq!(cell.fg(), Color::Default);
|
||||
|
@ -464,8 +470,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::with_char('x');
|
||||
/// assert_eq!(cell.ch(), 'x');
|
||||
/// assert_eq!(cell.fg(), Color::Default);
|
||||
|
@ -480,8 +485,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::with_style(Color::Default, Color::Red, Attr::Bold);
|
||||
/// assert_eq!(cell.fg(), Color::Default);
|
||||
/// assert_eq!(cell.bg(), Color::Red);
|
||||
|
@ -496,8 +500,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::with_char('x');
|
||||
/// assert_eq!(cell.ch(), 'x');
|
||||
/// ```
|
||||
|
@ -509,8 +512,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::with_char('x');
|
||||
/// assert_eq!(cell.ch(), 'x');
|
||||
///
|
||||
|
@ -528,8 +530,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::with_style(Color::Blue, Color::Default, Attr::Default);
|
||||
/// assert_eq!(cell.fg(), Color::Blue);
|
||||
/// ```
|
||||
|
@ -541,8 +542,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::default();
|
||||
/// assert_eq!(cell.fg(), Color::Default);
|
||||
///
|
||||
|
@ -560,7 +560,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::with_style(Color::Default, Color::Green, Attr::Default);
|
||||
/// assert_eq!(cell.bg(), Color::Green);
|
||||
/// ```
|
||||
|
@ -572,7 +572,7 @@ impl Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::default();
|
||||
/// assert_eq!(cell.bg(), Color::Default);
|
||||
///
|
||||
|
@ -626,8 +626,7 @@ impl Default for Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// let mut cell = Cell::default();
|
||||
/// assert_eq!(cell.ch(), ' ');
|
||||
/// assert_eq!(cell.fg(), Color::Default);
|
||||
|
@ -650,8 +649,7 @@ impl Default for Cell {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// // The default color.
|
||||
/// let default = Color::Default;
|
||||
///
|
||||
|
@ -676,6 +674,7 @@ pub enum Color {
|
|||
White,
|
||||
Byte(u8),
|
||||
Rgb(u8, u8, u8),
|
||||
/// Terminal default.
|
||||
Default,
|
||||
}
|
||||
|
||||
|
@ -1371,8 +1370,7 @@ impl Serialize for Color {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```norun
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Default attribute.
|
||||
/// let def = Attr::Default;
|
||||
///
|
||||
|
@ -1384,6 +1382,7 @@ impl Serialize for Color {
|
|||
/// ```
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Attr {
|
||||
/// Terminal default.
|
||||
Default = 0b000,
|
||||
Bold = 0b001,
|
||||
Underline = 0b100,
|
||||
|
@ -2003,7 +2002,7 @@ pub mod ansi {
|
|||
/// the iterator will simply return `None` when it reaches the end of the row.
|
||||
/// `RowIterator` can be created via the `CellBuffer::row_iter` method and can be returned by
|
||||
/// `BoundsIterator` which iterates each row.
|
||||
/// ```norun
|
||||
/// ```no_run
|
||||
/// for c in grid.row_iter(
|
||||
/// x..(x + 11),
|
||||
/// 0,
|
||||
|
@ -2017,7 +2016,7 @@ pub struct RowIterator {
|
|||
}
|
||||
|
||||
/// `BoundsIterator` iterates each row returning a `RowIterator`.
|
||||
/// ```norun
|
||||
/// ```no_run
|
||||
/// /* Visit each `Cell` in `area`. */
|
||||
/// for c in grid.bounds_iter(area) {
|
||||
/// grid[c].set_ch('w');
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2020 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2020 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -135,6 +135,7 @@ impl PartialEq<Key> for &Key {
|
|||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
/// Keep track of whether we're accepting normal user input or a pasted string.
|
||||
enum InputMode {
|
||||
Normal,
|
||||
Paste,
|
||||
|
@ -142,10 +143,13 @@ enum InputMode {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Main process sends commands to the input thread.
|
||||
pub enum InputCommand {
|
||||
/// Exit thread
|
||||
Kill,
|
||||
/// Send Raw bytes as well
|
||||
/// Send raw bytes as well
|
||||
Raw,
|
||||
/// Ignore raw bytes
|
||||
NoRaw,
|
||||
}
|
||||
|
||||
|
@ -158,6 +162,7 @@ use termion::input::TermReadEventsAndRaw;
|
|||
*
|
||||
* The main loop uses try_wait_on_child() to check if child has exited.
|
||||
*/
|
||||
/// The thread function that listens for user input and forwards it to the main event loop.
|
||||
pub fn get_events(
|
||||
mut closure: impl FnMut(Key),
|
||||
closure_raw: impl FnMut((Key, Vec<u8>)),
|
||||
|
@ -202,6 +207,7 @@ pub fn get_events(
|
|||
}
|
||||
}
|
||||
|
||||
/// Same as `get_events` but also forwards the raw bytes of the input as well
|
||||
pub fn get_events_raw(
|
||||
closure_nonraw: impl FnMut(Key),
|
||||
mut closure: impl FnMut((Key, Vec<u8>)),
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2020 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -18,6 +18,18 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! UI types used throughout meli.
|
||||
*
|
||||
* The `segment_tree` module performs maximum range queries. This is used in getting the maximum
|
||||
* element of a column within a specific range in e-mail lists. That way a very large value that
|
||||
* is not the in the currently displayed page does not cause the column to be rendered bigger
|
||||
* than it has to.
|
||||
*
|
||||
* `UIMode` describes the application's... mode. Same as in the modal editor `vi`.
|
||||
*
|
||||
* `UIEvent` is the type passed around `Component`s when something happens.
|
||||
*/
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
mod helpers;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -19,177 +19,29 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* This library exports the public types and methods of its modules
|
||||
/*! UNIX and POSIX interfaces.
|
||||
*/
|
||||
|
||||
#[macro_use]
|
||||
extern crate melib;
|
||||
extern crate notify_rust;
|
||||
extern crate text_processing;
|
||||
pub extern crate xdg_utils;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate linkify;
|
||||
extern crate uuid;
|
||||
|
||||
extern crate fnv;
|
||||
extern crate termion;
|
||||
|
||||
#[macro_use]
|
||||
extern crate nom;
|
||||
|
||||
extern crate serde_json;
|
||||
pub extern crate smallvec;
|
||||
|
||||
use melib::*;
|
||||
use std::collections::VecDeque;
|
||||
use text_processing::*;
|
||||
|
||||
#[macro_use]
|
||||
mod types;
|
||||
pub use crate::types::*;
|
||||
|
||||
#[macro_use]
|
||||
mod terminal;
|
||||
pub use crate::terminal::*;
|
||||
|
||||
#[macro_use]
|
||||
mod execute;
|
||||
use crate::execute::*;
|
||||
|
||||
pub mod state;
|
||||
pub use crate::state::*;
|
||||
|
||||
pub mod components;
|
||||
pub use crate::components::*;
|
||||
|
||||
#[macro_use]
|
||||
pub mod conf;
|
||||
pub use crate::conf::*;
|
||||
|
||||
pub mod workers;
|
||||
pub use crate::workers::*;
|
||||
|
||||
#[cfg(feature = "sqlite3")]
|
||||
pub mod sqlite3;
|
||||
|
||||
pub mod cache;
|
||||
|
||||
pub mod mailcap;
|
||||
|
||||
pub mod plugins;
|
||||
|
||||
pub use crate::username::*;
|
||||
pub mod username {
|
||||
use libc;
|
||||
use std::ptr::null_mut;
|
||||
/* taken from whoami-0.1.1 */
|
||||
fn getpwuid() -> libc::passwd {
|
||||
let mut pwentp = null_mut();
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let mut buffer = [0u8; 16384]; // from the man page
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
let mut buffer = [0i8; 16384]; // from the man page
|
||||
#[cfg(any(
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
{
|
||||
let mut pwent = libc::passwd {
|
||||
pw_name: null_mut(),
|
||||
pw_passwd: null_mut(),
|
||||
pw_uid: 0,
|
||||
pw_gid: 0,
|
||||
pw_change: 0,
|
||||
pw_class: null_mut(),
|
||||
pw_gecos: null_mut(),
|
||||
pw_dir: null_mut(),
|
||||
pw_shell: null_mut(),
|
||||
pw_expire: 0,
|
||||
};
|
||||
unsafe {
|
||||
libc::getpwuid_r(
|
||||
libc::geteuid(),
|
||||
&mut pwent,
|
||||
&mut buffer[0],
|
||||
16384,
|
||||
&mut pwentp,
|
||||
);
|
||||
}
|
||||
|
||||
pwent
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let mut pwent = libc::passwd {
|
||||
pw_name: null_mut(),
|
||||
pw_passwd: null_mut(),
|
||||
pw_uid: 0,
|
||||
pw_gid: 0,
|
||||
pw_gecos: null_mut(),
|
||||
pw_dir: null_mut(),
|
||||
pw_shell: null_mut(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
libc::getpwuid_r(
|
||||
libc::geteuid(),
|
||||
&mut pwent,
|
||||
&mut buffer[0],
|
||||
16384,
|
||||
&mut pwentp,
|
||||
);
|
||||
}
|
||||
|
||||
pwent
|
||||
}
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn ptr_to_string(name: *mut u8) -> String {
|
||||
let uname = name as *const u8;
|
||||
|
||||
let s;
|
||||
let string;
|
||||
|
||||
unsafe {
|
||||
s = ::std::slice::from_raw_parts(uname, libc::strlen(name));
|
||||
string = String::from_utf8_lossy(s).to_string();
|
||||
}
|
||||
|
||||
string
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
fn ptr_to_string(name: *mut i8) -> String {
|
||||
let uname = name as *mut _ as *mut u8;
|
||||
|
||||
let s;
|
||||
let string;
|
||||
|
||||
unsafe {
|
||||
s = ::std::slice::from_raw_parts(uname, libc::strlen(name));
|
||||
string = String::from_utf8_lossy(s).to_string();
|
||||
}
|
||||
|
||||
string
|
||||
}
|
||||
pub fn username() -> String {
|
||||
let pwent = getpwuid();
|
||||
|
||||
ptr_to_string(pwent.pw_name)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod timer {
|
||||
use super::{MeliError, Result};
|
||||
//! POSIX timers
|
||||
//!
|
||||
//! # Example usage
|
||||
//! ```no_run
|
||||
//! let timer = crate::timer::PosixTimer::new_with_signal(
|
||||
//! std::time::Duration::from_secs(0),
|
||||
//! std::time::Duration::from_secs(1),
|
||||
//! nix::sys::signal::Signal::SIGALRM,
|
||||
//! )
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! // some time passes, we should receive and handle the SIGALRM
|
||||
//! // The timer remains unarmed since the interval given was zero, until we rearm it explicitly.
|
||||
//! self.timer.rearm();
|
||||
//! ```
|
||||
use libc::clockid_t;
|
||||
use libc::sigevent;
|
||||
use libc::{itimerspec, timespec};
|
||||
use melib::{MeliError, Result};
|
||||
use nix::sys::signal::{SigEvent, SigevNotify};
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryInto;
|
||||
|
@ -216,8 +68,11 @@ pub mod timer {
|
|||
#[derive(Debug)]
|
||||
pub struct PosixTimer {
|
||||
timer_id: timer_t,
|
||||
/// Interval for periodic timer.
|
||||
interval: Duration,
|
||||
/// Time until next expiration.
|
||||
value: Duration,
|
||||
/// `si_value` is a byte accessible from the signal handler when it receives signals from this timer.
|
||||
pub si_value: u8,
|
||||
}
|
||||
|
||||
|
@ -230,6 +85,7 @@ pub mod timer {
|
|||
}
|
||||
|
||||
impl PosixTimer {
|
||||
/// Arm without changing interval and value.
|
||||
pub fn rearm(&mut self) {
|
||||
let spec = itimerspec {
|
||||
it_interval: timespec {
|
||||
|
@ -316,6 +172,7 @@ pub mod timer {
|
|||
self.interval = interval;
|
||||
}
|
||||
|
||||
/// Arm by changing interval and value.
|
||||
pub fn arm(&mut self, value: Duration) {
|
||||
let spec = itimerspec {
|
||||
it_interval: timespec {
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
* meli
|
||||
*
|
||||
* Copyright 2017-2020 Manos Pitsidianakis
|
||||
*
|
||||
|
@ -19,6 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Simple blocking job control.
|
||||
*/
|
||||
use crate::types::ThreadEvent;
|
||||
use crossbeam::{
|
||||
channel::{bounded, unbounded, Sender},
|
|
@ -8,9 +8,6 @@ edition = "2018"
|
|||
[[bin]]
|
||||
name = "emailparse"
|
||||
path = "src/email_parse.rs"
|
||||
[[bin]]
|
||||
name = "linebreak"
|
||||
path = "src/linebreak.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "imapconn"
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
extern crate melib;
|
||||
use melib::Result;
|
||||
use melib::*;
|
||||
|
||||
use melib::Result;
|
||||
/// Parses e-mail from files and prints the debug information of the parsed `Envelope`
|
||||
///
|
||||
/// # Example invocation
|
||||
/// ```sh
|
||||
/// ./emailparse /path/to/email [/path/to/email2 /path/to/email3 ..]"
|
||||
/// ```
|
||||
|
||||
fn main() -> Result<()> {
|
||||
if args.len() == 1 {
|
||||
eprintln!("Usage: ./emailparse /path/to/email [/path/to/email2 /path/to/email3 ..]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
for i in std::env::args().skip(1) {
|
||||
println!("i is {}", i);
|
||||
println!("Path is {}", i);
|
||||
let filename = std::path::PathBuf::from(i);
|
||||
|
||||
if filename.is_file() {
|
||||
let buffer = std::fs::read_to_string(&filename).expect(&format!(
|
||||
"Something went wrong reading the file {}",
|
||||
filename.display()
|
||||
));
|
||||
if filename.exists() && filename.is_file() {
|
||||
let buffer = std::fs::read_to_string(&filename)
|
||||
.expect(&format!("Something went wrong reading the file {}", i,));
|
||||
let env = Envelope::from_bytes(&buffer.as_bytes(), None).expect("Couldn't parse email");
|
||||
eprintln!("Env is {:#?}", env);
|
||||
eprintln!("{:?}", env.body_bytes(buffer.as_bytes()));
|
||||
println!("Env is {:#?}", env);
|
||||
println!("{:?}", env.body_bytes(buffer.as_bytes()));
|
||||
} else {
|
||||
println!("it's not a file");
|
||||
println!("{} is not a valid file.", i);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -4,6 +4,15 @@ use melib::backends::ImapType;
|
|||
use melib::AccountSettings;
|
||||
use melib::Result;
|
||||
|
||||
/// Opens an interactive shell on an IMAP server. Suggested use is with rlwrap(1)
|
||||
///
|
||||
/// # Example invocation:
|
||||
/// ```sh
|
||||
/// ./imap_conn server_hostname server_username server_password server_port");
|
||||
/// ```
|
||||
///
|
||||
/// `danger_accept_invalid_certs` is turned on by default, so no certificate validation is performed.
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut args = std::env::args().skip(1).collect::<Vec<String>>();
|
||||
if args.len() != 4 {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use melib;
|
||||
use ui::xdg_utils;
|
||||
|
||||
use melib::email::Draft;
|
||||
use xdg_utils::query_mime_info;
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
[package]
|
||||
name = "ui"
|
||||
version = "0.4.1"
|
||||
authors = ["Manos Pitsidianakis <el13635@mail.ntua.gr>"]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
xdg = "2.1.0" # >:c
|
||||
serde = "1.0.71"
|
||||
serde_derive = "1.0.71"
|
||||
serde_json = "1.0"
|
||||
toml = "0.5.3"
|
||||
crossbeam = "0.7.2"
|
||||
fnv = "1.0.3" # >:c
|
||||
linkify = "0.3.1" # >:c
|
||||
melib = { path = "../melib", version = "*" }
|
||||
xdg-utils = "0.3.0"
|
||||
nom = "3.2.0"
|
||||
notify = "4.0.1" # >:c
|
||||
notify-rust = "^3" # >:c
|
||||
termion = "1.5.1"
|
||||
bincode = "1.2.0"
|
||||
uuid = { version = "0.7.4", features = ["serde", "v4"] }
|
||||
unicode-segmentation = "1.2.1" # >:c
|
||||
text_processing = { path = "../text_processing", version = "*" }
|
||||
libc = {version = "0.2.59", features = ["extra_traits",]}
|
||||
nix = "0.16.1"
|
||||
rusqlite = {version = "0.20.0", optional =true }
|
||||
rmp = "^0.8"
|
||||
rmpv = { version = "^0.4.2", features=["with-serde",] }
|
||||
rmp-serde = "^0.14.0"
|
||||
smallvec = { version = "1.1.0", features = ["serde", ] }
|
||||
|
||||
[features]
|
||||
default = ["sqlite3"]
|
||||
notmuch = []
|
||||
sqlite3 = ["rusqlite"]
|
||||
|
||||
# Print tracing logs as meli runs
|
||||
debug-tracing = []
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* meli - ui crate.
|
||||
*
|
||||
* Copyright 2017-2018 Manos Pitsidianakis
|
||||
*
|
||||
* This file is part of meli.
|
||||
*
|
||||
* meli is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* meli is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*! Entities that handle Mail specific functions.
|
||||
*/
|
||||
use super::*;
|
||||
|
||||
pub mod index;
|
||||
pub use self::index::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MenuEntry {
|
||||
name: String,
|
||||
subentries: Vec<MenuEntry>,
|
||||
index: Index,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Indexer {
|
||||
entries: Vec<MenuEntry>,
|
||||
dirty: bool,
|
||||
cursor: Vec<usize>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for Indexer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// TODO display subject/info
|
||||
write!(f, "index")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Indexer {
|
||||
fn default() -> Self {
|
||||
Indexer {
|
||||
entries: Vec::with_capacity(8),
|
||||
dirty: true,
|
||||
cursor: Vec::with_capacity(8),
|
||||
id: ComponentId::new_v4(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Indexer {
|
||||
fn draw_menu(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
||||
}
|
||||
|
||||
impl Component for Indexer {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if !self.is_dirty() {
|
||||
return;
|
||||
}
|
||||
|
||||
clear_area(grid, area);
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
|
||||
let total_cols = get_x(bottom_right) - get_x(upper_left);
|
||||
let index_entity_width = (30 * total_cols) / 100;
|
||||
let mid = get_x(bottom_right) - index_entity_width;
|
||||
for i in get_y(upper_left)..=get_y(bottom_right) {
|
||||
set_and_join_box(grid, (mid, i), BoxBoundary::Vertical);
|
||||
}
|
||||
|
||||
let left_menu_area = (upper_left, (set_x(bottom_right, mid - 1)));
|
||||
let right_index_area = (set_x(upper_left, mid + 1), bottom_right);
|
||||
|
||||
self.draw_menu(grid, left_menu_area, context);
|
||||
self.entries[self.cursor[0]]
|
||||
.index
|
||||
.draw(grid, right_index_area, context);
|
||||
|
||||
self.dirty = false;
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
|
||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||
if !self.entries[self.cursor[0]]
|
||||
.index
|
||||
.process_event(event, _context)
|
||||
{
|
||||
for i in 0..self.entries.len() {
|
||||
if i == self.cursor[0] {
|
||||
continue;
|
||||
}
|
||||
self.entries[i].index.process_event(event, _context);
|
||||
}
|
||||
}
|
||||
|
||||
match *event {
|
||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||
self.dirty = true;
|
||||
}
|
||||
UIEvent::Resize => {
|
||||
self.dirty = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.dirty
|
||||
}
|
||||
|
||||
fn set_dirty(&mut self, value: bool) {
|
||||
self.dirty = value;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
use super::*;
|
||||
|
||||
pub trait IndexContent: Component {
|
||||
/* Handles the drawing of one entry */
|
||||
fn make_entry(&mut self, idx: usize) -> ();
|
||||
|
||||
/* Handles what happens when the user selects an entry in the index listing */
|
||||
fn enter_entry(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) -> ();
|
||||
|
||||
/* Refreshes content */
|
||||
fn refresh(&mut self, context: &mut Context) -> ();
|
||||
|
||||
fn search(&self, term: &str) -> Option<usize>;
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum IndexState {
|
||||
//Uninitialized,
|
||||
Listing,
|
||||
Unfocused,
|
||||
//Search,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Index {
|
||||
cursor_pos: usize,
|
||||
new_cursor_pos: usize,
|
||||
length: usize,
|
||||
|
||||
/// Cache current view.
|
||||
canvas: CellBuffer,
|
||||
/// If we must redraw on next redraw event
|
||||
dirty: bool,
|
||||
state: IndexState,
|
||||
|
||||
content: Box<dyn IndexContent>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
fn highlight_line(&self, grid: &mut CellBuffer, area: Area, idx: usize) {
|
||||
let fg_color = Color::Default;
|
||||
let bg_color = if self.cursor_pos == idx {
|
||||
Color::Byte(246)
|
||||
/* } else if idx % 2 == 0 {
|
||||
Color::Byte(236)*/
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
change_colors(grid, area, fg_color, bg_color);
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Index {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if !self.dirty {
|
||||
return;
|
||||
}
|
||||
|
||||
match self.state {
|
||||
IndexState::Listing => {
|
||||
/* rehighlight entries, redraw pages */
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
|
||||
let prev_page_no = (self.cursor_pos).wrapping_div(rows);
|
||||
let page_no = (self.new_cursor_pos).wrapping_div(rows);
|
||||
|
||||
let top_idx = page_no * rows;
|
||||
if self.new_cursor_pos >= self.length {
|
||||
self.new_cursor_pos = self.length - 1;
|
||||
}
|
||||
/* If cursor position has changed, remove the highlight from the previous position and
|
||||
* apply it in the new one. */
|
||||
if self.cursor_pos != self.new_cursor_pos && prev_page_no == page_no {
|
||||
let old_cursor_pos = self.cursor_pos;
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
for idx in &[old_cursor_pos, self.new_cursor_pos] {
|
||||
if *idx >= self.length {
|
||||
continue; //bounds check
|
||||
}
|
||||
let new_area = (
|
||||
set_y(upper_left, get_y(upper_left) + (*idx % rows)),
|
||||
set_y(bottom_right, get_y(upper_left) + (*idx % rows)),
|
||||
);
|
||||
self.highlight_line(grid, new_area, *idx);
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
return;
|
||||
} else if self.cursor_pos != self.new_cursor_pos {
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
}
|
||||
|
||||
/* Page_no has changed, so draw new page */
|
||||
copy_area(
|
||||
grid,
|
||||
&self.canvas,
|
||||
area,
|
||||
((0, top_idx), (500 - 1, self.length)),
|
||||
);
|
||||
self.highlight_line(
|
||||
grid,
|
||||
(
|
||||
(
|
||||
get_x(upper_left),
|
||||
get_y(upper_left) + (self.cursor_pos % rows),
|
||||
),
|
||||
(
|
||||
get_x(bottom_right),
|
||||
get_y(upper_left) + (self.cursor_pos % rows),
|
||||
),
|
||||
),
|
||||
self.cursor_pos,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
IndexState::Unfocused => {
|
||||
self.content.draw(grid, area, context);
|
||||
}
|
||||
}
|
||||
|
||||
self.dirty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
if self.content.process_event(event, context) {
|
||||
return true;
|
||||
}
|
||||
match *event {
|
||||
UIEvent::Input(Key::Up) => {
|
||||
if self.cursor_pos > 0 {
|
||||
self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(Key::Down) => {
|
||||
if self.length > 0 && self.new_cursor_pos < self.length - 1 {
|
||||
self.new_cursor_pos += 1;
|
||||
self.set_dirty(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(Key::Char('\n')) if self.state == IndexState::Listing => {
|
||||
self.state = IndexState::Unfocused;
|
||||
self.set_dirty(true);
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(Key::Char('i')) if self.state == IndexState::Unfocused => {
|
||||
self.state = IndexState::Listing;
|
||||
self.set_dirty(true);
|
||||
return true;
|
||||
}
|
||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||
self.set_dirty(true);
|
||||
}
|
||||
UIEvent::Resize => {
|
||||
self.set_dirty(true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.dirty || self.content.is_dirty()
|
||||
}
|
||||
fn set_dirty(&mut self, value: bool) {
|
||||
self.dirty = value;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Index {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.content, f)
|
||||
}
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
"""
|
||||
meli - sample plugin
|
||||
|
||||
Copyright 2019 Manos Pitsidianakis
|
||||
|
||||
This file is part of meli.
|
||||
|
||||
meli is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
meli is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import msgpack
|
||||
import socket
|
||||
import time
|
||||
import struct
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
class IPCError(Exception):
|
||||
pass
|
||||
|
||||
class UnknownMessageClass(IPCError):
|
||||
pass
|
||||
|
||||
class InvalidSerialization(IPCError):
|
||||
pass
|
||||
|
||||
class ConnectionClosed(IPCError):
|
||||
pass
|
||||
|
||||
|
||||
def _read_objects(sock):
|
||||
unpacker = msgpack.Unpacker()
|
||||
ret = []
|
||||
#reader = socket.socket.makefile(sock, 'rb')
|
||||
while True:
|
||||
try:
|
||||
buf = sock.recv(1024**2)
|
||||
if not buf:
|
||||
break
|
||||
unpacker.feed(buf)
|
||||
for o in unpacker:
|
||||
ret.append(o)
|
||||
except:
|
||||
break
|
||||
return ret
|
||||
|
||||
#try:
|
||||
# for unpack in unpacker:
|
||||
# return unpack
|
||||
#except Exception as e:
|
||||
# print("_read_objects error ", e, file=sys.stderr,)
|
||||
# return None
|
||||
#finally:
|
||||
# reader.flush()
|
||||
|
||||
def _write_objects(sock, objects):
|
||||
data = msgpack.packb(objects)
|
||||
sock.sendall(data)
|
||||
|
||||
def _recursive_subclasses(cls):
|
||||
classmap = {}
|
||||
for subcls in cls.__subclasses__():
|
||||
classmap[subcls.__name__] = subcls
|
||||
classmap.update(_recursive_subclasses(subcls))
|
||||
return classmap
|
||||
|
||||
|
||||
class Client(object):
|
||||
def __init__(self, server_address):
|
||||
self.addr = server_address
|
||||
if isinstance(self.addr, str):
|
||||
address_family = socket.AF_UNIX
|
||||
else:
|
||||
address_family = socket.AF_INET
|
||||
self.sock = socket.socket(address_family, socket.SOCK_STREAM)
|
||||
self.sock.setblocking(0)
|
||||
|
||||
def connect(self):
|
||||
try:
|
||||
self.sock.connect(self.addr)
|
||||
print("connected", file=sys.stderr)
|
||||
except socket.error as msg:
|
||||
print(msg,file=sys.stderr, )
|
||||
sys.exit(1)
|
||||
|
||||
def close(self):
|
||||
self.sock.close()
|
||||
|
||||
def __enter__(self):
|
||||
self.connect()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.close()
|
||||
|
||||
def send(self, objects):
|
||||
_write_objects(self.sock, objects)
|
||||
print("wrote object ", objects, file=sys.stderr)
|
||||
return self.read()
|
||||
|
||||
def read(self):
|
||||
return _read_objects(self.sock)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
server_address = './soworkfile'
|
||||
client = Client(server_address)
|
||||
client.connect()
|
||||
client.send({ "version": "dev" })
|
||||
counter = 0
|
||||
try:
|
||||
while True:
|
||||
message = "This is the message. And this is the well {}.".format(counter)
|
||||
counter += 1
|
||||
time.sleep(0.05)
|
||||
print('sending {!r}'.format(message),file=sys.stderr, )
|
||||
print('returned :', client.send(message), file=sys.stderr,)
|
||||
except Exception as msg:
|
||||
print(msg, file=sys.stderr,)
|
||||
|
Loading…
Reference in New Issue