From e6956ad27826ef2a8833eda414cd39d2ed95b099 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 As indenting and line wrapping hints are implemented teogether, we always track indent and linewrapping hints, but only make use of them when indenting, or linewrapping, are enabled. --- lib/custom_streams.gi | 7 +- lib/streams.gd | 38 ++++--- lib/streams.gi | 73 +++++++++----- src/io.c | 93 ++++++++++++------ src/io.h | 23 ++++- tst/testbugfix/2017-10-20-runprocess.tst | 4 +- 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, 390 insertions(+), 108 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 c3c582446f..9fdfbbf590 100644 --- a/lib/custom_streams.gi +++ b/lib/custom_streams.gi @@ -339,11 +339,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/src/io.c b/src/io.c index 0f18688890..7bca777cfd 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 @@ -1235,20 +1238,12 @@ static void PutChrTo(TypOutputFile * stream, Char ch) // '\01', increment indentation level if ( ch == '\01' ) { - - if (!stream->format) - return; - // add hint to break line addLineBreakHint(stream, stream->pos, 16*stream->indent, 1); } // '\02', decrement indentation level else if ( ch == '\02' ) { - - if (!stream->format) - return; - // if this is a better place to split the line remember it addLineBreakHint(stream, stream->pos, 16*stream->indent, -1); } @@ -1282,8 +1277,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 +1312,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 +1334,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 +1357,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,8 +1370,7 @@ static void PutChrTo(TypOutputFile * stream, Char ch) stream->pos = 0; stream->line[ stream->pos++ ] = ch; - if (stream->format) - stream->hints[0] = -1; + stream->hints[0] = -1; } } @@ -1816,6 +1809,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 +1861,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 +1874,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 +1892,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 +1911,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 +1993,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/testbugfix/2017-10-20-runprocess.tst b/tst/testbugfix/2017-10-20-runprocess.tst index bb7fac5170..a1759e3efb 100644 --- a/tst/testbugfix/2017-10-20-runprocess.tst +++ b/tst/testbugfix/2017-10-20-runprocess.tst @@ -7,7 +7,7 @@ gap> func1 := function() > local line,s; > if f <> fail then > s := InputOutputLocalProcess(d,f,[]);; -> if PrintFormattingStatus(s) <> false then +> if PrintFormattingStatus(s) <> rec(linewrap := false, indent := false) then > Print( "unexpected PrintFormattingStatus value\n" ); > fi; > SetPrintFormattingStatus(s,false); @@ -30,7 +30,7 @@ gap> func2 := function() > local line,s; > if f <> fail then > s := InputOutputLocalProcess(d,f,[]);; -> if PrintFormattingStatus(s) <> false then +> if PrintFormattingStatus(s) <> rec(linewrap := false, indent := false) then > Print( "unexpected PrintFormattingStatus value\n" ); > fi; > SetPrintFormattingStatus(s,false); 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;