=encoding utf8

=head1 NAME

User::Identity::Archive::Plain - simple, plain text archiver

=head1 INHERITANCE

 User::Identity::Archive::Plain
   is a User::Identity::Archive
   is a User::Identity::Item

=head1 SYNOPSIS

  use User::Identity::Archive::Plain;
  my $friends = User::Identity::Archive::Plain->new('friends');
  $friends->from(\*FH);
  $friends->from('.friends');

=head1 DESCRIPTION

This archiver, which extends L<User::Identity::Archive|User::Identity::Archive>, uses a very
simple plain text file to store the information of users.  The syntax
is described in the DETAILS section, below.

Extends L<"DESCRIPTION" in User::Identity::Archive|User::Identity::Archive/"DESCRIPTION">.

=head1 OVERLOADED

Extends L<"OVERLOADED" in User::Identity::Archive|User::Identity::Archive/"OVERLOADED">.

=head1 METHODS

Extends L<"METHODS" in User::Identity::Archive|User::Identity::Archive/"METHODS">.

=head2 Constructors

Extends L<"Constructors" in User::Identity::Archive|User::Identity::Archive/"Constructors">.

=over 4

=item $class-E<gt>B<new>( [$name], %options )

Z<>

 -Option       --Defined in             --Default
  abbreviations                           []
  description    User::Identity::Item     undef
  from           User::Identity::Archive  undef
  name           User::Identity::Item     <required>
  only                                    []
  parent         User::Identity::Item     undef
  tabstop                                 8

=over 2

=item abbreviations => HASH|ARRAY

Adds a set of abbreviations for collections to the syntax of the
plain text archiver.  See section L</Simplified class names> for
a list of predefined names.

=item description => STRING

=item from => $filehandle|$file

=item name => STRING

=item only => \@abbrevs|$abbrev

Lists the only information (as (LIST of) abbreviations) which should be
read.  Other information is removed before even checking whether it is
a valid abbreviation or not.

=item parent => OBJECT

=item tabstop => INTEGER

Sets the default tab-stop width.

=back

=back

=head2 Attributes

Extends L<"Attributes" in User::Identity::Archive|User::Identity::Archive/"Attributes">.

=over 4

=item $obj-E<gt>B<abbreviation>( $name, [$class] )

Returns the class which is capable of storing information which is
grouped as C<$name>.  With C<$class> argument, you add (or overrule) the
definitions of an abbreviation.  The C<$class> is automatically loaded.

If C<$class> is C<undef>, then the abbreviation is deleted.  The class
name which is deleted is returned.

=item $obj-E<gt>B<abbreviations>()

Returns a sorted list of all names which are known as abbreviations.

=item $obj-E<gt>B<defaultTabStop>( [$integer] )

Returns the width of a tab, optionally after setting it.  This must be
the same as set in your editor.

=item $obj-E<gt>B<description>()

Inherited, see L<User::Identity::Item/"Attributes">

=item $obj-E<gt>B<name>( [$newname] )

Inherited, see L<User::Identity::Item/"Attributes">

=back

=head2 Collections

Extends L<"Collections" in User::Identity::Archive|User::Identity::Archive/"Collections">.

=over 4

=item $obj-E<gt>B<add>($collection, $role)

Inherited, see L<User::Identity::Item/"Collections">

=item $obj-E<gt>B<addCollection>( $object | <[$type], %options> )

Inherited, see L<User::Identity::Item/"Collections">

=item $obj-E<gt>B<collection>($name)

Inherited, see L<User::Identity::Item/"Collections">

=item $obj-E<gt>B<parent>( [$parent] )

Inherited, see L<User::Identity::Item/"Collections">

=item $obj-E<gt>B<removeCollection>($object|$name)

Inherited, see L<User::Identity::Item/"Collections">

=item $any-E<gt>B<type>()

Inherited, see L<User::Identity::Item/"Collections">

=item $obj-E<gt>B<user>()

Inherited, see L<User::Identity::Item/"Collections">

=back

=head2 Searching

Extends L<"Searching" in User::Identity::Archive|User::Identity::Archive/"Searching">.

=over 4

=item $obj-E<gt>B<find>($collection, $role)

Inherited, see L<User::Identity::Item/"Searching">

=back

=head2 Access to the archive

Extends L<"Access to the archive" in User::Identity::Archive|User::Identity::Archive/"Access to the archive">.

=over 4

=item $obj-E<gt>B<from>( <$fh|$filename|ARRAY>, %options )

Read the plain text information from the specified C<$fh>, C<$filename>,
STRING, or C<ARRAY> of lines.
Improves base, see L<User::Identity::Archive/"Access to the archive">

 -Option --Default
  tabstop  <default from object>

=over 2

=item tabstop => INTEGER

=back

=back

=head1 DETAILS

=head2 The Plain Archiver Format

=head3 Simplified class names

It is too much work to specify full class named on each spot where you
want to create a new object with data.  Therefore, abbreviations are
introduced.  Use L<new(abbreviations)|User::Identity::Archive::Plain/"METHODS"> or L<abbreviations()|User::Identity::Archive::Plain/"Attributes"> to add extra
abbreviations or to overrule some predefined.

Predefined names:
  user         User::Identity
  email        Mail::Identity
  location     User::Identity::Location
  system       User::Identity::System
  list         User::Identity::Collection::Emails

It would have been nicer to refer to a I<person> in stead of a I<user>,
however that would add to the confusion with the name-space.

=head3 Indentation says all

The syntax is as simple as possible. An extra indentation on a line
means that the variable or class is a collection within the class on
the line before.

  user markov
    location home
       country NL
    email home
       address  mark@overmeer.net
       location home
    email work
       address  solutions@overmeer.bet

  email tux
     address tux@fish.net

The above defines two items: one L<User::Identity|User::Identity> named C<markov>, and
an e-mail address C<tux>.  The user has two collections: one contains
a single location, and one stores two e-mail addresses.

To add to the confusion: the C<location> is defined as field in C<email>
and as collection.  The difference is easily detected: if there are
indented fields following the line it is a collection.  Mistakes will
in most cases result in an error message.

=head3 Long lines

If you want to continue on the next line, because your content is too
large, then add a backslash to the end, like this:

  email home
     description This is my home address,     \
                 But I sometimes use this for \
                 work as well
     address tux@fish.aq

Continuations do not play the game of indentation, so what you also
can do is:

  email home
     description               \
  This is my home address,     \
  But I sometimes use this for \
  work as well
     address tux@fish.aq

The fields C<comment> and C<address> must be correctly indented.
The line terminations are lost, which is useful for most fields.  However,
if you need them, you have to check the description of the applicable field.

=head3 Comments

You may add comments and white spaces.  Comments start with a C<'#'> as
first non-blank character on the line.  Comments are B<not allowed> on
the same line as real data, as some languages (like Perl) permit.

You can insert comments and blank lines on all places where you need
them:

  user markov

     # my home address
     email home

        # useless comment statement
        address tux@fish.aq
        location #mind_the_hash

is equivalent to:

  user markov
     email home
        address tux@fish.aq
        location #mind_the_hash

=head3 References

Often you will have the need to add the same information to two items,
for instance, multiple people share the same address.  In this case,
you can create a reference.  However, this is only permitted for
whole items: you can refer to someone's location, but not to the person's
street.

To create a reference to an item of someone else, use

  user markov
     location home = user(cleo).location(home)
     location work
        organization   MARKOV Solutions

=head3 Configuration parameters

You can add some configuration lines as well.  On the moment, the only
one defined is

  tabstop = 4

which can be used to change the meaning of tabs in the file.  The default
setting is 8, but some people prefer 4 (or other values).

=head1 DIAGNOSTICS

=over 4

=item Error: cannot load collection module for $type ($class): $@

Either the specified C<$type> does not exist, or that module named C<$class> returns
compilation errors.  If the type as specified in the warning is not
the name of a package, you specified a nickname which was not defined.
Maybe you forgot the 'require' the package which defines the nickname.
Cast by C<addCollection()>

=item Error: cannot read archive from a $type.

Cast by C<from()>

=item Fault: cannot read archive from file $file: $!

Cast by C<from()>

=item Error: nvalid collection $name.

The collection with C<$name> does not exist and can not be created.
Cast by C<add()>

=item Warning: option 'only' specifies undefined abbreviation '$abbrev'.

Cast by C<new()>

=item Info: reading archive data from $source.

Cast by C<from()>

=item Error: this $object is not a collection.

Cast by C<addCollection()>

=back

=head1 SEE ALSO

This module is part of User-Identity version 4.00,
built on December 12, 2025. Website: F<http://perl.overmeer.net/CPAN/>

=head1 LICENSE

For contributors see file ChangeLog.

This software is copyright (c) 2003-2025 by Mark Overmeer.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

