Better line wrapping
This commit is contained in:
parent
ebe56f3e56
commit
df676b9fad
93
src/dfmt.d
93
src/dfmt.d
|
@ -425,6 +425,12 @@ private:
|
||||||
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
|
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
|
||||||
config, currentLineLength, indentLevel);
|
config, currentLineLength, indentLevel);
|
||||||
break;
|
break;
|
||||||
|
case tok!"&&":
|
||||||
|
case tok!"||":
|
||||||
|
immutable size_t i = expressionEndIndex();
|
||||||
|
linebreakHints = chooseLineBreakTokens(index, tokens[index .. i],
|
||||||
|
config, currentLineLength, indentLevel);
|
||||||
|
goto case;
|
||||||
case tok!"^^":
|
case tok!"^^":
|
||||||
case tok!"^=":
|
case tok!"^=":
|
||||||
case tok!"^":
|
case tok!"^":
|
||||||
|
@ -440,7 +446,6 @@ private:
|
||||||
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!"!<>=":
|
||||||
|
@ -453,7 +458,6 @@ private:
|
||||||
case tok!"/":
|
case tok!"/":
|
||||||
case tok!"..":
|
case tok!"..":
|
||||||
case tok!"%":
|
case tok!"%":
|
||||||
case tok!"&&":
|
|
||||||
binary:
|
binary:
|
||||||
if (linebreakHints.canFind(index))
|
if (linebreakHints.canFind(index))
|
||||||
{
|
{
|
||||||
|
@ -986,21 +990,21 @@ string generateFixedLengthCases()
|
||||||
"finally", "float", "for", "foreach", "foreach_reverse", "function",
|
"finally", "float", "for", "foreach", "foreach_reverse", "function",
|
||||||
"goto", "idouble", "if", "ifloat", "immutable", "import", "in", "inout",
|
"goto", "idouble", "if", "ifloat", "immutable", "import", "in", "inout",
|
||||||
"int", "interface", "invariant", "ireal", "is", "lazy", "long", "macro",
|
"int", "interface", "invariant", "ireal", "is", "lazy", "long", "macro",
|
||||||
"mixin", "module", "new", "nothrow", "null", "out", "override",
|
"mixin", "module", "new", "nothrow", "null", "out", "override", "package",
|
||||||
"package", "pragma", "private", "protected", "public", "pure", "real",
|
"pragma", "private", "protected", "public", "pure", "real", "ref",
|
||||||
"ref", "return", "scope", "shared", "short", "static", "struct", "super",
|
"return", "scope", "shared", "short", "static", "struct", "super",
|
||||||
"switch", "synchronized", "template", "this", "throw", "true", "try",
|
"switch", "synchronized", "template", "this", "throw", "true", "try",
|
||||||
"typedef", "typeid", "typeof", "ubyte", "ucent", "uint", "ulong",
|
"typedef", "typeid", "typeof", "ubyte", "ucent", "uint", "ulong", "union",
|
||||||
"union", "unittest", "ushort", "version", "void", "volatile", "wchar",
|
"unittest", "ushort", "version", "void", "volatile", "wchar", "while",
|
||||||
"while", "with", "__DATE__", "__EOF__", "__FILE__", "__FUNCTION__",
|
"with", "__DATE__", "__EOF__", "__FILE__", "__FUNCTION__", "__gshared",
|
||||||
"__gshared", "__LINE__", "__MODULE__", "__parameters",
|
"__LINE__", "__MODULE__", "__parameters", "__PRETTY_FUNCTION__",
|
||||||
"__PRETTY_FUNCTION__", "__TIME__", "__TIMESTAMP__", "__traits",
|
"__TIME__", "__TIMESTAMP__", "__traits", "__vector", "__VENDOR__",
|
||||||
"__vector", "__VENDOR__", "__VERSION__", ",", ".", "..", "...", "/",
|
"__VERSION__", ",", ".", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>",
|
||||||
"/=", "!", "!<", "!<=", "!<>", "!<>=", "!=", "!>", "!>=", "$", "%", "%=",
|
"!<>=", "!=", "!>", "!>=", "$", "%", "%=", "&", "&&", "&=", "(", ")", "*",
|
||||||
"&", "&&", "&=", "(", ")", "*", "*=", "+", "++", "+=", "-", "--", "-=",
|
"*=", "+", "++", "+=", "-", "--", "-=", ":", ";", "<", "<<", "<<=", "<=",
|
||||||
":", ";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==", "=>", ">",
|
"<>", "<>=", "=", "==", "=>", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?",
|
||||||
">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "]", "^", "^=", "^^",
|
"@", "[", "]", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "}", "~",
|
||||||
"^^=", "{", "|", "|=", "||", "}", "~", "~="];
|
"~="];
|
||||||
return fixedLengthTokens.map!(a => format(`case tok!"%s": return %d;`, a,
|
return fixedLengthTokens.map!(a => format(`case tok!"%s": return %d;`, a,
|
||||||
a.length)).join("\n\t");
|
a.length)).join("\n\t");
|
||||||
}
|
}
|
||||||
|
@ -1162,7 +1166,9 @@ struct State
|
||||||
this.breaks = breaks;
|
this.breaks = breaks;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
import std.algorithm : map, sum;
|
import std.algorithm : map, sum;
|
||||||
this._cost = breaks.map!(b => breakCost(tokens[b].type)).sum() + ((depth - 1) * 200);
|
|
||||||
|
this._cost = breaks.map!(b => breakCost(tokens[b].type)).sum()
|
||||||
|
+ (depth * 300);
|
||||||
int ll = currentLineLength;
|
int ll = currentLineLength;
|
||||||
size_t breakIndex = 0;
|
size_t breakIndex = 0;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -1177,7 +1183,8 @@ struct State
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
immutable size_t j = breakIndex < breaks.length ? breaks[breakIndex] : tokens.length;
|
immutable size_t j = breakIndex < breaks.length
|
||||||
|
? breaks[breakIndex] : tokens.length;
|
||||||
ll += tokens[i .. j].map!(a => tokenLength(a)).sum();
|
ll += tokens[i .. j].map!(a => tokenLength(a)).sum();
|
||||||
if (ll > formatterConfig.columnSoftLimit)
|
if (ll > formatterConfig.columnSoftLimit)
|
||||||
{
|
{
|
||||||
|
@ -1193,16 +1200,26 @@ struct State
|
||||||
this._solved = s;
|
this._solved = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cost() const pure nothrow @safe @property { return _cost; }
|
int cost() const pure nothrow @safe @property
|
||||||
int depth() const pure nothrow @safe @property { return _depth; }
|
{
|
||||||
int solved() const pure nothrow @safe @property { return _solved; }
|
return _cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
int depth() const pure nothrow @safe @property
|
||||||
|
{
|
||||||
|
return _depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int solved() const pure nothrow @safe @property
|
||||||
|
{
|
||||||
|
return _solved;
|
||||||
|
}
|
||||||
|
|
||||||
int opCmp(ref const State other) const pure nothrow @safe
|
int opCmp(ref const State other) const pure nothrow @safe
|
||||||
{
|
{
|
||||||
if (cost < other.cost
|
if (cost < other.cost || (cost == other.cost && ((breaks.length
|
||||||
|| (cost == other.cost
|
&& other.breaks.length && breaks[0] > other.breaks[0]) || (_solved
|
||||||
&& ((breaks.length && other.breaks.length && breaks[0] > other.breaks[0])
|
&& !other.solved))))
|
||||||
|| (_solved && !other.solved))))
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1225,19 +1242,20 @@ private:
|
||||||
int _depth;
|
int _depth;
|
||||||
bool _solved;
|
bool _solved;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
|
size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
|
||||||
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel)
|
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel)
|
||||||
{
|
{
|
||||||
import std.container.rbtree : RedBlackTree;
|
import std.container.rbtree : RedBlackTree;
|
||||||
import std.algorithm : min;
|
import std.algorithm : filter, min;
|
||||||
import core.memory : GC;
|
import core.memory : GC;
|
||||||
|
|
||||||
enum ALGORITHMIC_COMPLEXITY_SUCKS = 20;
|
enum ALGORITHMIC_COMPLEXITY_SUCKS = 20;
|
||||||
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, formatterConfig,
|
open.insert(State(cast(size_t[])[], tokens[0 .. tokensEnd], depth,
|
||||||
currentLineLength, indentLevel));
|
formatterConfig, currentLineLength, indentLevel));
|
||||||
GC.disable();
|
GC.disable();
|
||||||
scope(exit) GC.enable();
|
scope(exit) GC.enable();
|
||||||
while (!open.empty)
|
while (!open.empty)
|
||||||
|
@ -1249,18 +1267,25 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
|
||||||
current.breaks[] += index;
|
current.breaks[] += index;
|
||||||
return current.breaks;
|
return current.breaks;
|
||||||
}
|
}
|
||||||
foreach (next; validMoves(tokens[0 .. tokensEnd], current, formatterConfig,
|
foreach (next; validMoves(tokens[0 .. tokensEnd], current,
|
||||||
currentLineLength, indentLevel, depth))
|
formatterConfig, currentLineLength, indentLevel, depth))
|
||||||
{
|
{
|
||||||
open.insert(next);
|
open.insert(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size_t[] retVal = open.empty ? [] : open.front().breaks;
|
if (open.empty)
|
||||||
retVal[] += index;
|
return isBreakToken(tokens[0].type) ? [index] : [];
|
||||||
return retVal;
|
foreach (r; open[].filter!(a => a.solved))
|
||||||
|
{
|
||||||
|
r.breaks[] += index;
|
||||||
|
return r.breaks;
|
||||||
|
}
|
||||||
|
assert (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
State[] validMoves(const Token[] tokens, ref const State current,
|
State[] validMoves(const Token[] tokens, ref const State current,
|
||||||
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel, int depth)
|
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel,
|
||||||
|
int depth)
|
||||||
{
|
{
|
||||||
import std.algorithm : sort, canFind;
|
import std.algorithm : sort, canFind;
|
||||||
import std.array : insertInPlace;
|
import std.array : insertInPlace;
|
||||||
|
|
Loading…
Reference in New Issue