libremessages(1) -- common Bash routines
========================================

## SYNOPSIS

`. "$(librelib messages)"`<br>
`. libremessages`<br>
`libremessages` <COMMAND>

## DESCRIPTION

`libremessages` is a shell library containing many common routines.
The name is a bit of a misnomer, it mostly deals with printing
messages, but also has other things.

`libremessages` uses `common.sh`(3) internally for a large portion of
it's functionality.  The authors make no promises that functionality
that is implemented in `libremessages` won't move into `common.sh` or
vice-versa.  So, it is recommended that you use `libremessages`, not
`common.sh`.

### STAND ALONE USAGE

The "normal" way to use libremessages is to source it, then call the
provided routines.

However, if you call libremessages directly, the first argument is
taken as the function to call, and the remaining arguments are passed
to it.  The only cases where this doesn't work are the lockfile
routines (`lock`, `slock`, and `lock_close`), because lockfiles are
managed as file descriptors.

### VARIABLES

The following variables for printing terminal color codes are set:
`ALL_OFF`, `BOLD`, `BLUE`, `GREEN`, `RED`, `YELLOW`.  If standard
error is not a terminal (see `isatty`(3)), they are set, but empty.
They are marked as readonly, so it is an error to try to set them
afterwards.

The following variables for numeric exit codes are set: a basic
`EXIT_TRUE=0` and `EXIT_FALSE=1`, as well as several based on the
[LSB recommendations for SysV init scripts][1]: `EXIT_SUCCESS`, `EXIT
FAILURE`, `EXIT_INVALIDARGUMENT`, `EXIT_NOTIMPLEMENTED`,
`EXIT_NOPERMISSION`, `EXIT_NOTINSTALLED`, and `EXIT_NOTCONFIGURED`.
They are marked as readonly, so it is an error to try to set them
afterwards.

[1]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html

### MESSAGE FORMAT

All routines feed the message/format string through `gettext`(1), if
it is available.

The descriptions will frequently reference `printf`(1)--this isn't
really that `printf`.  The program described by the manual page
`printf`(1) is probably the version from GNU coreutils, every time it
is used here, it is `bash`(1)'s internal implementation; try running
the command `help printf` from a Bash shell for more information.

### GENERAL ROUTINES

Unless otherwise noted, these do not implicitly call `gettext`.

   * `_` <MESSAGE>:
     If `gettext` is available, calls `gettext`, otherwise just prints
     the arguments given.

   * `in_array` <NEEDLE> <HAYSTACK>...:
     Evaluates whether <HAYSTACK> includes <NEEDLE>; returns 0 if it
     does, non-zero if it doesn't.

   * `panic` [<MESG> [<ARGS>...]]:
     For the times when you can't reasonably continue, similar to
     "assert" in some programming languages.

   * `setup_traps` [<HANDLER>]:
     Sets traps on TERM, HUP, QUIT and INT signals, as sell as the ERR
     event, similar to makepkg.  If <HANDLER> is specified, instead of
     using the default handler (which is good for most purposes), it
     will call <HANDLER> with the arguments
     `<HANDLER> <SIGNAL_NAME> <MESSAGE> [<MESSAGE_ARGS>...]`, where
     <MESSAGE> is a `printf`(1)-formatted string that is fed through
     `gettext`, and <MESSAGE_ARGS> are its arguments.

   * `whitespace_collapse`:
     Collapses whitespace on stadard I/O, similar to HTML whitespace
     collapsing, with the exception that it puts two spaces between
     sentences.  It considers newline, tab, and space to be
     whitespace.

### PROSE ROUTINES

These routines print to standard output, and are useful for printing
word-wrapped prose.

For each of these, <MESSAGE> is fed through `gettext` automatically.

To generate gettext `.pot` files for programs using these routines,
plain `xgettext`(1) won't work because it doesn't know about
word-wrapping.  Instead, you should use the `librexgettext`(1) program
which knows how do handle word-wrapping, and knows about each of these
routines by default.

   * `prose` <MESSAGE> [<ARGS>...]:
     Takes a `printf`(1)-formatted string, collapses whitespace
     (HTML-style), and then word-wraps it.

   * `bullet` <MESSAGE> [<ARGS>...]:
     Similar to `prose`, but prints a bullet point before the first
     line, and indents the remaining lines.

   * `flag` [<FLAG> <DESCRIPTION>|<HEADING>:]...:
     Print a flag and description formatted for `--help` text.  For
     example:<br>
     `flag '-N' 'Disable networking in the chroot'`<br>
     The description is fed through `gettext`, the flag is not, so if
     part of the flag needs to be translated, you must do that
     yourself:<br>
     `flag "-C <$(_ FILE)>" 'Use this file instead of pacman.conf'`<br>
     Newlines in the description are ignored; it is
     whitespace-collapsed (so newlines are stripped), then it is
     re-word-wrapped, in the same way as `prose` and `bullet`.  If you
     pass in multiple flag/description pairs to the same invocation,
     the descriptions are all aligned together.  The ability to do
     insert headings without resetting the alignment is the motivation
     for also allowing headings to be in the list.  In order to tell
     the difference between a flag and a heading, a heading must end
     with a colon (':'), and a flag must not.

### NOTIFICATION ROUTINES

These routines print to standard error, and all take arguments in the
same format as `printf`(1), except for `stat_done`, which doesn't take
any arguments.  Each of these print to stderr, not stdout.

For each of these, <MESSAGE> is fed through `gettext` automatically.

To generate gettext `.pot` files for programs using these routines,
plain `xgettext`(1) will work if given correct flags, but you'll find
it easier to use `librexgettext`(1), which will handle each of these
without any extra flags.

Informational notifications (these may be silenced by setting `QUIET`
to a non-zero integer):

   * `plain` <MESSAGE> [<ARGS>...]:
     Prints a "plain" message in bold, indented with 4 spaces.

   * `msg` <MESSAGE> [<ARGS>...]:
     Prints a top-level priority notification.

   * `msg2` <MESSAGE> [<ARGS>...]:
     Prints a secondary notification.

   * `stat_busy` <MESSAGE> [<ARGS>...]:
     Prints a "working..." type message without a trailing newline.

   * `stat_done`:
     Prints a "done" type message to terminate `stat_busy`.

Essential notifications (are *not* silenced by `QUIET`):

   * `ask <MESSAGE> [<ARGS>...]:`
     Prints a prompt to show to the user.  Is *not* silenced by
     `QUIET`.

   * `print` <MESSAGE> [<ARGS>...]:
     Like `printf`(1), but `gettext`-aware, and automatically prints a
     trailing newline.  Is *not* silenced by `QUIET`.

   * `term_title` <MESSAGE> [<ARGS>...]:
     Sets the terminal title to the specified message.

Error notifications (are *not* silenced by `QUIET`):

   * `warning` <MESSAGE> [<ARGS>...]:
     Prints a warning.

   * `error` <MESSAGE> [<ARGS>...]:
     Prints an error message.

   * `plainerr` <MESSAGE> [<ARGS>...]:
     Prints continuation of a warning or error message; formatted
     similarly to `plain`.

   * `gnuerror` <MESSAGE> [<ARGS>...]:
     Like `error`, but formats the message GNU error(3); useful for
     printing errors about incorrect CLI usage.

### TEMPORARY DIRECTORY MANAGEMENT

These are used by devtools, and not used within the rest of
libretools.

They work by creating and removing the directory referred to by the
variable $<WORKDIR>; `libretools.conf`(5) uses the same variable to
where the user saves all their work.  If you aren't careful with
these, you could end up deleting a lot of someone's work.

   * `setup_workdir`:
     Creates a temporary directory, and sets the environmental
     variable $<WORKDIR> to it.  Also sets traps for the signals INT,
     QUIT, TERM and HUP to run `abort`; and EXIT to run `cleanup`
     (see `signal`(7)).

   * `cleanup` [<EXIT_STATUS>]:
     *If* `setup_workdir` has been run, `rm -rf "$WORKDIR"`.  If given
     a numeric argument, it will then call `exit`(1) with that
     argument, otherwise it calls `exit`(1) with a status of 0.

   * `abort`:
     Calls `msg` with the message "Aborting...", then calls
     `cleanup 255`.

   * `die` <MESSAGE> [<ARGS>...]:
     Exactly like `error`, but calls `cleanup` and calls `exit`(1)
     with a status of 255.

### LOCKFILE ROUTINES

   * `lock` <FD> <LOCKFILE> <MESSAGE> [<MSG_ARGS>...]:
     Opens (creating if necessary) the file <LOCKFILE> with file
     descriptor <FD> in the current process, and gets an exclusive
     lock on it.  If another program already has a lock on the file,
     and this program needs to wait for the lock to be released, then
     it uses `stat_busy`/`stat_done` to print <MESSAGE>.

   * `slock` <FD> <LOCKFILE> <MESSAGE> [<MSG_ARGS>...]:
     Identical like `lock`, but opens a shared lock.  This is also
     known as a "read lock".  Many programs can have a shared lock at
     the same time, as long as no one has an exclusive lock on it.

   * `lock_close` <FD>:
     Closes file descriptor <FD>, releasing the lock opened on it.

### MAKEPKG ROUTINES

These routines relate to `makepkg`(8).

   * `find_cached_package` <PKGNAME> <PKGVER>[-<PKGREL] <ARCH>:
     Searches for a locally built copy of the specified package, in
     <PKGDEST> and the current working directory.  If <PKGREL> is not
     specified, any value will match.  If multiple matching files are
     found (not counting duplicate links), then an error is printed to
     stderr and nothing is printed to stdout.

   * `find_cached_srcpackage` <PKGNAME> <PKGVER>[-<PKGREL] <ARCH>:
     Similar to `find_cached_package`, but searches <SRCPKGDEST> for
     source packages produced by libremakepkg.

   * `get_full_version` [<PKGNAME>]:
     Inspects variables that are set, and prints the full version
     spec, including <epoch> if necessary, <pkgver>, and <pkgrel>.  By
     default, it will print the information for <pkgbase>, following
     the normal rules for finding <pkgbase>.  If <PKGNAME> is given,
     it will print the information for that sub-package.  The versions
     for different parts of a split package don't have to be the same!

## BUGS

`term_title` currently only knows about the terminals screen, tmux,
xterm and rxvt (and their various <TERM> values;
"rxvt-unicode-256color" is still rxvt).

## SEE ALSO

librexgettext(1), librelib(7), gettext(1), common.sh(3)

Things that were mentioned:

bash(1), xgettext(1), exit(1), isatty(3), libretools.conf(5),
makepkg(8), printf(1), signal(7)

<!--
  Copyright (C) 2013-2018, 2024  Luke T. Shumaker <lukeshu@parabola.nu>

  SPDX-License-Identifier: GPL-2.0-or-later

  This file is part of Parabola Libretools.

  Libretools 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 2 of the License, or
  (at your option) any later version.

  Libretools 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-->
