Semi-automatic indentation in streams possible?

K

Klaus Nowikow

I would like to be able to do the following:

std::cout // Or any other ostream
<< "Line 1\n"
<< push_tab
<< "Line 2\n"
<< "Line 3\n"
<< push_tab
<< "Line 4\n"
<< pop_tab
<< "Line 5"
<< std::endl;

producing the following output:
Line 1
Line 2
Line 3
Line 4
Line 5

That is, a '\n' character should automatically be replaced by '\n' plus
(4*indentation) spaces (later I want to add a tabsize() modifier).

I came up with the following "semi-solution" (sorry for the long post):

// my_ios.h ***************
#include <iostream>

struct index
{
static int indent();
};

template <class charT, class traits>
std::basic_ostream<charT, traits>& indent(
std::basic_ostream<charT, traits>& strm
)
{
const long& in = strm.iword(index::indent());
for(long i = 0; i < in; ++i)
strm << " ";
return strm;
}

template <class charT, class traits>
std::basic_ostream<charT, traits>& push_indent(
std::basic_ostream<charT, traits>& strm
)
{
strm.iword(index::indent())++;
return strm;
}

template <class charT, class traits>
std::basic_ostream<charT, traits>& pop_indent(
std::basic_ostream<charT, traits>& strm
)
{
long in = strm.iword(index::indent());
if(in > 0)
strm.iword(index::indent()) = in - 1;
return strm;
}
// eof ----------------------------

// my_ios.cpp *************************
#include "my_ios.h"
/*static*/ int index::indent()
{
static const int idx = std::ios_base::xalloc();
return idx;
}

// eof ------------------------------------

Now i can do the following:
#include "my_ios.h"
#include <iostream>

int main(int argc, char* argv[])
{
std::cout
<< indent << "Line 1\n"
<< push_indent
<< indent << "Line 2\n"
<< indent << "Line 3\n"
<< push_indent
<< indent << "Line 4\n"
<< pop_indent
<< indent << "Line 5\n"
;
return 0;
}

i.e., I have to put
<< indent
to the beginning of each output line. Things like
cout << push_indent << "Line 1\nLine 2";
producing the desired result are not possible.

Do you know of any way to do this?

Best regards,
Klaus
 
V

Victor Bazarov

Klaus Nowikow said:
I would like to be able to do the following:

std::cout // Or any other ostream
<< "Line 1\n"
<< push_tab
<< "Line 2\n"
<< "Line 3\n"
<< push_tab
<< "Line 4\n"
<< pop_tab
<< "Line 5"
<< std::endl;

producing the following output:
Line 1
Line 2
Line 3
Line 4
Line 5

That is, a '\n' character should automatically be replaced by '\n' plus
(4*indentation) spaces (later I want to add a tabsize() modifier).

[...]
Do you know of any way to do this?

I'd look into two possible ways: (a) modification of the streambuf which
when \n is output automatically appends the necessary amount of whitespace
and (b) creating your own 'endl' for the same purpose instead of using
'\n'.

Victor
 
G

Graham Dumpleton

Klaus Nowikow said:
I would like to be able to do the following:

std::cout // Or any other ostream
<< "Line 1\n"
<< push_tab
<< "Line 2\n"
<< "Line 3\n"
<< push_tab
<< "Line 4\n"
<< pop_tab
<< "Line 5"
<< std::endl;

You are heading in the right direction with the use of ios::iword() etc,
but to do it how you want, you really need to implement a streambuf
which intercepts the character stream looking for the start of each
new line and which interjects the appropriate spacing.

Rather than post a lot of code here, go grab a copy of OSE from:

http://ose.sourceforge.net

and look at how its OTC_TraceStream and OTC_TraceBuf classes work.
These classes implement an indenting scheme in the style that you are
looking for.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top