1 /*
2  * This file is part of gir-to-d.
3  *
4  * gir-to-d is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation, either version 3
7  * of the License, or (at your option) any later version.
8  *
9  * gir-to-d is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with gir-to-d.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 module gtd.IndentedStringBuilder;
19 
20 import std.algorithm: canFind, startsWith, endsWith;
21 import std.range: empty;
22 import std.string: strip;
23 
24 /** Keeps track of indentation level while building up a string */
25 public class IndentedStringBuilder
26 {
27 	string tabs;
28 	bool statement;
29 	bool paramList;
30 
31 	this()
32 	{
33 		this("");
34 	}
35 
36 	this(string t)
37 	{
38 		tabs = t;
39 	}
40 
41 	/**
42 	 * Formats the input line while keeping track of indentation.
43 	 * Params:
44 	 *    	lines = The lines to format
45 	 */
46 	public string format(string line)
47 	{
48 		string text;
49 		line = line.strip();
50 
51 		if ( (endsWith(line, '{') && !startsWith(line, "}")) || endsWith(line, "(") )
52 		{
53 			statement = false;
54 		}
55 
56 		//Don't change the indentation when the line is a comment.
57 		if ( startsWith(line, '*') )
58 		{
59 			return tabs ~" "~ line ~ "\n";
60 		}
61 
62 		if ( endsWith(line, "}", "};") || startsWith(line, "}", "};") || line == "));" || line == "connectFlags);" || (paramList && endsWith(line, ");", ")")) )
63 		{
64 			if ( !canFind(line, '{') && tabs.length > 0 )
65 				tabs.length = tabs.length -1;
66 
67 			if ( line == "connectFlags);" )
68 				statement = true;
69 
70 			if ( endsWith(line, ");") && !endsWith(line, "));") && line != ");" )
71 				statement = true;
72 
73 			paramList = false;
74 		}
75 
76 		if ( line.empty )
77 		{
78 			return "\n";
79 		}
80 		else if ( startsWith(line, "&&", "||") )
81 		{
82 			text = tabs ~"\t"~ line ~"\n";
83 		}
84 		else if ( statement )
85 		{
86 			text = tabs ~"\t"~ line ~"\n";
87 			statement = false;
88 		}
89 		else
90 		{
91 			text = tabs ~ line ~"\n";
92 		}
93 
94 		if ( startsWith(line, "if", "else", "static if","version", "debug", "do", "while") && !endsWith(line, "}", ";") )
95 		{
96 			statement = true;
97 		}
98 		else if ( (endsWith(line, '{') && !startsWith(line, "}")) )
99 		{
100 			tabs ~= '\t';
101 		}
102 		else if ( endsWith(line, "(") )
103 		{
104 			tabs ~= '\t';
105 			paramList = true;
106 		}
107 
108 		return text;
109 	}
110 
111 	/**
112 	 * Formats the input lines while keeping track of indentation
113 	 * Params:
114 	 *    	lines = The lines to format
115 	 */
116 	public string format(string[] lines)
117 	{
118 		string text = "";
119 		foreach(string line ; lines )
120 			text ~= format(line);
121 		return text;
122 	}
123 
124 	public void setIndent(string t)
125 	{
126 		tabs = t;
127 	}
128 }