441 lines
13 KiB
Markdown
441 lines
13 KiB
Markdown
|
|
BrmBuro
|
|
=======
|
|
|
|
Brmlab Bureacratic system.
|
|
|
|
License
|
|
-------
|
|
|
|
ISC License
|
|
|
|
Copyright 2023 Brmlab, z.s.
|
|
Dominik Pantůček <dominik.pantucek@trustica.cz>
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
for any purpose with or without fee is hereby granted, provided
|
|
that the above copyright notice and this permission notice appear
|
|
in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL
|
|
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
Features
|
|
--------
|
|
|
|
* members base management
|
|
* member files parsing and validation
|
|
* member ids validation
|
|
* generating new member id
|
|
* per-month statistics of active, suspended, destroyed and student
|
|
members
|
|
* detailed member information
|
|
* querying members by id or nick
|
|
|
|
Requirements
|
|
------------
|
|
|
|
There are no runtime requirements, it is possible to build binary that
|
|
requires only libc.
|
|
|
|
Build requirements:
|
|
|
|
* Chicken Scheme 5
|
|
* make (tested with GNU make)
|
|
|
|
Building a shared binary with .so modules:
|
|
|
|
make shared
|
|
|
|
Building static binary:
|
|
|
|
make static
|
|
|
|
It is possible to run the main tool as script with Chicken Scheme
|
|
interpreter and POSIX-compatible shell for the purpose of development.
|
|
|
|
Development requirements:
|
|
|
|
* POSIX shell
|
|
|
|
Preparing module import files for running as script:
|
|
|
|
make
|
|
|
|
Cleaning the built files from the build directory:
|
|
|
|
make clean
|
|
|
|
Building the import module files, shared and static binaries together:
|
|
|
|
make all
|
|
|
|
Functional Modules
|
|
------------------
|
|
|
|
### Configuration
|
|
|
|
### Member File
|
|
|
|
### Member Record
|
|
|
|
### Member Base
|
|
|
|
### Month
|
|
|
|
### Period
|
|
|
|
### Primes
|
|
|
|
Support Modules
|
|
---------------
|
|
|
|
There modules are not specific to this project but had to be
|
|
implemented anyway to not require any external dependencies.
|
|
|
|
### ANSI
|
|
|
|
A simple module for creating ANSI (ECMA-48) sequence strings.
|
|
|
|
(ansi . args)
|
|
|
|
* ```args``` - a list of color/style keywords
|
|
|
|
Produces an ANSI CSI (Control Sequence Introducer) SGR (Select Graphic
|
|
Rendition) strings with given attributes (re)set.
|
|
|
|
It understands the following keywords:
|
|
|
|
* ```#:black``` - black text foreground color
|
|
* ```#:red``` - red text foreground color
|
|
* ```#:green``` - green text foreground color
|
|
* ```#:yellow``` - yellow text foreground color
|
|
* ```#:blue``` - blue text foreground color
|
|
* ```#:magenta``` - magenta text foreground color
|
|
* ```#:cyan``` - cyan text foreground color
|
|
* ```#:white``` - white (grey) text foreground color
|
|
* ```#:default``` - reset all attributes to terminal defaults
|
|
* ```#:bold``` - bold font (and/or bright foreground color on some terminals)
|
|
|
|
The order is important as the ```#:default``` resets all attributes
|
|
given even in the same attribute list.
|
|
|
|
a:error
|
|
|
|
Used to signal errors. Defaults to red bold text.
|
|
|
|
a:warning
|
|
|
|
Used to signal non-fatal warnings. Defaults to regular yellow text.
|
|
|
|
a:success
|
|
|
|
Signals success of an operation. Defaults to bold green text.
|
|
|
|
a:neutral
|
|
|
|
Used for generic text. Defaults to regular white (grey) text.
|
|
|
|
a:default
|
|
|
|
Special style which just resets the terminal output attributes to
|
|
terminal defaults.
|
|
|
|
a:muted
|
|
|
|
Used for displaying the text "muted" (dimmed). Defaults to bold/bright
|
|
black text.
|
|
|
|
a:highlight
|
|
|
|
Generic highlight of given text. Defaults to bold blue text.
|
|
|
|
### Command Line parsing
|
|
|
|
Generic syntax-based implementation of command-line options parsing
|
|
with focus on generated help and ergonomic binding of option
|
|
arguments.
|
|
|
|
(command-line print-help (opt (args ...) help body ...) ...)
|
|
|
|
* ```print-help``` - identifier binding for the help printing procedure
|
|
* ```opt``` - command-line option name as identifier (unquoted symbol)
|
|
* ```args ...``` - optional arguments of given option
|
|
* ```help``` - help string for this option
|
|
* ```body ...``` - expressions to be evaluated upon option match
|
|
|
|
Parses command-line arguments based on the specification given. If
|
|
evaluated inside ```csi``` script, only options and arguments after
|
|
the ```--``` meta-option are parsed. If evaluated inside compiled
|
|
binary, all arguments are parsed as usual.
|
|
|
|
Each option is represented by the ```opt``` option identifier
|
|
(unquoted symbol), optional arguments ```args``` which become bound in
|
|
the option specification ```body ...``` expressions, help string and
|
|
the actual expressions to be evaluated when the option (and possibly
|
|
its arguments) match.
|
|
|
|
If an option is encountered on the command-line and not enough
|
|
arguments (according to the option specification) are provided for it,
|
|
an exception is raised.
|
|
|
|
Within any of the ```body ...``` expressions the ```print-help```
|
|
procedure can be used to print the options, their argument names and
|
|
help strings in a nice, human-readable format.
|
|
|
|
### Dictionary
|
|
|
|
Simple key/value dictionary with most operations implemented in linear
|
|
time. The dictionary is internally represented as ```assq``` list and
|
|
is best suitable for symbols and numbers as keys.
|
|
|
|
(make-dict)
|
|
|
|
Creates an empty dictionary.
|
|
|
|
(dict-has-key? d k)
|
|
|
|
* ```d``` - the dictionary
|
|
* ```k``` - key to check
|
|
|
|
Returns ```#t``` (true) if the dictionary ```d``` contains the key
|
|
```k```.
|
|
|
|
(dict-ref d k [v])
|
|
|
|
* ```d``` - the dictionary
|
|
* ```k``` - the key to retrieve
|
|
* ```v``` - optional default value
|
|
|
|
Retrieves given key ```k``` from the dictionary ```d```.
|
|
|
|
If the key is not stored in the dictionary an error is raised unless
|
|
an optional value ```v``` is provided which is then returned in that
|
|
case.
|
|
|
|
(dict-remove d k)
|
|
|
|
* ```d``` - the dictionary
|
|
* ```k``` - the key to remove
|
|
|
|
Removes the key ```k``` from the given dictionary ```d``` raising an
|
|
exception if the key is not stored in the dictionary.
|
|
|
|
(dict-set d k v)
|
|
|
|
* ```d``` - the dictionary
|
|
* ```k``` - key to (re)set
|
|
* ```v``` - the value to set
|
|
|
|
If the dictionary ```d``` does not contain the key ```k```, adds the
|
|
value ```v``` into it under the given key. If the key is present, its
|
|
value is then replaced.
|
|
|
|
(dict-keys d)
|
|
|
|
* ```d``` - the dictionary
|
|
|
|
Returns the list of keys contained in the dictionary ```d```.
|
|
|
|
(dict-map proc d)
|
|
|
|
* ```proc``` - procedure for processing
|
|
* ```d``` - the dictionary
|
|
|
|
Returns a dictionary created by processing all elements of the
|
|
dictionary ```d``` using the procedure ```proc```.
|
|
|
|
If the procedure accepts just one argument, only values are passed to
|
|
it. If the procedure accepts two arguments, both the key and value are
|
|
passed to it. In both cases, the procedure must produce only the value.
|
|
|
|
(dict-filter pred? d)
|
|
|
|
* ```pred?``` - predicate procedure
|
|
* ```d``` - the dictionary
|
|
|
|
Returns a new dictionary created by keeping only the key/value pairs
|
|
from the dictionary ```d``` matching the predicate ```pred?```.
|
|
|
|
If the procedure accepts just one argument, only values are passed to
|
|
it. If the procedure accepts two arguments, both the key and value are
|
|
passed to it.
|
|
|
|
(dict-reduce init proc d)
|
|
|
|
* ```init``` - arbitrary initial value
|
|
* ```proc``` - procedure for performing the reducing step
|
|
* ```d``` - the dictionary to reduce
|
|
|
|
Iterates over the key/value pairs of given dictionary ```d```
|
|
initializing the algorithm with the ```init``` value given. In each
|
|
step the procedure ```proc``` is called with three arguments: the
|
|
value accumulated so far, key and value.
|
|
|
|
### Listing
|
|
|
|
This module implements listing a text file with line numbers and
|
|
optional highlights of given source lines, optionally with comments
|
|
for those lines.
|
|
|
|
(print-source-listing lines highlights context hl-pre hl-post ctx-pre ctx-post ellipsis)
|
|
|
|
* ```lines``` - list of string representing lines of the text file
|
|
* ```highlights``` - list of highlights (see below)
|
|
* ```context``` - number of context lines to be shown around highlighted lies
|
|
* ```hl-pre``` - string introducing highlighted lines
|
|
* ```hl-post``` - string terminating highlighted lines
|
|
* ```ctx-pre``` - string introducing context lines
|
|
* ```ctx-post``` - string terminating context lines
|
|
* ```ellipsis``` - string representing lines omitted from the output
|
|
|
|
Prints given text file represented by the ```lines``` list of strings.
|
|
|
|
Lines to be highlighted can be specified in the ```highlights```
|
|
list. The highlight specification is either a number or a list
|
|
containing the line number and string comment.
|
|
|
|
The lines are actually highlighted by prepending them with
|
|
```hl-pre``` string and the highlight is finished by appending
|
|
```hl-post``` to them. Usually some constants from the ```ansi```
|
|
module are used.
|
|
|
|
If some lines are highlighted a number of ```context``` lines
|
|
surrounding them may be printed as well. If this argument is negative,
|
|
all non-highlighted lines are printed as context lines.
|
|
|
|
Context lines are prepended with ```ctx-pre``` string and terminated
|
|
by ```ctx-post``` string.
|
|
|
|
If some lines between highlight and/or context lines are omitted,
|
|
```ellipsis``` string is printed on single line as a substitute.
|
|
|
|
|
|
### Progress
|
|
|
|
Provides syntax forms and procedures for showing progress of a
|
|
process.
|
|
|
|
(with-progress echo? pre post body ...)
|
|
|
|
* ```echo?``` - flag enabling progress output
|
|
* ```pre``` - string to be printed at start
|
|
* ```post``` - string to be printed after finish
|
|
* ```body ...``` - expressions of the process tracked
|
|
|
|
Displays process progress starting with the ```pre``` string, adding
|
|
arbitrary string to the output using the ```progress-advance``` during
|
|
each and every step. If the process reaches its finish, the output
|
|
line is finished with the ```post``` string and cursor is moved to new
|
|
line.
|
|
|
|
During the steps, the whole line is always refreshed when the progress
|
|
gets updated.
|
|
|
|
If ```echo?``` is ```#f``` (false), nothing is output.
|
|
|
|
(progress-advance [str])
|
|
|
|
* ```str``` - string to add to progress, defaults to "."
|
|
|
|
Adds given string to current progress and refreshes the progress
|
|
line. Must be evaluated within ```with-progress``` expression.
|
|
|
|
(progress-break body ...)
|
|
|
|
* ```body ...``` - arbitrary expressions to be evaluated
|
|
|
|
Evaluates the ```body ...``` expressions. Hides current progress line
|
|
before the evaluation and redisplays it when finished.
|
|
|
|
### Testing
|
|
|
|
This module provides simple syntax forms for (unit) testing of other
|
|
modules.
|
|
|
|
(run-tests name body ...)
|
|
|
|
* ```name``` - identifier describing the module being tested
|
|
* ```body ...``` - test expressions
|
|
|
|
Runs all tests specified on the ```body ...```. Firstly it prints
|
|
"[test] name " at the beginning of the line. Secondly it runs all
|
|
tests, printing "." for each test successfully passed. If all tests
|
|
pass, prints " ok." and moves the cursor to the next line.
|
|
|
|
In case any of the tests fails, exception is raised and program
|
|
terminates.
|
|
|
|
(test-eq? name expression expected-result)
|
|
|
|
* ```name``` - identifier representing the name of the test
|
|
* ```expression``` - expression to be evaluated
|
|
* ```expected-result``` - expected result of the test expression
|
|
|
|
Evaluates the test ```expression``` and compares the result with
|
|
```expected-result``` using ```eq?```. If the comparison fails, an
|
|
exception is raised with the ```name``` of the test added to the
|
|
exception. If the test passes, prints "." like all tests from this
|
|
module do.
|
|
|
|
(test-equal? name expression expected-result)
|
|
|
|
* ```name``` - identifier representing the name of the test
|
|
* ```expression``` - expression to be evaluated
|
|
* ```expected-result``` - expected result of the test expression
|
|
|
|
Evaluates the test ```expression``` and compares the result with
|
|
```expected-result``` using ```equal?```. If the comparison fails, an
|
|
exception is raised with the ```name``` of the test added to the
|
|
exception. If the test passes, prints "." like all tests from this
|
|
module do.
|
|
|
|
(test-true name expression)
|
|
|
|
* ```name``` - identifier representing the name of the test
|
|
* ```expression``` - expression to be evaluated
|
|
|
|
Evaluates the test ```expression``` and checks whether the result is
|
|
```#t``` (true). An exception is raised if it is not with the
|
|
```name``` of the test added to the exception. If the test passes,
|
|
prints "." like all tests from this module do.
|
|
|
|
(test-false name expression)
|
|
|
|
* ```name``` - identifier representing the name of the test
|
|
* ```expression``` - expression to be evaluated
|
|
|
|
Evaluates the test ```expression``` and checks whether the result is
|
|
```#f``` (false). An exception is raised if it is not with the
|
|
```name``` of the test added to the exception. If the test passes,
|
|
prints "." like all tests from this module do.
|
|
|
|
(test-exn name expression)
|
|
|
|
* ```name``` - identifier representing the name of the test
|
|
* ```expression``` - expression to be evaluated
|
|
|
|
Evaluates the test ```expression``` and checks whether it raised an
|
|
exception. An exception is raised if no exception was raised during
|
|
the evaluation. If the test passes, prints "." like all tests from
|
|
this module do.
|
|
|
|
### Utils
|
|
|
|
To ensure there are no external dependencies (including chicken eggs),
|
|
this module re-implements any basic procedures which are required for
|
|
any algorithms used.
|
|
|
|
(filter pred? lst)
|
|
|
|
* ```pred?``` - procedure accepting any value and returning #t or #f
|
|
* ```lst``` - list to be filtered
|
|
|
|
Returns a list containing only elements matching given ```pred?```
|
|
predicate.
|