On se bouge, on signe la pétition en masse :
— Non c’est Non, Monsieur Duplomb !
— Pour la santé, la sécurité, l’intelligence collective.

👨‍💻 about me home CV/Resume News 🖊️ Contact Codeberg Github LinkedIn 🏆 Best of LuaX (tools) pub bang ypp panda lsvg ldc yreq Fizzbuzz Calculadoira TPG picfg Belenos (intro) 🔀 Git Repos

Made in Europe

yreq – Requirement management for ypp

yreq – Requirement management for ypp

Introduction

yreq is a minimalistic requirement management tool.

It is a ypp plugin and can describe requirements and relations between requirements as well as build coverage matrices.

Releases

It is strongly recommended to build Yreq from source, as this is the only reliable way to install the exact version you need.

However, if you do require precompiled binaries, this page offers a selection for various platforms: https://cdelord.fr/pub.

Support

If you like yreq (or LuaX) and are willing to support its development, please consider donating:

Donate using Liberapay Buy Me a Coffee at ko-fi.com

Installation

yreq requires bang and ypp.

# install yreq in ~/.local/lib
$ git clone https://codeberg.org/cdsoft/yreq
$ cd yreq
$ bang
$ ninja install

or set $PREFIX to install yreq to a custom directory ($PREFIX/lib):

$ export PREFIX=/path # install req to /path/lib
$ git clone https://codeberg.org/cdsoft/yreq
$ cd yreq
$ bang
$ ninja install

This will install yreq in $PREFIX/lib.

In case prepackaged libraries are needed, some can be found at cdelord.fr/pub. These archives contain yreq as well as some other softwares more or less related to LuaX.

Usage

[spec: Usage]

yreq is a ypp plugin. It can be loaded by ypp with the -l. If $PREFIX/lib is not in LUA_PATH, the library path can be given to ypp with the -p option. E.g.:

$ ypp -p $PREFIX/lib -l yreq file.md -o output.md

bang may also be a nice option to write a more complex build system.

Specification

Definitions

yreq is inspired by tagref. It reuses the notion of tags and references while providing a different syntax that is compatible with ypp. yreq builds a requirement graph and renders requirements in the final document using ypp.

To avoid ambiguous wording, yreq keeps using tags (instead of requirements) and refs (abbreviation for references).

tags (a.k.a requirements)

[spec: Tag]

In engineering, a requirement is a condition that must be satisfied for the output of a work effort to be acceptable. It is an explicit, objective, clear and often quantitative description of a condition to be satisfied by a material, design, product, or service.

Wikipedia

With yreq a tag is a piece of specification/code/test/… It starts at a tag marker and ends before the next tag.

A tag starts with a ypp macro that is a user-defined tag (a noun). It takes a tag identifier (a string) and an optional Lua table. E.g.:

    @noun "IDENTIFIER"

or

    @noun "IDENTIFIER" { "optional short description",
        attribute1=value1,
        attribute2=value2,
        ...
    }

The optional table is not used by req itself but is provided to user scripts (e.g. project specific attributes). The optional table can contain a short description of the tag. This description is printed after the tag identifier in the final document. The table can also contain optional attributes which are in fact not used by yreq but available in user scripts (e.g. to store some status or test results).

In ypp scripts a tag is a table with some predefined fields:

Field Description
id identifier of the tag
noun noun describing the tag
up list of the upstream tags (i.e. tags that reference this tag)
down list of the downstream tags (i.e. tags that reference this tag)
file filename of the current requirement
attr optional table

By convention, a tag name is a noun that describes the type or nature of the tag.

refs (a.k.a references)

[spec: Ref]

A reference is an oriented link from the current tag to an upstream tag.

A reference is a ypp macro that is a user-defined ref name (a verb). It takes a tag identifier (a string). E.g.:

Upstream document Current document

@spec "UPSTREAM_TAG_ID"

Lorem ipsum ...


@code "CURRENT_TAG_ID"

Lorem ipsum ...

@refines "UPSTREAM_TAG_ID"

In this example, CURRENT_TAG_ID is a refinement of UPSTREAM_TAG_ID.

In ypp scripts a ref is a table with some predefined fields:

Field Description
id identifier of the referenced tag
verb verb describing the relation with the referenced tag

By convention, a ref name is a verb that describes the relation between the current tag and the upstream tag.

Configuration

[spec: Configuration]

There is no specific configuration file. yreq is configured through its ypp API. The configuration can be loaded from a Lua script or embeded in the documentation itself.

The configuration shall define:

Tag extraction

[spec: Tag extraction]

The user can extract a subset of the tags. These tags can be used by ypp scripts to implement some coverage checks (e.g. to check all specification tags are implemented).

Coverage matrix

[spec: Coverage matrix]

ypp builds a coverage matrix that lists all tags along with their upstream and downstream tags.

Usage

yreq is used as a ypp plugin. A typical usage consists in providing a configuration script and one or more input files (e.g. Markdown files) and generating a single output document that can later be converted to a distributable document (HTML, PDF…).

The input documentation can be split into several files, each documentation level being a refinement of the previous one(s). E.g.:

The output document shall be a single file for several reasons:

Implementation

yreq is a single Lua script meant to be run as a ypp plugin. It provides functions to parse and render tags and refs as well as helper functions to render coverage matrices or write user scripts.

It is executed by ypp:

$ ypp -l yreq ...

This will load the yreq module in the yreq global variable.

Tags and refs parser

Tag definitions (nouns)

[code: Tag function] [implements: Tag] [implements: Configuration]

@yreq.tags { "noun1", "noun2", ... }

yreq.tags declares nouns that will be used as tag names. Each noun creates a ypp macro of the same name that is used to create tags. They take the new tag identifier and an optional table with a short description and some user-defined fields). If only the short description is needed, it can be provided as a simple string. E.g.:

No description:

@noun1 "TAG ID"

Description without attributes:

@noun1 "TAG ID" "short description"

Description and attributes:

@noun1 "TAG ID" { "short description",
    attribute1 = value1,
    attribute2 = value2,
}

Ref definitions (verbs)

[code: Ref function] [implements: Ref] [implements: Configuration]

@yreq.refs { "verb1", "verb2", ... }

yreq.refs declares verbs that will be used as ref names. Each verb creates a ypp macro of the same name that is used to create refs. They take the referenced tag identifier. E.g.:

@verb1 "TAG ID"

Lazy attribute definition

yreq.lazy(func)

yreq.lazy returns a function that will be called when the tag is added to the internal tag list. This helps computing attributes from a partial tag (e.g. to avoid duplicating tag identifiers in attributes). E.g.:

@noun "ID" {
    attribute = yreq.lazy(function(tag) return ... end),
}

Tag subset extraction

[code: Tag extraction function] [implements: Tag extraction]

yreq.extract {
    tags = { list of nouns },
    refs = { list of verbs },
}

yreq.extract returns a subset of the existing tags. This subset can be used in user scripts to perform various checks (e.g. checking that some tags are fully covered by some downstream tags). The tags and refs parameters define the lists of nouns and verbs to extract. The result if a table containing the selected tags, indexed by their identifiers.

[code: Tag order function] [implements: Tag extraction]

yreq.order(tags)

yreq.order returns an ordered list of tags from a tag table (e.g. as returned by yreq.extract. Tags are returned in the same order than in the input documents.

Tag anchor identifier

yreq.anchor(tag)

yreq.anchor returns the label that identifies a tag and is used to reference it. This function is mainly used internaly to generate hyperlinks.

Tag short text

yreq.text(tag)

yreq.text returns the short text associated to the tag. This function is mainly used internaly to render tags and generate the coverage matrix.

Coverage matrices

Coverage matrix

[code: Coverage matrix function] [implements: Coverage matrix]

@yreq.coverage()

yreq.coverage returns the coverage matrix containing all known requirements. The table is a list of lines of Markdown code that can be embeded in a document with ypp.

The coverage matrix shall be generated once and only once to avoid missing or duplicate links. It shall be at the end of the document, or at least after all tags, otherwise some tags may not be in the matrix.

Tests

yreq is tested through its documentation. The test result is the generated README.md file. It is versioned and any modifications shall be reviewed before pushing new versions.

Usage

[test: Usage test]

The bang build file calls ypp and loads the yreq plugin ([tests: Usage]). It also loads a configuration script ([tests: Configuration]).

Tags and refs definitions

[test: Tag test]

Tags and refs are defined in the project documentation. They shall be rendered accurately in the output document (README.md) ([tests: Tag], [tests: Ref]) where they are initially defined as well as in the coverage matrix ([tests: Coverage matrix]).

The nouns and verbs are defined in the configuration script ([tests: Configuration]).

Tag extraction

[test: Tag extraction test]

This test checks the structure of a tag subset ([tests: Tag extraction]). E.g. the implementation relation (verb implements) between the specification and the source code (nouns spec and code) is extracted with:

    tags = yreq.extract{tags={"spec", "code"}, refs={"implements"}}

and returns a table with these keys: "Usage", "Tag", "Ref", "Configuration", "Tag extraction", "Coverage matrix", "Tag function", "Ref function", "Tag extraction function", "Tag order function" and "Coverage matrix function".

The complete tags list (yreq.extract called with no parameter or an empty table) is: "Usage", "Tag", "Ref", "Configuration", "Tag extraction", "Coverage matrix", "Tag function", "Ref function", "Tag extraction function", "Tag order function", "Coverage matrix function", "Usage test", "Tag test" and "Tag extraction test".

Note that this list won’t contain the test tags defined after this point.

Tag format

[test: Tag format test]

A tag looks like:

tags["Tag function"] = {
    attr = {},
    down = {},
    file = "lib/yreq.lua",
    id = "Tag function",
    noun = "code",
    up = {{
            id = "Tag",
            verb = "implements",
        }, {
            id = "Configuration",
            verb = "implements",
        }},
}

Coverage matrix

[test: Coverage matrix test] [tests: Coverage matrix]

Upstream Tags Downstream

License

yreq is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

yreq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with yreq. If not, see https://www.gnu.org/licenses/.

For further information about yreq you can visit https://codeberg.org/cdsoft/yreq

This site is powered by LuaX, bang, ypp, cdsoft.css and Pandoc.

Mirrors: cdelord.frchristophe.delord.free.frcdsoft.codeberg.page