From 74277455f11b9bb57f212a59a23838847cb006e2 Mon Sep 17 00:00:00 2001 From: Chris Jefferson Date: Thu, 11 Jan 2024 16:49:39 +0800 Subject: [PATCH] Extend StreamFormatting to seperate linewrap and indenting --- lib/custom_streams.gi | 7 +- lib/streams.gd | 38 +++++--- lib/streams.gi | 73 ++++++++++----- lib/string.gi | 2 +- src/io.c | 88 ++++++++++++------ src/io.h | 23 ++++- tst/testinstall/compressed.tst | 4 +- tst/testinstall/format.tst | 4 +- tst/testinstall/streams.tst | 92 +++++++++++++++---- tst/testinstall/stringobj.tst | 4 +- tst/testspecial/format.g | 20 +++++ tst/testspecial/format.g.out | 120 +++++++++++++++++++++++++ tst/testspecial/print-formatting.g.out | 16 ++-- 13 files changed, 391 insertions(+), 100 deletions(-) create mode 100644 tst/testspecial/format.g create mode 100644 tst/testspecial/format.g.out diff --git a/lib/custom_streams.gi b/lib/custom_streams.gi index 01798f9ddc..e30821be8e 100644 --- a/lib/custom_streams.gi +++ b/lib/custom_streams.gi @@ -343,11 +343,8 @@ InstallMethod( PrintFormattingStatus, "output text custom", ## InstallMethod( SetPrintFormattingStatus, "output text custom", [IsOutputTextCustomRep and IsOutputTextStream, - IsBool], + IsObject], function( str, stat) - if stat = fail then - Error("Print formatting status must be true or false"); - else + CheckValidPrintFormattingStatus(stat); str!.formatting := stat; - fi; end); diff --git a/lib/streams.gd b/lib/streams.gd index 0f39b66973..995c1cf7cc 100644 --- a/lib/streams.gd +++ b/lib/streams.gd @@ -959,24 +959,31 @@ DeclareGlobalFunction( "InputOutputLocalProcess" ); ## and harmless if it to passed as input to ⪆, ## but may be unhelpful if the output is to be passed as input to another ## program. -## It is possible to turn off this behaviour for a stream using the -## operation, and to test whether it -## is on or off using . +## It is possible to control this behaviour for a stream using the +## operation, and to query it +## using . +##

+## The formatting status is stored in a record with two members, +## linewrap and indent, which control if GAP wraps lines, +## or indents, respectively. These two both take a boolean. +##

+## For backwards compatability, all functions which control print formatting +## will also take a boolean, which sets linewrap and indent to +## the given boolean value. ##

## sets whether output sent to the ## output stream stream via , ## , etc. ## will be formatted with line breaks and -## indentation. If the second argument newstatus is true -## then output will be so formatted, and if false then it will not. -## If the stream is not a text stream, only false is allowed. +## indentation. The second argument newstatus is a record or boolean, +## as described above. +## If the stream is not a text stream, both linewrap and indent +## can only be set to false. ##

-## returns true if output sent to -## the output text stream stream via , -## , etc. -## will be formatted with line breaks and -## indentation, and false otherwise. -## For non-text streams, it returns false. +## returns a record containing the +## current value of linewrap and indent for the output text +## stream stream. For non-text streams, these values area always +## both false. ## If as argument stream the string "*stdout*" is given, these ## functions refer to the formatting status of the standard output (so usually ## the user's terminal screen).

@@ -997,7 +1004,7 @@ DeclareGlobalFunction( "InputOutputLocalProcess" ); ## gap> Print(s,"\n"); ## [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, ## 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 ] -## gap> SetPrintFormattingStatus(str, false); +## gap> SetPrintFormattingStatus(str, rec(indent:=false,linewrap:=false)); ## gap> PrintTo(str,Primes{[1..30]}); ## gap> s; ## "[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,\ @@ -1015,7 +1022,7 @@ DeclareGlobalFunction( "InputOutputLocalProcess" ); ## ## <#/GAPDoc> ## -DeclareOperation( "SetPrintFormattingStatus", [IsOutputStream, IsBool] ); +DeclareOperation( "SetPrintFormattingStatus", [IsOutputStream, IsObject] ); DeclareOperation( "PrintFormattingStatus", [IsOutputStream] ); @@ -1259,3 +1266,6 @@ DeclareGlobalFunction( "InputFromUser" ); ## <#/GAPDoc> ## DeclareGlobalFunction( "OpenExternal" ); + +DeclareGlobalFunction( "_CheckValidPrintFormattingStatus"); +DeclareGlobalFunction( "_DefaultPrintFormattingStatus"); diff --git a/lib/streams.gi b/lib/streams.gi index df426f85b2..11005a736b 100644 --- a/lib/streams.gi +++ b/lib/streams.gi @@ -860,7 +860,8 @@ function( str, append ) Unbind(str[i]); od; fi; - return Objectify( OutputTextStringType, [ str, true ] ); + return Objectify( OutputTextStringType, + [ str, _DefaultPrintFormattingStatus() ] ); end ); @@ -929,13 +930,9 @@ InstallMethod( PrintFormattingStatus, "output text string", ## InstallMethod( SetPrintFormattingStatus, "output text string", [IsOutputTextStringRep and IsOutputTextStream, - IsBool], + IsObject], function( str, stat) - if stat = fail then - Error("Print formatting status must be true or false"); - else - str![2] := stat; - fi; + str![2] := _CheckValidPrintFormattingStatus(stat); end); @@ -994,7 +991,8 @@ function( str, append ) atomic OutputTextFileStillOpen do AddSet( OutputTextFileStillOpen, fid ); od; - return Objectify( OutputTextFileType, [fid, Immutable(str), true] ); + return Objectify( OutputTextFileType, + [fid, Immutable(str), _DefaultPrintFormattingStatus()]); fi; end ); @@ -1025,7 +1023,8 @@ function( str, append ) atomic OutputTextFileStillOpen do AddSet( OutputTextFileStillOpen, fid ); od; - return Objectify( OutputTextFileType, [fid, Immutable(str), true] ); + return Objectify( OutputTextFileType, + [fid, Immutable(str), _DefaultPrintFormattingStatus() ] ); fi; end ); @@ -1130,13 +1129,9 @@ InstallMethod( PrintFormattingStatus, "output text file", ## InstallMethod( SetPrintFormattingStatus, "output text file", [IsOutputTextFileRep and IsOutputTextStream, - IsBool], + IsObject], function( str, stat) - if stat = fail then - Error("Print formatting status must be true or false"); - else - str![3] := stat; - fi; + str![3] := _CheckValidPrintFormattingStatus(stat); end); ## formatting status for stdout or current output @@ -1151,7 +1146,7 @@ function(str) fi; end); -InstallOtherMethod( SetPrintFormattingStatus, "for stdout", [IsString, IsBool], +InstallOtherMethod( SetPrintFormattingStatus, "for stdout", [IsString, IsObject], function(str, status) if str = "*stdout*" then SET_PRINT_FORMATTING_STDOUT(status); @@ -1255,9 +1250,7 @@ InstallMethod( SetPrintFormattingStatus, "output text none", [IsOutputTextNoneRep and IsOutputTextNone, IsBool], function( str, stat) - if stat = fail then - Error("Print formatting status must be true or false"); - fi; + _CheckValidPrintFormattingStatus(stat); end); @@ -1661,7 +1654,7 @@ function ( str ) if IsOutputTextStream( str ) then TryNextMethod(); fi; - return false; + return Immutable(rec(indent := false, linewrap := false) ); end); @@ -1676,13 +1669,45 @@ InstallMethod( SetPrintFormattingStatus, "for non-text output stream", TryNextMethod(); fi; - if stat = true then - Error("non-text streams support onlyPrint formatting status false"); - elif stat = fail then - Error("Print formatting status must be true or false"); + stat := _CheckValidPrintFormattingStatus(stat); + if stat.linewrap or stat.indent then + Error("non-text streams do not support print formatting"); + fi; +end); + + +InstallGlobalFunction( "_CheckValidPrintFormattingStatus", +function(fs) + local r; + if IsBool(fs) then + if fs = fail then + Error("Formatting status cannot be 'fail'"); + fi; + elif IsRecord(fs) then + if Set(RecNames(fs)) <> ["indent", "linewrap"] then + Error("Formatting status records must contain exactly two components, named 'indent' and 'linewrap'"); + fi; + for r in ["indent","linewrap"] do + if not fs.(r) in [false, true] then + Error(Concatenation(r, " must be 'true' or 'false' in formatting status record")); + fi; + od; + else + Error("Formatting status must be a boolean or a record"); + fi; + + if fs = true then + fs := rec(indent := true, linewrap := true); + elif fs = false then + fs := rec(indent := false, linewrap := false); fi; + return Immutable(ShallowCopy(fs)); end); +InstallGlobalFunction( "_DefaultPrintFormattingStatus", +function() + return Immutable(rec(linewrap := true, indent := true)); +end); ############################################################################# ## diff --git a/lib/string.gi b/lib/string.gi index b5cf315b65..fc97fa4565 100644 --- a/lib/string.gi +++ b/lib/string.gi @@ -1405,7 +1405,7 @@ InstallGlobalFunction(StringFormatted, function(s, data...) fi; str := ""; stream := OutputTextString(str, false); - SetPrintFormattingStatus(stream, false); + SetPrintFormattingStatus(stream, rec(linewrap := false, indent := true)); CallFuncList(PrintToFormatted, Concatenation([stream, s], data)); return str; diff --git a/src/io.c b/src/io.c index 0f18688890..9f23b7ed36 100644 --- a/src/io.c +++ b/src/io.c @@ -32,7 +32,9 @@ #include "lists.h" #include "modules.h" #include "plist.h" +#include "precord.h" #include "read.h" +#include "records.h" #include "scanner.h" #include "stringobj.h" #include "symbols.h" @@ -115,8 +117,8 @@ struct IOModuleState { Int NoSplitLine; - BOOL PrintFormattingForStdout; - BOOL PrintFormattingForErrout; + StreamFormat PrintFormattingForStdout; + StreamFormat PrintFormattingForErrout; }; // for debugging from GDB / lldb, we mark this as extern inline @@ -851,7 +853,7 @@ UInt OpenOutput(TypOutputFile * output, const Char * filename, BOOL append) else if (streq(filename, "*errout*")) output->format = IO()->PrintFormattingForErrout; else - output->format = TRUE; + output->format = MakeStreamFormat(TRUE, TRUE); output->indent = 0; // variables related to line splitting, very bad place to split @@ -886,7 +888,8 @@ UInt OpenOutputStream(TypOutputFile * output, Obj stream) output->file = -1; output->line[0] = '\0'; output->pos = 0; - output->format = (CALL_1ARGS(PrintFormattingStatus, stream) == True); + output->format = + StreamFormatFromObj(CALL_1ARGS(PrintFormattingStatus, stream)); output->indent = 0; // variables related to line splitting, very bad place to split @@ -1236,7 +1239,7 @@ static void PutChrTo(TypOutputFile * stream, Char ch) // '\01', increment indentation level if ( ch == '\01' ) { - if (!stream->format) + if (NoStreamFormat(stream->format)) return; // add hint to break line @@ -1246,7 +1249,7 @@ static void PutChrTo(TypOutputFile * stream, Char ch) // '\02', decrement indentation level else if ( ch == '\02' ) { - if (!stream->format) + if (NoStreamFormat(stream->format)) return; // if this is a better place to split the line remember it @@ -1282,8 +1285,7 @@ static void PutChrTo(TypOutputFile * stream, Char ch) // and dump it from the buffer stream->pos = 0; - if (stream->format) - { + if (stream->format.indent) { // indent for next line for ( i = 0; i < stream->indent; i++ ) stream->line[ stream->pos++ ] = ' '; @@ -1318,12 +1320,12 @@ static void PutChrTo(TypOutputFile * stream, Char ch) /* if we are going to split at the end of the line, and we are formatting discard blanks */ - if ( stream->format && spos == stream->pos && ch == ' ' ) { + if (stream->format.linewrap && spos == stream->pos && ch == ' ') { ; } // full line, acceptable split position - else if ( stream->format && spos != 0 ) { + else if (stream->format.linewrap && spos != 0) { // add character to the line, terminate it stream->line[ stream->pos++ ] = ch; @@ -1340,18 +1342,19 @@ static void PutChrTo(TypOutputFile * stream, Char ch) PutLineTo( stream, spos ); spos--; - // indent for the rest stream->pos = 0; + if (stream->format.indent) { + // indent for the rest for ( i = 0; i < stream->hints[3*hint+2]; i++ ) stream->line[ stream->pos++ ] = ' '; spos -= stream->hints[3*hint+2]; + } // copy the rest onto the next line for ( i = 0; str[ i ] != '\0'; i++ ) stream->line[ stream->pos++ ] = str[ i ]; // recover line break hints for copied rest - for ( i = hint+1; stream->hints[3*i] != -1; i++ ) - { + for (i = hint + 1; stream->hints[3 * i] != -1; i++) { stream->hints[3*(i-hint-1)] = stream->hints[3*i]-spos; stream->hints[3*(i-hint-1)+1] = stream->hints[3*i+1]; stream->hints[3*(i-hint-1)+2] = stream->hints[3*i+2]; @@ -1362,9 +1365,8 @@ static void PutChrTo(TypOutputFile * stream, Char ch) // full line, no split position else { - if (stream->format) - { - /* append a '\',*/ + if (stream->format.linewrap) { + // append a '\' stream->line[ stream->pos++ ] = '\\'; stream->line[ stream->pos++ ] = '\n'; } @@ -1376,7 +1378,7 @@ static void PutChrTo(TypOutputFile * stream, Char ch) stream->pos = 0; stream->line[ stream->pos++ ] = ch; - if (stream->format) + if (stream->format.indent) stream->hints[0] = -1; } @@ -1816,6 +1818,42 @@ void SPrTo(Char *buffer, UInt maxlen, const Char *format, Int arg1, Int arg2) } +// Convert GAP-level print formatting objects to kernel level, and vice-versa + +StreamFormat StreamFormatFromObj(Obj o) +{ + if (o == True) { + return MakeStreamFormat(TRUE, TRUE); + } + if (o == False) { + return MakeStreamFormat(FALSE, FALSE); + } + + RequirePlainRec("Stream formatting", o); + + Obj indent = ElmPRec(o, RNamName("indent")); + Obj linewrap = ElmPRec(o, RNamName("linewrap")); + + RequireTrueOrFalse("indent in stream formatting", indent); + RequireTrueOrFalse("linewrap in stream formatting", linewrap); + + BOOL i = (indent == True); + BOOL l = (linewrap == True); + + return MakeStreamFormat(l, i); +} + +Obj ObjFromStreamFormat(StreamFormat sf) +{ + Obj o = NEW_PREC(2); + Obj indent = sf.indent ? True : False; + Obj linewrap = sf.linewrap ? True : False; + AssPRec(o, RNamName("indent"), indent); + AssPRec(o, RNamName("linewrap"), linewrap); + return o; +} + + static Obj FuncINPUT_FILENAME(Obj self) { if (IO()->Input == 0) @@ -1832,7 +1870,7 @@ static Obj FuncINPUT_LINENUMBER(Obj self) static Obj FuncSET_PRINT_FORMATTING_STDOUT(Obj self, Obj val) { - BOOL format = (val != False); + StreamFormat format = StreamFormatFromObj(val); TypOutputFile * output = IO()->Output; while (output) { if (!output->stream && output->file == 1) @@ -1845,12 +1883,12 @@ static Obj FuncSET_PRINT_FORMATTING_STDOUT(Obj self, Obj val) static Obj FuncPRINT_FORMATTING_STDOUT(Obj self) { - return IO()->PrintFormattingForStdout ? True : False; + return ObjFromStreamFormat(IO()->PrintFormattingForStdout); } static Obj FuncSET_PRINT_FORMATTING_ERROUT(Obj self, Obj val) { - BOOL format = (val != False); + StreamFormat format = StreamFormatFromObj(val); TypOutputFile * output = IO()->Output; while (output) { if (!output->stream && output->file == 3) @@ -1863,7 +1901,7 @@ static Obj FuncSET_PRINT_FORMATTING_ERROUT(Obj self, Obj val) static Obj FuncPRINT_FORMATTING_ERROUT(Obj self) { - return IO()->PrintFormattingForErrout ? True : False; + return ObjFromStreamFormat(IO()->PrintFormattingForErrout); } /**************************************************************************** @@ -1882,8 +1920,8 @@ static Obj FuncCALL_WITH_FORMATTING_STATUS(Obj self, Obj status, Obj func, Obj a if (!output) ErrorMayQuit("CALL_WITH_FORMATTING_STATUS called while no output is open", 0, 0); - BOOL old = output->format; - output->format = (status != False); + StreamFormat old = output->format; + output->format = StreamFormatFromObj(status); Obj result; GAP_TRY @@ -1964,8 +2002,8 @@ static Int InitKernel ( IO()->Output = 0; IO()->InputLog = 0; IO()->OutputLog = 0; - IO()->PrintFormattingForStdout = TRUE; - IO()->PrintFormattingForErrout = TRUE; + IO()->PrintFormattingForStdout = MakeStreamFormat(TRUE, TRUE); + IO()->PrintFormattingForErrout = MakeStreamFormat(TRUE, TRUE); OpenOutput(&IO()->DefaultOutput, "*stdout*", FALSE); diff --git a/src/io.h b/src/io.h index 1fbe59a392..d876dd8be0 100644 --- a/src/io.h +++ b/src/io.h @@ -92,6 +92,27 @@ enum { MAXLENOUTPUTLINE = 4096, }; +typedef struct { + BOOL linewrap; + BOOL indent; +} StreamFormat; + +EXPORT_INLINE StreamFormat MakeStreamFormat(BOOL linewrap, BOOL indent) +{ + StreamFormat s = {}; + s.linewrap = linewrap; + s.indent = indent; + return s; +} + +EXPORT_INLINE BOOL NoStreamFormat(StreamFormat sf) +{ + return !sf.linewrap && !sf.indent; +} + + +StreamFormat StreamFormatFromObj(Obj o); +Obj ObjFromStreamFormat(StreamFormat sf); /**************************************************************************** ** @@ -113,7 +134,7 @@ struct TypOutputFile { char line[MAXLENOUTPUTLINE]; Int pos; - BOOL format; + StreamFormat format; Int indent; // each hint is a triple (position, value, indent) diff --git a/tst/testinstall/compressed.tst b/tst/testinstall/compressed.tst index 9ab8eb7313..3acd519fbb 100644 --- a/tst/testinstall/compressed.tst +++ b/tst/testinstall/compressed.tst @@ -169,7 +169,7 @@ gap> CloseStream(stream); # test PrintFormattingStatus gap> stream := OutputGzipFile( fname, false );; gap> PrintFormattingStatus(stream); -true +rec( indent := true, linewrap := true ) gap> PrintTo( stream, "a very long line that GAP is going to wrap at 80 chars by default if we don't do anything about it\n"); gap> CloseStream(stream); gap> StringFile(fname); @@ -178,7 +178,7 @@ gap> StringFile(fname); gap> stream := OutputGzipFile( fname, false );; gap> SetPrintFormattingStatus(stream, false); gap> PrintFormattingStatus(stream); -false +rec( indent := false, linewrap := false ) gap> PrintTo( stream, "a very long line that GAP is going to wrap at 80 chars by default if we don't do anything about it\n"); gap> CloseStream(stream); gap> StringFile(fname); diff --git a/tst/testinstall/format.tst b/tst/testinstall/format.tst index 9e3b4ded6c..b9e703ded2 100644 --- a/tst/testinstall/format.tst +++ b/tst/testinstall/format.tst @@ -70,9 +70,9 @@ gap> ListWithIdenticalEntries(1000, 'a') = true # Test line breaks -gap> StringFormatted("{}", "\>1\<") = "\>1\<"; +gap> StringFormatted("{}", "\>1\<") = "1"; true -gap> StringFormatted("\>1\<") = "\>1\<"; +gap> StringFormatted("\>1\<") = "1"; true # Test alternative functions diff --git a/tst/testinstall/streams.tst b/tst/testinstall/streams.tst index c4a863fcb2..e249579d62 100644 --- a/tst/testinstall/streams.tst +++ b/tst/testinstall/streams.tst @@ -1,4 +1,4 @@ -#@local dir,fname,file,line,stream,tmpdir,res,streams,i +#@local dir,fname,file,line,stream,tmpdir,res,streams,i,func,linewrap,indent gap> START_TEST("streams.tst"); # @@ -85,23 +85,83 @@ gap> ReadAll(stream, 3); gap> CloseStream(stream); # test PrintFormattingStatus -gap> stream := OutputTextFile( fname, false );; +gap> func := function(x) if x then return "a very long line that GAP is going to wrap at 80 chars by default if we don't do anything about it"; fi; end;; +gap> for linewrap in [false,true] do +> for indent in [false,true] do +> stream := OutputTextFile(fname, false); +> SetPrintFormattingStatus(stream, rec(linewrap := linewrap, indent := indent)); +> PrintTo(stream, func); +> CloseStream(stream); +> Print([linewrap, indent, StringFile(fname)],"\n"); +> od; +> od; +[ false, false, + "function ( x )\nif x then\nreturn \"a very long line that GAP is going to w\ +rap at 80 chars by default if we don't do anything about it\";\nfi;\nreturn;\n\ +end" ] +[ false, true, + "function ( x )\n if x then\n return \"a very long line that GAP i\ +s going to wrap at 80 chars by default if we don't do anything about it\";\n \ + fi;\n return;\nend" ] +[ true, false, + "function ( x )\nif x then\nreturn \"a very long line that GAP is going to w\ +rap at 80 chars by default if w\\\ne don't do anything about it\";\nfi;\nretur\ +n;\nend" ] +[ true, true, + "function ( x )\n if x then\n return \n \"a very long line\ + that GAP is going to wrap at 80 chars by default if\\\n we don't do anything \ +about it\";\n fi;\n return;\nend" ] +gap> for linewrap in [false,true] do +> for indent in [false,true] do +> res := ""; +> stream := OutputTextString(res, true); +> SetPrintFormattingStatus(stream, rec(linewrap := linewrap, indent := indent)); +> PrintTo(stream, func); +> CloseStream(stream); +> Print([linewrap, indent, res],"\n"); +> od; +> od; +[ false, false, + "function ( x )\nif x then\nreturn \"a very long line that GAP is going to w\ +rap at 80 chars by default if we don't do anything about it\";\nfi;\nreturn;\n\ +end" ] +[ false, true, + "function ( x )\n if x then\n return \"a very long line that GAP i\ +s going to wrap at 80 chars by default if we don't do anything about it\";\n \ + fi;\n return;\nend" ] +[ true, false, + "function ( x )\nif x then\nreturn \"a very long line that GAP is going to w\ +rap at 80 chars by default if w\\\ne don't do anything about it\";\nfi;\nretur\ +n;\nend" ] +[ true, true, + "function ( x )\n if x then\n return \n \"a very long line\ + that GAP is going to wrap at 80 chars by default if\\\n we don't do anything \ +about it\";\n fi;\n return;\nend" ] +gap> stream := OutputTextString(res, true); +OutputTextString(181) +gap> SetPrintFormattingStatus(stream, true); gap> PrintFormattingStatus(stream); -true -gap> PrintTo( stream, "a very long line that GAP is going to wrap at 80 chars by default if we don't do anything about it\n"); -gap> CloseStream(stream); -gap> StringFile(fname); -"a very long line that GAP is going to wrap at 80 chars by default if we don't\ - \\\ndo anything about it\n" -gap> stream := OutputTextFile( fname, false );; +rec( indent := true, linewrap := true ) gap> SetPrintFormattingStatus(stream, false); gap> PrintFormattingStatus(stream); -false -gap> PrintTo( stream, "a very long line that GAP is going to wrap at 80 chars by default if we don't do anything about it\n"); -gap> CloseStream(stream); -gap> StringFile(fname); -"a very long line that GAP is going to wrap at 80 chars by default if we don't\ - do anything about it\n" +rec( indent := false, linewrap := false ) +gap> SetPrintFormattingStatus(stream, rec(indent := false, linewrap := true)); +gap> PrintFormattingStatus(stream); +rec( indent := false, linewrap := true ) +gap> SetPrintFormattingStatus(stream, fail); +Error, Formatting status cannot be 'fail' +gap> SetPrintFormattingStatus(stream, 6); +Error, Formatting status must be a boolean or a record +gap> SetPrintFormattingStatus(stream, rec(indent := false)); +Error, Formatting status records must contain exactly two components, named 'i\ +ndent' and 'linewrap' +gap> SetPrintFormattingStatus(stream, rec(indent := false, linewrap := 12)); +Error, linewrap must be 'true' or 'false' in formatting status record +gap> SetPrintFormattingStatus(stream, rec(indent := false, linewrap := false, extra := true)); +Error, Formatting status records must contain exactly two components, named 'i\ +ndent' and 'linewrap' +gap> PrintFormattingStatus(stream); +rec( indent := false, linewrap := true ) # # string streams @@ -208,7 +268,7 @@ true gap> WriteByte(stream, 300); Error, must an integer between 0 and 255 gap> SetPrintFormattingStatus(stream, fail); -Error, Print formatting status must be true or false +Error, Formatting status cannot be 'fail' # too many open files gap> streams := [ ];; diff --git a/tst/testinstall/stringobj.tst b/tst/testinstall/stringobj.tst index de8cf30480..edd3815ee0 100644 --- a/tst/testinstall/stringobj.tst +++ b/tst/testinstall/stringobj.tst @@ -171,9 +171,9 @@ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", field2 := "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ) ] -gap> PrintFormattingStatus(sstream) = false; +gap> PrintFormattingStatus(sstream) = rec( indent := false, linewrap := false ); true -gap> PrintFormattingStatus(fstream) = true; +gap> PrintFormattingStatus(fstream) = rec( indent := true, linewrap := true ); true gap> CloseStream(sstream); gap> CloseStream(fstream); diff --git a/tst/testspecial/format.g b/tst/testspecial/format.g new file mode 100644 index 0000000000..8a58de7317 --- /dev/null +++ b/tst/testspecial/format.g @@ -0,0 +1,20 @@ +SizeScreen([40,40]); +l := List([1..100], x -> x*x);; +s := ListWithIdenticalEntries(100, 'q');; +r := rec(aaaa := rec(bbbb := rec(cccc := l)));; +SetPrintFormattingStatus("*stdout*", rec(linewrap := false, indent := false)); +Print(l,"\n"); +Print(s,"\n"); +Print(r,"\n"); +SetPrintFormattingStatus("*stdout*", rec(linewrap := false, indent := true)); +Print(l,"\n"); +Print(s,"\n"); +Print(r,"\n"); +SetPrintFormattingStatus("*stdout*", rec(linewrap := true, indent := false)); +Print(l,"\n"); +Print(s,"\n"); +Print(r,"\n"); +SetPrintFormattingStatus("*stdout*", rec(linewrap := true, indent := true)); +Print(l,"\n"); +Print(s,"\n"); +Print(r,"\n"); diff --git a/tst/testspecial/format.g.out b/tst/testspecial/format.g.out new file mode 100644 index 0000000000..3ec70729c4 --- /dev/null +++ b/tst/testspecial/format.g.out @@ -0,0 +1,120 @@ +gap> SizeScreen([40,40]); +[ 40, 40 ] +gap> l := List([1..100], x -> x*x);; +gap> s := ListWithIdenticalEntries(100, 'q');; +gap> r := rec(aaaa := rec(bbbb := rec(cccc := l)));; +gap> SetPrintFormattingStatus("*stdout*", rec(linewrap := false, indent := false)); +gap> Print(l,"\n"); +[ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000 ] +gap> Print(s,"\n"); +qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq +gap> Print(r,"\n"); +rec( +aaaa := rec( +bbbb := rec( +cccc := [ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000 ] ) ) ) +gap> SetPrintFormattingStatus("*stdout*", rec(linewrap := false, indent := true)); +gap> Print(l,"\n"); +[ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000 ] +gap> Print(s,"\n"); +qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq +gap> Print(r,"\n"); +rec( + aaaa := rec( + bbbb := rec( + cccc := [ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000 ] ) ) ) +gap> SetPrintFormattingStatus("*stdout*", rec(linewrap := true, indent := false)); +gap> Print(l,"\n"); +[ 1, 4, 9, 16, 25, 36, 49, 64, 81, +100, 121, 144, 169, 196, 225, 256, +289, 324, 361, 400, 441, 484, 529, +576, 625, 676, 729, 784, 841, 900, +961, 1024, 1089, 1156, 1225, 1296, +1369, 1444, 1521, 1600, 1681, 1764, +1849, 1936, 2025, 2116, 2209, 2304, +2401, 2500, 2601, 2704, 2809, 2916, +3025, 3136, 3249, 3364, 3481, 3600, +3721, 3844, 3969, 4096, 4225, 4356, +4489, 4624, 4761, 4900, 5041, 5184, +5329, 5476, 5625, 5776, 5929, 6084, +6241, 6400, 6561, 6724, 6889, 7056, +7225, 7396, 7569, 7744, 7921, 8100, +8281, 8464, 8649, 8836, 9025, 9216, +9409, 9604, 9801, 10000 ] +gap> Print(s,"\n"); +qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ +qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ +qqqqqqqqqqqqqqqqqqqqqqqq +gap> Print(r,"\n"); +rec( +aaaa := rec( +bbbb := rec( +cccc := [ 1, 4, 9, 16, 25, 36, 49, +64, 81, 100, 121, 144, 169, 196, 225, +256, 289, 324, 361, 400, 441, 484, +529, 576, 625, 676, 729, 784, 841, +900, 961, 1024, 1089, 1156, 1225, +1296, 1369, 1444, 1521, 1600, 1681, +1764, 1849, 1936, 2025, 2116, 2209, +2304, 2401, 2500, 2601, 2704, 2809, +2916, 3025, 3136, 3249, 3364, 3481, +3600, 3721, 3844, 3969, 4096, 4225, +4356, 4489, 4624, 4761, 4900, 5041, +5184, 5329, 5476, 5625, 5776, 5929, +6084, 6241, 6400, 6561, 6724, 6889, +7056, 7225, 7396, 7569, 7744, 7921, +8100, 8281, 8464, 8649, 8836, 9025, +9216, 9409, 9604, 9801, 10000 ] ) ) ) +gap> SetPrintFormattingStatus("*stdout*", rec(linewrap := true, indent := true)); +gap> Print(l,"\n"); +[ 1, 4, 9, 16, 25, 36, 49, 64, 81, + 100, 121, 144, 169, 196, 225, 256, + 289, 324, 361, 400, 441, 484, 529, + 576, 625, 676, 729, 784, 841, 900, + 961, 1024, 1089, 1156, 1225, 1296, + 1369, 1444, 1521, 1600, 1681, 1764, + 1849, 1936, 2025, 2116, 2209, 2304, + 2401, 2500, 2601, 2704, 2809, 2916, + 3025, 3136, 3249, 3364, 3481, 3600, + 3721, 3844, 3969, 4096, 4225, 4356, + 4489, 4624, 4761, 4900, 5041, 5184, + 5329, 5476, 5625, 5776, 5929, 6084, + 6241, 6400, 6561, 6724, 6889, 7056, + 7225, 7396, 7569, 7744, 7921, 8100, + 8281, 8464, 8649, 8836, 9025, 9216, + 9409, 9604, 9801, 10000 ] +gap> Print(s,"\n"); +qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ +qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ +qqqqqqqqqqqqqqqqqqqqqqqq +gap> Print(r,"\n"); +rec( + aaaa := rec( + bbbb := rec( + cccc := + [ 1, 4, 9, 16, 25, 36, 49, + 64, 81, 100, 121, 144, + 169, 196, 225, 256, + 289, 324, 361, 400, + 441, 484, 529, 576, + 625, 676, 729, 784, + 841, 900, 961, 1024, + 1089, 1156, 1225, 1296, + 1369, 1444, 1521, 1600, + 1681, 1764, 1849, 1936, + 2025, 2116, 2209, 2304, + 2401, 2500, 2601, 2704, + 2809, 2916, 3025, 3136, + 3249, 3364, 3481, 3600, + 3721, 3844, 3969, 4096, + 4225, 4356, 4489, 4624, + 4761, 4900, 5041, 5184, + 5329, 5476, 5625, 5776, + 5929, 6084, 6241, 6400, + 6561, 6724, 6889, 7056, + 7225, 7396, 7569, 7744, + 7921, 8100, 8281, 8464, + 8649, 8836, 9025, 9216, + 9409, 9604, 9801, 10000 + ] ) ) ) +gap> QUIT; diff --git a/tst/testspecial/print-formatting.g.out b/tst/testspecial/print-formatting.g.out index 91e7af8741..d79b3e81a9 100644 --- a/tst/testspecial/print-formatting.g.out +++ b/tst/testspecial/print-formatting.g.out @@ -1,23 +1,23 @@ gap> # test formatting status for stdout gap> old := PrintFormattingStatus("*stdout*"); -true +rec( indent := true, linewrap := true ) gap> SetPrintFormattingStatus("*stdout*", false); gap> PrintFormattingStatus("*stdout*"); -false +rec( indent := false, linewrap := false ) gap> Display(x -> x); function ( x ) return x; end gap> SetPrintFormattingStatus("*stdout*", true); gap> PrintFormattingStatus("*stdout*"); -true +rec( indent := true, linewrap := true ) gap> Display(x -> x); function ( x ) return x; end gap> SetPrintFormattingStatus("*stdout*", old);; gap> PrintFormattingStatus("*stdout*"); -true +rec( indent := true, linewrap := true ) gap> gap> # test formatting status for errout gap> 1/0; # trigger a break loop @@ -25,22 +25,22 @@ Error, Rational operations: must not be zero not in any function at *stdin*:14 type 'quit;' to quit to outer loop brk> old := PrintFormattingStatus("*errout*"); -true +rec( indent := true, linewrap := true ) brk> SetPrintFormattingStatus("*errout*", false); brk> PrintFormattingStatus("*errout*"); -false +rec( indent := false, linewrap := false ) brk> Display(x -> x); function ( x ) return x; end brk> SetPrintFormattingStatus("*errout*", true); brk> PrintFormattingStatus("*errout*"); -true +rec( indent := true, linewrap := true ) brk> Display(x -> x); function ( x ) return x; end brk> SetPrintFormattingStatus("*errout*", old);; brk> PrintFormattingStatus("*errout*"); -true +rec( indent := true, linewrap := true ) brk> QUIT;