commit
212ff3945e
7 changed files with 203 additions and 148 deletions
|
@ -2,13 +2,21 @@
|
|||
|
||||
This document is the user documentation for imag, the personal
|
||||
information management suite for the commandline. Besides beeing a documentation,
|
||||
it servey also as "roadmap" where this project should go. Parts which are not
|
||||
yet implemented might be documented already, therefore. A list on what is
|
||||
implemented and what is not can be found at the end of this document.
|
||||
it serves also as "roadmap" where this project should go. Parts which are not
|
||||
yet implemented might be documented already, therefore. Also, because this is a
|
||||
hobby thing, parts which are implemented might be documented falsely or not at
|
||||
all.
|
||||
A list on what is implemented and what is not can be found at the end of this
|
||||
document.
|
||||
It might be outdated though.
|
||||
|
||||
**Basically: This is Hobby stuff. Expect incompleteness, false statements and
|
||||
generally read with big grain of salt.**
|
||||
|
||||
If you have any objections, suggestions for improvements, bugs, etc, please file
|
||||
them. A way to reach out to the imag project maintainer(s) is described in the
|
||||
CONTRIBUTING file of the repository or in this document, on the appropriate
|
||||
them.
|
||||
A way to reach out to the imag project maintainer(s) is described in the
|
||||
CONTRIBUTING file of the repository or in this document, on the appropriate
|
||||
section.
|
||||
|
||||
## The Problem {#sec:intro:problem}
|
||||
|
@ -28,6 +36,9 @@ date, but that _all things_ can be linked together. For example that a wiki
|
|||
article can be linked to a date which is linked to a todo which is linked to a
|
||||
note which is linked to a contact.
|
||||
|
||||
Also, having an all-in-one scriptable modular commandline personal information
|
||||
management suite seemed nice at the time and still does.
|
||||
|
||||
## The Approach {#sec:intro:approach}
|
||||
|
||||
The approach "imag" takes on solving this problem is to store content in a
|
||||
|
|
|
@ -1,23 +1,41 @@
|
|||
# Architecture of the imag code
|
||||
|
||||
The imag codebase has a rather simple overall architecture. But before introducing the reader to it, a few things have to be introduced.
|
||||
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.
|
||||
|
||||
## Crate types
|
||||
|
||||
There are different types of crates in the imag world. A crate is a rust project.
|
||||
There are different types of crates in the imag world. A crate is a rust
|
||||
project.
|
||||
|
||||
First of all, there are core crates. These crates provide the very core of imag and almost all other crates use them:
|
||||
First of all, there are core crates. These crates provide the very core of imag
|
||||
and almost all other crates use them:
|
||||
|
||||
* libimagstore - The imag store is the abstraction overbthe filesystem. It provides primitives to get, write and manipulate store entries and their header information.
|
||||
* 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 "clap" crate).
|
||||
* 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.
|
||||
* libimagstore - The imag store is the abstraction over the filesystem. It
|
||||
provides primitives to get, write and manipulate store entries and their
|
||||
header information.
|
||||
* 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 "clap" crate).
|
||||
* 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.
|
||||
* libimagutil - Utilities.
|
||||
|
||||
The next type of imag crates are entry extension libraries. Those provide extensional functionality for the types from libimagstore. For example, there is "libimagentrylink" which provides functionality to link two entries in the store.
|
||||
The next type of imag crates are entry extension libraries. Those provide
|
||||
extensional functionality for the types from libimagstore. For example, there is
|
||||
"libimagentrylink" which provides functionality to link two entries in the
|
||||
store.
|
||||
|
||||
The next kind of crate is the one that offers end-user functionality for a imag aspect, for example "libimagtodo" provides functionality to track todos.
|
||||
The third kind of crate is the one that offers end-user functionality for a imag
|
||||
domain, for example "libimagtodo" provides functionality to track todos.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Besides these, there are some other utility crates.
|
||||
|
||||
## Architecture of an imag module
|
||||
|
||||
|
@ -47,22 +65,47 @@ With the things from above, a module could have the following architecture:
|
|||
+-----------------------------------+---------+
|
||||
```
|
||||
|
||||
The foundation of all imag modules is the store, as one can see from the image. Above this there is the libimagrt, which provides the basic runtime and access to the `Store` 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.
|
||||
The foundation of all imag modules is the store, as one can see in the image.
|
||||
Above the store library there is the libimagrt, which provides the basic runtime
|
||||
and access to the `Store` 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.
|
||||
|
||||
Theoretically, the commandline interface crate could be replaced to build a
|
||||
terminal user interface, graphical user interface or web interface.
|
||||
|
||||
## Types
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
First of all, there is the Runtime 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 `Store`.
|
||||
First of all, there is the `Runtime` 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 `Store`.
|
||||
|
||||
It is provided by the libimagstore library, the heart of everything.
|
||||
The `Store` type is provided by the libimagstore library, the heart of
|
||||
everything.
|
||||
|
||||
When interacting with the store, two types are visible: `FileLockEntry` and `Entry` whereas the former derefs to the latter, which basically means that the former wraps the latter.
|
||||
The `FileLockEntry` is a necessary wrapper for ensuring that when working concurrently with the store, an entry is only _borrowed_ once from the store. It also ensures that the object is alive as long as the store is.
|
||||
When interacting with the store, two types are visible: `FileLockEntry` and
|
||||
`Entry` whereas the former derefs to the latter, which basically means that the
|
||||
former wraps the latter. The `FileLockEntry` is a necessary wrapper for
|
||||
ensuring that when working concurrently with the store, an entry is only
|
||||
_borrowed_ once from the store. It also ensures that the object is alive as long
|
||||
as the store is.
|
||||
|
||||
The `Entry` 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 `FileLockEntry`.
|
||||
The `Entry` 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 `FileLockEntry`.
|
||||
|
||||
The `Entry` provides access to its header, which is a `toml::Value`, where toml is the toml-rs crate (external project). Conveniance functionality is provided via the `toml-query` crate, which is an external project which was initiated and extracted from the imag project.
|
||||
The `Entry` provides access to its header, which is a `toml::Value`, where toml
|
||||
is the toml-rs crate (external project). Convenience functionality is provided
|
||||
via the `toml-query` crate, which is an external project which was initiated and
|
||||
extracted from the imag project.
|
||||
|
||||
Error types are also important. All errors in the imag prijects are generated by libimagerror usage and are interoperable. User code hardly handles the actual `Error` type but its inner one, `ErrorKind`, which is an enum where each member can be mapped to a representing text. Imag error types do never contain payload (they can via extensions, though it is not really practical and there is no usage for it).
|
||||
Error types are also important.
|
||||
All errors in imag projects should be created with `error-chain`.
|
||||
libimagerror provides functionality to enhance the experience with `Result`
|
||||
types and general tracing of errors.
|
||||
|
|
|
@ -4,13 +4,19 @@ 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.
|
||||
|
||||
One could say that the store is simply a databases, and it really is. We opted
|
||||
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.
|
||||
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
|
||||
_really_ much won't exceed the Gigabytes ever.
|
||||
|
||||
Having a storage format which is plain-text based is the superior approach, as
|
||||
text editors will always be there.
|
||||
|
||||
A user should always be able to read her data without great effort and putting
|
||||
everything in a _real_ 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 therefor better to
|
||||
Text is readable until the worlds end and we think it is therefore better to
|
||||
store the data in plain text.
|
||||
|
||||
The following sections describe the store and the file format we use to store
|
||||
|
@ -19,10 +25,10 @@ to dig into the store with their editors.
|
|||
|
||||
## File Format {#sec:thestore:fileformat}
|
||||
|
||||
The contents of the store are encoded in either UTF-8 or ASCII. Either way, a
|
||||
normal text editor (like `vim` or the other one) will always be sufficient to
|
||||
dog into the store and modify files. For simple viewing even a pager (like
|
||||
`less`) is sufficient.
|
||||
The contents of the store are encoded in UTF-8.
|
||||
A normal text editor (like `vim` or the other one) will always be sufficient to
|
||||
dig into the store and modify files.
|
||||
For simple viewing even a pager (like `less`) is sufficient.
|
||||
|
||||
Each entry in the store consists of two parts:
|
||||
|
||||
|
@ -44,24 +50,24 @@ restricted in their way of altering the data.
|
|||
|
||||
So normally there are several sections in the header. One section (`[imag]`) is
|
||||
always present. It contains a `version` field, which tells imag which version
|
||||
this file was created with (the version information is _also_ encoded in the
|
||||
filename, just in case things change in the future). It also contains a `links`
|
||||
field which is an Array of values. This `links` field is for linking (see
|
||||
@sec:thestore:linking) to other entries in the store.
|
||||
this file was created with.
|
||||
|
||||
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. This is not enforced by imag itself, though.
|
||||
read other sections than its own.
|
||||
|
||||
These conventions are not enforced by imag itself, though.
|
||||
|
||||
### Content Format {#sec:thestore:fileformat:content}
|
||||
|
||||
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 code of imag.
|
||||
the markup implementation is not inside the very core of imag.
|
||||
|
||||
Technically it would be possible that the content part of a file is used to
|
||||
store binary data. We don't want this, though.
|
||||
store binary data.
|
||||
We don't want this, though, as it is contrary to the goals of imag.
|
||||
|
||||
### Example {#sec:thestore:fileformat:example}
|
||||
|
||||
|
@ -88,7 +94,7 @@ This is an example text, written by the user.
|
|||
|
||||
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.
|
||||
other directory the user has read-write-access to.
|
||||
|
||||
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
|
||||
|
@ -100,54 +106,23 @@ So if the store exists in `/home/user/store/`, a file with the storepath
|
|||
`/example.file` is (on the filesystem) located at
|
||||
`/home/user/store/example.file`.
|
||||
|
||||
A storepath contains predefined parts:
|
||||
By convention, each `libimagentry<name>` and `libimag<name>` module stores its
|
||||
entries in in `/<name>/`.
|
||||
|
||||
* The module name of the Module the Entry belongs to, as said above.
|
||||
This part is always a directory.
|
||||
* The version (semantic versioning applies) of the module storing the entry.
|
||||
This part is a postfix to the filename.
|
||||
|
||||
The pattern for the storepath is
|
||||
So, the pattern for the storepath is
|
||||
|
||||
```
|
||||
/<module name>/<optional sub-folders>/<file name>~<sem version>
|
||||
/<module name>/<optional sub-folders>/<file name>
|
||||
```
|
||||
|
||||
So if a module named "example-module" with version "0.1.0" stores a file in the
|
||||
Store, the storepath for a file with the name "example" is
|
||||
"/example-module/example~0.1.0".
|
||||
|
||||
Any number of subdirectories may be used, so creating folder hierarchies is
|
||||
possible and valid. A file "example" for a module "module" in version "0.1.0"
|
||||
would be stored in sub-folders like this:
|
||||
possible and valid.
|
||||
A file "example" for a module "module" could be stored in sub-folders like this:
|
||||
|
||||
```
|
||||
/module/some/sub/folder/example~0.1.0
|
||||
/module/some/sub/folder/example
|
||||
```
|
||||
|
||||
For example, it is valid if these files exist at the same time:
|
||||
|
||||
* /foo/bar~0.2
|
||||
* /foo/bar~1.3
|
||||
|
||||
It might not be sane, though.
|
||||
|
||||
To future-proof the system it is necessary to provide a way for modules to
|
||||
differentiate in their versions on the store level. Thus if a module wants to
|
||||
retrieve a file from the store it must at least accept files from it's current
|
||||
advertised version. It may accept older files and it may transform them and
|
||||
resubmit them in the newer version.
|
||||
|
||||
## Store path links {#sec:thestore:links}
|
||||
|
||||
Linking entries is version independent.
|
||||
|
||||
This means if an entry "a" from a module "A" gets written to the store, it may
|
||||
link to an entry "b" from a module "B", which is in version "0.1.0" at the
|
||||
moment. If the module "B" gets updated, it might update its entries in the store
|
||||
as well. The link from the "a" should never get invalid in this case, though it
|
||||
is not ensured by the core of imag itself.
|
||||
|
||||
## Backends {#sec:thestore:backends}
|
||||
|
||||
The store itself also has a backend. This backend is the "filesystem
|
||||
|
@ -158,21 +133,21 @@ Note: This is a very core thing. Casual users might want to skip this section.
|
|||
### Problem {#sec:thestore:backends:problem}
|
||||
|
||||
First, we had a compiletime backend for the store.
|
||||
This means that the actual filesystem operations were compiled into the stores
|
||||
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 eachother.
|
||||
that did not interfere with each other.
|
||||
|
||||
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.
|
||||
the filesystem and mess up other currently-running tests.
|
||||
|
||||
Hence we implemented this.
|
||||
Hence we implemented store backends.
|
||||
|
||||
### Implementation {#sec:thestore:backends:implementation}
|
||||
|
||||
|
@ -213,7 +188,7 @@ backend in other ways, too.
|
|||
|
||||
This is a backend for the imag store which is created
|
||||
from stdin, by piping contents into the store (via JSON or TOML) and piping the
|
||||
store contents (as JSON or TOML) to stdout when the the backend is destructed.
|
||||
store contents (as JSON or TOML) to stdout when the backend is destructed.
|
||||
|
||||
This is one of some components which make command-chaining in imag possible.
|
||||
With this, the application does not have to know whether the store actually
|
||||
|
@ -227,12 +202,8 @@ implementation are possible.
|
|||
|
||||
The following section assumes a JSON mapper.
|
||||
|
||||
The mapper reads the JSON, parses it (thanks serde!) and translates it to
|
||||
a `Entry`, which is the in-memory representation of the files.
|
||||
The `Entry` contains a `Header` part and a `Content` part.
|
||||
|
||||
This is then made available to the store codebase.
|
||||
|
||||
The mapper reads the JSON, parses it and translates it to a `Entry`.
|
||||
Then, the entry is made available to the store codebase.
|
||||
To summarize what we do right now, lets have a look at the awesome ascii-art
|
||||
below:
|
||||
|
||||
|
@ -243,9 +214,7 @@ below:
|
|||
IO Mapper Store Mapper IO
|
||||
+--+---------+----------------+--------+--+
|
||||
| | | | | |
|
||||
JSON -> Entry -> JSON
|
||||
+ Header
|
||||
+ Content
|
||||
JSON -> Entry -> JSON
|
||||
```
|
||||
|
||||
This is what gets translated where for one imag call with a stdio store backend.
|
||||
|
|
|
@ -1,58 +1,104 @@
|
|||
# Conventions, best practices
|
||||
|
||||
This section goes about best practices in the imag codebase. It is mainly focused on developers, but a user may read it for getting to know how imag works.
|
||||
This section goes about best practices in the imag codebase. It is mainly
|
||||
focused on developers, but a user may read it for getting to know how imag
|
||||
works.
|
||||
|
||||
Lets work our way up from the store and how to extend it to the commandline user interface.
|
||||
Lets work our way up from the store and how to extend it to the commandline user
|
||||
interface.
|
||||
|
||||
## Versioning
|
||||
|
||||
All imag crates are versioned with the same version number until we reach some
|
||||
`"1.0.0"` 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.
|
||||
|
||||
## Store and Entry functionality
|
||||
|
||||
A `Entry` does not offer much functionality by itself. So its the job of libraries to _extend_ their functionality. This should never be done by wrapping the `Entry` type itself but by providing and implementing an extension trait on it.
|
||||
A `Entry` does not offer much functionality by itself. So its the job of
|
||||
libraries to _extend_ its functionality. This should never be done by wrapping
|
||||
the `Entry` type itself but by providing and implementing an extension trait on
|
||||
it.
|
||||
|
||||
Same goes for extending the `Store` type: never wrap it, always provide an extension trait for it.
|
||||
Same goes for extending the `Store` type: never wrap it, always provide an
|
||||
extension trait for it.
|
||||
|
||||
These two rules ensure that the type does not lose any functionality from a wrapping. `Deref` 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 `Result<_, _>`.
|
||||
These two rules ensure that the type does not lose any functionality from a
|
||||
wrapping. `Deref` 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 `Result<_, _>`.
|
||||
|
||||
## Libraries
|
||||
|
||||
In the next few sections, conventions and best practices for writing a imag library are written down.
|
||||
In the next few sections, conventions and best practices for writing a imag
|
||||
library are written down.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
### Library naming
|
||||
|
||||
Libraries which provide functionality for entries or the store (most likely entries or both) should be named "libimagentrything" whereas "thing" stands for what the library provides.
|
||||
Libraries which provide functionality for entries or the store (most likely
|
||||
entries or both) should be named "libimagentrything" whereas "thing" stands for
|
||||
what the library provides.
|
||||
|
||||
All other libraries should be prefixed with "libimag" at least. Most likely, one will not write such a library but rather a "libimagentrything" library.
|
||||
All other libraries should be prefixed with "libimag" at least. Most likely, one
|
||||
will not write such a library but rather a "libimagentrything" library.
|
||||
|
||||
### Library scope
|
||||
|
||||
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" might be a place where such a function would be put, or, if not yet available, a "libimagentryutil" could be created.
|
||||
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" might be a place where such a function would be put, or, if not
|
||||
yet available, a "libimagentryutil" could be created.
|
||||
|
||||
If a library has to introduce free functions in its public interface, one should think hard whether this is really necessary.
|
||||
If a library has to introduce free functions in its public interface, one should
|
||||
think hard whether this is really necessary.
|
||||
|
||||
### Library error types/kinds
|
||||
|
||||
Libraries must use the "libimagerror" tools to create error types and kinds. Most likely, a library needs some kinds for wrapping the errors from underlying libraries, such as the store itself.
|
||||
Libraries must use the "libimagerror" tools to create error types and kinds.
|
||||
Most likely, a library needs some kinds for wrapping the errors from underlying
|
||||
libraries, such as the store itself.
|
||||
|
||||
A library must _never_ introduce multiple error types, but is free to introduce as many error kinds as required. Indeed, more kinds is better than fewer.
|
||||
A library must _never_ introduce multiple error types, but is free to introduce
|
||||
as many error kinds as required. Indeed, more kinds is better than fewer.
|
||||
|
||||
### Libraries with commandline frontends
|
||||
|
||||
Libraries with commandline frontends provide end-user functionality. 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.
|
||||
Libraries with commandline frontends provide end-user functionality. 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.
|
||||
|
||||
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 ve outsourced to a more general "libimagentrything". It is not forbidden, though.
|
||||
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". It is not forbidden, though.
|
||||
|
||||
A library which implements a functionality for imag may contain helper functions for commandline stuff, but that is discouraged.
|
||||
A library which implements a functionality for imag may contain helper functions
|
||||
for commandline stuff, but that is discouraged.
|
||||
|
||||
### Library testing
|
||||
|
||||
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!
|
||||
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!
|
||||
|
||||
## Commandline tools
|
||||
|
||||
The next few sections describe how the commandline frontends are implemented. Each imag functionality (or module) has its own library and a commandline frontend for it.
|
||||
The next few sections describe how the commandline frontends are implemented.
|
||||
Each imag functionality (or module) has its own library and a commandline
|
||||
frontend for it.
|
||||
|
||||
The commandline frontends do contain little to no functionality. They simply translate the commandline parameters and options to calls to the appropriate library functions.
|
||||
The commandline frontends do contain little to no functionality. They simply
|
||||
translate the commandline parameters and options to calls to the appropriate
|
||||
library functions.
|
||||
|
||||
## Commandline tool testing
|
||||
|
||||
|
|
|
@ -6,36 +6,13 @@ There is a huge list of modules available in the imag core distribution.
|
|||
From a naming perspective, we do not differ between low-level and high-level
|
||||
modules. 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 (which by the way shouldn't be used by the end-user at all).
|
||||
interface itself.
|
||||
Others cover things like diary, notes, wiki or bookmarks.
|
||||
These are also called "domains".
|
||||
|
||||
We try really hard to offer a consistent commandline user interface over all of
|
||||
these modules.
|
||||
|
||||
The following sections describe each module in detail, including its purpose and
|
||||
its provided backends.
|
||||
|
||||
A backend is simply an external tool imag might be able to use.
|
||||
For example, the `imag-todo` module offers a `taskwarrior` interface, so imag
|
||||
itself does not cover anything which has to do with todo management, but lets
|
||||
you continue using `taskwarrior` for that (which does a really good job).
|
||||
So what does the `imag-todo` module do?
|
||||
Well, it offers you ways to track tasks created in `taskwarrior` and putting
|
||||
files which can be used as references to tasks then.
|
||||
For example, if you create a task in `taskwarrior`, you end up with an UUID for
|
||||
this task.
|
||||
imag stores this UUID in a store entry and you are now able to `imag-link` this
|
||||
file with other files in the store.
|
||||
This way you can link `taskwarrior` tasks with other data (of course,
|
||||
`imag-todo` offers some more commands, for searching tasks and so on).
|
||||
|
||||
But what if you do not like `taskwarrior`?
|
||||
That's what backends are for.
|
||||
The goal of imag is to provide backends for not just one tool which implements a
|
||||
PIM aspect, but for many.
|
||||
So you can change the configuration for `imag-todo` to not use `taskwarrior` but
|
||||
some other todo tool.
|
||||
|
||||
(This is all hypothetical by now because these things are not yet implemented.
|
||||
Anyhow, we aim for exactly what is described above)
|
||||
its provided functionality.
|
||||
|
||||
|
|
|
@ -11,9 +11,12 @@ short note what each module should do.
|
|||
First the modules which have been implemented in some way (not necessarily
|
||||
perfect or feature-complete):
|
||||
|
||||
- [x] imag-annotate - A helper for quickly annotating entries in the store
|
||||
- [x] imag-bookmark - A bookmark manager for web browsing.
|
||||
- [x] imag-counter - Counting things.
|
||||
- [x] imag-diary - A diary, or multiple.
|
||||
- [x] imag-gps - Adding GPS coordinates to entries
|
||||
- [x] imag-grep - A helper to grep through the store (not entry headers)
|
||||
- [x] imag-grep - A utility for greping through content
|
||||
- [x] imag-link - Linking imag entries to eachother
|
||||
- [x] imag-notes - Note taking
|
||||
|
@ -37,7 +40,6 @@ Now the modules that are not yet started:
|
|||
based on a predicate specified via the CLI and write the store back to stdout.
|
||||
- [ ] imag-git - wrapper to call git commands on the imag store no matter
|
||||
whether the current working directory is the store or not
|
||||
- [ ] imag-gps - Adding GPS coordinates to entries
|
||||
- [ ] imag-habit - Tracking ones habits (create habits and make sure you do what
|
||||
you've planned)
|
||||
- [ ] imag-image - Image referencing, categorizing, etc.
|
||||
|
|
|
@ -11,16 +11,17 @@ section](#prerequisites). If you don't know what you could do, start here.
|
|||
|
||||
## Without Github
|
||||
|
||||
If you do not want to use github for your contribution, this is completely okay.
|
||||
Contributing without a github account is perfectly fine.
|
||||
Feel free to contact [us via our mailinglist](http://imag-pim.org/mailinglist/)
|
||||
via mail, feel also free to submit patches via mail (use `git format-patch` and
|
||||
and/or submit patches via mail (use `git format-patch` and
|
||||
`git send-email`, always add a cover letter to describe your submission).
|
||||
|
||||
Also ensure that each commit has
|
||||
[a "Signed-off-by: " line](https://stackoverflow.com/questions/1962094/what-is-the-sign-off-feature-in-git-for).
|
||||
By adding that line, you agree to our
|
||||
[developer certificate of origin](#developer-certificate-of-origin).
|
||||
If you do not add the "Signed-off-by: " line, I cannot take your patch, sorry.
|
||||
If you do not add the "Signed-off-by: " line,
|
||||
I reserve the right to reject your patch.
|
||||
|
||||
Once _I am_ okay with your patchset, I will
|
||||
submit it as PR in the github repository, so more people can review it and CI
|
||||
|
@ -36,6 +37,8 @@ Finding an issue is simple: We have
|
|||
[a special label in our issues section](https://github.com/matthiasbeyer/imag/issues?q=is%3Aissue+is%3Aopen+label%3Acomplexity%2Feasy)
|
||||
for easy-to-solve issues. You can start there, don't hesitate to ask questions
|
||||
if you do not understand the issue comment!
|
||||
If there are currently no issues with that tag, just browse the issues or the
|
||||
code... you'll always find things to improve!
|
||||
|
||||
Also, if you've found bugs or outdated stuff in our documentation, feel free to
|
||||
file issues about them or even better: Write a pull request to fix them!
|
||||
|
@ -48,8 +51,6 @@ Dependencies are listed in the
|
|||
[default.nix file](http://git.imag-pim.org/imag/tree/default.nix),
|
||||
though you do not have to have `nix` installed to build imag.
|
||||
|
||||
`make` can be helpful to automate the build process.
|
||||
|
||||
Note that this software is targeted towards commandline linux users and we do
|
||||
not aim to be portable to Windows or Mac OSX (though I wouldn't mind merging
|
||||
patches for OS X compatibility).
|
||||
|
@ -70,11 +71,15 @@ All dependencies are installable with the nix package manager by using a
|
|||
Please don't refer to issues or PRs from inside a commit message, if possible.
|
||||
Make sure your PR does not contain "Fixup" commits when publishing it, but feel
|
||||
free to push "Fixup" commits in the review process. We will ask you to clean
|
||||
your history before merging! If you're submitting via patch-mail, I will do the fixup squashing myself.
|
||||
your history before merging! If you're submitting via patch-mail, I will do the
|
||||
fixup squashing myself.
|
||||
|
||||
Make sure to prefix your commits with `"doc: "` if you change the document. Do
|
||||
not change document and code in one commit, always separate them.
|
||||
|
||||
If your changes are user-visible, make sure to add a note in the
|
||||
`CHANGELOG.md` file.
|
||||
|
||||
We do not follow some official Rust styleguide for our codebase, but we try to
|
||||
write minimal and readable code. 100 characters per line, as few lines as
|
||||
possible, avoid noise in the codebase, ... you get it.
|
||||
|
@ -93,9 +98,9 @@ for example "libimagstore/add-debugging-calls", that would be awesome.
|
|||
|
||||
You are welcome to publish your PR as soon as there is one commit in your
|
||||
branch. This gives us the possibility to review whether your ideas go into a
|
||||
nice direction or whether there are issues with your approach and we can report
|
||||
them to you rather quickly. Rewriting a whole PR is not satisfactory and we'd
|
||||
like to make your contribution process enjoyable.
|
||||
nice direction or whether there are issues with your approach so we can report
|
||||
them to you quickly. Rewriting a whole PR is not satisfactory and we'd
|
||||
like to make your contribution process enjoyable for you.
|
||||
|
||||
# Merging tools which use the imag core functionality into this repo
|
||||
|
||||
|
@ -107,12 +112,14 @@ requirements:
|
|||
1. It has a commandline interface which is the main interface to the module
|
||||
OR it is a utility library for creating new kinds of functionality within the
|
||||
imag core.
|
||||
The commandline interface should be structured like the existing interfaces
|
||||
(as in commands, options and arguments).
|
||||
1. It is licensed under the terms of GNU LGPLv2.1 OR all of your contributors
|
||||
approve a commit which changes the license of your codebase to GNU LGPLv2.1
|
||||
(The word "approve" in this sentence is to be defined).
|
||||
|
||||
(If your tool does not fulfill these requirements, I won't merge it into the
|
||||
imag core distribution.)
|
||||
If your tool does not fulfill these requirements, I won't merge it into the
|
||||
imag core distribution.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
|
|
Loading…
Reference in a new issue