summaryrefslogtreecommitdiffstats
path: root/content/doc/web/0.10.0/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'content/doc/web/0.10.0/index.html')
-rw-r--r--content/doc/web/0.10.0/index.html1491
1 files changed, 1491 insertions, 0 deletions
diff --git a/content/doc/web/0.10.0/index.html b/content/doc/web/0.10.0/index.html
new file mode 100644
index 0000000..4b91ab1
--- /dev/null
+++ b/content/doc/web/0.10.0/index.html
@@ -0,0 +1,1491 @@
+<!DOCTYPE html>
+<html lang="de">
+<head>
+ <meta charset="utf-8">
+ <meta name="generator" content="pandoc">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
+
+ <meta name="dcterms.date" content="December 2019">
+
+ <title>imag User Documentation</title>
+ <style type="text/css">code{white-space: pre;}</style>
+ <!--[if lt IE 9]>
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+
+ <style type="text/css">
+ pre > code.sourceCode { white-space: pre; position: relative; }
+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
+ pre > code.sourceCode > span:empty { height: 1.2em; }
+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
+ div.sourceCode { margin: 1em 0; }
+ pre.sourceCode { margin: 0; }
+ @media screen {
+ div.sourceCode { overflow: auto; }
+ }
+ @media print {
+ pre > code.sourceCode { white-space: pre-wrap; }
+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
+ }
+ pre.numberSource code
+ { counter-reset: source-line 0; }
+ pre.numberSource code > span
+ { position: relative; left: -4em; counter-increment: source-line; }
+ pre.numberSource code > span > a:first-child::before
+ { content: counter(source-line);
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
+ border: none; display: inline-block;
+ -webkit-touch-callout: none; -webkit-user-select: none;
+ -khtml-user-select: none; -moz-user-select: none;
+ -ms-user-select: none; user-select: none;
+ padding: 0 4px; width: 4em;
+ color: #aaaaaa;
+ }
+ pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
+ div.sourceCode
+ { }
+ @media screen {
+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
+ }
+ code span.al { color: #ff0000; font-weight: bold; } /* Alert */
+ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
+ code span.at { color: #7d9029; } /* Attribute */
+ code span.bn { color: #40a070; } /* BaseN */
+ code span.bu { } /* BuiltIn */
+ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
+ code span.ch { color: #4070a0; } /* Char */
+ code span.cn { color: #880000; } /* Constant */
+ code span.co { color: #60a0b0; font-style: italic; } /* Comment */
+ code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
+ code span.do { color: #ba2121; font-style: italic; } /* Documentation */
+ code span.dt { color: #902000; } /* DataType */
+ code span.dv { color: #40a070; } /* DecVal */
+ code span.er { color: #ff0000; font-weight: bold; } /* Error */
+ code span.ex { } /* Extension */
+ code span.fl { color: #40a070; } /* Float */
+ code span.fu { color: #06287e; } /* Function */
+ code span.im { } /* Import */
+ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
+ code span.kw { color: #007020; font-weight: bold; } /* Keyword */
+ code span.op { color: #666666; } /* Operator */
+ code span.ot { color: #007020; } /* Other */
+ code span.pp { color: #bc7a00; } /* Preprocessor */
+ code span.sc { color: #4070a0; } /* SpecialChar */
+ code span.ss { color: #bb6688; } /* SpecialString */
+ code span.st { color: #4070a0; } /* String */
+ code span.va { color: #19177c; } /* Variable */
+ code span.vs { color: #4070a0; } /* VerbatimString */
+ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
+ </style>
+
+ <link rel="stylesheet" href="/home/m/archive/development/rust/imag/doc/templates/css/table.css">
+
+</head>
+ <body style="margin-left: 20%; margin-right: 20%;">
+ <header>
+ <h1 class="title">imag User Documentation</h1>
+ <small class="date">December 2019</small>
+
+ <small class="date">Version: 0.10.0</small>
+ </header>
+ <hr />
+
+ <h1 id="sec:introduction">Introduction</h1>
+ <p>This document is the user documentation for imag, the personal information management suite for the commandline.</p>
+ <p><strong>Basically: This is Hobby stuff. Expect incompleteness, outdated documentation, false statements and generally read with grain of salt.</strong></p>
+ <p>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.</p>
+ <h2 id="sec:intro:problem">The Problem</h2>
+ <p>The problem this project tries to solve is to provide a modular commandline application for personal information management.</p>
+ <p>It targets “power users” or “commandline users”, uses plain text as a storage format and tries to be as scriptable as possible. imag offers the ability to link data from different “PIM aspects” (such as “diary”, “contacts” and “bookmark” for example).</p>
+ <p>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.</p>
+ <p>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.</p>
+ <h2 id="sec:intro:approach">The Approach</h2>
+ <p>The approach “imag” takes on solving this problem is to store content in a “store” 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 “domain modules” using the store. While content is stored in <em>one</em> 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.</p>
+ <p>Detailed explanation on this approach follows in the chapters of this work.</p>
+ <h2 id="sec:intro:implementation">Implementation</h2>
+ <p>The program is written in the Rust programming language.</p>
+ <p>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.</p>
+ <p>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.</p>
+ <h2 id="sec:intro:alternatives">Alternative Projects</h2>
+ <p>imag is not the only project which tries to solve that particular problem. For example there is <a href="https://orgmode.org">org mode</a> for the <a href="https://www.gnu.org/software/emacs/">emacs</a> text editor. There is also <a href="http://zim-wiki.org/">zim</a>, a desktop wiki editor which is intended to be used for a personal wiki.</p>
+ <p>The difference between imag and the mentioned projects is: * emacs orgmode is (from what I know and see) for <em>orgabizing</em> 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</p>
+ <p>imag is not there yet, though. Some parts can be used, though it is far away from being feature-complete.</p>
+ <p>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 “grep”, “awk” and “sed” entries without much hassle and even write bash scripts for automatically filling imag entries with data.</p>
+ <h1 id="architecture-of-the-imag-code">Architecture of the imag code</h1>
+ <p>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.</p>
+ <h2 id="crate-types">Crate types</h2>
+ <p>There are different types of crates in the imag world:</p>
+ <ul>
+ <li>“core” crates:
+ <ul>
+ <li>libimagstore - The imag store is the abstraction over the filesystem. It provides primitives to get, write and manipulate store entries and their header information.</li>
+ <li>libimagrt - The runtime library, which provides default argument parser setup, interfacing with STDIN/STDOUT, configuration loading and parsing. Simply put: It provides the runtime for a imag commandline application.</li>
+ <li>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. (Note: This library might be removed in the future.)</li>
+ </ul></li>
+ <li>“entry” crates: “Entry” crates provide extensional functionality for the types from libimagstore. For example, there is “libimagentrylink” which provides functionality to link two entries in the store.</li>
+ <li>“domain” crates offer end-user functionality for a imag domain, for example “libimagtodo” provides functionality to track todos.</li>
+ <li>“etc”/“util” crates for simple utilities.</li>
+ </ul>
+ <p>These are all libraries. There are also binary crates in the imag project (though they are technically <em>also</em> library crates):</p>
+ <ul>
+ <li>“core” binary crates, which implement core functionality of imag, such as commandline interfaces for tagging, linking, … entries as well as querying them from the store and altering their data.</li>
+ <li>“domain” binary crates, which implement a domain such as “todo” handling or “calendar” handling.</li>
+ </ul>
+ <h2 id="architecture-of-an-imag-module">Architecture of an imag module</h2>
+ <p>With the things from above, a module could have the following architecture:</p>
+ <pre><code>+-----------------------------------+---------+
+ | imag-foo | |
+ +-----------------------------------+ |
+ | libimagfoo | |
+ +-----------------+-----------------+ |
+ | | | |
+ | libimagentrybar | libimagentrybaz | |
+ | | | lib |
+ +-----------------+-----------------+ |
+ | | |
+ | &lt;more library crates&gt; | |
+ | | imag |
+ +-----------------------------------+ |
+ | | |
+ | libimagstore | rt |
+ | | |
+ +-----------------------------------+---------+</code></pre>
+ <p>External dependencies are not listed in this graphic.</p>
+ <p>The foundation of all imag modules is the store, as one can see in the visualization from above. Above the store level, entry libraries and domain libraries are used to implement functionality. 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. libimagrt is used by the binary to construct the runtime, which itself constructs and initializes the Store, so this library is used in the full stack more or less.</p>
+ <p>Theoretically, the commandline interface crate could be replaced to build a terminal user interface, graphical user interface or web interface.</p>
+ <h2 id="types">Types</h2>
+ <p>The imag core, hence the libimagstore and libimagrt, provide a set of types that a user (as in a library writer) should be aware of.</p>
+ <p>First of all, there is the <code>Runtime</code> 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 <code>Store</code>.</p>
+ <p>The <code>Store</code> type is provided by the libimagstore library, the heart of everything.</p>
+ <p>When interacting with the store, two types are visible: <code>FileLockEntry</code> and <code>Entry</code> whereas the former derefs to the latter, which basically means that the former wraps the latter. The <code>FileLockEntry</code> is a necessary wrapper for ensuring that when working concurrently with the store, an entry is only <em>borrowed</em> once from the store. It also ensures that the object is alive as long as the store is.</p>
+ <p>The <code>Entry</code> 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 <code>FileLockEntry</code>.</p>
+ <p>The <code>Entry</code> provides access to its header, which is a <code>toml::Value</code>, where toml is the toml-rs crate (external project). Convenience functionality is provided via the <code>toml-query</code> crate, an external project which was initiated and extracted from the imag project.</p>
+ <h1 id="sec:thestore">The Store</h1>
+ <p>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.</p>
+ <p>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 <em>really</em> much won’t exceed the Gigabytes ever.</p>
+ <p>Having a storage format which is plain-text based is the superior approach, as text editors will always be there.</p>
+ <p>A user should always be able to read her data without great effort and putting everything in a <em>real</em> database like sqlite or even postgresql would need a user to install additional software just to read his own data. We don’t want that. Text is readable until the worlds end and we think it is therefore better to store the data in plain text.</p>
+ <p>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.</p>
+ <h2 id="sec:thestore:fileformat">File Format</h2>
+ <p>The contents of the store are encoded in UTF-8. A normal text editor (like <code>vim</code> or the other one) will always be sufficient to dig into the store and modify files. For simple viewing even a pager (like <code>less</code>) is sufficient.</p>
+ <p>Each entry in the store consists of two parts:</p>
+ <ol type="1">
+ <li>Header</li>
+ <li>Content</li>
+ </ol>
+ <p>The following section describe their purpose.</p>
+ <h3 id="sec:thestore:fileformat:header">Header Format</h3>
+ <p>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 (<code>---</code>). Between these three dashes there is structured data. imag uses <code>TOML</code> as data format for this structured data.</p>
+ <p>The header can contain any amount of data, but modules (see Section 6) are restricted (by convention) in their way of altering the data.</p>
+ <p>Normally there are several sections in the header. One section (<code>[imag]</code>) is always present, it is automatically created by the store and contains a <code>version</code> field, which tells imag which version this file was created with. The store automatically verifies that it is compatible (satisfying semver) with the version of imag an entry was created with, and if it is not, it fails loading the entry.</p>
+ <p>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 or write other sections than its own.</p>
+ <h3 id="sec:thestore:fileformat:content">Content Format</h3>
+ <p>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 any specific markup.</p>
+ <p>Technically it would be possible that the content part of a file is used to store binary data. We don’t want this, though, as it is contrary to the goals of imag.</p>
+ <h3 id="sec:thestore:fileformat:example">Example</h3>
+ <p>An example for a file in the store follows.</p>
+ <pre class="text"><code>
+ ---
+ [imag]
+ version = &quot;0.10.0&quot;
+
+ [note]
+ name = &quot;foo&quot;
+
+ [link]
+ internal = [&quot;some/other/imag/entry&quot;]
+ ---
+
+ This is an example text, written by the user.
+ </code></pre>
+ <h2 id="sec:thestore:fileorganization">File organization</h2>
+ <p>The “Entries” are stored as files in the “Store”, 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.</p>
+ <p>Each module stores its data in an own subdirectory in the store, by convention.</p>
+ <p>The path to a file in the store is named “Store id” (or short “ID”) and we refer to it by using the store location as root. So if the store exists in <code>/home/user/.imag/store/</code>, a file with the storepath <code>example.file</code> is (on the filesystem) located at <code>/home/user/.imag/store/example.file</code>.</p>
+ <p>By convention, each <code>libimagentry&lt;name&gt;</code> and <code>libimag&lt;name&gt;</code> module stores its entries in in <code>&lt;name&gt;/</code>.</p>
+ <p>So, the pattern for the storepath is</p>
+ <pre><code>&lt;module name&gt;/&lt;optional sub-folders&gt;/&lt;file name&gt;</code></pre>
+ <p>Any number of subdirectories may be used, so creating folder hierarchies is possible and valid. A file “example” for a module “module” could be stored in sub-folders like this:</p>
+ <pre><code>module/some/sub/folder/example</code></pre>
+ <p>The above is not enforced or a strict rule, but rather a “rule of thumb”.</p>
+ <h2 id="sec:thestore:backends">Backends</h2>
+ <p>The store itself also has a backend. This backend is the “filesystem abstraction” code.</p>
+ <p>Note: This is a very core thing. Casual users might want to skip this section.</p>
+ <h3 id="sec:thestore:backends:problem">Problem</h3>
+ <p>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.</p>
+ <p>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.</p>
+ <p>Hence we implemented store backends.</p>
+ <h3 id="sec:thestore:backends:implementation">Implementation</h3>
+ <p>The filesystem is abstracted via a trait <code>FileAbstraction</code> which contains the essential functions for working with the filesystem.</p>
+ <p>Two implementations are provided in the code:</p>
+ <ul>
+ <li>FSFileAbstraction</li>
+ <li>InMemoryFileAbstraction</li>
+ </ul>
+ <p>whereas the first actually works with the filesystem and the latter works with an in-memory HashMap that is used as filesystem.</p>
+ <p>Further, the trait <code>FileAbstractionInstance</code> was introduced for functions which are executed on actual instances of content from the filesystem, which was previousely tied into the general abstraction mechanism.</p>
+ <p>So, the <code>FileAbstraction</code> trait is for working with the filesystem, the <code>FileAbstractionInstance</code> trait is for working with instances of content from the filesystem (speak: actual Files).</p>
+ <p>In case of the <code>FSFileAbstractionInstance</code>, which is the implementation of the <code>FileAbstractionInstance</code> for the actual filesystem-hitting code, the underlying resource is managed like with the old code before. The <code>InMemoryFileAbstractionInstance</code> implementation is corrosponding to the <code>InMemoryFileAbstraction</code> implementation - for the in-memory “filesystem”.</p>
+ <h1 id="conventions-best-practices">Conventions, best practices</h1>
+ <p>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.</p>
+ <p>Lets work our way up from the store and how to extend it to the commandline user interface.</p>
+ <h2 id="versioning">Versioning</h2>
+ <p>All imag crates are versioned with the same version number until we reach some <code>"1.0.0"</code> 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.</p>
+ <h2 id="store-and-entry-functionality">Store and Entry functionality</h2>
+ <p>A <code>Entry</code> does not offer much functionality by itself. So its the job of libraries to <em>extend</em> its functionality. This should never be done by wrapping the <code>Entry</code> type itself but by providing and implementing an extension trait on it.</p>
+ <p>Same goes for extending the <code>Store</code> type: never wrap it, always provide an extension trait for it.</p>
+ <p>These two rules ensure that the type does not lose any functionality from a wrapping. <code>Deref</code> 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 <code>Result&lt;_, _&gt;</code>.</p>
+ <h2 id="libraries">Libraries</h2>
+ <p>In the next few sections, conventions and best practices for writing a imag library are written down.</p>
+ <p>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.</p>
+ <h3 id="library-naming">Library naming</h3>
+ <p>Libraries which provide functionality for entries or the store but no domain-functionality should be named “libimagentrything” whereas “thing” stands for what the library provides.</p>
+ <p>All domain libraries should be prefixed with “libimag”.</p>
+ <h3 id="library-scope">Library scope</h3>
+ <p>A library should never introduce utility functionality which could be useful for other libraries as well. If there is no such functionality available, the “libimagutil” or “libimagentryutil” might be a place where such a function would go to.</p>
+ <p>If a library has to introduce free functions in its public interface, one should think hard whether this is really necessary.</p>
+ <h3 id="library-error-typeskinds">Library error types/kinds</h3>
+ <p>Libraries must use “failure” to create error objects.</p>
+ <h3 id="libraries-with-commandline-frontends">Libraries with commandline frontends</h3>
+ <p>Libraries with commandline frontends provide end-user functionality. They are called “domain” libraries. Normally, they depend on one or more “libimagentrything” libraries. They should be named “libimagthing”, though. For example: “libimagdiary”, “libimagtimetrack” or “libimagwiki”, whereas the commandline frontends would be “imag-diary”, “imag-timetrack” and “imag-wiki”, respectively.</p>
+ <p>If such a library needs to depend on another “libimagthing”, for example if “libimagdiary” needs to depend on “libimagnote”, one should think about this and whether the functionality could be outsourced to a more general “libimagentrything”.</p>
+ <h3 id="library-testing">Library testing</h3>
+ <p>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!</p>
+ <h2 id="commandline-tools">Commandline tools</h2>
+ <p>The commandline tools are the CLI-frontends for their respective libraries. So <code>libimagdiary</code> has a CLI frontend <code>imag-diary</code>.</p>
+ <p>Those CLI frontends use functionality from <code>libimagrt</code> to build a commandline interface which is consistent with the rest of the ecosystem.</p>
+ <p>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).</p>
+ <p>Commandline applications are <em>only</em> interactive when specified by the user (normally via a <code>--interactive</code> flag). An application <em>must</em> provide the full functionality via its commandline interface, thus it is not allowed to provide functionality which is only usable in interactive mode.</p>
+ <h3 id="io">IO</h3>
+ <p>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 <code>libimagrt</code> to do IO of any kind.</p>
+ <p>For more information, or if not using Rust as programming language: the documentation of <code>libimagrt</code> describes how IO should happen (which output stream to use, how input should be done).</p>
+ <h1 id="writing-an-imag-module">Writing an imag module</h1>
+ <p>So you want to write a module for imag. That’s nice.</p>
+ <p>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.</p>
+ <h2 id="data-layout">Data layout</h2>
+ <p>First, you have to think about what data you want to store. What functionality do you want to provide and what data that creates.</p>
+ <p>In this example, we’re writing a module that stores numbers. We’re writing the appropriate library for that as well as a commandline frontend.</p>
+ <h2 id="libimagnumberstorage">libimagnumberstorage</h2>
+ <p>We’re writing a <code>libimagnumberstorage</code> which provides the core functionality of our module: Storing numbers.</p>
+ <p>That library can then be used by other library authors and by the commandline interface implementation.</p>
+ <h3 id="setup">Setup</h3>
+ <p>So what do we need to do to write this library:</p>
+ <ol type="1">
+ <li>Create a new “lib” crate. Because we’re writing a “domain” library, we’re doing this in the <code>lib/domain</code> subdirectory: <code>cd lib/domain; cargo new --lib libimagnumberstorage</code>.</li>
+ <li>After creating the library, we have to add the new library to the <code>/Cargo.toml</code> field and add the missing metadata in the new <code>/lib/domain/libimagnumberstorage/Cargo.toml</code> file.</li>
+ </ol>
+ <p>That was the setup part. Now we can implement our functionality. For that, we need to <em>extend</em> two types from <code>libimagstore</code>, so we have our first dependency here.</p>
+ <h3 id="dependencies-to-other-libraries">Dependencies to other libraries</h3>
+ <ol start="3" type="1">
+ <li>Put <code>libimagstore</code> as a dependency in the <code>/lib/domain/libimagnumberstorage/Cargo.toml</code> file. By using <code>libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }</code> we automatically get all the goodness of Cargo, so that releases automagically work as expected, but when developing locally, the local version of <code>libimagstore</code> is used. Of course, the <code>version</code> has to be the latest released version.</li>
+ <li>For error handling, we also need to import <code>libimagerror</code>.</li>
+ <li>For easy header-editing, we import <code>toml</code> and <code>toml-query</code>.</li>
+ <li>For error-type creating, we import <code>error-chain</code>.</li>
+ </ol>
+ <h3 id="interface">Interface</h3>
+ <ol start="7" type="1">
+ <li>Then, we have to <em>extend</em> two types:
+ <ol type="1">
+ <li><code>libimagstore::store::Store</code> has to be extended so we can implement a CRUD interface for our special entries.</li>
+ <li><code>libimagstore::store::Entry</code> has to be extended so we can get our stored numbers in a convenient way.</li>
+ </ol></li>
+ </ol>
+ <p>Our interface should roughly look like this:</p>
+ <pre><code>store.get_stored_number(&quot;5&quot;) -&gt; Result&lt;FileLockEntry, _&gt;
+ store.store_number(&quot;5&quot;) -&gt; Result&lt;FileLockEntry, _&gt;
+ store.delete_number(&quot;5&quot;) -&gt; Result&lt;(), _&gt;</code></pre>
+ <p>You notice that the <code>Store</code> returns <code>FileLockEntry</code> objects rather than <code>Entry</code> objects. And that’s ok. A <code>FileLockEntry</code> is a <code>Entry</code>, but ensures that we are the only ones editing that entry. So, we have to implement our number-storing-interface on <code>Entry</code> as well:</p>
+ <pre><code>entry.get_number() -&gt; Result&lt;usize&gt;
+ entry.set_number(usize) -&gt; Result&lt;()&gt;</code></pre>
+ <p>All those “extensions” are implemented as traits which are then implemented for <code>Store</code> and <code>Entry</code>.</p>
+ <p>Normally, we create new files for that, as well as for the error types we need:</p>
+ <ul>
+ <li><code>/lib/domain/libimagnumberstorage/src/store.rs</code></li>
+ <li><code>/lib/domain/libimagnumberstorage/src/entry.rs</code></li>
+ <li><code>/lib/domain/libimagnumberstorage/src/error.rs</code></li>
+ </ul>
+ <p>where <code>store.rs</code> contains a trait <code>NumberStorage</code> and <code>entry.rs</code> contains a trait <code>NumberEntry</code>. <code>error.rs</code> contains the invocation of the <code>error_chain!{}</code> macro. Error types from <code>libimagstore</code> and others are linked in.</p>
+ <h1 id="sec:modules">Modules</h1>
+ <p>A module is a functionality of the program. There is a huge list of modules available in the imag core distribution.</p>
+ <p>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 “domains”.</p>
+ <p>We try really hard to offer a consistent commandline user interface over all of these modules.</p>
+ <p>The following sections describe each module in detail, including its purpose and its provided functionality.</p>
+ <h2 id="sec:modules:bookmarks">Bookmarks</h2>
+ <p>The Bookmarks module is for keeping URLs as bookmarks, tagging and categorizing them and finally also open them in the browser.</p>
+ <h2 id="sec:modules:category">Category</h2>
+ <p>A tool to create categories and set/get them for entries.</p>
+ <p>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 “category entry” internally.</p>
+ <h2 id="sec:modules:diary">Diary</h2>
+ <p>The diary module is for keeping your diary notes.</p>
+ <p>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).</p>
+ <p>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.</p>
+ <h2 id="sec:modules:edit">Edit</h2>
+ <p>The <code>imag-edit</code> command is for simply editing store entries with the <code>$EDITOR</code>.</p>
+ <p>It is based on libimagentryedit (Section 7.8).</p>
+ <h2 id="sec:modules:entry">Entry</h2>
+ <p>Plumbing tool for modifying and querying structured data in entries.</p>
+ <h2 id="sec:modules:init">Init</h2>
+ <p>This is the only <code>imag-*</code> command which does <em>not</em> set up a runtime and check whether the store is available. This command can be used to set up a imag store.</p>
+ <p>It also puts a default configuration in the right place and initializes a git repository, if there is a <code>git</code> command in <code>$PATH</code> (via calling git on the commandline, not via <code>libgit2</code> or some other library).</p>
+ <h2 id="sec:modules:link">Link</h2>
+ <p>The linking module <code>imag-link</code> is one of the plumbing modules. It offers the possibility to link entries in the store.</p>
+ <p>It also offers the functionality to link to external sources. This functionality <em>can</em> be used to link to external URLs, but the bookmarking module should be used to do this (see Section 6.1).</p>
+ <p>The linking module offers functionality to add, remove and list both internal (store entry to store entry) and external (store entry to URL) links.</p>
+ <h3 id="internal-linking">Internal linking</h3>
+ <!-- internal linking description remains to be written -->
+ <h3 id="external-linking">External linking</h3>
+ <p>A store entry can only have <em>one</em> 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.</p>
+ <h2 id="sec:modules:log">Log</h2>
+ <p>The “imag-log” module is a lightweight interface to the “imag-diary” command.</p>
+ <p>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:</p>
+ <h3 id="usage">Usage</h3>
+ <p>Logs can be created via an entry in the configuration file in the section <code>log</code>:</p>
+ <pre><code>[log]
+ logs = [&quot;work&quot;, &quot;hobby&quot;, &quot;music&quot;]
+ default = &quot;hobby&quot;</code></pre>
+ <p>The <code>default</code> key is required and the name which is used here <em>must</em> appear in the <code>logs</code> array.</p>
+ <p>In the above configuration snippet, the logs <code>work</code>, <code>hobby</code> and <code>music</code> are created. The user may now log to one of these logs with:</p>
+ <pre><code>imag log --to &lt;logname&gt; &quot;Some message&quot;
+ # or
+ imag log -t &lt;logname&gt; &quot;Some message&quot;
+ # or, to the default log:
+ imag log &quot;Some message&quot;</code></pre>
+ <p>Logs can be read by naming the log:</p>
+ <pre><code>imag log show work</code></pre>
+ <p>which prints one log per line (including time it was logged).</p>
+ <h2 id="sec:modules:mails">Mails</h2>
+ <hr />
+ <p><strong>NOTE:</strong> This is mostly a todo-list for the <code>imag-mail</code> command. Nothing shown here is implemented. This “documentation-to-be” should be moved to <code>imag-mail --help</code> eventually. This list might be incomplete, details might be not possible to implement in the way described or other dragons.</p>
+ <p><strong>Target audience:</strong> People who want to implement <code>imag-mail</code>.</p>
+ <hr />
+ <p>The Mails module implements a commandline email client. Emails can be written (via <code>$EDITOR</code>) and viewed, also in threads. Emails can be crawled for creating new contacts.</p>
+ <p>A Text User Interface is not planned, but might be there at some point.</p>
+ <p>The mail module implements a minimal Email client. It does not handle IMAP syncing or SMTP things, it is just a <em>viewer</em> for emails (a MUA).</p>
+ <p>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 <code>imag-link</code> to link an entry with a mail - or the imag entry representing that mail).</p>
+ <p>So this module offers functionality to read (Maildir) mailboxes, search for and list mails and mail-threads and reply to mails (by spawning the <code>$EDITOR</code>).</p>
+ <p>Outgoing mails are pushed to a special directory and can later on be send via <code>imag-mail</code> which calls a MTA (for example msmtp) and also creates store entries for the outgoing mails.</p>
+ <h3 id="configuration">Configuration</h3>
+ <p>The following configuration variables are available for the imag-mail command:</p>
+ <ul>
+ <li><code>mail.defaultaccount</code>: 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 <code>mail.accounts</code> array.</li>
+ <li><code>mail.accounts</code>: An array of account configuration. Each element in the array is a table of the following key-value pairs:
+ <ul>
+ <li><code>name</code>: the name of the account. Names must be unique. Required.</li>
+ <li><code>outgoingbox</code>: Path to mailbox to use for outgoing email. Required.</li>
+ <li><code>draftbox</code>: Path to mailbox to use for outgoing email. Required.</li>
+ <li><code>sentbox</code>: Path to mailbox to use for sent email. Required. <code></code>maildirroot`: Path to folder where all mailboxes for this account are located. Required.</li>
+ <li><code>fetchcommand</code>: What commandline to invoke for fetching mails for this account. Optional - if not used, the global <code>mail.fetchcommand</code> will be used.</li>
+ <li><code>postfetchcommand</code>: What commandline to invoke after fetching mails for this account. Optional - if not used, the global <code>mail.postfetchcommand</code> will be used.</li>
+ <li><code>sendcommand</code>: What commandline to invoke for sending mails for this account. Optional - if not used, the global <code>mail.sendcommand</code> will be used.</li>
+ <li><code>postsendcommand</code>: What commandline to invoke after sending mails for this account. Optional - if not used, the global <code>mail.postsendcommand</code> will be used.</li>
+ </ul></li>
+ <li><code>mail.fetchcommand</code>: Command to use for fetching mail if no account-specific command was specified Available variables:
+ <ul>
+ <li><code>accountname</code> - name of the account to fetch mail for.</li>
+ <li><code>boxes</code> - 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 <code>offlineimap</code> might look like this: <code>offlineimap -a accountname -f concatsep "," (replace "/home/user/mails/" "" boxes)</code> to concatenate all boxes with a comma after removing a prefix. For a complete list of transformation functions, the <code>--help</code> flag shall be consulted. For more complicated transformations a bash/ruby/python script might be appropriate.</li>
+ </ul></li>
+ <li><code>mail.postfetchcommand</code>: Command to use after fetching mail if no account-specific command was specified Available variables: Same as <code>mail.fetchcommand</code>.</li>
+ <li><code>mail.postsendcommand</code>: Command to use after sending mail if no account-specific command was specified Available variables: Same as <code>mail.sendcommand</code>.</li>
+ <li><code>mail.sendcommand</code>: Command to use for sending mail if no account-specific command was specified
+ <ul>
+ <li><code>accountname</code> - name of the account to fetch mail for.</li>
+ <li><code>mailfile</code> - The path of the mail to send</li>
+ </ul></li>
+ </ul>
+ <h3 id="cli">CLI</h3>
+ <p>The CLI of the imag-mail module is planned as follows:</p>
+ <ul>
+ <li><p>imag mail</p>
+ <p>-A, –account - Specify the “account” to use for the opperation by name. If none is specified, the configuration is searched for a default command.</p></li>
+ <li><p>imag mail track <path> [opts…] Track a new mail, mail file passed as path</p></li>
+ <li><p>imag mail scan <path> [opts…] Scan a maildir and track all untracked mails</p>
+ <p>–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’s another entry in the imag store refering to the same file.</p></li>
+ <li><p>imag mail list &lt;args…&gt; List mails in a given mailbox for a given account or the default account</p>
+ <p>-S, –style - print messages in a certain style Available: - ‘linewise’ - ‘thread’</p>
+ <p>-g, –grep - Filter by grepping for a pattern in body and subject</p>
+ <p>-d, –daterange - Filter by date(range)</p>
+ <p>-F, –filter - Filter by passed filter</p>
+ <pre><code> --thread - Print only messages from the same thread as the found ones</code></pre>
+ <p>–format=<fmt> - Format mails for showing. –format always colorizes output (specify color in config) except when using –no-pager or piping output.</p>
+ <pre><code> When --tree is passed, the format is applied to the
+ fragment _after_ the tree graphic.
+
+ Default mode is &#39;default&#39;.
+
+ Modes:
+ - &#39;subject&#39;: &lt;Subject&gt;
+ - &#39;simple&#39;: &lt;From&gt;: &lt;Subject&gt;
+ - &#39;default&#39;: &lt;Date&gt; - &lt;From&gt;: &lt;Subject&gt;
+ - &#39;fmt:&lt;fmt&gt;&#39; 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.</code></pre>
+ <p>–color - Colorize output (default). –no-color - Do never colorize output.</p></li>
+ <li><p>imag mail show &lt;args…&gt; Sho