TAB EXPANSION USING VISUAL PROLOG 7.5
This approach uses a stream to collect the text, avoiding creation of multiple intermediate strings or managing your own binary buffer.
class predicates
expandTabs : ( string Input, positive TabSize ) -> string ExpandedString.
clauses
expandTabs( S, 0 ) = S :- !.
expandTabs( S, TabSize ) = ExpandedString :-
OS = outputStream_string::new(),
StrX0 = string::length(S) - 1,
foreach X0 = std::fromTo(0,StrX0) do
C = subChar(S,X0),
if C = '\t' then
advanceTab( OS, TabSize, ' ' )
else
OS:write(C)
end if
end foreach,
ExpandedString = OS:getString().
class predicates
advanceTab : ( outputStream_string, positive TabSize, char FillChar ).
clauses
advanceTab( OS, TabSize, FillChar ):-
OnTabColumn = { () :-
OS:getPosition() mod (2*TabSize) = 0
},
if OnTabColumn() then
% emit a full tab if on a tab column
foreach _ = std::fromTo(1,TabSize) do
OS:write(FillChar)
end foreach, !
else
% emit tab characters until reach next tab column
std::repeat(),
OS:write(FillChar),
OnTabColumn(), !
end if.
advanceTab( _,_,_ ):-
error( predicate_fullname(),
"Should never get here but needed to make advanceTab/3 a procedure.").
A test/0 predicate is below. Note the use of anomymous predicates
Prepare,
Restore and
ShowMe to simplify the code.
open core, string, list, outputstream_string, vpiCommonDialogs
clauses
test():-
S1 = "[ ][ ][tab]Hello, world!",
S2 = "[ ][ ][ ][ ]Hello, World!",
S3 = "[ ][ ][ ][tab][tab][ ][tab]Hello, world!",
Prepare = { (S) = TestStr :-
TestStr = replaceAll(
replaceAll(S,"[ ]"," "),
"[tab]", "\t" )
},
Restore = { (S) = RestoredStr :-
RestoredStr = replaceAll(
replaceAll(S," ","[ ]"),
"\t","[tab]")
},
ShowMe = { (SS) :-
foreach M = list::getMember_nd( SS ) do
PreppedStr = Prepare( M ),
DeTabStr = expandTabs(PreppedStr,4),
RestoredStr = Restore( DeTabStr ),
stdio::write("\n\n",M, "<== trial string in display mode",
"\n", PreppedStr, "<== string to test",
"\n", DeTabStr, "<== expanded tab string",
"\n", RestoredStr, "<== expanded tab string in display mode" )
end foreach
},
ShowMe( [S1, S2, S3] ).
Output of the test/0 predicate is below:
TEST OUTPUT:
[ ] ][tab]Hello, world!<== trial string in display mode
Hello, world!<== string to test
Hello, world!<== expanded tab string
[ ] ][ ][ ]Hello,[ ]world!<== expanded tab string in display mode
[ ] ][ ][ ]Hello, World!<== trial string in display mode
Hello, World!<== string to test
Hello, World!<== expanded tab string
[ ] ][ ][ ]Hello,[ ]World!<== expanded tab string in display mode
[ ] ][ ][tab][tab][ ][tab]Hello, world!<== trial string in display mode
Hello, world!<== string to test
Hello, world!<== expanded tab string
[ ] ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]Hello,[ ]world!<== expanded tab string in display mode