From ca46a45c520a2c5fb6b132c5d131dbf45768ef77 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Dec 2019 10:48:07 +0100 Subject: Add release: imag v0.10.0 --- content/blog/2019-12-24-imag-0-10-0.md | 81 + content/doc.md | 4 + content/doc/man/0.10.0/imag.5 | 3361 ++++++++++++++++++++++++++++++++ content/doc/pdf/0.10.0.pdf | Bin 0 -> 254833 bytes content/doc/web/0.10.0/index.html | 1491 ++++++++++++++ 5 files changed, 4937 insertions(+) create mode 100644 content/blog/2019-12-24-imag-0-10-0.md create mode 100644 content/doc/man/0.10.0/imag.5 create mode 100644 content/doc/pdf/0.10.0.pdf create mode 100644 content/doc/web/0.10.0/index.html diff --git a/content/blog/2019-12-24-imag-0-10-0.md b/content/blog/2019-12-24-imag-0-10-0.md new file mode 100644 index 0000000..a7f4bb3 --- /dev/null +++ b/content/blog/2019-12-24-imag-0-10-0.md @@ -0,0 +1,81 @@ +--- +title: "imag 0.10.0" +slug: "imag-0-10-0" +date: "2019-12-24T11:10:09" +tags: [ "linux", "open source", "programming", "rust", "software", "tools", "imag" ] +--- + + + +I know it is christmas, so I'll make this one short: +imag v0.10.0 is released! Yippie! + + +# What's in there + +* 741 commits +* 78 merge-commits / 663 non-merge commits +* 495 files changed +* 21537 insertions(+), 14066 deletions(-) + +Some more statistics about the codebase (thank you, +[tokei](https://github.com/Aaronepower/tokei)), because why not: + +``` +------------------------------------------------------------------------------- + Language Files Lines Code Comments Blanks +------------------------------------------------------------------------------- + BASH 8 181 119 18 44 + CSS 1 27 24 0 3 + Makefile 1 161 97 29 35 + Markdown 67 3290 3290 0 0 + Nix 2 99 67 11 21 + Rust 349 39431 25132 8257 6042 + Shell 12 518 288 152 78 + TOML 69 3617 2671 293 653 +------------------------------------------------------------------------------- + Total 509 47324 31688 8760 6876 +------------------------------------------------------------------------------- +``` + +The highlights: + +* All binary crates propagate errors to their main() function now rather than + calling exit() somewhere in between. +* Clippy linting was enabled for the repository +* UI testing was introduced, though not many binaries are tested yet. +* Annotations (imag-annotate) are now unnamed. +* New CLI tool: imag-header +* libimagentryref was rewritten +* The code for the libimagmail and related crates was rewritten +* libimagnotification was removed +* The "edit" command for imag-contact was added +* imag-ref can list dead references now +* imag-markdown was added to print markdown representation of entries +* imag-create was added for creating entries +* libimagcalendar was added +* imag-calendar was added +* Preparations for compiling imag into a single binary and provide commandline +* libimagtodo was rewritten from scratch and so was imag-todo +* imag-bookmark does no longer contain the concept of "collections" +* imag-bookmark can now call a command to open links + +The full +[changelog](http://git.imag-pim.org/imag/tree/CHANGELOG.md?h=v0.10.0) +is rather long, because a lot of stuff was changed and fixed +(and not even the changelog contains all changes). +Its best to look up the changes there and in the +[git commit history](https://git.imag-pim.org/imag/). + + +## What will be in imag 0.11.0 + +The next version will focus on "imag mail" entirely. Of course there will be +smaller fixes and changes to the other tools as well, but the main focus will be +imag-mail and as soon as I'm satisfied with that, I will release imag version +0.11.0! + + +
+ +And now, have a merry christmas and a happy new year! diff --git a/content/doc.md b/content/doc.md index 0101a08..628418f 100644 --- a/content/doc.md +++ b/content/doc.md @@ -9,6 +9,10 @@ is the latest release for which documentation is published. The source-documentation is hosted with [docs.rs](https://docs.rs/releases/search?query=imag). +* v0.10.0 + * [pdf](/doc/pdf/0.10.0.pdf) + * [html](/doc/web/0.10.0/) + * [man](/doc/man/0.10.0/imag.5) * v0.8.0 * [pdf](/doc/pdf/0.8.0.pdf) * [html](/doc/web/0.8.0/) diff --git a/content/doc/man/0.10.0/imag.5 b/content/doc/man/0.10.0/imag.5 new file mode 100644 index 0000000..d1867cb --- /dev/null +++ b/content/doc/man/0.10.0/imag.5 @@ -0,0 +1,3361 @@ +.\" Automatically generated by Pandoc 2.7.1 +.\" +.TH "imag User Documentation" "5" "May 2018" "" "" +.hy +.SH Introduction +.PP +This document is the user documentation for imag, the personal +information management suite for the commandline. +.PP +\f[B]Basically: This is Hobby stuff. Expect incompleteness, false +statements and generally read with grain of salt.\f[R] +.PP +If you have any objections, suggestions for improvements, bugs, etc, +please file them (See Section\ 8). +A way to reach out to the imag project maintainer(s) is described in the +Section\ 8 section. +.SS The Problem +.PP +The problem this project tries to solve is to provide a modular +commandline application for personal information management. +.PP +It targets \[lq]power users\[rq] or \[lq]commandline users\[rq], uses +plain text as a storage format and tries to be as scriptable as +possible. +imag offers the ability to link data from different \[lq]PIM +aspects\[rq] (such as \[lq]diary\[rq], \[lq]contacts\[rq] and +\[lq]bookmark\[rq] for example). +.PP +One major goal of imag is to make the PIM data traverseable and +queryable. +For example: a wiki article can be linked to an appointment which is +linked to a todo which is linked to a note which is linked to a contact. +.PP +imag wants to offer an all-in-one scriptable modular commandline +personal information management suite for all PIM aspects one could +possibly think of. +Because imag uses plain text (TOML headers for structured data and plain +text which can be rendered using markdown, for example, for continuous +text) the user is always able to access their data without the imag +tools at hand. +.SS The Approach +.PP +The approach \[lq]imag\[rq] takes on solving this problem is to store +content in a \[lq]store\[rq] and persisting content in a unified way. +Meta-information is attached to the content which can be used to store +structured data. +This can be used to implement a variety of \[lq]domain modules\[rq] +using the store. +While content is stored in \f[I]one\f[R] place, imag does not duplicate +content. +imag does not copy or move icalendar files, emails, vcard files, music +or movies to the store, but tries to remember the actual files are and +stores meta-information about them in the store. +.PP +Detailed explanation on this approach follows in the chapters of this +work. +.SS Implementation +.PP +The program is written in the Rust programming language. +.PP +The program consists of libraries which can be re-used by other projects +to implement and adapt imag functionality. +An external program may use a library of the imag distribution to store +content in the store of imag and make it visible to imag this way. +.PP +This is a technical detail a user does not necessarily need to know, but +as imag is intended for power-users anyways, we would say it fits here. +.SS Alternative Projects +.PP +imag is not the only project which tries to solve that particular +problem. +For example there is org mode (https://orgmode.org) for the +emacs (https://www.gnu.org/software/emacs/) text editor. +There is also zim (http://zim-wiki.org/), a desktop wiki editor which is +intended to be used for a personal wiki. +.PP +The difference between imag and the mentioned projects is: * emacs +orgmode is (from what I know and see) for \f[I]orgabizing\f[R] things. +imag is intended not only for organizing, but also for recording, +tracking and querying. +* zim is a wiki, which could be used for PIM but is not specialized for +it. +Recording habits might be possible, but not that simple as with imag +.PP +imag is not there yet, though. +Some parts can be used, though it is far away from being +feature-complete. +.PP +In addition: imag is text-editor independent and other tools than imag +might be used to access data stored in the imag store. +For example, one could \[lq]grep\[rq], \[lq]awk\[rq] and \[lq]sed\[rq] +entries without much hassle and even write bash scripts for +automatically filling imag entries with data. +.SH Architecture of the imag code +.PP +The imag codebase has a rather simple overall architecture. +In this chapter the types of crates, architecture of an imag module and +the type structure are described. +.SS Crate types +.PP +There are different types of crates in the imag world. +A crate is a rust project. +.PP +First of all, there are core crates. +These crates provide the very core of imag and almost all other crates +use them: +.IP \[bu] 2 +libimagstore - The imag store is the abstraction over the filesystem. +It provides primitives to get, write and manipulate store entries and +their header information. +.IP \[bu] 2 +libimagrt - The runtime library, which provides functionality to create +a store object from libimagstore, helps with configurarion loading and +commandline argument handling (through the external \[lq]clap\[rq] +crate). +.IP \[bu] 2 +libimagerror - Error handling library for handling errors the imag way. +Used in all other crates, even the store itself. +It also offers functionality to log and trace errors as well as exiting +the application, if necessary. +.IP \[bu] 2 +libimagutil - Utilities. +.PP +The next type of imag crates are entry extension libraries. +Those provide extensional functionality for the types from libimagstore. +For example, there is \[lq]libimagentrylink\[rq] which provides +functionality to link two entries in the store. +.PP +The third kind of crate is the one that offers end-user functionality +for a imag domain, for example \[lq]libimagtodo\[rq] provides +functionality to track todos. +.PP +And last, but not least, the commandline frontend crates provide the +user interface. +These are the kind of crates that are not library crates, but binaries. +.PP +Besides these, there are some other utility crates. +.SS Architecture of an imag module +.PP +With the things from above, a module could have the following +architecture: +.IP +.nf +\f[C] ++---------------------------------------------+ +| imag-foo | ++-----------------------------------+---------+ +| libimagfoo | | ++-----------------+-----------------+ | +| | | | +| libimagentrybar | libimagentrybaz | | +| | | lib | ++-----------------+-----------------+ | +| | | +| ... | | +| | imag | ++-----------------------------------+ | +| | | +| libimagrt | | +| | error | ++-----------------------------------+ | +| | | +| libimagstore | | +| | | ++-----------------------------------+---------+ +\f[R] +.fi +.PP +The foundation of all imag modules is the store, as one can see in the +visualization from above. +Above the store library there is the libimagrt, which provides the basic +runtime and access to the \f[C]Store\f[R] object. +Cross-cutting, there is the error library (and possibly the util +library, but we do not care about this one here), which is used through +all levels. +The highest level of all imag modules is the commandline interface on +top of the domain library. +In between can be any number of entry extension libraries, or none if +not needed. +.PP +Theoretically, the commandline interface crate could be replaced to +build a terminal user interface, graphical user interface or web +interface. +.SS Types +.PP +The imag core, hence the libimagstore, libimagrt and libimagerror, +provide a set of types that a user (as in a library writer) should be +aware of. +.PP +First of all, there is the \f[C]Runtime\f[R] type which is provided by +the libimagrt. +It provides basic access to whether debugging or verbosity is enabled as +well as the most important core object: The \f[C]Store\f[R]. +.PP +The \f[C]Store\f[R] type is provided by the libimagstore library, the +heart of everything. +.PP +When interacting with the store, two types are visible: +\f[C]FileLockEntry\f[R] and \f[C]Entry\f[R] whereas the former derefs to +the latter, which basically means that the former wraps the latter. +The \f[C]FileLockEntry\f[R] is a necessary wrapper for ensuring that +when working concurrently with the store, an entry is only +\f[I]borrowed\f[R] once from the store. +It also ensures that the object is alive as long as the store is. +.PP +The \f[C]Entry\f[R] type provides functionality like reading the actual +content, its header and so on. +Extensions for its functionality are implemented on this type, not on +the \f[C]FileLockEntry\f[R]. +.PP +The \f[C]Entry\f[R] provides access to its header, which is a +\f[C]toml::Value\f[R], where toml is the toml-rs crate (external +project). +Convenience functionality is provided via the \f[C]toml-query\f[R] +crate, which is an external project which was initiated and extracted +from the imag project. +.PP +Error types are also important. +All errors in imag projects should be created with +\f[C]error-chain\f[R]. +libimagerror provides functionality to enhance the experience with +\f[C]Result\f[R] types and general tracing of errors. +.SH The Store +.PP +The store is where all the good things happen. +The store is basically just a directory on the filesystem imag manages +and keeps its state in. +.PP +One could say that the store is simply a database, and it really is. +We opted to go for plain text, though, as we believe that plain text is +the only sane way to do such a thing, especially because the amount of +data which is to be expected in this domain is in the lower Megabytes +range and even if it is \f[I]really\f[R] much won\[cq]t exceed the +Gigabytes ever. +.PP +Having a storage format which is plain-text based is the superior +approach, as text editors will always be there. +.PP +A user should always be able to read her data without great effort and +putting everything in a \f[I]real\f[R] database like sqlite or even +postgresql would need a user to install additional software just to read +his own data. +We don\[cq]t want that. +Text is readable until the worlds end and we think it is therefore +better to store the data in plain text. +.PP +The following sections describe the store and the file format we use to +store data. +One may skip the following sections, they are included for users who +want to dig into the store with their editors. +.SS File Format +.PP +The contents of the store are encoded in UTF-8. +A normal text editor (like \f[C]vim\f[R] or the other one) will always +be sufficient to dig into the store and modify files. +For simple viewing even a pager (like \f[C]less\f[R]) is sufficient. +.PP +Each entry in the store consists of two parts: +.IP "1." 3 +Header +.IP "2." 3 +Content +.PP +The following section describe their purpose. +.SS Header Format +.PP +The header format is where imag stores its data. +The header is an area at the top of every file which is seperated from +the content part by three dashes (\f[C]---\f[R]). +Between these three dashes there is structured data. +imag uses \f[C]TOML\f[R] as data format for this structured data, +because it fits best and the available \f[C]TOML\f[R] parser for the +rust programming language is really good. +.PP +The header can contain any amount of data, but modules (see Section\ 6) +are restricted in their way of altering the data. +.PP +So normally there are several sections in the header. +One section (\f[C][imag]\f[R]) is always present. +It contains a \f[C]version\f[R] field, which tells imag which version +this file was created with. +.PP +Other sections are named like the modules which created them. +Every module is allowed to store arbitrary data under its own section +and a module may never read other sections than its own. +.PP +These conventions are not enforced by imag itself, though. +.SS Content Format +.PP +The content is the part of the file where the user is free to enter any +textual content. +The content may be rendered as Markdown or other markup format for the +users convenience. +The store does never expect and specific markup and actually the markup +implementation is not inside the very core of imag. +.PP +Technically it would be possible that the content part of a file is used +to store binary data. +We don\[cq]t want this, though, as it is contrary to the goals of imag. +.SS Example +.PP +An example for a file in the store follows. +.IP +.nf +\f[C] + +--- +[imag] +version = \[dq]0.10.0\[dq] + +[note] +name = \[dq]foo\[dq] + +[link] +internal = [\[dq]some/other/imag/entry\[dq]] +--- + +This is an example text, written by the user. +\f[R] +.fi +.SS File organization +.PP +The \[lq]Entries\[rq] are stored as files in the \[lq]Store\[rq], which +is a directory the user has access to. +The store may exist in the users Home-directory or any other directory +the user has read-write-access to. +.PP +Each module stores its data in an own subdirectory in the store. +This is because we like to keep things ordered and clean, not because it +is technically necessary. +.PP +We name the path to a file in the store \[lq]Store id\[rq] or +\[lq]Storepath\[rq] and we often refer to it by using the store location +as root. +So if the store exists in \f[C]/home/user/store/\f[R], a file with the +storepath \f[C]example.file\f[R] is (on the filesystem) located at +\f[C]/home/user/store/example.file\f[R]. +.PP +By convention, each \f[C]libimagentry\f[R] and +\f[C]libimag\f[R] module stores its entries in in +\f[C]/\f[R]. +.PP +So, the pattern for the storepath is +.IP +.nf +\f[C] +// +\f[R] +.fi +.PP +Any number of subdirectories may be used, so creating folder hierarchies +is possible and valid. +A file \[lq]example\[rq] for a module \[lq]module\[rq] could be stored +in sub-folders like this: +.IP +.nf +\f[C] +module/some/sub/folder/example +\f[R] +.fi +.PP +The above is not enforced or a strict rule, but rather a \[lq]rule of +thumb\[rq]. +.SS Backends +.PP +The store itself also has a backend. +This backend is the \[lq]filesystem abstraction\[rq] code. +.PP +Note: This is a very core thing. +Casual users might want to skip this section. +.SS Problem +.PP +First, we had a compiletime backend for the store. +This means that the actual filesystem operations were compiled into the +store either as real filesystem operations (in a normal debug or release +build) but as a in-memory variant in the `test' case. +So tests did not hit the filesystem when running. +This gave us us the possibility to run tests concurrently with multiple +stores that did not interfere with each other. +.PP +This approach worked perfectly well until we started to test not the +store itself but crates that depend on the store implementation. +When running tests in a crate that depends on the store, the store +itself was compiled with the filesystem-hitting-backend. +This was problematic, as tests could not be implemented without hitting +the filesystem and mess up other currently-running tests. +.PP +Hence we implemented store backends. +.SS Implementation +.PP +The filesystem is abstracted via a trait \f[C]FileAbstraction\f[R] which +contains the essential functions for working with the filesystem. +.PP +Two implementations are provided in the code: +.IP \[bu] 2 +FSFileAbstraction +.IP \[bu] 2 +InMemoryFileAbstraction +.PP +whereas the first actually works with the filesystem and the latter +works with an in-memory HashMap that is used as filesystem. +.PP +Further, the trait \f[C]FileAbstractionInstance\f[R] was introduced for +functions which are executed on actual instances of content from the +filesystem, which was previousely tied into the general abstraction +mechanism. +.PP +So, the \f[C]FileAbstraction\f[R] trait is for working with the +filesystem, the \f[C]FileAbstractionInstance\f[R] trait is for working +with instances of content from the filesystem (speak: actual Files). +.PP +In case of the \f[C]FSFileAbstractionInstance\f[R], which is the +implementation of the \f[C]FileAbstractionInstance\f[R] for the actual +filesystem-hitting code, the underlying resource is managed like with +the old code before. +The \f[C]InMemoryFileAbstractionInstance\f[R] implementation is +corrosponding to the \f[C]InMemoryFileAbstraction\f[R] implementation - +for the in-memory \[lq]filesystem\[rq]. +.SH Conventions, best practices +.PP +This section explains conventions used in the imag codebase. +It is mainly focused on developers, but a user may read it for getting +to know how imag works. +.PP +Lets work our way up from the store and how to extend it to the +commandline user interface. +.SS Versioning +.PP +All imag crates are versioned with the same version number until we +reach some \f[C]\[dq]1.0.0\[dq]\f[R] version. +This means that all imag tools are only tested for compatibility with +libraries and such if their version numbers match. +It might not be possible to import one imag library in version 0.3.0 and +another one in 0.4.0 and make them work together. +It also means that if new tools are introduced into the imag codebase, +they might start with their first version not at 0.1.0 but at something +like 0.5.0. +.SS Store and Entry functionality +.PP +A \f[C]Entry\f[R] does not offer much functionality by itself. +So its the job of libraries to \f[I]extend\f[R] its functionality. +This should never be done by wrapping the \f[C]Entry\f[R] type itself +but by providing and implementing an extension trait on it. +.PP +Same goes for extending the \f[C]Store\f[R] type: never wrap it, always +provide an extension trait for it. +.PP +These two rules ensure that the type does not lose any functionality +from a wrapping. +\f[C]Deref\f[R] could do that, but not over muliple levels, so extension +traits it is. +It also most likely results in functions inside the extension trait +which all return a \f[C]Result<_, _>\f[R]. +.SS Libraries +.PP +In the next few sections, conventions and best practices for writing a +imag library are written down. +.PP +A developer of imag should read this carefully, a user may skip this +section or cross-read it for better understanding of the imag project. +.SS Library naming +.PP +Libraries which provide functionality for entries or the store but no +domain-functionality should be named \[lq]libimagentrything\[rq] whereas +\[lq]thing\[rq] stands for what the library provides. +.PP +All domain libraries should be prefixed with \[lq]libimag\[rq]. +.SS Library scope +.PP +A library should never introduce utility functionality which could be +useful for other libraries as well. +If there is no such functionality available, the \[lq]libimagutil\[rq] +or \[lq]libimagentryutil\[rq] might be a place where such a function +would go to. +.PP +If a library has to introduce free functions in its public interface, +one should think hard whether this is really necessary. +.SS Library error types/kinds +.PP +Libraries must use \[lq]failure\[rq] to create error objects. +.SS Libraries with commandline frontends +.PP +Libraries with commandline frontends provide end-user functionality. +They are called \[lq]domain\[rq] libraries. +Normally, they depend on one or more \[lq]libimagentrything\[rq] +libraries. +They should be named \[lq]libimagthing\[rq], though. +For example: \[lq]libimagdiary\[rq], \[lq]libimagtimetrack\[rq] or +\[lq]libimagwiki\[rq], whereas the commandline frontends would be +\[lq]imag-diary\[rq], \[lq]imag-timetrack\[rq] and \[lq]imag-wiki\[rq], +respectively. +.PP +If such a library needs to depend on another \[lq]libimagthing\[rq], for +example if \[lq]libimagdiary\[rq] needs to depend on +\[lq]libimagnote\[rq], one should think about this and whether the +functionality could be outsourced to a more general +\[lq]libimagentrything\[rq]. +.SS Library testing +.PP +All libraries should be tested as much as possible. +Sometimes it may not be possible without a lot of effort, but still: +more tests = better! +.SS Commandline tools +.PP +The commandline tools are the CLI-frontends for their respective +libraries. +So \f[C]libimagdiary\f[R] has a CLI frontend \f[C]imag-diary\f[R]. +.PP +Those CLI frontends use functionality from \f[C]libimagrt\f[R] to build +a commandline interface which is consistent with the rest of the +ecosystem. +.PP +Commandline applications use the runtime interfaces for receiving IDs +from the CLI or IDs which are piped into the application. +Commandline applications use the `stdin'/`stdout'/`stderr' wrappers +provided by the runtime (see section below). +.PP +Commandline applications are \f[I]only\f[R] interactive when specified +by the user (normally via a \f[C]--interactive\f[R] flag). +An application \f[I]must\f[R] provide the full functionality via its +commandline interface, thus it is not allowed to provide functionality +which is only usable in interactive mode. +.SS IO +.PP +There are minor restrictions how imag tools should do IO. +A good rule of thumb is (but most certainly only applicable when +programming an imag tool in Rust): use \f[C]libimagrt\f[R] to do IO of +any kind. +.PP +For more information, or if not using Rust as programming language: the +documentation of \f[C]libimagrt\f[R] describes how IO should happen +(which output stream to use, how input should be done). +.SH Writing an imag module +.PP +So you want to write a module for imag. +That\[cq]s nice. +.PP +This guide helps you getting started. +It also can help you understanding how imag modules work, so even if you +do not want to write a full new module, but extend or alter one, this +guide may help you. +.SS Data layout +.PP +First, you have to think about what data you want to store. +What functionality do you want to provide and what data that creates. +.PP +In this example, we\[cq]re writing a module that stores numbers. +We\[cq]re writing the appropriate library for that as well as a +commandline frontend. +.SS libimagnumberstorage +.PP +We\[cq]re writing a \f[C]libimagnumberstorage\f[R] which provides the +core functionality of our module: Storing numbers. +.PP +That library can then be used by other library authors and by the +commandline interface implementation. +.SS Setup +.PP +So what do we need to do to write this library: +.IP "1." 3 +Create a new \[lq]lib\[rq] crate. +Because we\[cq]re writing a \[lq]domain\[rq] library, we\[cq]re doing +this in the \f[C]lib/domain\f[R] subdirectory: +\f[C]cd lib/domain; cargo new --lib libimagnumberstorage\f[R]. +.IP "2." 3 +After creating the library, we have to add the new library to the +\f[C]/Cargo.toml\f[R] field and add the missing metadata in the new +\f[C]/lib/domain/libimagnumberstorage/Cargo.toml\f[R] file. +.PP +That was the setup part. +Now we can implement our functionality. +For that, we need to \f[I]extend\f[R] two types from +\f[C]libimagstore\f[R], so we have our first dependency here. +.SS Dependencies to other libraries +.IP "3." 3 +Put \f[C]libimagstore\f[R] as a dependency in the +\f[C]/lib/domain/libimagnumberstorage/Cargo.toml\f[R] file. +By using +\f[C]libimagstore = { version = \[dq]0.10.0\[dq], path = \[dq]../../../lib/core/libimagstore\[dq] }\f[R] +we automatically get all the goodness of Cargo, so that releases +automagically work as expected, but when developing locally, the local +version of \f[C]libimagstore\f[R] is used. +Of course, the \f[C]version\f[R] has to be the latest released version. +.IP "4." 3 +For error handling, we also need to import \f[C]libimagerror\f[R]. +.IP "5." 3 +For easy header-editing, we import \f[C]toml\f[R] and +\f[C]toml-query\f[R]. +.IP "6." 3 +For error-type creating, we import \f[C]error-chain\f[R]. +.SS Interface +.IP "7." 3 +Then, we have to \f[I]extend\f[R] two types: +.RS 4 +.IP "1." 3 +\f[C]libimagstore::store::Store\f[R] has to be extended so we can +implement a CRUD interface for our special entries. +.IP "2." 3 +\f[C]libimagstore::store::Entry\f[R] has to be extended so we can get +our stored numbers in a convenient way. +.RE +.PP +Our interface should roughly look like this: +.IP +.nf +\f[C] +store.get_stored_number(\[dq]5\[dq]) -> Result +store.store_number(\[dq]5\[dq]) -> Result +store.delete_number(\[dq]5\[dq]) -> Result<(), _> +\f[R] +.fi +.PP +You notice that the \f[C]Store\f[R] returns \f[C]FileLockEntry\f[R] +objects rather than \f[C]Entry\f[R] objects. +And that\[cq]s ok. +A \f[C]FileLockEntry\f[R] is a \f[C]Entry\f[R], but ensures that we are +the only ones editing that entry. +So, we have to implement our number-storing-interface on \f[C]Entry\f[R] +as well: +.IP +.nf +\f[C] +entry.get_number() -> Result +entry.set_number(usize) -> Result<()> +\f[R] +.fi +.PP +All those \[lq]extensions\[rq] are implemented as traits which are then +implemented for \f[C]Store\f[R] and \f[C]Entry\f[R]. +.PP +Normally, we create new files for that, as well as for the error types +we need: +.IP \[bu] 2 +\f[C]/lib/domain/libimagnumberstorage/src/store.rs\f[R] +.IP \[bu] 2 +\f[C]/lib/domain/libimagnumberstorage/src/entry.rs\f[R] +.IP \[bu] 2 +\f[C]/lib/domain/libimagnumberstorage/src/error.rs\f[R] +.PP +where \f[C]store.rs\f[R] contains a trait \f[C]NumberStorage\f[R] and +\f[C]entry.rs\f[R] contains a trait \f[C]NumberEntry\f[R]. +\f[C]error.rs\f[R] contains the invocation of the +\f[C]error_chain!{}\f[R] macro. +Error types from \f[C]libimagstore\f[R] and others are linked in. +.SH Modules +.PP +A module is a functionality of the program. +There is a huge list of modules available in the imag core distribution. +.PP +Some of the modules shipped with imag cover core functionality such as +linking, tagging or references to files outside of the store or even the +store interface itself. +Others cover things like diary, notes, wiki or bookmarks. +These are also called \[lq]domains\[rq]. +.PP +We try really hard to offer a consistent commandline user interface over +all of these modules. +.PP +The following sections describe each module in detail, including its +purpose and its provided functionality. +.SS Bookmarks +.PP +The Bookmarks module is for keeping URLs as bookmarks, tagging and +categorizing them and finally also open them in the browser. +.SS Category +.PP +A tool to create categories and set/get them for entries. +.PP +The difference between a category and a tag is that a category must +exist before it can be used and all entries of a category are linked to +the \[lq]category entry\[rq] internally. +.SS Diary +.PP +The diary module is for keeping your diary notes. +.PP +The diary module giv3s you the possibility to write your diary in imag. +It offers daily, hourly and minutely entries (the latter beeing more +like a private tumble-blog). +.PP +Exporting the diary is possible, so one can write it in markdown and +later pass that to pandoc, if desired, to generate a website or book +from it. +.SS Edit +.PP +The \f[C]imag-edit\f[R] command is for simply editing store entries with +the \f[C]$EDITOR\f[R]. +.PP +It is based on libimagentryedit (Section\ 7.7). +.SS Entry +.PP +Plumbing tool for modifying and querying structured data in entries. +.SS Init +.PP +This is the only \f[C]imag-*\f[R] command which does \f[I]not\f[R] set +up a runtime and check whether the store is available. +This command can be used to set up a imag store. +.PP +It also puts a default configuration in the right place and initializes +a git repository, if there is a \f[C]git\f[R] command in \f[C]$PATH\f[R] +(via calling git on the commandline, not via \f[C]libgit2\f[R] or some +other library). +.SS Link +.PP +The linking module \f[C]imag-link\f[R] is one of the plumbing modules. +It offers the possibility to link entries in the store. +.PP +It also offers the functionality to link to external sources. +This functionality \f[I]can\f[R] be used to link to external URLs, but +the bookmarking module should be used to do this (see Section\ 6.1). +.PP +The linking module offers functionality to add, remove and list both +internal (store entry to store entry) and external (store entry to URL) +links. +.SS Internal linking +.SS External linking +.PP +A store entry can only have \f[I]one\f[R] external link. +Therefor, when you create an external link, the linking module creates a +new entry in the store which links to this URL. +The linking module then links you entry with this new entry by using an +internal link. +This way one entry can have multiple external links attached to it and +external links are deduplicated automatically. +.SS Log +.PP +The \[lq]imag-log\[rq] module is a lightweight interface to the +\[lq]imag-diary\[rq] command. +.PP +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: +.SS Usage +.PP +Logs can be created via an entry in the configuration file in the +section \f[C]log\f[R]: +.IP +.nf +\f[C] +[log] +logs = [\[dq]work\[dq], \[dq]hobby\[dq], \[dq]music\[dq]] +default = \[dq]hobby\[dq] +\f[R] +.fi +.PP +The \f[C]default\f[R] key is required and the name which is used here +\f[I]must\f[R] appear in the \f[C]logs\f[R] array. +.PP +In the above configuration snippet, the logs \f[C]work\f[R], +\f[C]hobby\f[R] and \f[C]music\f[R] are created. +The user may now log to one of these logs with: +.IP +.nf +\f[C] +imag log --to \[dq]Some message\[dq] +# or +imag log -t \[dq]Some message\[dq] +# or, to the default log: +imag log \[dq]Some message\[dq] +\f[R] +.fi +.PP +Logs can be read by naming the log: +.IP +.nf +\f[C] +imag log show work +\f[R] +.fi +.PP +which prints one log per line (including time it was logged). +.SS Mails +.PP + * * * * * +.PP +\f[B]NOTE:\f[R] This is mostly a todo-list for the \f[C]imag-mail\f[R] +command. +Nothing shown here is implemented. +This \[lq]documentation-to-be\[rq] should be moved to +\f[C]imag-mail --help\f[R] eventually. +This list might be incomplete, details might be not possible to +implement in the way described or other dragons. +.PP +\f[B]Target audience:\f[R] People who want to implement +\f[C]imag-mail\f[R]. +.PP + * * * * * +.PP +The Mails module implements a commandline email client. +Emails can be written (via \f[C]$EDITOR\f[R]) and viewed, also in +threads. +Emails can be crawled for creating new contacts. +.PP +A Text User Interface is not planned, but might be there at some point. +.PP +The mail module implements a minimal Email client. +It does not handle IMAP syncing or SMTP things, it is just a +\f[I]viewer\f[R] for emails (a MUA). +.PP +The goal of the initial implementation is only a CLI, not a TUI like +mutt offers, for example (but that might be implemented later). +As this is an imag module, it also creates references to mails inside +the imag store which can be used by other tools then (for example +\f[C]imag-link\f[R] to link an entry with a mail - or the imag entry +representing that mail). +.PP +So this module offers functionality to read (Maildir) mailboxes, search +for and list mails and mail-threads and reply to mails (by spawning the +\f[C]$EDITOR\f[R]). +.PP +Outgoing mails are pushed to a special directory and can later on be +send via \f[C]imag-mail\f[R] which calls a MTA (for example msmtp) and +also creates store entries for the outgoing mails. +.SS Configuration +.PP +The following configuration variables are available for the imag-mail +command: +.IP \[bu] 2 +\f[C]mail.defaultaccount\f[R]: The name of the default account to use if +the commandline parameters do not specify which account to use. +The name must be in the \f[C]mail.accounts\f[R] array. +.IP \[bu] 2 +\f[C]mail.accounts\f[R]: An array of account configuration. +Each element in the array is a table of the following key-value pairs: +.RS 2 +.IP \[bu] 2 +\f[C]name\f[R]: the name of the account. +Names must be unique. +Required. +.IP \[bu] 2 +\f[C]outgoingbox\f[R]: Path to mailbox to use for outgoing email. +Required. +.IP \[bu] 2 +\f[C]draftbox\f[R]: Path to mailbox to use for outgoing email. +Required. +.IP \[bu] 2 +\f[C]sentbox\f[R]: Path to mailbox to use for sent email. +Required. +\f[C]\f[R]maildirroot\[ga]: Path to folder where all mailboxes for this +account are located. +Required. +.IP \[bu] 2 +\f[C]fetchcommand\f[R]: What commandline to invoke for fetching mails +for this account. +Optional - if not used, the global \f[C]mail.fetchcommand\f[R] will be +used. +.IP \[bu] 2 +\f[C]postfetchcommand\f[R]: What commandline to invoke after fetching +mails for this account. +Optional - if not used, the global \f[C]mail.postfetchcommand\f[R] will +be used. +.IP \[bu] 2 +\f[C]sendcommand\f[R]: What commandline to invoke for sending mails for +this account. +Optional - if not used, the global \f[C]mail.sendcommand\f[R] will be +used. +.IP \[bu] 2 +\f[C]postsendcommand\f[R]: What commandline to invoke after sending +mails for this account. +Optional - if not used, the global \f[C]mail.postsendcommand\f[R] will +be used. +.RE +.IP \[bu] 2 +\f[C]mail.fetchcommand\f[R]: Command to use for fetching mail if no +account-specific command was specified Available variables: +.RS 2 +.IP \[bu] 2 +\f[C]{{accountname}}\f[R] - name of the account to fetch mail for. +.IP \[bu] 2 +\f[C]{{boxes}}\f[R] - a list of maildir paths to the boxes to fetch +email for. +imag provides primitives to transform this array. +An example configuration for fetching with \f[C]offlineimap\f[R] might +look like this: +\f[C]offlineimap -a {{accountname}} -f {{concatsep \[dq],\[dq] (replace \[dq]/home/user/mails/\[dq] \[dq]\[dq] boxes)}}\f[R] +to concatenate all boxes with a comma after removing a prefix. +For a complete list of transformation functions, the \f[C]--help\f[R] +flag shall be consulted. +For more complicated transformations a bash/ruby/python script might be +appropriate. +.RE +.IP \[bu] 2 +\f[C]mail.postfetchcommand\f[R]: Command to use after fetching mail if +no account-specific command was specified Available variables: Same as +\f[C]mail.fetchcommand\f[R]. +.IP \[bu] 2 +\f[C]mail.postsendcommand\f[R]: Command to use after sending mail if no +account-specific command was specified Available variables: Same as +\f[C]mail.sendcommand\f[R]. +.IP \[bu] 2 +\f[C]mail.sendcommand\f[R]: Command to use for sending mail if no +account-specific command was specified +.RS 2 +.IP \[bu] 2 +\f[C]{{accountname}}\f[R] - name of the account to fetch mail for. +.IP \[bu] 2 +\f[C]{{mailfile}}\f[R] - The path of the mail to send +.RE +.SS CLI +.PP +The CLI of the imag-mail module is planned as follows: +.IP \[bu] 2 +imag mail +.RS 2 +.PP +-A, \[en]account - Specify the \[lq]account\[rq] to use for the +opperation by name. +If none is specified, the configuration is searched for a default +command. +.RE +.IP \[bu] 2 +imag mail track [opts\&...] Track a new mail, mail file passed as path +.IP \[bu] 2 +imag mail scan [opts\&...] Scan a maildir and track all untracked mails +.RS 2 +.PP +\[en]refind - re-find messages. +Loads all messages which are known to imag and compares identifiers, to +update the imag-internal cache if a mail got moved. +Without this flag, a modified email file might be added to the imag +store again, even if there\[cq]s another entry in the imag store +refering to the same file. +.RE +.IP \[bu] 2 +imag mail list List mails in a given mailbox for a given +account or the default account +.RS 2 +.PP +-S, \[en]style - print messages in a certain style Available: - +`linewise' - `thread' +.PP +-g, \[en]grep - Filter by grepping for a pattern in body and subject +.PP +-d, \[en]daterange - Filter by date(range) +.PP +-F, \[en]filter - Filter by passed filter +.IP +.nf +\f[C] + --thread - Print only messages from the same thread as the found ones +\f[R] +.fi +.PP +\[en]format= - Format mails for showing. +\[en]format always colorizes output (specify color in config) except +when using \[en]no-pager or piping output. +.IP +.nf +\f[C] + When --tree is passed, the format is applied to the + fragment _after_ the tree graphic. + + Default mode is \[aq]default\[aq]. + + Modes: + - \[aq]subject\[aq]: + - \[aq]simple\[aq]: : + - \[aq]default\[aq]: - : + - \[aq]fmt:\[aq] format with passed format + + Additional formats can be specified via the configuration + file. If a format has the same name as a predefined one, + the config overrides the predefined formats. +\f[R] +.fi +.PP +\[en]color - Colorize output (default). +\[en]no-color - Do never colorize output. +.RE +.IP \[bu] 2 +imag mail show Show mail(s) - either in pager or by printing +them to stdout. +.RS 2 +.PP +Mails are specified by message id or imag entry +.PP +\[en]refind - If a imag entry is passed but the mail file is not there, +try to re-find it. +.PP +\[en]refind-in - Same as \[en]refind, but a path to a Maildir or a tree +of Maildirs might be passed to narrow down search space. +.PP +-C, \[en]concat - Open all mails in one pager (by concatenating them) +instead of one pager per message. +.PP +\[en]pager - Use pager to show mails (default). +.PP +\[en]no-pager - Do not use pager to show mails. +.PP +\[en]multipager - Pass all mails as arguments to one pager call instead +of calling the pager on each mail individually (default). +Only possible with \[en]pager. +.PP +\[en]no-multipager - Disable \[en]multipager. +Only possible with \[en]pager. +.PP +\[en]format= - Format mails for showing. +\[en]format always colorizes emails (specify color in config) except +when using \[en]no-pager or piping output. +.IP +.nf +\f[C] + Modes: + - \[aq]simple\[aq]: Remove headers, except + From, To, Cc, Subject, Date, + Message-Id/References/In-Reply-To + - \[aq]simple-imag\[aq]: Same as \[aq]simple\[aq] but also show imag + entry id. + - \[aq]print\[aq]: Show everything + - \[aq]full\[aq]: Show everything and add imag entry id + - \[aq]minimal\[aq]: Remove headers, except From, To, Cc, Subject, Date, + - \[aq]tiny\[aq]: Remove headers, except From, To, Subject + - \[aq]fmt:\[aq] format with passed format + + Additional formats can be specified via the configuration + file. If a format has the same name as a predefined one, + the config overrides the predefined formats. +\f[R] +.fi +.PP +\[en]no-format - Disable all formatting (same as \[en]pretty=print and +disabling color output). +.PP +\[en]color - Colorize output (default). +\[en]no-color - Do never colorize output. +.RE +.IP \[bu] 2 +imag mail new Craft a new mail and safe it in the folder +.RS 2 +.PP +Requires configuration: +.IP \[bu] 2 +mail.accounts.[.draftbox] +.IP \[bu] 2 +mail.accounts.[.outgoingbox] +.RS 2 +.PP +\[en]outbox - Specify the outbox for where the new mail should be stored +in, if it is not given in the config (or to override it) +.PP +\[en]to - Specify to whom to send. +If the specified string does not contain a valid email address, +\f[C]imag contact find\f[R] is used to find the email address (if not +suppressed via \[en]no-autofind). +Multiple allowed. +.PP +\[en]cc - Specify to whom to send in CC. +If the specified string does not contain a valid email address, +\f[C]imag contact find\f[R] is used to find the email address (if not +suppressed via \[en]no-autofind). +Multiple allowed. +.PP +\[en]bcc - Specify to whom to send in BCC. +If the specified string does not contain a valid email address, +\f[C]imag contact find\f[R] is used to find the email address (if not +suppressed via \[en]no-autofind). +Multiple allowed. +.RE +.PP +\[en]no-autofind - Do not automatically find contacts with +\f[C]imag contact find\f[R]. +.IP +.nf +\f[C] + --fcc - Specify to store a copy of the mail somewhere. + Multiple allowed. + + --subject - Specify subject. + + --gpg-sign - Sign with gpg. + + --gpg-crypt - Crypt with gpg to all recipients. + + --no-track - Do not track new mailfile with imag. +\f[R] +.fi +.PP +-D, \[en]draft - Do not safe in \[lq]outgoing\[rq] box but rather in +\[lq]draft\[rq] box. +.RE +.IP \[bu] 2 +imag mail compose Same as `new'. +.IP \[bu] 2 +imag mail fetch Fetch emails +.RS 2 +.PP +Requires configuration: +.IP \[bu] 2 +mail.fetchcommand or mail.accounts[.fetchcommand] +.IP \[bu] 2 +mail.postfetchcommand or mail.accounts[.postfetchcommand] (optional) +.PP +\[en]all - Fetch for all accounts \[en]boxes - Fetch only some boxes +(does not work with \[en]all) +.RE +.IP \[bu] 2 +imag mail send Send emails from the outgoing folder, also +move them to `sent' boxes +.RS 2 +.PP +Requires configuration: +.IP \[bu] 2 +mail.accounts.[.outgoingbox] +.IP \[bu] 2 +mail.accounts.[.sentbox] +.IP \[bu] 2 +mail.sendcommand or mail.accounts[.sendcommand] +.IP \[bu] 2 +mail.postsendcommand or mail.accounts[.postsendcommand] (optional) +.PP +\[en]outbox - Specify the outbox for where the mails that are about to +be send are stored in, if it is not given in the config (or to override +it). +.PP +\[en]sentbox - Specify the sentbox for where the sent mails should be +moved after sending them, if it is not given in the config (or to +override it). +.PP +\[en]no-move-sent - Do not move mail to the \[lq]sent\[rq] folder after +sending it. +.PP +\[en]confirm - Confirm each mail before sending (default). +.PP +\[en]no-confirm - Do not confirm each mail before sending. +.PP +\[en]no-track - Do not track mailfile with imag. +Does only work if \f[C]imag mail new\f[R] was +invoked with \f[C]--no-track\f[R] (so that the mail is not tracked +already). +.RE +.IP \[bu] 2 +imag mail mv Move a mail to another mailbox +.RS 2 +.PP +\[en]thread - Move the complete thread of emails belonging to the +specified mail. +.PP +\[en]no-track - Do not track new mailfile with imag. +Does not work if mailfile is already tracked with imag. +.RE +.IP \[bu] 2 +imag mail find Search for a mail (by header field (msgid, +from, to, cc, subject, date, date-range), body, \&...) +.RS 2 +.PP +\[en]msgid \[en]no-msgid \[en]from \[en]no-from \[en]to \[en]no-to +\[en]cc \[en]no-cc \[en]subject \[en]no-subject \[en]date \[en]no-date +\[en]body \[en]no-body \[en]daterange - Toggle where to look at +.PP +\[en]print-entryid - Print imag entry id when finding mail +\[en]no-print-entryid - Do not print imag entry id when finding mail +(default). +.PP +\[en]print= - What to print for the found mails. +Valid values: - msgid - subject - from - cc - to - date - filepath +(default) +.RE +.IP \[bu] 2 +imag mail reply Reply to an email. +.RS 2 +.PP +Requires configuration: mail.accounts[.outgoingbox] +.PP +Specify the mail to reply to by msgid, filepath or imag entry id. +.PP +\[en]add-to \[en]add-cc \[en]add-bcc - Add another recipient. +Multiple allowed. +.PP +\[en]no-track - Do not track new mailfile with imag. +.RE +.SS Format specifiers +.PP +The \f[C]imag-mail\f[R] command supports formatting output automatically +and via predefined formats in the configuration file or by passing +formatting specifications via CLI. +.PP +The available formatting variables are: +.IP \[bu] 2 +\f[C]H\f[R]: The complete message header as key-value-table +.IP \[bu] 2 +\f[C]subject\f[R]: The subject of the message +.IP \[bu] 2 +\f[C]date\f[R]: The date field of the message +.IP \[bu] 2 +\f[C]body\f[R]: The body of the message +.IP \[bu] 2 +\f[C]from\f[R]: The sender of the message +.IP \[bu] 2 +\f[C]to\f[R]: The address of the receipient of message +.IP \[bu] 2 +\f[C]fancyfromto\f[R]: The address of the sender of the message, or, if +the sender was you, the receipient (prefixed with \f[C]F:\f[R] or +\f[C]T:\f[R] respecively). +.SS Notes +.PP +The Notes module is intended to keep notes. +These notes can be inserted as plain text, markdown or other markup +languages. +.PP +The notes module offers: +.IP \[bu] 2 +adding, removing and settings of tags +.IP \[bu] 2 +listing notes, optionally filtered by +.RS 2 +.IP \[bu] 2 +tags +.IP \[bu] 2 +\f[C]grep\f[R]ping through note content and listing +.RS 2 +.IP \[bu] 2 +the matches +.IP \[bu] 2 +files with matches +.RE +.RE +.IP \[bu] 2 +opening a note via \f[C]xdg-open\f[R] (rendered as HTML if content is +written in a markup language) +.SS Reference +.PP +The Reference module. +.SS Store +.PP +The Store module. +.SS Tagging +.PP +The Tagging module. +.PP +A valid tag matches the regex \f[C][a-zA-Z][0-9a-zA-Z]*\f[R]. +.SS Timetrack +.PP +The Timetrack module implements a \f[C]timewarrior\f[R]-like +timetracking functionality for imag. +.PP +Each timetracking is a `tag' which can be started and stopped. +These tags are \f[I]no\f[R] tags as in imag-tag, but timetracking-tags. +.PP +Summaries can be printed, also filtered by tags if desired. +.SS Todo +.PP +The \[lq]todo\[rq] module implements a task manager. +.SS View +.PP +The View module. +.SS Wiki +.PP +The Wiki module provides a personal wiki implementation. +.PP +The wiki entries are markdown-formatted files in the imag store. +All entries are automatically searched for links and those links are +automatically added to the header (or as external link, depending on the +format). +.PP +Wiki entries can have no or one category and a arbitrary number of tags. +Entries can be listed (as a \[lq]tree\[rq] shape) and filtered by +content, category and tag. +.SH Libraries +.PP +This section of the documentation is only relevant for developers and +you might skip it if you\[cq]re only a user of the imag tool. +.PP +The following sections contain a short documentation on what the several +libraries are supposed to do. +It is generated from the \f[C]README.md\f[R] files of each library and +only gives a general overview what can be done with the library. +For a more comprehensive documentation of the library, one might consult +the appropriate documentation generated from the source of the library +itself. +.PP +The documentation of the libraries is sorted \f[I]alphabetically\f[R]. +.SS libimagbookmark +.PP +This library crate implements functionality for bookmarks. +.PP +It uses \f[C]libimagentrylink\f[R] to create external links and therefor +deduplicates equivalent external links (\f[C]libimagentrylink\f[R] +deduplicates - you cannot store two different store entries for +\f[C]https://imag-pim.org\f[R] in the store). +.PP +It supports bookmark collections and all basic functionality that one +might need. +.SS libimagcontacts +.PP +The contact library basically only creates references to the actual +vcard files, though it also can parse (via the \f[C]vobject\f[R] crate) +the information and return it from an entry directly. +.PP +The architecture of indirections is as follows: +.IP +.nf +\f[C] + ++--------------------------------+ +| | +| Store, as ContactStore | +| | ++----------------+---------------+ + | + | Provides access to + | ++----------------v---------------+ +| | +| (FileLock)Entry as Contact | +| | +| which is actually a: | +| | +| (FileLock)Entry as Ref | +| | ++----------------+---------------+ + | + | refers to + | ++----------------v---------------+ +| | +| vcard file (outside store) | +| | ++----------------+---------------+ + | + | contains + | ++----------------v---------------+ +| | +| vcard data | +| | ++--------------------------------+ +\f[R] +.fi +.SS libimagdiary +.PP +This library crates implements a full diary. +.PP +One can have one or more diaries in the store, each diary can have +unlimited entries. +.PP +The diary provides \f[I]daily\f[R], \f[I]hourly\f[R] and even +\f[I]minutely\f[R] diary entries. +For twitter-like log keeping, have a look at \[lq]libimaglog\[rq], +though. +.SS libimagentryannotation +.PP +This library provides annotation functionality for entries. +.PP +Annotations are normal Store entries, but their header at +\f[C]annotation.is_annotation\f[R] is set to \f[C]true\f[R]. +.PP +Annotations are linked to an entry (as in \f[C]libimagentrylink\f[R]). +.SS Library functionality +.PP +The library features two traits: One to extend an \f[C]Entry\f[R] with +annotation functionality and another one for extending the +\f[C]Store\f[R] with functionality to get annotations of an entry and +all annotations in the store. +.SS libimagentrycategory +.PP +This library provides category functionality for entries. +.SS libimagentrydatetime +.PP +Provides date/time functionality for entries. +.SS libimagentryedit +.PP +Provides edit (as in spawning an \f[C]$EDITOR\f[R]) functionality for +entries. +.SS libimagentryfilter +.PP +Helper library to filter lists of entries by certain predicated. +Offers filters for filtering by header values and other predicates. +.PP +A commandline-to-filter DSL is planned for this, so commandline +applications can use this to implement a uniform filter interface. +.SS libimagentrylink +.PP +Linking library for linking entries with other entries. +.SS libimagentrymarkdown +.PP +Helper crate to add useful functionality in a wrapper around +hoedown (https://crates.io/crates/hoedown) for imag. +.PP +Adds functionality to extract links, parse content into HTML and other +things which might be useful for markdown rendering in imag. +.SS libimagentryref +.PP +This library crate contains functionality to generate +\f[I]references\f[R] within the imag store. +.SS Problem +.PP +The problem this library solves is the following: A user wants to refer +to a file which exists on her filesystem from within imag. +But unfortunately, the user has several devices and the filesystem +layout (the way the $HOME is organized) is not the same on every device. +With this library, the user is able to refer to a file, but without +specifying the whole path. +.PP +Each device can have a different \[lq]base path\[rq], files are re-found +via their hashes and file names, assuming that the files are equal on +different devices or have at least the same name. +.SS User Story / Usecase +.PP +Alice has a music library on her workstation and on her notebook. +On her workstation, the music collection is at +\f[C]home/alice/music\f[R], on the notebook, it exists in +\f[C]/home/al/media/music\f[R]. +.PP +From within imag, alice wants to create a link to a file +\f[C]$music_store/Psy_trance_2018_yearmix.mp3\f[R]. +.PP +\f[C]libimagentryref\f[R] helps her, because she can provide a \[lq]base +path\[rq] in the imag configuration file of each device and then link +the file. +imag only stores data about the file and its relative path, but not its +abolute path. +.PP +When moving the imag store from the workstation to the notebook, the +base path for the music collection is not \f[C]/home/alice/music\f[R] +anymore, but \f[C]/home/al/media/music\f[R] and imag can find the file +automatically. +.SS Solution, Details +.PP +libimagentryref does store the following data: +.IP +.nf +\f[C] +[ref] +basepath = \[dq]music\[dq] +is_ref = true # marker that this entry is actually a \[dq]ref\[dq] +relpath = \[dq]Psy_trance_2018_yearmix.mp3\[dq] + +[ref.hash] +sha1 = \[dq]\[dq] +\f[R] +.fi +.PP +The filehash is stored so that libimagentryref can re-find the file +whenever it was moved. +The \f[C]sha1\f[R] key is added to be able to upgrade hashes later to +other hashing algorithms. +\f[C]relpath\f[R] is the part of the path that when joined with the +\[lq]base\[rq] path from the configuration results in the full path of +the file for the current machine. +The \[lq]collection\[rq] key hints to the configuration key in the imag +config file. +.PP +The configuration section for the collections looks like this: +.IP +.nf +\f[C] +[ref.basepathes] +music = \[dq]/home/alice/music\[dq] +documents = \[dq]/home/alice/doc\[dq] +\f[R] +.fi +.PP +libimagentryref provides functionality to get the file. +libimagentryref also offers functionality to find files \f[I]only\f[R] +using their filename (x)or filehash and correct the filehash or filename +respectively (automatically or explicitely). +.SS Limits +.PP +As soon as the file is renamed \f[I]and\f[R] modified, this fails. +This does also not cover the use case where the same file has different +names on different machines. +.SS libimagentrytag +.PP +Library for tagging entries. +Used in \[lq]imag-tag\[rq] but should be used in all other modules which +contain tagging functionality, so the backend and frontend look the same +for all modules. +.SS libimagentryutil +.PP +This library contains utilities for working with +\f[C]libimagstore::store::Entry\f[R] objects where the functionality +does not necessarily belong into \f[C]libimagstore\f[R]. +.SS libimagentryview +.PP +Provides viewing (as in piping to stdout, opening in \f[C]$EDITOR\f[R] +or in \f[C]$BROWSER\f[R]) functionality for entries. +.SS libimagerror +.PP +In imag, we do not panic. +.PP +Whatever we do, if we fail as hard as possible, the end-user should +\f[I]never ever\f[R] see a backtrace from a \f[C]panic!()\f[R]. +.PP +Anyways, the user \f[I]might\f[R] see a error trace generated by imag. +That is because imag is software for power-users, for nerds (I use the +term \[lq]nerd\[rq] because for me it is a good thing - I do not want to +offend anyone by using it). +This target group can read backtraces without getting confused. +\f[C]IO Error\f[R] and \f[C]Permission denied Error\f[R] are things that +nerds can understand and they already know what to do in the most +obvious cases (such as \f[C]Permission denied Error\f[R]). +.PP +This library crate is for generating error types and handle them in a +nice way. +It can be seen as mini-framework inside imag which was written to work +with error types in a specified way. +All imag crates \f[I]must\f[R] use this library if they can return +errors in any way, except the \f[C]libimagutil\f[R] - which is for the +most basic utilities. +.SS libimaghabit +.PP +The habit library implements a habit tracker. +.PP +A habit can be instantiated with a name and a time-period in which it +should be fullfilled (eg. +daily, ever 3 days, weekly\&...). +.PP +The module offers ways to generate statistics about habits. +.SS libimaginteraction +.PP +A crate for more general interaction with the user (interactive +commandline interface). +.PP +Offers functions for asking the user Y/N questions, for (numeric) +values, etc. +.SS libimaglog +.PP +A small extension over libimagdiary which strips down the functionality +of libimagdiary to some defaults for writing a \f[C]log\f[R] (a +tumbleblog like diary) with rather short messages. +.PP +Provides only basic functionality over libimagdiary, most notably the +\[lq]log.is_log\[rq] header entry, so the \f[C]imag-log\f[R] CLI can +distinguish between \[lq]logs\[rq] and \[lq]diary entries\[rq]. +.SS libimagmails +.PP +The mail library implements everything that is needed for beeing used to +implement a mail reader (MUA). +.PP +It therefor providea reading mailboxes, getting related content or +mails, saving attachements to external locations, crafting new mails and +responses,\&... +.PP +It also offers, natively, ways to search for mails (which are +represented as imag entries) via tags, categories or even other +metadata. +.PP +For more information on the domain of the \f[C]imag-mail\f[R] command, +look at the documentation of the Section\ 6.9 module. +.SS libimagnotes +.SS libimagrt +.PP +This library provides utility functionality for the modules and the +binary frontends, such as reading and parsing the configuration file, a +builder helper for the commandline interface and such. +.PP +It also contains the store object and creates it from configuration. +.PP +the \f[C]libimagrt::runtime::Runtime\f[R] object is the first complex +object that comes to live in a imag binary. +.SS IO with libimagrt +.PP +libimagrt also provides IO primitives which should be used by all imag +tools and libraries: +.PP +The IO story in imag is pretty easy. +As imag is mainly a CLI tool, IO is either \f[C]stdout\f[R] or +\f[C]stderr\f[R] and \f[C]stdin\f[R]. +.SS Output +.PP +libimagrt provides getters for an output stream for \[lq]normal\[rq] +output, like logging, status information, etc. +It also provides an output for \[lq]touched entries\[rq]. +.PP +Whenever an imag tool touches an entry in any way (either reading or +writing), it should report this to libimagrt. +libimagrt then does \[lq]the right thing\[rq] which is printing it to +stdout or swallowing the output. +Normal output (logging, status information, explicitely queried +information) goes to the right sink automatically, that is: +.IP \[bu] 2 +If the user provides the appropriate flags, normal output goes to +\f[C]stderr\f[R] and \[lq]touched entries\[rq] go to \f[C]stdout\f[R]. +This allows a user to `chain' imag calls. +.IP \[bu] 2 +If the user does not provide these flags, normal output goes to +\f[C]stdout\f[R] (for piping to other tools, e.g.\ \f[C]grep\f[R]) and +\[lq]touched entries\[rq] are not printed. +.IP \[bu] 2 +\f[C]stdin\f[R] can be used for reading store-ids which shall be +processed by an imag tool. +For example \f[C]imag-tag\f[R] can receive a list of entries to add tags +to via \f[C]stdin\f[R] like this: +\f[C]echo some/entry some/other | imag tag -I add sometag\f[R]. +.PP +With these two settings in place, calls to imag can be chained and mixed +with external tools pretty easily: +.IP +.nf +\f[C] +imag -O ids where \[aq]some.header == 1\[aq] | \[rs] +imag -I -O tag add foo | \[rs] +imag -I -O category set bar | \[rs] +fzf | \[rs] +imag -I tag add baz +\f[R] +.fi +.PP +The first line gets all imag entries where \f[C]some.header\f[R] equals +\f[C]1\f[R]. +The touched entries are printed to \f[C]stdout\f[R] (\f[C]-O\f[R]). +The second line tags all entries which are passed via \f[C]stdin\f[R] +(\f[C]-I\f[R]) with \f[C]foo\f[R] and prints them to \f[C]stdout\f[R] +(\f[C]-O\f[R]) The third line sets the category for all entries which +are passed via \f[C]stdin\f[R] with \f[C]bar\f[R] and prints them to +\f[C]stdout\f[R]. +The fourth line calls the \f[C]fzf\f[R] program and lets the user select +one entry and the last line reads that entry via \f[C]stdin\f[R] and +tags it with \f[C]baz\f[R]. +.PP +Automatically detecting the appropriate input/output settings is +possible, but hidden behind a environment-flag, as it is considered +experimental. +To test this, set \f[C]IMAG_IO_EXPERIMENTAL=1\f[R] in your environment. +Note that \f[C]stdin\f[R] may be detected as \[lq]store id stream\[rq] +when it is actually not. +\f[C]libimagrt\f[R] can take care of this when passing +\f[C]--interactive\f[R]. +.SS Input +.PP +\f[C]libimagrt\f[R] also provides primitives for input. +As documented in the paragraph on \[lq]Output\[rq], imag tools may get +store ids passed via \f[C]stdin\f[R]. +Hence, imag tools may/can not interactive when passing store ids via +\f[C]stdin\f[R]. +\f[C]libimagrt\f[R] provides functionality to query data from the user. +These functions automatically fail if the user passes store-ids via +\f[C]stdin\f[R]. +.PP +The next paragraph documents the details of this and may be skipped. +.PP +The user tells imag that \f[C]stdin\f[R] contains store-ids by setting +the \f[C]-I\f[R] (\f[C]--ids-in\f[R]) flag on the commandline. +If that flag is given, the interactive funct