From 807102051896c1b007cfab956dd4f2d54fe5132f Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 10 Jan 2019 14:24:11 +0100
Subject: [PATCH] ENH: make List output compile-time configurable (#1160)

- introduced a ListPolicy details to make the transition between
  a short list (space separated) and a long list (newline separated)
  more configurable.

  We suppress line breaks for commonly used types that often have
  short content: (word, wordRes, keyType).
---
 applications/test/List/Test-List.C            |  65 ++++++++++-
 .../containers/Bits/PackedList/PackedList.H   |  24 ++--
 .../containers/Bits/PackedList/PackedListIO.C |  13 +--
 src/OpenFOAM/containers/Bits/bitSet/bitSet.H  |  15 ++-
 .../containers/Bits/bitSet/bitSetIO.C         |   8 +-
 .../containers/HashTables/HashSet/HashSet.C   |   4 +-
 .../containers/HashTables/HashSet/HashSet.H   |   8 +-
 .../HashTables/HashTable/HashTable.H          |   6 +-
 .../HashTables/HashTable/HashTableIO.C        |   8 +-
 .../LinkedLists/accessTypes/LList/LList.H     |   7 +-
 .../LinkedLists/accessTypes/LList/LListIO.C   |   8 +-
 .../LinkedLists/accessTypes/UILList/UILList.H |   7 +-
 .../accessTypes/UILList/UILListIO.C           |   6 +-
 .../containers/Lists/FixedList/FixedList.H    |   9 +-
 .../containers/Lists/FixedList/FixedListIO.C  |  14 ++-
 .../Lists/UIndirectList/UIndirectList.H       |  25 ++--
 .../Lists/UIndirectList/UIndirectListIO.C     |  29 ++---
 src/OpenFOAM/containers/Lists/UList/UList.H   |  30 ++---
 src/OpenFOAM/containers/Lists/UList/UListIO.C |  25 ++--
 .../containers/Lists/policy/ListPolicy.H      | 108 ++++++++++++++++++
 20 files changed, 298 insertions(+), 121 deletions(-)
 create mode 100644 src/OpenFOAM/containers/Lists/policy/ListPolicy.H

diff --git a/applications/test/List/Test-List.C b/applications/test/List/Test-List.C
index 5ec2bab8438..5d3d5164dee 100644
--- a/applications/test/List/Test-List.C
+++ b/applications/test/List/Test-List.C
@@ -46,6 +46,7 @@ See also
 #include "HashOps.H"
 #include "ListOps.H"
 #include "SubList.H"
+#include "ListPolicy.H"
 
 #include <list>
 #include <numeric>
@@ -64,9 +65,22 @@ public:
     using List<string>::List;
 };
 
+
+
+namespace Detail
+{
+namespace ListPolicy
+{
+
+// Override on a per-type basis
+template<> struct short_length<short> : std::integral_constant<short,20> {};
+
+} // End namespace ListPolicy
+} // End namespace Detail
 } // End namespace Foam
 
 
+
 using namespace Foam;
 
 template<class T, class ListType>
@@ -92,6 +106,20 @@ void printMyString(const UList<string>& lst)
 }
 
 
+template<class T>
+Ostream& printListOutputType(const char* what)
+{
+    Info<< what
+        << " (contiguous="
+        << contiguous<T>() << " no_linebreak="
+        << Detail::ListPolicy::no_linebreak<T>::value
+        << " short_length="
+        << Detail::ListPolicy::short_length<T>::value << ')';
+
+    return Info;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 //  Main program:
 
@@ -251,23 +279,54 @@ int main(int argc, char *argv[])
 
         Info<<"scalar identity:" << flatOutput(slist) << endl;
 
-        Info<< "labels (contiguous=" << contiguous<label>() << ")" << nl;
+        printListOutputType<label>("labels") << nl;
 
         Info<< "normal: " << longLabelList << nl;
         Info<< "flatOutput: " << flatOutput(longLabelList) << nl;
         // Info<< "flatOutput(14): " << flatOutput(longLabelList, 14) << nl;
 
+        auto shrtList = ListOps::create<short>
+        (
+            longLabelList,
+            [](const label& val){ return val; }
+        );
+
+        printListOutputType<short>("short") << nl;
+        Info<< "normal: " << shrtList << nl;
+
+
         stringList longStringList(12);
         forAll(longStringList, i)
         {
             longStringList[i].resize(3, 'a' + i);
         }
 
-        Info<< "string (contiguous=" << contiguous<string>() << ")" << nl;
+        printListOutputType<string>("string") << nl;
 
         Info<< "normal: " << longStringList << nl;
         Info<< "flatOutput: " << flatOutput(longStringList) << nl;
-        // contiguous longStringList[i].resize(3, 'a' + i);
+
+        auto wList = ListOps::create<word>
+        (
+            longStringList,
+            [](const std::string& val){ return val; }
+        );
+
+        printListOutputType<word>("word") << nl;
+
+        Info<< "normal: " << wList << nl;
+
+        // Shorten
+        longStringList.resize(8);
+        wList.resize(8);
+
+        Info<< "Test shorter lists" << nl;
+
+        printListOutputType<string>("string") << nl;
+        Info<< "normal: " << longStringList << nl;
+
+        printListOutputType<word>("word") << nl;
+        Info<< "normal: " << wList << nl;
     }
 
     // test SubList and labelRange
diff --git a/src/OpenFOAM/containers/Bits/PackedList/PackedList.H b/src/OpenFOAM/containers/Bits/PackedList/PackedList.H
index c30710c02fd..a77213b9e8b 100644
--- a/src/OpenFOAM/containers/Bits/PackedList/PackedList.H
+++ b/src/OpenFOAM/containers/Bits/PackedList/PackedList.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017-2018 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -400,10 +400,9 @@ public:
         //- Clear list and read from stream
         Istream& read(Istream& is);
 
-        //- Write the List, with line-breaks in ASCII if the list length
-        //- exceeds shortListLen.
+        //- Write List, with line-breaks in ASCII when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const;
+        Ostream& writeList(Ostream& os, const label shortLen=0) const;
 
         //- Write as a dictionary entry with keyword
         void writeEntry(const word& keyword, Ostream& os) const;
@@ -492,15 +491,20 @@ public:
             Istream& is,
             PackedList<Width>& list
         );
-
-        friend Ostream& operator<< <Width>
-        (
-            Ostream& os,
-            const PackedList<Width>& list
-        );
 };
 
 
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
+
+//- Write List to Ostream, as per UList::writeList() with default length.
+//  The default short-length is given by Detail::ListPolicy::short_length
+template<unsigned Width>
+Ostream& operator<<(Ostream& os, const PackedList<Width>& list)
+{
+    return list.writeList(os, Detail::ListPolicy::short_length<void>::value);
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/containers/Bits/PackedList/PackedListIO.C b/src/OpenFOAM/containers/Bits/PackedList/PackedListIO.C
index 84b529ae298..a6196f334a3 100644
--- a/src/OpenFOAM/containers/Bits/PackedList/PackedListIO.C
+++ b/src/OpenFOAM/containers/Bits/PackedList/PackedListIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -206,7 +206,7 @@ template<unsigned Width>
 Foam::Ostream& Foam::PackedList<Width>::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const PackedList<Width>& list = *this;
@@ -220,7 +220,7 @@ Foam::Ostream& Foam::PackedList<Width>::writeList
             // Two or more entries, and all entries have identical values.
             os  << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
         }
-        else if (!shortListLen || len <= shortListLen)
+        else if (!shortLen || len <= shortLen)
         {
             // Shorter list, or line-breaks suppressed
             os  << len << token::BEGIN_LIST;
@@ -284,13 +284,6 @@ Foam::Istream& Foam::operator>>(Istream& is, PackedList<Width>& list)
 }
 
 
-template<unsigned Width>
-Foam::Ostream& Foam::operator<<(Ostream& os, const PackedList<Width>& list)
-{
-    return list.writeList(os, 10);
-}
-
-
 template<unsigned Width>
 Foam::Ostream& Foam::operator<<
 (
diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSet.H b/src/OpenFOAM/containers/Bits/bitSet/bitSet.H
index 961450c31df..69d78444ee1 100644
--- a/src/OpenFOAM/containers/Bits/bitSet/bitSet.H
+++ b/src/OpenFOAM/containers/Bits/bitSet/bitSet.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -541,10 +541,9 @@ public:
 
     // IO
 
-        //- Write the bitSet, with line-breaks in ASCII if the size
-        //- exceeds shortListLen.
+        //- Write bitSet, with line-breaks (ASCII) when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const;
+        Ostream& writeList(Ostream& os, const label shortLen=0) const;
 
         //- Write as a dictionary entry with keyword
         void writeEntry(const word& keyword, Ostream& os) const;
@@ -561,7 +560,7 @@ public:
 
     // Housekeeping
 
-        //- \deprecated(2018-04) compatibility name for PackedBoolList
+        //- Deprecated(2018-04) compatibility name for PackedBoolList
         //  \deprecated(2018-04) - use toc() method
         inline labelList used() const { return toc(); }
 
@@ -570,9 +569,13 @@ public:
 
 // Global Operators
 
-Ostream& operator<<(Ostream& os, const InfoProxy<bitSet>& info);
+//- Write bitset to Ostream, as per bitSet::writeList() with default length
+//- of 40 items.
 Ostream& operator<<(Ostream& os, const bitSet& bitset);
 
+//- Output bitset information
+Ostream& operator<<(Ostream& os, const InfoProxy<bitSet>& info);
+
 
 //- Bitwise-AND of two bitsets.
 //  See bitSet::operator&= for more details.
diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSetIO.C b/src/OpenFOAM/containers/Bits/bitSet/bitSetIO.C
index b8cee2c8714..472700dbf3c 100644
--- a/src/OpenFOAM/containers/Bits/bitSet/bitSetIO.C
+++ b/src/OpenFOAM/containers/Bits/bitSet/bitSetIO.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2018 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2018-2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -39,7 +39,7 @@ void Foam::bitSet::writeEntry(Ostream& os) const
 Foam::Ostream& Foam::bitSet::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const bitSet& list = *this;
@@ -53,7 +53,7 @@ Foam::Ostream& Foam::bitSet::writeList
             // Two or more entries, and all entries have identical values.
             os  << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
         }
-        else if (!shortListLen || len <= shortListLen)
+        else if (!shortLen || len <= shortLen)
         {
             // Shorter list, or line-breaks suppressed
             os  << len << token::BEGIN_LIST;
@@ -111,7 +111,7 @@ void Foam::bitSet::writeEntry
 
 Foam::Ostream& Foam::operator<<(Ostream& os, const bitSet& bitset)
 {
-    return bitset.writeList(os, 10);
+    return bitset.writeList(os, 40);
 }
 
 
diff --git a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C
index 178d2871d9a..663a0630b51 100644
--- a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C
+++ b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -362,7 +362,7 @@ Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
 template<class Key, class Hash>
 Foam::Ostream& Foam::operator<<(Ostream& os, const HashSet<Key, Hash>& tbl)
 {
-    return tbl.writeList(os, 10);  // 10=consistent with UList
+    return tbl.writeKeys(os, Detail::ListPolicy::short_length<Key>::value);
 }
 
 
diff --git a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H
index cbc166175ce..83e26974be5 100644
--- a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H
+++ b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H
@@ -290,12 +290,12 @@ public:
 
     // Writing
 
-        //- Write the unordered keys as a list, with line-breaks if list length
-        //- exceeds shortListLen.
+        //- Write unordered keys (list), with line-breaks
+        //- when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const
+        Ostream& writeList(Ostream& os, const label shortLen=0) const
         {
-            return this->writeKeys(os, shortListLen);
+            return this->writeKeys(os, shortLen);
         }
 
 
diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
index 8046f4d6a33..d7bdadc46f5 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
@@ -870,10 +870,10 @@ public:
         //- Print information
         Ostream& printInfo(Ostream& os) const;
 
-        //- Write the unordered keys as a list, with line-breaks if list length
-        //- exceeds shortListLen.
+        //- Write unordered keys (list), with line-breaks
+        //- when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeKeys(Ostream& os, const label shortListLen=0) const;
+        Ostream& writeKeys(Ostream& os, const label shortLen=0) const;
 
 
     // IOstream Operator
diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C
index 108b1f153c4..6fe637eec83 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C
@@ -115,7 +115,7 @@ template<class T, class Key, class Hash>
 Foam::Ostream& Foam::HashTable<T, Key, Hash>::writeKeys
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     // Similar to UList::writeList version except the following:
@@ -124,7 +124,11 @@ Foam::Ostream& Foam::HashTable<T, Key, Hash>::writeKeys
 
     label i = this->size();
 
-    if (i <= 1 || !shortListLen || (i <= shortListLen))
+    if
+    (
+        (i <= 1 || !shortLen)
+     || (i <= shortLen)
+    )
     {
         // Write size and start delimiter
         os << i << token::BEGIN_LIST;
diff --git a/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LList.H b/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LList.H
index d964202b826..0872b6eaf8e 100644
--- a/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LList.H
+++ b/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LList.H
@@ -294,10 +294,9 @@ public:
 
     // IOstream operators
 
-        //- Write LList with line-breaks when its length exceeds
-        //- shortListLen.
+        //- Write LList with line-breaks when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const;
+        Ostream& writeList(Ostream& os, const label shortLen=0) const;
 
         //- Read list from Istream
         friend Istream& operator>> <LListBase, T>
@@ -307,7 +306,7 @@ public:
         );
 
         //- Write LList to Ostream with line breaks,
-        //- as per writeList() with shortListLen=-1
+        //- as per writeList with shortLen=-1
         friend Ostream& operator<< <LListBase, T>
         (
             Ostream& os,
diff --git a/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LListIO.C b/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LListIO.C
index 93ba63f6386..3bebd99e3d6 100644
--- a/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LListIO.C
+++ b/src/OpenFOAM/containers/LinkedLists/accessTypes/LList/LListIO.C
@@ -130,15 +130,15 @@ template<class LListBase, class T>
 Foam::Ostream& Foam::LList<LListBase, T>::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const label len = this->size();
 
     if
     (
-        len <= 1 || !shortListLen
-     || (len <= shortListLen)
+        (len <= 1 || !shortLen)
+     || (len <= shortLen)
     )
     {
         // Size and start delimiter
@@ -179,7 +179,7 @@ Foam::Ostream& Foam::LList<LListBase, T>::writeList
 template<class LListBase, class T>
 Foam::Ostream& Foam::operator<<(Ostream& os, const LList<LListBase, T>& lst)
 {
-    return lst.writeList(os, -1);  // always with line breaks
+    return lst.writeList(os, -1);  // Always with line breaks
 }
 
 
diff --git a/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILList.H b/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILList.H
index b2c27aaf0b9..92e315d789f 100644
--- a/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILList.H
+++ b/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILList.H
@@ -178,13 +178,12 @@ public:
 
     // IOstream operators
 
-        //- Write UILList with line-breaks when its length exceeds
-        //- shortListLen.
+        //- Write UILList with line-breaks when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const;
+        Ostream& writeList(Ostream& os, const label shortLen=0) const;
 
         //- Write UILList to Ostream with line breaks,
-        //- as per writeList() with shortListLen=-1
+        //- as per writeList() with shortLen=-1
         friend Ostream& operator<< <LListBase, T>
         (
             Ostream& os,
diff --git a/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILListIO.C b/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILListIO.C
index 843f75e39b8..65b811c21a1 100644
--- a/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILListIO.C
+++ b/src/OpenFOAM/containers/LinkedLists/accessTypes/UILList/UILListIO.C
@@ -33,15 +33,15 @@ template<class LListBase, class T>
 Foam::Ostream& Foam::UILList<LListBase, T>::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const label len = this->size();
 
     if
     (
-        len <= 1 || !shortListLen
-     || (len <= shortListLen)
+        (len <= 1 || !shortLen)
+     || (len <= shortLen)
     )
     {
         // Size and start delimiter
diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H
index 49b9f561f2e..497e03c13a8 100644
--- a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H
+++ b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H
@@ -46,6 +46,7 @@ SourceFiles
 #include "Swap.H"
 #include "HashFwd.H"
 #include "SLListFwd.H"
+#include "ListPolicy.H"
 
 #include <initializer_list>
 #include <iterator>
@@ -400,8 +401,7 @@ public:
         //- Write the list as a dictionary entry with keyword
         void writeEntry(const word& keyword, Ostream& os) const;
 
-        //- Write the list, with line-breaks in ASCII if the length
-        //- exceeds shortLen.
+        //- Write List, with line-breaks in ASCII when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
         Ostream& writeList(Ostream& os, const label shortLen=0) const;
 
@@ -480,11 +480,12 @@ struct Hash<FixedList<T, N>>
 
 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
-//- Write to Ostream, as per FixedList::writeList() with shortLen=10
+//- Write List to Ostream, as per FixedList::writeList() with default length.
+//  The default short-length is given by Detail::ListPolicy::short_length
 template<class T, unsigned N>
 Ostream& operator<<(Ostream& os, const FixedList<T, N>& list)
 {
-    return list.writeList(os, 10);
+    return list.writeList(os, Detail::ListPolicy::short_length<T>::value);
 }
 
 
diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedListIO.C b/src/OpenFOAM/containers/Lists/FixedList/FixedListIO.C
index 78ac42bff1a..56512fe4650 100644
--- a/src/OpenFOAM/containers/Lists/FixedList/FixedListIO.C
+++ b/src/OpenFOAM/containers/Lists/FixedList/FixedListIO.C
@@ -62,7 +62,7 @@ template<class T, unsigned N>
 Foam::Ostream& Foam::FixedList<T, N>::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const FixedList<T, N>& list = *this;
@@ -77,8 +77,16 @@ Foam::Ostream& Foam::FixedList<T, N>::writeList
     {
         if
         (
-            N <= 1 || !shortListLen
-         || (N <= unsigned(shortListLen) && contiguous<T>())
+            (N <= 1 || !shortLen)
+         ||
+            (
+                (N <= unsigned(shortLen))
+             &&
+                (
+                    Detail::ListPolicy::no_linebreak<T>::value
+                 || contiguous<T>()
+                )
+            )
         )
         {
             // Start delimiter
diff --git a/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectList.H b/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectList.H
index 7c3191f936a..3a2f583af23 100644
--- a/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectList.H
+++ b/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectList.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017-2018 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -50,7 +50,6 @@ namespace Foam
 
 // Forward declarations
 template<class T> class UIndirectList;
-template<class T> Ostream& operator<<(Ostream&, const UIndirectList<T>&);
 
 // Commonly required list types
 typedef UIndirectList<bool> boolUIndList;
@@ -320,21 +319,21 @@ public:
 
     // Writing
 
-        //- Write the list, with line-breaks in ASCII if its length
-        //- exceeds shortListLen.
+        //- Write List, with line-breaks in ASCII when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const;
+        Ostream& writeList(Ostream& os, const label shortLen=0) const;
+};
 
 
-    // Ostream operator
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
-        //- Write list to Ostream, as per writeList() with shortListLen=10
-        friend Ostream& operator<< <T>
-        (
-            Ostream& os,
-            const UIndirectList<T>& list
-        );
-};
+//- Write List to Ostream, as per UList::writeList() with default length.
+//  The default short-length is given by Detail::ListPolicy::short_length
+template<class T>
+Ostream& operator<<(Ostream& os, const UIndirectList<T>& list)
+{
+    return list.writeList(os, Detail::ListPolicy::short_length<T>::value);
+}
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectListIO.C b/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectListIO.C
index 863288c302f..874c00c7636 100644
--- a/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectListIO.C
+++ b/src/OpenFOAM/containers/Lists/UIndirectList/UIndirectListIO.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2014 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,7 +34,7 @@ template<class T>
 Foam::Ostream& Foam::UIndirectList<T>::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const UIndirectList<T>& list = *this;
@@ -51,8 +51,16 @@ Foam::Ostream& Foam::UIndirectList<T>::writeList
         }
         else if
         (
-            len <= 1 || !shortListLen
-         || (len <= shortListLen && contiguous<T>())
+            (len <= 1 || !shortLen)
+         ||
+            (
+                (len <= shortLen)
+             &&
+                (
+                    Detail::ListPolicy::no_linebreak<T>::value
+                 || contiguous<T>()
+                )
+            )
         )
         {
             // Size and start delimiter
@@ -114,17 +122,4 @@ Foam::Ostream& Foam::UIndirectList<T>::writeList
 }
 
 
-// * * * * * * * * * * * * * * * Ostream Operator *  * * * * * * * * * * * * //
-
-template<class T>
-Foam::Ostream& Foam::operator<<
-(
-    Foam::Ostream& os,
-    const Foam::UIndirectList<T>& list
-)
-{
-    return list.writeList(os, 10);
-}
-
-
 // ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Lists/UList/UList.H b/src/OpenFOAM/containers/Lists/UList/UList.H
index 3d8302f7f71..40bf4be2891 100644
--- a/src/OpenFOAM/containers/Lists/UList/UList.H
+++ b/src/OpenFOAM/containers/Lists/UList/UList.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017-2018 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2017-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -51,6 +51,7 @@ SourceFiles
 #include "stdFoam.H"
 #include "Swap.H"
 #include "HashFwd.H"
+#include "ListPolicy.H"
 
 #include <initializer_list>
 #include <iterator>
@@ -66,8 +67,8 @@ class labelRange;
 template<class T> class List;
 template<class T> class SubList;
 template<class T> class UList;
-template<class T> Ostream& operator<<(Ostream&, const UList<T>&);
 template<class T> Istream& operator>>(Istream&, UList<T>&);
+template<class T> Ostream& operator<<(Ostream&, const UList<T>&);
 
 // Common list types
 typedef UList<char> charUList;
@@ -471,20 +472,12 @@ public:
         //- Write the List as a dictionary entry with keyword
         void writeEntry(const word& keyword, Ostream& os) const;
 
-        //- Write the List, with line-breaks in ASCII if the list length
-        //- exceeds shortListLen.
+        //- Write List, with line-breaks in ASCII when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
-        Ostream& writeList(Ostream& os, const label shortListLen=0) const;
-
+        Ostream& writeList(Ostream& os, const label shortLen=0) const;
 
-    // IOstream operators
 
-        //- Write List to Ostream, as per writeList() with shortListLen=10
-        friend Ostream& operator<< <T>
-        (
-            Ostream& os,
-            const UList<T>& list
-        );
+    // IOstream Operators
 
         //- Read List contents from Istream.
         //  Requires size to have been set before
@@ -562,6 +555,17 @@ public:
 };
 
 
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
+
+//- Write List to Ostream, as per UList::writeList() with default length.
+//  The default short-length is given by Detail::ListPolicy::short_length
+template<class T>
+Ostream& operator<<(Ostream& os, const UList<T>& list)
+{
+    return list.writeList(os, Detail::ListPolicy::short_length<T>::value);
+}
+
+
 // * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * * //
 
 template<class T>
diff --git a/src/OpenFOAM/containers/Lists/UList/UListIO.C b/src/OpenFOAM/containers/Lists/UList/UListIO.C
index 7b5805964b7..3ba28d08eb1 100644
--- a/src/OpenFOAM/containers/Lists/UList/UListIO.C
+++ b/src/OpenFOAM/containers/Lists/UList/UListIO.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2019 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -71,7 +71,7 @@ template<class T>
 Foam::Ostream& Foam::UList<T>::writeList
 (
     Ostream& os,
-    const label shortListLen
+    const label shortLen
 ) const
 {
     const UList<T>& list = *this;
@@ -88,8 +88,16 @@ Foam::Ostream& Foam::UList<T>::writeList
         }
         else if
         (
-            len <= 1 || !shortListLen
-         || (len <= shortListLen && contiguous<T>())
+            (len <= 1 || !shortLen)
+         ||
+            (
+                (len <= shortLen)
+             &&
+                (
+                    Detail::ListPolicy::no_linebreak<T>::value
+                 || contiguous<T>()
+                )
+            )
         )
         {
             // Size and start delimiter
@@ -141,14 +149,7 @@ Foam::Ostream& Foam::UList<T>::writeList
 }
 
 
-// * * * * * * * * * * * * * * * Ostream Operator *  * * * * * * * * * * * * //
-
-template<class T>
-Foam::Ostream& Foam::operator<<(Ostream& os, const UList<T>& list)
-{
-    return list.writeList(os, 10);
-}
-
+// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
 
 template<class T>
 Foam::Istream& Foam::operator>>(Istream& is, UList<T>& list)
diff --git a/src/OpenFOAM/containers/Lists/policy/ListPolicy.H b/src/OpenFOAM/containers/Lists/policy/ListPolicy.H
new file mode 100644
index 00000000000..7697c61b22c
--- /dev/null
+++ b/src/OpenFOAM/containers/Lists/policy/ListPolicy.H
@@ -0,0 +1,108 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM 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 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM 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 OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Namespace
+    Foam::Detail::ListPolicy
+
+Description
+    Additional compile-time controls of List behaviour
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef ListPolicy_H
+#define ListPolicy_H
+
+#include "label.H"
+#include <type_traits>
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward Declarations
+class word;
+class wordRe;
+class keyType;
+
+namespace Detail
+{
+namespace ListPolicy
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- Number of items before requiring line-breaks in the list ouput.
+//
+//  Default definition: 10
+template<class T>
+struct short_length : std::integral_constant<label,10> {};
+
+// Could override on a per-type basis
+// Eg,
+// template<> struct short_length<label> : std::integral_constant<label,20> {};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- Can suppress additional line breaks separate ASCII data content
+//- when the data elements are primitives, or contiguous
+//
+//  Default definition: (integral | floating-point) are contiguous and thus
+//  never need any line breaks
+template<class T>
+struct no_linebreak
+:
+    std::integral_constant
+    <
+        bool,
+        std::is_integral<T>::value || std::is_floating_point<T>::value
+    >
+{};
+
+
+// Specialization for word, wordRe, keyType
+// These elements are normally fairly short, so ok to output a few (eg, 10)
+// of them on a single line.
+
+//- Suppress line-breaks for word
+template<> struct no_linebreak<word> : std::true_type {};
+
+//- Suppress line-breaks for wordRe
+template<> struct no_linebreak<wordRe> : std::true_type {};
+
+//- Suppress line-breaks for keyType
+template<> struct no_linebreak<keyType> : std::true_type {};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace ListPolicy
+} // End namespace Detail
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab