Line wrapping improvements

This commit is contained in:
Hackerpilot 2015-02-22 00:45:34 -08:00
parent 4206c1f8d1
commit 6d23aaaef5
4 changed files with 56 additions and 26 deletions

View File

@ -422,9 +422,7 @@ private:
writeToken(); writeToken();
write(" "); write(" ");
} }
immutable size_t i = expressionEndIndex(); regenLineBreakHintsIfNecessary(index - 1);
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
break; break;
case tok!"=": case tok!"=":
case tok!">=": case tok!">=":
@ -440,15 +438,11 @@ private:
write(" "); write(" ");
writeToken(); writeToken();
write(" "); write(" ");
immutable size_t i = expressionEndIndex(); regenLineBreakHintsIfNecessary(index - 1);
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
break; break;
case tok!"&&": case tok!"&&":
case tok!"||": case tok!"||":
immutable size_t i = expressionEndIndex(); regenLineBreakHintsIfNecessary(index);
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
goto case; goto case;
case tok!"^^": case tok!"^^":
case tok!"^=": case tok!"^=":
@ -506,6 +500,16 @@ private:
assert (false, str(current.type)); assert (false, str(current.type));
} }
void regenLineBreakHintsIfNecessary(immutable size_t i)
{
if (linebreakHints.length == 0 || linebreakHints[$ - 1] <= i - 1)
{
immutable size_t j = expressionEndIndex(i);
linebreakHints = chooseLineBreakTokens(i, tokens[i .. j],
config, currentLineLength, indentLevel);
}
}
/// Pushes a temporary indent level /// Pushes a temporary indent level
void pushIndent() void pushIndent()
{ {
@ -520,11 +524,11 @@ private:
tempIndent--; tempIndent--;
} }
size_t expressionEndIndex() const pure @safe @nogc size_t expressionEndIndex(size_t i) const pure @safe @nogc
{ {
size_t i = index;
int parenDepth = 0; int parenDepth = 0;
loop: while (i < tokens.length) switch (tokens[i].type) loop : while (i < tokens.length)
switch (tokens[i].type)
{ {
case tok!"(": case tok!"(":
parenDepth++; parenDepth++;
@ -616,6 +620,8 @@ private:
} }
body body
{ {
import std.range : assumeSorted;
immutable t = tempIndent; immutable t = tempIndent;
int depth = 0; int depth = 0;
do do
@ -631,15 +637,15 @@ private:
{ {
writeToken(); writeToken();
depth++; depth++;
immutable size_t i = expressionEndIndex(); if (!assumeSorted(linebreakHints).equalRange(index - 1).empty
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i], || (linebreakHints.length == 0
config, currentLineLength, indentLevel); && currentLineLength > config.columnSoftLimit
if (linebreakHints.length == 0 && currentLineLength > config.columnSoftLimit && current.type != tok!")"))
&& current.type != tok!")")
{ {
pushIndent(); pushIndent();
newline(); newline();
} }
regenLineBreakHintsIfNecessary(index - 1);
continue; continue;
} }
else if (current.type == tok!")") else if (current.type == tok!")")
@ -1086,6 +1092,7 @@ bool isBreakToken(IdType t)
case tok!"||": case tok!"||":
case tok!"&&": case tok!"&&":
case tok!"(": case tok!"(":
case tok!"[":
case tok!",": case tok!",":
case tok!"^^": case tok!"^^":
case tok!"^=": case tok!"^=":
@ -1142,6 +1149,7 @@ int breakCost(IdType t)
case tok!"||": case tok!"||":
case tok!"&&": case tok!"&&":
return 0; return 0;
case tok!"[":
case tok!"(": case tok!"(":
case tok!",": case tok!",":
return 10; return 10;
@ -1205,7 +1213,7 @@ struct State
import std.algorithm : map, sum; import std.algorithm : map, sum;
this._cost = breaks.map!(b => breakCost(tokens[b].type)).sum() this._cost = breaks.map!(b => breakCost(tokens[b].type)).sum()
+ (depth * 300); + (depth * 500);
int ll = currentLineLength; int ll = currentLineLength;
size_t breakIndex = 0; size_t breakIndex = 0;
size_t i = 0; size_t i = 0;
@ -1287,17 +1295,20 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
import std.algorithm : filter, min; import std.algorithm : filter, min;
import core.memory : GC; import core.memory : GC;
enum ALGORITHMIC_COMPLEXITY_SUCKS = 20; enum ALGORITHMIC_COMPLEXITY_SUCKS = 25;
immutable size_t tokensEnd = min(tokens.length, ALGORITHMIC_COMPLEXITY_SUCKS); immutable size_t tokensEnd = min(tokens.length, ALGORITHMIC_COMPLEXITY_SUCKS);
int depth = 0; int depth = 0;
auto open = new RedBlackTree!State; auto open = new RedBlackTree!State;
open.insert(State(cast(size_t[])[], tokens[0 .. tokensEnd], depth, open.insert(State(cast(size_t[])[], tokens[0 .. tokensEnd], depth,
formatterConfig, currentLineLength, indentLevel)); formatterConfig, currentLineLength, indentLevel));
State lowest;
GC.disable(); GC.disable();
scope(exit) GC.enable(); scope(exit) GC.enable();
while (!open.empty) while (!open.empty)
{ {
State current = open.front(); State current = open.front();
if (current.cost < lowest.cost)
lowest = current;
open.removeFront(); open.removeFront();
if (current.solved) if (current.solved)
{ {
@ -1311,7 +1322,10 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
} }
} }
if (open.empty) if (open.empty)
return (tokens.length > 0 && isBreakToken(tokens[0].type)) ? [index] : []; {
lowest.breaks[] += index;
return lowest.breaks;
}
foreach (r; open[].filter!(a => a.solved)) foreach (r; open[].filter!(a => a.solved))
{ {
r.breaks[] += index; r.breaks[] += index;
@ -1330,7 +1344,7 @@ State[] validMoves(const Token[] tokens, ref const State current,
State[] states; State[] states;
foreach (i, token; tokens) foreach (i, token; tokens)
{ {
if (!isBreakToken(token.type) || current.breaks.canFind(i)) if (current.breaks.canFind(i) || !isBreakToken(token.type))
continue; continue;
size_t[] breaks; size_t[] breaks;
breaks ~= current.breaks; breaks ~= current.breaks;

View File

@ -3,8 +3,8 @@ import std.stdio, std.random, std.typecons, std.conv, std.string, std.range;
void main() void main()
{ {
immutable interval = tuple(1, 100); immutable interval = tuple(1, 100);
writefln("Guess my target number that is between " writefln("Guess my target number that is between " ~ "%d and %d (inclusive).\n",
~ "%d and %d (inclusive).\n", interval[]); interval[]);
immutable target = uniform!"[]"(interval[]); immutable target = uniform!"[]"(interval[]);
foreach (immutable i; sequence!q{n}) foreach (immutable i; sequence!q{n})
{ {

7
tests/wrapping1.d Normal file
View File

@ -0,0 +1,7 @@
void main(string[] args)
{
if (prevLocation != size_t.max)
{
addErrorMessage(line, column, KEY, "Expression %s is true: already checked on line %d.".format(expressions[prevLocation].formatted, expressions[prevLocation].line));
}
}

9
tests/wrapping1.d.ref Normal file
View File

@ -0,0 +1,9 @@
void main(string[] args)
{
if (prevLocation != size_t.max)
{
addErrorMessage(line, column, KEY,
"Expression %s is true: already checked on line %d.".format(
expressions[prevLocation].formatted, expressions[prevLocation].line));
}
}