Rand Stats

Fortune

zef:samy

NAME

Fortune - Unix fortune database interface

SYNOPSIS

use Fortune;

## Object-oriented interface

my $fortune = Fortune.new: '/path/to/database';

my $pick = $fortune.fortune.pick;

$fortune.fortune.append: (q:to/HERE/).chomp;
Arnold's Laws of Documentation:
        (1) If it should exist, it doesn't.
        (2) If it does exist, it's out of date.
        (3) Only documentation for useless programs transcends the
            first two laws.
HERE

$fortune.write: '/path/to/new/database', :header('/path/to/header');

## Some convenience subs

strfile '/path/to/database', '/path/to/header';

$pick = fortune;

DESCRIPTION

Fortune is a Raku module that provides an interface for reading and writing Unix fortune files, both the text database files and the binary header files.

class Fortune

Attributes

fortune

has Str @.fortune is rw

Str array of fortunes. Manipulating this array is how you can modify a fortune database.

# Add a fortune
$fortune.fortune.append: "A new fortune";

# Remove a fortune
$fortune.fortune.pop;

# Sort fortunes
$fortune.fortune.=sort;

# Shuffle fortunes
$fortune.fortune.=pick(*);

# etc. etc.

order

has FortuneOrder $.order is rw

Attribute that determines the order to write the header's offset table in. Does not determine the order of the fortunes stored in the object's fortune attribute.

See the FortuneOrder documentation below for documentation on valid values for order.

rot13

has Bool $.rot13 is rw

Bool that determines whether the source fortune database was ROT-13 ciphered or not. When set to True, the Fortune object will read and write databases as if they were ROT-13 ciphered.

delimit

has Char $.delimit is rw

Character that is used for delimitting lines in a source fortune database. Is usually a single percentage sign ('%'). delimit must be a string that represents a single ASCII character.

version

has Int $.version is rw

Version number of the fortune header. Valid values are 1 and 2. Version 1 is the version used by most strfile implementations, version 2 is the version used by OpenBSD. The difference between the two versions is the way they store offsets in the fortune header: 1 stores offsets as 64-bit unsigned integars while 2 stores them as 32-bit unsigned integars. The version has no effect on the source fortune database.

Methods

new

method new(
	$database?,
	:$header,
	:@fortune,
	FortuneOrder :$order,
	Bool :$rot13,
	Char :$delimit,
	Int :$version
)

Returns a new Fortune object. Will either create an entirely new database if $database is not provided, or read from an existing one if $database is provided.

$database is the path to the database to read fortunes from. The fortunes can be accessed and manipulated from the object's fortune attribute.

$header is the path to the database's corresponding binary header to read from. If $header is a value that evaluates to False, new will not attempt to read any header file. By default, $header will either be $database with the '.dat' suffix appended if $database was provided and such a header does exist, otherwise it will be set to False. Please note that when reading from $header, new will override any custom attributes that were supplied.

@fortune is the list of fortune strings to supply for the fortune attribute. Defaults to Empty. If $database is also provided, new will append the list of fortunes read from $database to the list provided by @fortune.

$order is the value to supply for the order attribute. Defaults to FORTUNE_UNORDER.

$rot13 is the value to supply for the rot13 attribute. Defaults to False.

$delimit is the value to supply for the delimit attribute. Defaults to '%'.

$version is the value to supply for the version attribute. Defaults to 1.

read

method read(
	$database,
	:$header,
	Bool :$append
)

Reads data from the source database $database and (optionally) from the header $header.

$header will, by default, be $database with the '.dat' suffix if such a file exists, or False otherwise. If you do not wish to read from an existing header, $header can be set to False.

$append is a Bool determining whether to append new fortunes to the fortunes array or to overwrite it. Defautls to False.

Returns True, if successful.

read_header

method read_header($header)

Reads data from the header file $header.

Returns True, if successful.

read_database

method read_database(
	$database,
	Char :$delimit,
	Bool :$rot13,
	Bool :$append
)

Reads fortunes from the database file $database.

$delimit is the delimitting character to use when reading $database. Does not modify the delimit attribute. Defaults to the value of the delimit attribute.

$rot13 determines whether to ROT-13 cipher the fortunes in $database. Does not modify the rot13 attribute. Defaults to the value of the rot13 attribute.

$append is a Bool determining whether to override the current fortune list in fortune, or to just append to it. Defaults to False.

Returns True, if successful.

write

method write(
	$database,
	:$header
)

Write fortune database to $database and (optionally) fortune header to $header.

By default, $header will be $database with the '.dat' suffix. If set to any value that evaluates to False, write will not try to write a header file.

Returns list of IO objects for each written file.

write_database

method write_database($database)

Write fortune database to $database.

Returns IO object of written database.

write_header

method write_header($header)

Write fortune header to $header.

Returns IO object of written header.

Subroutines

The following subroutines were written to provide simple convenience functions for those who do not wish to interact with the object-oriented part of this module.

strfile

sub strfile(
	$database,
	$header?,
	Char :$delimit,
	FortuneOrder :$order,
	Bool :$rot13,
	Int :$version
)

Subroutine emulating the strfile(8) utility. Reads fortunes from $database and generates a corresponding fortune header to $header. If not supplied, $header will default to $database with the '.dat' suffix.

$delimit is the delimitting character $database uses. Defaults to '%'.

$order is the order to write the offset table in. Defaults to FORTUNE_UNORDER.

$rot13 is a Bool determining whether the source database was ROT-13 ciphered or not. Defaults to False.

$version is the version number to use for the generated header. Defaults to 1.

Returns the IO object of the written header.

fortune

multi sub fortune(
	Bool :$short,
	Bool :$long
)

multi sub fortune(
	$database,
	:$header,
	Bool :$short,
	Bool :$long,
	Bool :$equal,
	Bool :$all,
	Bool :$offensive,
	Char :$delimit,
	Bool :$rot13
)

multi sub fortune(
	$dir,
	Bool :$short,
	Bool :$long,
	Bool :$equal,
	Bool :$all,
	Bool :$offensive,
	Char :$delimit,
	Bool :$rot13
)

Subroutine somewhat emulating the fortune(6) utility. Picks a random fortune from a supplied database and returns it.

When ran without providing a fortune file/directory, returns a fortune from this module's own database.

When given a file as an argument, returns a random fortune from that file.

When given a directory as argument, returns a random fortune from one of the databases in that directory.

$header is the path to the header file to read from. Defaults to $database with the '.dat' suffix, or False if such a file does not exist. When False, fortune will not try to read any header file.

$short is a Bool determining whether to only pick from short fortunes. A short fortune is a fortune of 160 characters or less. Defaults to False.

$long is a Bool determining whether to only pick from long fortunes. A long fortune is a fortune that has more than 160 characters. Defaults to False.

$equal is a Bool determining whether to treat each fortune file in $dir of equal size. Is False by default, which means that fortune() is more likely to pick a fortune from a larger file.

$all is a Bool determining whether to include all fortunes files, including offensive ones, when picking a fortune. Is meaningless unless the fortune argument is a directory.

$offensive is a Bool that means fortune() will only pick offensive fortunes, which are fortunes located in a file with a '-o' suffix. Is meaningless unless the fortune argument is a directory. Also, to quote the fortune(6) manpage:

Please, please, please request a potentially offensive fortune if and only if
you believe, deep down in your heart, that you are willing to be offended.
(And that if you are, you'll just quit using [:offensive] rather than give us
grief about it, okay?)

    ...  let us keep in mind the basic governing philosophy of The Brotherhood,
    as handsomely summarized in these words:  we  believe  in  healthy,  hearty
    laughter -- at the expense of the whole human race, if needs be.  Needs be.
             --H. Allen Smith, "Rude Jokes"

$delimit is the delimitting character to use when reading from a database. Defaults to '%'.

$rot13 is a Bool determining whether the database is ROT-13 ciphered or not. Defaults to False.

This subroutine caches the Fortune object it creates from reading a database, and will re-use it as long as it has the same arguments as the previous fortune call. This makes it efficient to call this subroutine on the same database multiple times.

Global Variables

DATABASE

our constant $DATABASE

IO object of Fortune's personal fortune database, which is the one used by default by fortune() and the rfortune script. Can be accessed via $Fortune::DATABASE.

enum FortuneOrder

enum FortuneOrder <
	FORTUNE_UNORDER
	FORTUNE_ORDER
	FORTUNE_FC_ORDER
	FORTUNE_RANDOM
>

Enumeration representing the various ways a header file can order their offset tables.

AUTHOR

Written by Samuel Young, samyoung12788@gmail.com.

The source for this module can be found on its Codeberg page. Comments and pull requests are welcome.

COPYRIGHT

Copyright 2025, Samuel Young

This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.

SEE ALSO

fortune(6), strfile(8)