/* makelist.cpp
Copyright (c) 2008 Michael Zahniser
Please note the license terms (MIT license) at the end of this document.

This file was downloaded from http://www.zahniser.net/software/hyperlist/makelist.cpp .

Console program for converting a hierarchical list (where tabs denote the depth of each item)
into an HTML list. This is especially useful for handling the lists copied into the clipboard
by the HyperList program. For example, on the Mac you might do the following:

1. In the terminal, type "g++ -o makelist makelist.cpp".
2. In HyperList, select the lines you want to copy and type Control+Shift+C to copy without
	those lines without including the special flag characters.
3. In the terminal, type "pbpaste | ./makelist | pbcopy" to turn the clipboard contents into
	an HTML list.
	
Note: pbpaste is the Mac command for pasting the clipboard ("pb" = "pasteboard") contents into
the standard input stream, and pbcopy reads text back into the clipboard. If you are using a
different OS you will need to figure out the equivalent of these commands.
*/



#include <iostream>
#include <string>

using namespace std;



int main(int argc, char *argv[])
{
	bool atStart = true;
	int depth = 0;
	int previousDepth = 0;
	char c = cin.get();
	while(cin)
	{
		if(atStart)
		{
			// If we're at the start of a line, count tabs.
			if(c == '\t')
				++depth;
			else if(c == '\n')
			{
				// Ignore the '\n' in Windows-style line endings.	
			}
			else
			{
				// If the depth has decreased for this line, output closing tags for as many
				// sub-lists as we need to get out of.
				while(depth < previousDepth)
				{
					cout<<"</li></ul>";
					--previousDepth;
				}
				
				// We've now inserted enough closing tags to get us back to the current depth.
				// Or else, this line may be deeper than the previous line.
				// If it is _not_ deeper, close the previous line's <li> element.
				if(depth == previousDepth)
					cout<<"</li>";
				
				// Indent this line by an amount equal to the current depth.
				cout<<endl<<string(depth, '\t');
				
				// If the next line is deeper than this one, open a sub-list.
				if(depth > previousDepth)
				{
					cout<<"<ul>";
					++previousDepth;
				}

				// The depth should never increase by more than one at a time, so we should
				// never enter this while. But just in case, handle sudden increases of depth
				// by more than 1.
				while(depth > previousDepth)
				{
					cout<<"<li>&nbsp;<ul>";
					++previousDepth;
				}
				
				// Begin this list element.
				cout<<"<li>"<<c;
				
				// Now, we're parsing regular text instead of counting tabs.
				atStart = false;
			}
		}
		else if(c == '\r')
		{
			// If we hit the end of a line, We're now beginning a new line.
			atStart = true;
			depth = 0;
		}
		else
		{
			// If we just read ordinary text, echo it to the output.
			cout<<c;
		}
			
		c = cin.get();
	}
	
	// Close whatever lists we're still inside of.
	while(previousDepth)
	{
		cout<<"</li></ul>";
		--previousDepth;	
	}
	
	return 0;
}



/* Copyright (c) 2008 Michael Zahniser

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. */

