Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatted OutStreams #1816

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/ref/streams.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<#Include Label="IsOutputStream">
<#Include Label="IsOutputTextStream">
<#Include Label="IsOutputTextNone">
<#Include Label="IsOutputStreamFormatter">
<#Include Label="IsOutputStreamPrefixer">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No GAPDoc chunks with these names exist, hence the makemanuals tests fail.

<#Include Label="StreamsFamily">

</Section>
Expand Down
81 changes: 81 additions & 0 deletions lib/formatstreams.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Formatted output streams

## <#GAPDoc Label="OutputTextStreamFormatter">
## <ManSection>
## <Oper Name="OutputTextStreamFormatter" Arg='stream, indent'/>
## <Oper Name="OutputTextStreamFormatter" Arg='stream'/>
##
## <Description>
## returns an output stream that outputs received characters to the
## stream <A>stream</A>, adding indentation by a number of spaces
## after every newline character.
##
## The parameter <A>indent</A> specifie s an initial indentation, which defaults
## to <M>0</M>.
##
## Printing the character <C>\\&leq;</C> to the stream decreases indentation,
## printing <C>\\&geq;</C> increases indentation.
##
## <P/>
## <Example><![CDATA[
## gap> output := OutputTextStreamFormatter(StandardOutput);
## gap> WriteAll(output, "Hello, world\n");
## Hello, world
## true
## gap> WriteAll(output, "\>\>Hello, world\nSecond line\nthird\>\>\nfourth\n");
## Hello, world
## Second line
## third
## fourth
## true
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
# Output stream wrapping another output stream
DeclareCategory( "IsOutputTextStreamFormatter", IsOutputStream );
DeclareRepresentation( "IsOutputTextStreamFormatterRep",
IsOutputTextStreamFormatter and IsPositionalObjectRep,
["stream", "indent"] );

BindGlobal( "OutputTextStreamFormatterType",
NewType( StreamsFamily,
IsOutputTextStream and IsOutputTextStreamFormatterRep ) );

DeclareOperation( "OutputTextStreamFormatter", [ IsOutputStream, IsInt] );
DeclareOperation( "OutputTextStreamFormatter", [ IsOutputStream ] );
DeclareOperation( "SetIndentation", [ IsOutputTextStreamFormatter, IsInt ] );
DeclareOperation( "GetIndentation", [ IsOutputTextStreamFormatter ] );

## <#GAPDoc Label="OutputTextStreamPrefixer">
## <ManSection>
## <Oper Name="OutputTextStreamPrefixer" Arg='stream, prefix'/>
##
## <Description>
## returns an output stream that outputs received characters to the
## stream <A>stream</A>, adding <A>prefix</A> in front of every
## line.
##
## <P/>
## <Example><![CDATA[
## gap> output := OutputTextStreamPrefixer(StandardOutput, "informational: ");;
## gap> WriteAll(output, "Hello,\nworld");
## informational: Hello,
## informational: worldtrue
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
# Output stream prefixing every line
DeclareCategory( "IsOutputTextStreamPrefixer", IsOutputStream );
DeclareRepresentation( "IsOutputTextStreamPrefixerRep",
IsOutputTextStreamPrefixer and IsPositionalObjectRep,
["stream", "prefix"] );

BindGlobal( "OutputTextStreamPrefixerType",
NewType( StreamsFamily,
IsOutputTextStream and IsOutputTextStreamPrefixerRep ) );

DeclareOperation( "OutputTextStreamPrefixer", [ IsOutputStream, IsString] );
125 changes: 125 additions & 0 deletions lib/formatstreams.gi
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Formatting output streams

InstallMethod(OutputTextStreamFormatter,
"for a stream, and an int",
[ IsOutputStream, IsInt ],
function( stream, ident )
local i;

if ident < 0 then
Error("initial identation has to be >= 0");
fi;
return Objectify( OutputTextStreamFormatterType, [ stream, ident ] );
end);

InstallOtherMethod( OutputTextStreamFormatter,
"for an output stream",
[ IsOutputStream ],
function( stream )
return OutputTextStreamFormatter(stream, 0);
end );

InstallMethod( ViewString,
"for an output stream formatter",
[ IsOutputTextStreamFormatterRep ],
function( obj )
return "<wrapped output stream>";
end );

InstallMethod( WriteAll,
"for an output stream formatter",
[ IsOutputTextStream and IsOutputTextStreamFormatterRep,
IsString ],
function( stream, string )
local b;

WriteAll(stream![1], ListWithIdenticalEntries(stream![2], ' '));
for b in string do
WriteByte(stream, INT_CHAR(b));
od;
return true;
end );

InstallMethod( WriteByte,
"output text string",
[ IsOutputTextStream and IsOutputTextStreamFormatterRep,
IsInt ],
function( stream, byte )
if byte < 0 or 255 < byte then
Error( "<byte> must an integer between 0 and 255" );
fi;
if byte = INT_CHAR('\<') then
if stream![2] > 0 then
stream![2] := stream![2] - 1;
fi;
elif byte = INT_CHAR('\>') then
stream![2] := stream![2] + 1;
else
WriteByte(stream![1], byte);
if byte = INT_CHAR('\n') then
WriteAll(stream![1], ListWithIdenticalEntries(stream![2], ' '));
fi;
return true;
fi;
end );

InstallMethod( GetIndentation,
"for an output stream formatter",
[ IsOutputTextStreamFormatterRep ],
x -> x![2] );

InstallMethod( SetIndentation,
"for an output stream formatter",
[ IsOutputTextStreamFormatterRep, IsInt ],
function(stream, ident)
if ident < 0 then
Error("Indentation has to be >= 0");
fi;
stream![2] := ident;
return stream![2];
end);

# prefix output
InstallMethod( OutputTextStreamPrefixer,
"for a stream, and an int",
[ IsOutputStream, IsString ],
function( stream, prefix )
return Objectify( OutputTextStreamPrefixerType, [ stream, prefix ] );
end);

InstallMethod( ViewString,
"for an output stream formatter",
[ IsOutputTextStreamPrefixerRep ],
function( obj )
return Concatenation("<wrapped output stream, prefixing ", obj![2], ">");
end );

InstallMethod( WriteAll,
"for an output stream formatter",
[ IsOutputTextStream and IsOutputTextStreamPrefixerRep,
IsString ],
function( stream, string )
local b;

WriteAll(stream![1], stream![2]);
for b in string do
WriteByte(stream, INT_CHAR(b));
od;
return true;
end );

InstallMethod( WriteByte,
"output text string",
[ IsOutputTextStream and IsOutputTextStreamPrefixerRep,
IsInt ],
function( stream, byte )
if byte < 0 or 255 < byte then
Error( "<byte> must an integer between 0 and 255" );
fi;
WriteByte(stream![1], byte);
if byte = INT_CHAR('\n') then
WriteAll(stream![1], stream![2]);
fi;
return true;
end );

2 changes: 2 additions & 0 deletions lib/read2.g
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ ReadLib( "process.gd" );

ReadLib( "files.gi" );
ReadLib( "streams.gi" );
ReadLib( "formatstreams.gd" );
ReadLib( "formatstreams.gi" );
ReadLib( "process.gi" );