Index: doc/user/user.tex
===================================================================
--- doc/user/user.tex	(revision d3950125f9b8e14c660f3f5da742e6ad404ee9a7)
+++ doc/user/user.tex	(revision 86f384bba584191182741295324fe1ca6656b380)
@@ -11,6 +11,6 @@
 %% Created On       : Wed Apr  6 14:53:29 2016
 %% Last Modified By : Peter A. Buhr
-%% Last Modified On : Sat Jul  1 17:19:42 2017
-%% Update Count     : 2495
+%% Last Modified On : Sun Jul  2 09:49:56 2017
+%% Update Count     : 2503
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -2433,4 +2433,5 @@
 
 The goal of \CFA I/O is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way.
+The approach combines ideas from \CC and Python.
 The \CFA header file for the I/O library is \Indexc{fstream}.
 
@@ -2458,14 +2459,14 @@
 \end{tabular}
 \end{quote2}
-The \CFA form has half as many characters as the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
-Similar simplification occurs for \Index{tuple} I/O, which prints all a tuple's values, each separated by ``\lstinline[showspaces=true]@, @''.
+The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
+Similar simplification occurs for \Index{tuple} I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
 \begin{cfa}[mathescape=off,aboveskip=0pt,belowskip=0pt]
-[int, int] t1 = [1, 2], t2 = [3, 4];
+[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 3, [ 4, 5 ] ];
 sout | t1 | t2 | endl;					§\C{// print tuples}§
 \end{cfa}
 \begin{cfa}[mathescape=off,showspaces=true,belowskip=0pt]
-1®, ®2®, ®3®, ®4
-\end{cfa}
-Finally, \CFA uses the logical-or operator for I/O because it is the lowest-priority overloadable operator, other than assignment.
+1®, ®2®, ®3 3®, ®4®, ®5
+\end{cfa}
+Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
 Therefore, fewer output expressions require parenthesis.
 \begin{quote2}
@@ -2660,6 +2661,6 @@
 	int x = 1, y = 2, z = 3;
 	sout | x | y | z | endl;
-	[int, int] t1 = [1, 2], t2 = [3, 4];
-	sout | t1 | t2 | endl;						// print tuple
+	[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 3, [ 4, 5 ] ];
+	sout | t1 | t2 | endl;						// print tuples
 	sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;
 	sout | 1 | 2 | 3 | endl;
Index: src/libcfa/iostream
===================================================================
--- src/libcfa/iostream	(revision d3950125f9b8e14c660f3f5da742e6ad404ee9a7)
+++ src/libcfa/iostream	(revision 86f384bba584191182741295324fe1ca6656b380)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul  1 16:37:52 2017
-// Update Count     : 108
+// Last Modified On : Sun Jul  2 08:42:56 2017
+// Update Count     : 110
 //
 
@@ -26,4 +26,5 @@
 	const char * sepGetCur( ostype * );					// get current separator string
 	void sepSetCur( ostype *, const char * );			// set current separator string
+	_Bool lastSepOn( ostype * );						// last manipulator is setOn (context sensitive)
 	// public
 	void sepOn( ostype * );								// turn separator state on
@@ -31,5 +32,4 @@
 	_Bool sepDisable( ostype * );						// set default state to off, and return previous state
 	_Bool sepEnable( ostype * );						// set default state to on, and return previous state
-	_Bool lastSepOn( ostype * );						// last manipulator is setOn (context sensitive)
 
 	const char * sepGet( ostype * );					// get separator string
@@ -44,9 +44,9 @@
 	ostype * write( ostype *, const char *, unsigned long int );
 	int fmt( ostype *, const char fmt[], ... );
-};
+}; // ostream
 
 trait writeable( otype T ) {
 	forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, T );
-};
+}; // writeable
 
 // implement writable for intrinsic types
@@ -104,9 +104,9 @@
 	istype * ungetc( istype *, char );
 	int fmt( istype *, const char fmt[], ... );
-};
+}; // istream
 
 trait readable( otype T ) {
 	forall( dtype istype | istream( istype ) ) istype * ?|?( istype *, T );
-};
+}; // readable
 
 forall( dtype istype | istream( istype ) ) istype * ?|?( istype *, char * );
Index: src/libcfa/iostream.c
===================================================================
--- src/libcfa/iostream.c	(revision d3950125f9b8e14c660f3f5da742e6ad404ee9a7)
+++ src/libcfa/iostream.c	(revision 86f384bba584191182741295324fe1ca6656b380)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul  1 16:37:51 2017
-// Update Count     : 374
+// Last Modified On : Sun Jul  2 08:54:02 2017
+// Update Count     : 375
 //
 
@@ -201,6 +201,6 @@
 forall( dtype ostype, otype T, ttype Params | ostream( ostype ) | writeable( T ) | { ostype * ?|?( ostype *, Params ); } )
 ostype * ?|?( ostype * os, T arg, Params rest ) {
+	os | arg;											// print first argument
 	sepSetCur( os, sepGetTuple( os ) );					// switch to tuple separator
-	os | arg;											// print first argument
 	os | rest;											// print remaining arguments
 	sepSetCur( os, sepGet( os ) );						// switch to regular separator
Index: src/tests/.expect/io.txt
===================================================================
--- src/tests/.expect/io.txt	(revision d3950125f9b8e14c660f3f5da742e6ad404ee9a7)
+++ src/tests/.expect/io.txt	(revision 86f384bba584191182741295324fe1ca6656b380)
@@ -4,6 +4,11 @@
 123
 
+opening delimiters 
 x (1 x [2 x {3 x =4 x $5 x £6 x ¥7 x ¡8 x ¿9 x «10
+
+closing delimiters 
 1, x 2. x 3; x 4! x 5? x 6% x 7¢ x 8» x 9) x 10] x 11} x 
+
+opening/closing delimiters 
 x`1`x'2'x"3"x:4:x 5 x	6	x
 7
@@ -15,5 +20,11 @@
 10
 x 
+
+override opening/closing delimiters 
 x ( 1 ) x 2 , x 3 :x: 4
+
+input bacis types 
+
+output basic types 
 A 
 1 2 3 4 5 6 7 8
@@ -21,4 +32,8 @@
 1.1+2.3i 1.1-2.3i 1.1-2.3i
 
+tuples 
+1, 2, 3 3, 4, 5
+
+toggle separator 
 1.11.21.3
 1.1+2.3i1.1-2.3i1.1-2.3i
@@ -26,12 +41,16 @@
 abcxyz 
 
+change separator 
+from "  "to " , $"
 1.1, $1.2, $1.3
 1.1+2.3i, $1.1-2.3i, $1.1-2.3i
 abc, $xyz, $
+1, 2, 3, $3, 4, 5
 
-1, 2, 3, 4
-
-1, $2, $3 ", $"
-1 2 3 " "
+from ", $"to " "
+1.1 1.2 1.3
+1.1+2.3i 1.1-2.3i 1.1-2.3i
+abc xyz 
+1, 2, 3 3, 4, 5
 
  1 2 3 
@@ -49,7 +68,7 @@
 1 2 3
 
-1 2 3 4 " "
-1, 2, 3, 4 ", "
-1, 2, 3, 4
+1 2 3 3 4 5 " "
+1, 2, 3 3, 4, 5 ", "
+1, 2, 3 3, 4, 5
 
 3, 4, a, 7.2
@@ -57,3 +76,3 @@
 3 4 a 7.2
  3 4 a 7.234a7.23 4 a 7.2
-3-4-a-7.2^3^4-3-4-a-7.2
+3-4-a-7.2^3^4^3-4-a-7.2
Index: src/tests/io.c
===================================================================
--- src/tests/io.c	(revision d3950125f9b8e14c660f3f5da742e6ad404ee9a7)
+++ src/tests/io.c	(revision 86f384bba584191182741295324fe1ca6656b380)
@@ -10,6 +10,6 @@
 // Created On       : Wed Mar  2 16:56:02 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul  1 16:21:07 2017
-// Update Count     : 58
+// Last Modified On : Sun Jul  2 09:40:58 2017
+// Update Count     : 68
 // 
 
@@ -42,6 +42,6 @@
 	sout | endl;
 
+	sout | "opening delimiters" | endl;
 	sout
-		// opening delimiters
 		| "x (" | 1
 		| "x [" | 2
@@ -54,7 +54,8 @@
 		| "x ¿" | 9
 		| "x «" | 10
-		| endl;
+		| endl | endl;
+
+	sout | "closing delimiters" | endl;
 	sout
-		// closing delimiters
 		| 1 | ", x"
 		| 2 | ". x"
@@ -68,7 +69,8 @@
 		| 10 | "] x"
 		| 11 | "} x"
-		| endl;
+		| endl | endl;
+
+	sout | "opening/closing delimiters" | endl;
 	sout
-		// opening-closing delimiters
 		| "x`" | 1 | "`x'" | 2
 		| "'x\"" | 3 | "\"x:" | 4
@@ -76,11 +78,15 @@
 		| "\tx\f" | 7 | "\fx\v" | 8
 		| "\vx\n" | 9 | "\nx\r" | 10
-		| "\rx" |
-		endl;
+		| "\rx"
+		| endl | endl;
+
+	sout | "override opening/closing delimiters" | endl;
 	sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4 | endl;
+	sout | endl;
 
 	ifstream in;										// create / open file
 	open( &in, "io.data", "r" );
 
+	sout | "input bacis types" | endl;
 	&in | &c											// character
 		| &si | &usi | &i | &ui | &li | &uli | &lli | &ulli	// integral
@@ -88,5 +94,7 @@
 		| &fc | &dc | &ldc								// floating-point complex
 		| cstr( s1 ) | cstr( s2, size );				// C string, length unchecked and checked
+	sout | endl;
 
+	sout | "output basic types" | endl;
 	sout | c | ' ' | endl								// character
 		| si | usi | i | ui | li | uli | lli | ulli | endl // integral
@@ -94,4 +102,11 @@
 		| fc | dc | ldc | endl;							// complex
 	sout | endl;
+
+	sout | "tuples" | endl;
+	[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 3, [ 4, 5 ] ];
+	sout | t1 | t2 | endl;								// print tuple
+	sout | endl;
+
+	sout | "toggle separator" | endl;
 	sout | f | "" | d | "" | ld | endl					// floating point without separator
 		| sepDisable | fc | dc | ldc | sepEnable | endl	// complex without separator
@@ -100,19 +115,20 @@
 	sout | endl;
 
+	sout | "change separator" | endl;
+	sout | "from \" " | sepGet( sout ) | "\"";
 	sepSet( sout, ", $" );								// change separator, maximum of 15 characters
+	sout | "to \" " | sepGet( sout ) | "\"" | endl;
 	sout | f | d | ld | endl
 		| fc | dc | ldc | endl
-		| s1 | s2 | endl;
+		| s1 | s2 | endl
+		| t1 | t2 | endl;								// print tuple
 	sout | endl;
-
-	[int, int] t1 = [1, 2], t2 = [3, 4];
-	sout | t1 | t2 | endl;								// print tuple
-	sout | endl;
-
-	sepSet( sout, " " );
-	sepSet( sout, ", $" );								// set separator from " " to ", $"
-	sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"" | endl;
-	sepSet( sout, " " );								// reset separator to " "
-	sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"" | endl;
+	sout | "from \"" | sepGet( sout ) | "\"";
+	sepSet( sout, " " );								// restore separator
+	sout | "to \"" | sepGet( sout ) | "\"" | endl;
+	sout | f | d | ld | endl
+		| fc | dc | ldc | endl
+		| s1 | s2 | endl
+		| t1 | t2 | endl;								// print tuple
 	sout | endl;
 
