Merge pull request #1184 from matthiasbeyer/imag-log/init

imag-log: init
This commit is contained in:
Matthias Beyer 2018-01-04 10:31:00 +01:00 committed by GitHub
commit b60b5c8981
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 334 additions and 0 deletions

View File

@ -15,6 +15,7 @@ members = [
"bin/domain/imag-contact",
"bin/domain/imag-diary",
"bin/domain/imag-habit",
"bin/domain/imag-log",
"bin/domain/imag-mail",
"bin/domain/imag-notes",
"bin/domain/imag-timetrack",

View File

@ -0,0 +1,33 @@
[package]
name = "imag-log"
version = "0.6.0"
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
description = "Part of the imag core distribution: imag-bookmark command"
keywords = ["imag", "PIM", "personal", "information", "management"]
readme = "../../../README.md"
license = "LGPL-2.1"
documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
repository = "https://github.com/matthiasbeyer/imag"
homepage = "http://imag-pim.org"
[badges]
travis-ci = { repository = "matthiasbeyer/imag" }
is-it-maintained-issue-resolution = { repository = "matthiasbeyer/imag" }
is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" }
maintenance = { status = "actively-developed" }
[dependencies]
clap = ">=2.17"
log = "0.3"
version = "2.0.1"
toml = "0.4"
toml-query = "^0.4"
is-match = "0.1"
libimagrt = { version = "0.6.0", path = "../../../lib/core/libimagrt" }
libimagerror = { version = "0.6.0", path = "../../../lib/core/libimagerror" }
libimagdiary = { version = "0.6.0", path = "../../../lib/domain/libimagdiary" }
libimaglog = { version = "0.6.0", path = "../../../lib/domain/libimaglog" }

View File

@ -0,0 +1 @@
../../../doc/src/04020-module-log.md

View File

@ -0,0 +1,193 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#![deny(
non_camel_case_types,
non_snake_case,
path_statements,
trivial_numeric_casts,
unstable_features,
unused_allocation,
unused_import_braces,
unused_imports,
unused_must_use,
unused_mut,
unused_qualifications,
while_true,
)]
extern crate clap;
#[macro_use] extern crate is_match;
#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate toml;
extern crate toml_query;
extern crate libimaglog;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagdiary;
use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagdiary::diary::Diary;
use libimaglog::log::Log;
use libimaglog::error::LogError as LE;
mod ui;
use ui::build_ui;
use toml::Value;
fn main() {
let rt = generate_runtime_setup("imag-log",
&version!()[..],
"Overlay to imag-diary to 'log' single lines of text",
build_ui);
if let Some(scmd) = rt.cli() .subcommand_name() {
match scmd {
"show" => show(&rt),
_ => {
error!("Unknown command");
::std::process::exit(1)
},
}
} else {
let text = get_log_text(&rt);
let diary_name = rt.cli()
.value_of("diaryname")
.map(String::from)
.unwrap_or_else(|| get_diary_name(&rt));
debug!("Writing to '{}': {}", diary_name, text);
let _ = rt
.store()
.new_entry_now(&diary_name)
.map(|mut fle| {
let _ = fle.make_log_entry().map_err_trace_exit_unwrap(1);
*fle.get_content_mut() = text;
})
.map_err_trace_exit_unwrap(1);
info!("Ok");
}
}
fn show(rt: &Runtime) {
use libimagdiary::iter::DiaryEntryIterator;
use libimagdiary::entry::DiaryEntry;
let scmd = rt.cli().subcommand_matches("show").unwrap(); // safed by main()
let iters : Vec<DiaryEntryIterator> = match scmd.values_of("show-name") {
Some(values) => values
.map(|diary_name| Diary::entries(rt.store(), diary_name).map_err_trace_exit_unwrap(1))
.collect(),
None => if scmd.is_present("show-all") {
rt.store()
.diary_names()
.map_err_trace_exit_unwrap(1)
.map(|diary_name| {
let diary_name = diary_name.map_err_trace_exit_unwrap(1);
Diary::entries(rt.store(), &diary_name).map_err_trace_exit_unwrap(1)
})
.collect()
} else {
// showing default logs
vec![Diary::entries(rt.store(), &get_diary_name(rt)).map_err_trace_exit_unwrap(1)]
}
};
for iter in iters {
for element in iter {
let e = element.map_err_trace_exit_unwrap(1);
let id = e.diary_id().map_err_trace_exit_unwrap(1);
println!("{dname: >10} - {y: >4}-{m:0>2}-{d:0>2}T{H:0>2}:{M:0>2} - {text}",
dname = id.diary_name(),
y = id.year(),
m = id.month(),
d = id.day(),
H = id.hour(),
M = id.minute(),
text = e.get_content());
}
}
info!("Ready.");
}
fn get_diary_name(rt: &Runtime) -> String {
use toml_query::read::TomlValueReadExt;
let cfg = rt
.config()
.ok_or(LE::from("Configuration not present, cannot continue"))
.map_err_trace_exit_unwrap(1);
let logs = cfg
.read("log.logs")
.map_err_trace_exit_unwrap(1)
.ok_or(LE::from("Configuration missing: 'log.logs'"))
.map_err_trace_exit_unwrap(1)
.as_array()
.ok_or(LE::from("Configuration 'log.logs' is not an Array"))
.map_err_trace_exit_unwrap(1);
if !logs.iter().all(|e| is_match!(e, &Value::String(_))) {
error!("Configuration 'log.logs' is not an Array<String>!");
::std::process::exit(1);
}
let logs = logs
.into_iter()
.map(Value::as_str)
.map(Option::unwrap)
.collect::<Vec<_>>();
let current_log = cfg
.read("log.default")
.map_err_trace_exit_unwrap(1)
.ok_or(LE::from("Configuration missing: 'log.default'"))
.map_err_trace_exit_unwrap(1)
.as_str()
.ok_or(LE::from("Configuration 'log.default' is not a String"))
.map_err_trace_exit_unwrap(1);
if !logs.contains(&current_log) {
error!("'log.logs' does not contain 'log.default'");
::std::process::exit(1)
} else {
current_log.into()
}
}
fn get_log_text(rt: &Runtime) -> String {
rt.cli()
.values_of("text")
.unwrap() // safe by clap
.fold(String::with_capacity(500), |mut acc, e| {
acc.push_str(" ");
acc.push_str(e);
acc
})
}

View File

@ -0,0 +1,62 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use clap::{Arg, App, SubCommand};
pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
app
.arg(Arg::with_name("diaryname")
.long("to")
.short("t")
.takes_value(true)
.required(false)
.help("Use other than default diary"))
.arg(Arg::with_name("text")
.index(1)
.takes_value(true)
.multiple(true)
.required(false)
.help("Text to log. Multiple will be concatenated")
.value_name("TEXT"))
.subcommand(SubCommand::with_name("show")
.about("View log(s)")
.version("0.1")
.arg(Arg::with_name("show-all")
.long("all")
.short("a")
.takes_value(false)
.required(false)
.conflicts_with("show-name")
.help("Show all logs"))
.arg(Arg::with_name("show-name")
.index(1)
.takes_value(true)
.multiple(true)
.required(false)
.conflicts_with("show-all")
.help("Show logs. Multiple possible (will be sorted by date, still)."))
)
}

View File

@ -0,0 +1,40 @@
## Log {#sec:modules:log}
The "imag-log" module is a lightweight interface to the "imag-diary" command.
It is intended as a tumbeblog-like diary, where one does not care to fire up
an editor and type in a long text, but rather type a few words and forget
about it:
### Usage
Logs can be created via an entry in the configuration file in the section `log`:
```
[log]
logs = ["work", "hobby", "music"]
default = "hobby"
```
The `default` key is required and the name which is used here _must_ appear in
the `logs` array.
In the above configuration snippet, the logs `work`, `hobby` and `music` are
created. The user may now log to one of these logs with:
```
imag log --to <logname> "Some message"
# or
imag log -t <logname> "Some message"
# or, to the default log:
imag log "Some message"
```
Logs can be read by naming the log:
```
imag log show work
```
which prints one log per line (including time it was logged).

View File

@ -316,3 +316,7 @@ Email : {{EMAIL}}
Address : {{ADR}}
"""
[log]
logs = ["default"]
default = "default"