Skip to content

Commit

Permalink
Line wrapping improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Hackerpilot committed Feb 22, 2015
1 parent 4206c1f commit 6d23aaa
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 26 deletions.
62 changes: 38 additions & 24 deletions src/dfmt.d
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,7 @@ private:
writeToken();
write(" ");
}
immutable size_t i = expressionEndIndex();
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
regenLineBreakHintsIfNecessary(index - 1);
break;
case tok!"=":
case tok!">=":
Expand All @@ -440,15 +438,11 @@ private:
write(" ");
writeToken();
write(" ");
immutable size_t i = expressionEndIndex();
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
regenLineBreakHintsIfNecessary(index - 1);
break;
case tok!"&&":
case tok!"||":
immutable size_t i = expressionEndIndex();
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
regenLineBreakHintsIfNecessary(index);
goto case;
case tok!"^^":
case tok!"^=":
Expand Down Expand Up @@ -506,6 +500,16 @@ private:
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
void pushIndent()
{
Expand All @@ -520,14 +524,14 @@ private:
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;
loop: while (i < tokens.length) switch (tokens[i].type)
{
case tok!"(":
parenDepth++;
loop : while (i < tokens.length)
switch (tokens[i].type)
{
case tok!"(":
parenDepth++;
i++;
break;
case tok!")":
Expand Down Expand Up @@ -616,6 +620,8 @@ private:
}
body
{
import std.range : assumeSorted;

immutable t = tempIndent;
int depth = 0;
do
Expand All @@ -631,15 +637,15 @@ private:
{
writeToken();
depth++;
immutable size_t i = expressionEndIndex();
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
config, currentLineLength, indentLevel);
if (linebreakHints.length == 0 && currentLineLength > config.columnSoftLimit
&& current.type != tok!")")
if (!assumeSorted(linebreakHints).equalRange(index - 1).empty
|| (linebreakHints.length == 0
&& currentLineLength > config.columnSoftLimit
&& current.type != tok!")"))
{
pushIndent();
newline();
}
regenLineBreakHintsIfNecessary(index - 1);
continue;
}
else if (current.type == tok!")")
Expand Down Expand Up @@ -1086,6 +1092,7 @@ bool isBreakToken(IdType t)
case tok!"||":
case tok!"&&":
case tok!"(":
case tok!"[":
case tok!",":
case tok!"^^":
case tok!"^=":
Expand Down Expand Up @@ -1142,6 +1149,7 @@ int breakCost(IdType t)
case tok!"||":
case tok!"&&":
return 0;
case tok!"[":
case tok!"(":
case tok!",":
return 10;
Expand Down Expand Up @@ -1205,7 +1213,7 @@ struct State
import std.algorithm : map, sum;

this._cost = breaks.map!(b => breakCost(tokens[b].type)).sum()
+ (depth * 300);
+ (depth * 500);
int ll = currentLineLength;
size_t breakIndex = 0;
size_t i = 0;
Expand Down Expand Up @@ -1287,17 +1295,20 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
import std.algorithm : filter, min;
import core.memory : GC;

enum ALGORITHMIC_COMPLEXITY_SUCKS = 20;
enum ALGORITHMIC_COMPLEXITY_SUCKS = 25;
immutable size_t tokensEnd = min(tokens.length, ALGORITHMIC_COMPLEXITY_SUCKS);
int depth = 0;
auto open = new RedBlackTree!State;
open.insert(State(cast(size_t[])[], tokens[0 .. tokensEnd], depth,
formatterConfig, currentLineLength, indentLevel));
State lowest;
GC.disable();
scope(exit) GC.enable();
while (!open.empty)
{
State current = open.front();
if (current.cost < lowest.cost)
lowest = current;
open.removeFront();
if (current.solved)
{
Expand All @@ -1311,7 +1322,10 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
}
}
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))
{
r.breaks[] += index;
Expand All @@ -1330,7 +1344,7 @@ State[] validMoves(const Token[] tokens, ref const State current,
State[] states;
foreach (i, token; tokens)
{
if (!isBreakToken(token.type) || current.breaks.canFind(i))
if (current.breaks.canFind(i) || !isBreakToken(token.type))
continue;
size_t[] breaks;
breaks ~= current.breaks;
Expand Down
4 changes: 2 additions & 2 deletions tests/guessnumber.d.ref
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import std.stdio, std.random, std.typecons, std.conv, std.string, std.range;
void main()
{
immutable interval = tuple(1, 100);
writefln("Guess my target number that is between "
~ "%d and %d (inclusive).\n", interval[]);
writefln("Guess my target number that is between " ~ "%d and %d (inclusive).\n",
interval[]);
immutable target = uniform!"[]"(interval[]);
foreach (immutable i; sequence!q{n})
{
Expand Down
7 changes: 7 additions & 0 deletions tests/wrapping1.d
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions tests/wrapping1.d.ref
Original file line number Diff line number Diff line change
@@ -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));
}
}

0 comments on commit 6d23aaa

Please sign in to comment.