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, count, 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 	int paramList = 0;
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 > 0 && endsWith(line, ");", ")") && count(line, '(') != count(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 			if ( paramList > 0 )
74 				paramList--;
75 		}
76 
77 		if ( line.empty )
78 		{
79 			return "\n";
80 		}
81 		else if ( startsWith(line, "&&", "||") )
82 		{
83 			text = tabs ~"\t"~ line ~"\n";
84 		}
85 		else if ( statement )
86 		{
87 			text = tabs ~"\t"~ line ~"\n";
88 			statement = false;
89 		}
90 		else
91 		{
92 			text = tabs ~ line ~"\n";
93 		}
94 
95 		if ( startsWith(line, "if", "else", "static if","version", "debug", "do", "while") && !endsWith(line, "}", ";") )
96 		{
97 			statement = true;
98 		}
99 		else if ( (endsWith(line, '{') && !startsWith(line, "}")) )
100 		{
101 			tabs ~= '\t';
102 		}
103 		else if ( endsWith(line, "(") )
104 		{
105 			tabs ~= '\t';
106 			paramList++;
107 		}
108 
109 		return text;
110 	}
111 
112 	/**
113 	 * Formats the input lines while keeping track of indentation
114 	 * Params:
115 	 *    	lines = The lines to format
116 	 */
117 	public string format(string[] lines)
118 	{
119 		string text = "";
120 		foreach(string line ; lines )
121 			text ~= format(line);
122 		return text;
123 	}
124 
125 	public void setIndent(string t)
126 	{
127 		tabs = t;
128 	}
129 }