Skip to content

Latest commit

 

History

History
101 lines (83 loc) · 2.89 KB

rebash.md

File metadata and controls

101 lines (83 loc) · 2.89 KB

ReBash - bash/shell library/framework

Build Status

Motivation

Developing in bash has some serious flaws:

  • scoping - bash functions are always global
  • no exception handling
  • larger projects quickly become non-transparent
  • ...

Features

  • modular import system
  • advanced logging (colors, control stdout/stderr, log levels, ...)
  • error handling (exceptions, try-catch)
  • doc testing inspired by python
  • documentation generation
  • argument parser
  • utility functions

Doc test examples

./doc_test.sh array.sh -v

Gif of doc_test run on the array module

./doc_test.sh

Gif of full doc_test run

./doc_test.sh -v

Gif of full verbose doc_test run with failure

Usage

Source the core module and use core.import to import other modules.

#!/usr/bin/env bash
source path/to/core.sh
core.import <modulename>
core.import <another modulename>
# use modules ...

Installation

Currently only an archlinux package is available at the aur. After installation all rebash files are available under /usr/lib/rebash/. The doc_test and documentation modules are available as /usr/bin/rebash-doc-test and /usr/bin/rebash-documentation.

Module Concept

Modules are single files. The function core.import guarantees that each module is sourced only once. All variables and functions defined inside a module should be prefixed with the module name. E.g. core_import for the function import in module core. Aliases inside the module are used to define public functions and to have a convinient way to distinguish the module namespace from the function (alias core.import="core_import").

A typical minimal module looks like this (with filename mockup.sh):

#!/usr/bin/env bash
source "$(dirname "${BASH_SOURCE[0]}")/core.sh"
core.import logging
mockup_foo() {
    echo foo
}
alias mockup.foo="mockup_foo"

Best practices / coding style

No surprises

Loading modules (i.e. when sourced by the import mechanism) should be side-effect free, so only variable and function definitions should be made at the module level. If the module should be executable, use core.is_main. For example this module does activate exceptions only when run directly, not when being sourced.

#!/usr/bin/env bash
source path/to/core.sh
core.import exceptions
main() {
    exceptions.activate
    # do stuff
}
if core.is_main; then
    main
fi

Testing

Write doc_tests for every module and function. Write the tests before writing the implementation.

Linting with shellcheck

Use shellcheck to tackle common errors and pitfalls in bash.