Skip to content

Ada generic helper to print iterable containers content, with customizable formats

Notifications You must be signed in to change notification settings

LionelDraghi/List_Image

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

List_Image

Ada generic helper to print iterable containers content, with customizable styles.

License


Table of Contents


Why?

This started with a simple idea in mind : removing duplicate code in ArchiCheck. The same loop that print containers content with a presentation more or less close to

[A, B, C]

was duplicated more times in the code.

Writing a generic function for a specific container is simple, but if I want that generic to be instantiated with whatever iterable containers from the Ada standard containers lib (List, Maps and Sets, etc.), it becomes fairly more complex, because of Ada Containers design.

To quote Emmanuel Briot :

[Ada predefined] ... containers have a lot of similarity in their APIs. As a result, it is relatively easy to use any of the containers when we are familiar with one of them.
But this does not make it easy to write algorithms that are container agnostic.

Ada 2022

Ada 2022 generalized 'Image for all types. This is a very fortunate evolution, that removes completely one of the main use-case for List_Image, that is just debugging : if you're OK with the default Bracketed style of 'Image, just use it.

As a consequence, List_Image no more provide the Bracketed_List_Style generic instantiation in the versions following 2.0.0.

Versions

  • Version 1.x.x is stable, and the last compatible with Ada2012.

  • Version 2.x.x may change in incompatible ways to explore Ada 2022 consequences. Removing the Bracketed_List_Style generic instantiation is an example.

Usage

The List_Image package provides :

  1. The Image generic function, that is to be instantiated for each user defined Container.
    The function has a simple profile :

    function Image (Cont : in Container) return String;

    The function simply walk through the Container, and gather the image of each element.

  2. The Image_Style generic package, that is one of the Image generic parameters.
    The style of the presentation may be customized in a large way, see examples behind.

  3. A collection of predefined Image_Style instantiation.

use example

with List_Image;

with Ada.Containers.Indefinite_Hashed_Sets;
with Ada.Strings.Hash_Case_Insensitive;
...
   -- Example here with a set of identifier
   package Id_Sets is new Ada.Containers.Indefinite_Hashed_Sets
     (String, Ada.Strings.Hash_Case_Insensitive, "=");
   Id_Set : Id_Sets.Set;

   -- Start of List_Image related declarations ----------------------------------

   use Id_Sets;
   package Id_Sets_Cursors is new List_Image.Cursors_Signature
     (Container => Id_Sets.Set,
      Cursor    => Id_Sets.Cursor);

   function Image (C : Cursor) return String is (Element (C));

   function Id_Set_Image is new List_Image.Image
     (Cursors => Id_Sets_Cursors,
      Style   => List_Image.Bracketed_List_Style);

   -- End of List_Image related declarations ------------------------------------

   ...
   Id_Set.Insert ("Salt");
   Id_Set.Insert ("Pepper");
   Put_Line (Id_Set_Image (Id_Set));

   -- Note the use of the predefined style Bracketed_List_Style.
   -- Image will be [Salt, Pepper]

Predefined styles

Single Line styles

Those instantiations are provided in the List_Image package.

  • Simple style :

    A, B, C
    
  • Bracketed style :

    [A, B, C]
    
  • Markdown table style :

    | A | B | C |
    

    Note : Markdown don't define tables, but it's a common extension, like in Github Flavored Markdown for example.

Multi Line styles

Those instantiations are dependent on the platform definition of an End of Line. There is no standard way in Ada to know at run time what is the standard EOL. Therefore, Styles depending on this EOL definition are provided in platform specific packages, currently List_Image.Unix_Predefined_Styles and List_Image.Windows_Predefined_Styles.

  • Bulleted :

    - A
    - B
    - C
    
  • Markdown bulleted list :
    like the bulleted list, but surrounded by two empty lines (in some Markdown implementations, if the first bullet is not preceded by an empty line, the list is not recognized)

  • HTML bulleted list :

    <ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    </ul>
    

    Note : an empty list <ul></ul> is recognized by most navigator, but seems to be illegal html. No problem here, thanks to the _If_Empty parameters nothing will be generated if the list is empty.

Defining your own style

This signature package defines the style used by the Image function to print the list.

   generic
      Prefix    : String;
      Postfix   : String;
      Separator : String;

      Last_Separator    : String := Separator;
      Prefix_If_Empty   : String := Prefix;
      Postfix_If_Empty  : String := Postfix;
      Prefix_If_Single  : String := Prefix;
      Postfix_If_Single : String := Postfix;

      EOL               : String := "";

   package Image_Style is end Image_Style;

Prefix, Postfix and Separator parameters are self explaining.
If Prefix is set to '(', Postfix to ')', and Separator to ',', the returned Image will be of this kind :

(A,B,C,D)

If all parameters are set to "", the image will be :

ABCD

Special Prefix and Postfix are possible for null list, and for list with a single element.
This is useful when you want [A,B,C] as an image, but you want an empty string (and not []) when the list is empty.

An interesting application of this feature is to have well written comments regarding singular and plural!
If you want your image to be

A item found

but

A, B, C items found

just set Postfix to " items found", and Postfix_If_Single to " item found".

And by the way, if you want the Image to be "No item found" when the list is empty, Prefix_If_Empty or Postfix_If_Empty are here for you.

Last_Separator allows to have a different last separator, as in :

A, B, C and D

Both separators may be whatever String.
You may want to insert an End of Line sequence to split the list on several line, the EOL default String and formal parameter are provided for that purpose.

About

This package was created by Lionel Draghi, and is released under Apache License v2.0.

Special thanks to Emmanuel Briot and Randy Bruckardt for their help.

References

Building

Get the sources on the GitHub project page

To build and run the tests, just :

make

Portability

Only tested on my Linux box, but the sources and tests should run nice on most platform, including windows.

Outputs on several lines comes with the question of what is (or even "is there") a End Of Line marker on the platform. (search for EOL above for more details). The provided Windows_Predefined_Styles and Unix_Predefined_Styles packages should do the job on most todays platform.

Note

Version 1.x.x are compatible with Ada 2012, and version 2.x.x are only compatible with Ada 2022.


Help and comments

  • Discussions are welcome here

About

Ada generic helper to print iterable containers content, with customizable formats

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published