[Output Formatter]: Cascading Style Sheets (CSS) proposal

Throughout this e-mail, I assume the following aliases: namespace io = boost::io; namespace fmt = boost::io::format; namespace css = boost::io::css; NOTE: This is a design outline for features in a future version of the library. David Abrahams has suggested the ability to specify default formatting on a stream. I have implemented a simple version of this so that you can do: io::sequence_decorators< char > seq( "; " ); std::cout << '"' << seq.open( std::cout ) << "\"\n" // "[ " << '"' << seq.close( std::cout ) << "\"\n" // " ]" << '"' << seq.separator( std::cout ) << "\"\n"; // "; " where separator( std::cout ) uses the separator value specified by seq and the others use the values set on the std::cout stream. To change these defaults, you can use: std::cout << io::cdecorate( "[{ ", " }]" ); // [{ a, b, c }] The problem with this is that it changes the defaults for all the formatting used, thus you cannot have different defaults for sequences and n-ary types. Cascading Style Sheets (CSS) are a web standard [http://www.w3.org/Style/CSS/] used for controlling how HTML tags are displayed to different devices (screen, printer and speech). == Inlined Styles In HTML you can specify "inlined" styles using a style attribute, e.g.: <div style = "color: red;">Red Text</div> My library equivalent is to use the decorate() function, e.g.: fmt::range().decorate( "<-- ", " -->" ); == Dynamic Styles You can also set CSS properties within script code, e.g. tag.style.fontFamily = "Times New Roman"; This style behaviour is available in the new decorators, for example: io::wrapper_decorators< char > wrap; wrap.open = "<< "; wrap.close = " >>"; A more complex example that uses nested format objects: fmt::container_t< char, fmt::pair_t< char > > my_fo = fmt::container( fmt::pair()); my_fo.elem.open = "<< "; my_ob.elem.close = " >>"; my_ob.separator = " | "; std::cout << io::object( ob, my_ob ); // output: [ << a, 5 >> | << b, -1
]
== Cascading Style Sheets HTML provides a <style> tag to specify styling across the document without linking to an external file, e.g.: <style>h1{ color: orange; font-size: 2pc; }</style> The equivalent within my library would be to define the styling on a stream, e.g.: std::cout << css::element( "pair" ) [ ( css::attribute( "open" ) = "<< " ) + ( css::attribute( "close" ) = " >>" ) ] << css::element( "container" ) [ css::attribute( "separator" ) = " | " ] << io::object( ob ) // output: [ << a, 5 >> | << b, -1 >> ] << css::element( "pair" ) [ css::attribute( "separator" ) = " = " ] << io::object( ob ); // output: [ << a = 5 >> | << b = -1 >> ] HTML can import styling from an external CSS file. The equivalent would be to use an object to hold the styling, e.g.: css::stylesheet< char > style = css::element( "pair" ) [ css::attribute( "separator" ) = " = " ] + css::element( "container" ) [ ( css::attribute( "open" ) = "{ " ) + ( css::attribute( "close" ) = " }" ) ] ; std::cout << style << io::object( ob ); // output: { [ a = 5 ], [ b = -1 ] } It should be possible to provide the ability to save/load styling to/from a file and allow copying of style objects, e.g.: css::stylesheet< char > style2( "mystyles.style" ); // load styling style.load( "newstyles.style" ); style = style2; style.save( "stylings.sty" ); NOTE: The css::stylesheet class will store the styles using something like: std::map< std::string, std::map< std::string, std::string > > therefore it will be possible to use my library to implement the load and save facilities! Regards, Reece _________________________________________________________________ It's fast, it's easy and it's free. Get MSN Messenger today! http://www.msn.co.uk/messenger

Hi Reece,
io::sequence_decorators< char > seq( "; " ); std::cout << '"' << seq.open( std::cout ) << "\"\n" // "[ " << '"' << seq.close( std::cout ) << "\"\n" // " ]" << '"' << seq.separator( std::cout ) << "\"\n"; // "; "
where separator( std::cout ) uses the separator value specified by seq and the others use the values set on the std::cout stream.
I don't understand this phrase, could you clarify. What does it mean to "use the separator".
To change these defaults, you can use:
std::cout << io::cdecorate( "[{ ", " }]" ); // [{ a, b, c }]
The problem with this is that it changes the defaults for all the formatting used, thus you cannot have different defaults for sequences and n-ary types.
I don't undestand this, either. Probably I've missed something in earlier messages. What's "n-ary" type? Do you provide the ability to use different separators for sequences, sets and maps? Then I don't understand why you can set different default style for those kinds of object, and cannot selectively override the style
== Dynamic Styles
You can also set CSS properties within script code, e.g. tag.style.fontFamily = "Times New Roman";
This style behaviour is available in the new decorators, for example: io::wrapper_decorators< char > wrap; wrap.open = "<< "; wrap.close = " >>";
What does this decorator "wrap"?
== Cascading Style Sheets
HTML provides a <style> tag to specify styling across the document without linking to an external file, e.g.: <style>h1{ color: orange; font-size: 2pc; }</style>
The equivalent within my library would be to define the styling on a stream, e.g.:
std::cout << css::element( "pair" ) [ ( css::attribute( "open" ) = "<< " ) + ( css::attribute( "close" ) = " >>" ) ] << css::element( "container" ) [ css::attribute( "separator" ) = " | " ] << io::object( ob ) // output: [ << a, 5 >> | << b, -1 >> ] << css::element( "pair" ) [ css::attribute( "separator" ) = " = " ] << io::object( ob ); // output: [ << a = 5 >> | << b = -1 >> ]
I'm sorry, but I'm worried of the direction you took. For me, the primary utility of this library is debugging output. For that, I'd be happy with a single style, as long as it's something usable, like YAML (http://www.yaml.org/). I agree that you might want to store and then restore STL container from a file, and the library addresses this need to. But I don't understand why you would want to customize the formatting style. Basically, you either should the data to user, or not. In first case, you need a single usable style. For the second case, you might need another "compact" style. I don't see the point of customization. Finally, is this library going to be used for producing generic text files? E.g. code generation. I think no, to generate text you need some text template system, and that's way beyond the scope of the library. So, I'm not convinced custom style gives you anything. On the other hand, it will cost a lot. At the very least, even documenting the above will be considerable effort. And given that the library is header-only, this features will cost everyone extra compile time. Even is 'css' stuff is in separate header, you'd need the hooks for customization. Are you sure adding even more features is the way to go? - Volodya

"Reece Dunn" wrote:
Cascading Style Sheets (CSS) are a web standard [http://www.w3.org/Style/CSS/] used for controlling how HTML tags are displayed to different devices (screen, printer and speech).
It should be possible to provide the ability to save/load styling to/from a file and allow copying of style objects, e.g.:
Wouldn't it be easier (for user) to specify template-like file (HTML + some marks) and the library would fill in marked areas with data? HTML-like templates would be easy to create and verify. The C++ code won't need to contain complex embedded CCS. Mistakes in template could be handled gracefully. Missing template could be handled too. When I want debug dump the last thing I need is playing with subtlety of another language. /Pavel

My few cents: Serialization, iostreams, Spirit (great piece of code!) and new Output Formatter overlap enough in certain segments that, IMO, serious thought should be given to combining them in the best possible way; i.e. maintain the simplicity and specific target of each module while, eventually, promoting overlap areas into the new libraries. IOW, CSS would be unnecessary complication for Output Formatter at this stage. I like it this way:simple to understand and use. Formatting options are reasonably limited. Tony

Hi Reece, Read the whole CSS thread, and my oppinion is this: The CSS should be a different library, implemented *on top of* your library. I suggest you leave the library as is (of course - name changes, etc. are ok ;)), and implement only enough to make it possible for CSS to be implemented on top of your lib. Or even better, don't implement anything more. When you want to add CSS, just create a lib on top of Output Formatters. Then, you'll see what needs to be changed on Output Formatters library. As for what Dave Abrahams said (default formatting on a stream), this could indeed be a nice addition to Output Formatters. And it's really easy to add as well. There won't be any CSS. Just that for every type of formatter(decorator) class (pairfmt, containerfrmt,etc.) you can have a default stored within the stream class. *That's all*. When you need to use a formatter (decorator) object and it's not provided inline (at the time of read/write), just query the stream - if the stream has a default formatter, use that one. I think that is enough. Best, John -- John Torjo -- john@torjo.com Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.4.0 - save_dlg - true binding of your data to UI controls! + easily add validation rules (win32gui/examples/smart_dlg)
participants (5)
-
John Torjo
-
Pavel Vozenilek
-
Reece Dunn
-
Tony Juricic
-
Vladimir Prus