commit
b986115e51
28
README.md
28
README.md
|
|
@ -36,10 +36,11 @@ found in .editorconfig files.
|
||||||
* **--max_line_length**: See **max_line_length** below
|
* **--max_line_length**: See **max_line_length** below
|
||||||
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
|
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
|
||||||
* **--outdent_attributes**: See **dfmt_outdent_attributes** below
|
* **--outdent_attributes**: See **dfmt_outdent_attributes** below
|
||||||
* **--outdent_labels**: See **dfmt_outdent_labels** below
|
|
||||||
* **--space_after_cast**: See **dfmt_space_after_cast** below
|
* **--space_after_cast**: See **dfmt_space_after_cast** below
|
||||||
* **--split_operator_at_line_end**: See **dfmt_split_operator_at_line_end** below
|
* **--split_operator_at_line_end**: See **dfmt_split_operator_at_line_end** below
|
||||||
* **--tab_width**: See **tab_width** below
|
* **--tab_width**: See **tab_width** below
|
||||||
|
* **--selective_import_space**: See **dfmt_selective_import_space** below
|
||||||
|
* **--compact_labeled_statements**: See **dfmt_compact_labeled_statements** below
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```
|
```
|
||||||
|
|
@ -47,6 +48,28 @@ dfmt --inplace --space_after_cast=false --max_line_length=80 \
|
||||||
--soft_max_line_length=70 --brace_style=otbs file.d
|
--soft_max_line_length=70 --brace_style=otbs file.d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Disabling formatting
|
||||||
|
Formatting can be temporarily disabled by placing the comments ```// dfmt off```
|
||||||
|
and ```// dfmt on``` around code that you do not want formatted.
|
||||||
|
|
||||||
|
```d
|
||||||
|
void main(string[] args)
|
||||||
|
{
|
||||||
|
bool optionOne, optionTwo, optionThree;
|
||||||
|
|
||||||
|
// dfmt has no way of knowing that "getopt" is special, so it wraps the
|
||||||
|
// argument list normally
|
||||||
|
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
|
||||||
|
|
||||||
|
// dfmt off
|
||||||
|
getopt(args,
|
||||||
|
"optionOne", &optionOne,
|
||||||
|
"optionTwo", &optionTwo,
|
||||||
|
"optionThree", &optionThree);
|
||||||
|
// dfmt on
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
**dfmt** uses [EditorConfig](http://editorconfig.org/) configuration files.
|
**dfmt** uses [EditorConfig](http://editorconfig.org/) configuration files.
|
||||||
**dfmt**-specific properties are prefixed with *dfmt_*.
|
**dfmt**-specific properties are prefixed with *dfmt_*.
|
||||||
|
|
@ -66,12 +89,13 @@ Property Name | Allowed Values | Default Value | Description
|
||||||
--------------|----------------|---------------|------------
|
--------------|----------------|---------------|------------
|
||||||
dfmt_brace_style | `allman`, `otbs`, or `stroustrup` | `allman` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style)
|
dfmt_brace_style | `allman`, `otbs`, or `stroustrup` | `allman` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style)
|
||||||
dfmt_soft_max_line_length | positive integers | `80` | The formatting process will usually keep lines below this length, but they may be up to max_line_length columns long.
|
dfmt_soft_max_line_length | positive integers | `80` | The formatting process will usually keep lines below this length, but they may be up to max_line_length columns long.
|
||||||
dfmt_outdent_labels (Not yet implemented) | `true`, `false` | `true` | Decrease the indentation of labels
|
|
||||||
dfmt_align_switch_statements (Not yet implemented) | `true`, `false` | `true` | Align labels, cases, and defaults with their enclosing switch
|
dfmt_align_switch_statements (Not yet implemented) | `true`, `false` | `true` | Align labels, cases, and defaults with their enclosing switch
|
||||||
dfmt_outdent_attributes (Not yet implemented) | `true`, `false` | `true` | Decrease the indentation level of attributes
|
dfmt_outdent_attributes (Not yet implemented) | `true`, `false` | `true` | Decrease the indentation level of attributes
|
||||||
dfmt_split_operator_at_line_end | `true`, `false` | `false` | Place operators on the end of the previous line when splitting lines
|
dfmt_split_operator_at_line_end | `true`, `false` | `false` | Place operators on the end of the previous line when splitting lines
|
||||||
dfmt_space_after_cast | `true`, `false` | `false` | Insert space after the closing paren of a `cast` expression
|
dfmt_space_after_cast | `true`, `false` | `false` | Insert space after the closing paren of a `cast` expression
|
||||||
dfmt_space_after_keywords (Not yet implemented) | `true`, `false` | `true` | Insert space after `if`, `while`, `foreach`, etc, and before the `(`
|
dfmt_space_after_keywords (Not yet implemented) | `true`, `false` | `true` | Insert space after `if`, `while`, `foreach`, etc, and before the `(`
|
||||||
|
dfmt_selective_import_space | `true`, `false` | `true` | Insert space after the module name and before the `:` for selective imports
|
||||||
|
dfmt_compact_labeled_statements | `true`, `false` | `true` | Place labels on the same line as the labeled `switch`, `for`, `foreach`, or `while` statement
|
||||||
|
|
||||||
## Terminology
|
## Terminology
|
||||||
* Braces - `{` and `}`
|
* Braces - `{` and `}`
|
||||||
|
|
|
||||||
2
dub.json
2
dub.json
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "dfmt",
|
"name": "dfmt",
|
||||||
"description": "Dfmt is a formatter for D source code",
|
"description": "Dfmt is a formatter for D source code",
|
||||||
"version": "0.3.5",
|
"version": "0.4.0-beta",
|
||||||
"targetType": "executable",
|
"targetType": "executable",
|
||||||
"license": "BSL-1.0",
|
"license": "BSL-1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,6 @@ struct Config
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_outdent_attributes;
|
OptionalBoolean dfmt_outdent_attributes;
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_outdent_labels;
|
|
||||||
///
|
|
||||||
int dfmt_soft_max_line_length = -1;
|
int dfmt_soft_max_line_length = -1;
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_space_after_cast;
|
OptionalBoolean dfmt_space_after_cast;
|
||||||
|
|
@ -38,6 +36,10 @@ struct Config
|
||||||
OptionalBoolean dfmt_space_after_keywords;
|
OptionalBoolean dfmt_space_after_keywords;
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_split_operator_at_line_end;
|
OptionalBoolean dfmt_split_operator_at_line_end;
|
||||||
|
///
|
||||||
|
OptionalBoolean dfmt_selective_import_space;
|
||||||
|
///
|
||||||
|
OptionalBoolean dfmt_compact_labeled_statements;
|
||||||
|
|
||||||
mixin StandardEditorConfigFields;
|
mixin StandardEditorConfigFields;
|
||||||
|
|
||||||
|
|
@ -57,11 +59,12 @@ struct Config
|
||||||
dfmt_align_switch_statements = OptionalBoolean.t;
|
dfmt_align_switch_statements = OptionalBoolean.t;
|
||||||
dfmt_brace_style = BraceStyle.allman;
|
dfmt_brace_style = BraceStyle.allman;
|
||||||
dfmt_outdent_attributes = OptionalBoolean.t;
|
dfmt_outdent_attributes = OptionalBoolean.t;
|
||||||
dfmt_outdent_labels = OptionalBoolean.t;
|
|
||||||
dfmt_soft_max_line_length = 80;
|
dfmt_soft_max_line_length = 80;
|
||||||
dfmt_space_after_cast = OptionalBoolean.t;
|
dfmt_space_after_cast = OptionalBoolean.t;
|
||||||
dfmt_space_after_keywords = OptionalBoolean.t;
|
dfmt_space_after_keywords = OptionalBoolean.t;
|
||||||
dfmt_split_operator_at_line_end = OptionalBoolean.f;
|
dfmt_split_operator_at_line_end = OptionalBoolean.f;
|
||||||
|
dfmt_selective_import_space = OptionalBoolean.t;
|
||||||
|
dfmt_compact_labeled_statements = OptionalBoolean.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,7 +77,8 @@ struct Config
|
||||||
|
|
||||||
if (dfmt_soft_max_line_length > max_line_length)
|
if (dfmt_soft_max_line_length > max_line_length)
|
||||||
{
|
{
|
||||||
stderr.writeln("Column hard limit must be greater than or equal to column soft limit");
|
stderr.writefln("Column hard limit (%d) must be greater than or equal to column soft limit (%d)",
|
||||||
|
max_line_length, dfmt_soft_max_line_length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ void format(OutputRange)(string source_desc, ubyte[] buffer, OutputRange output,
|
||||||
astInformation.cleanup();
|
astInformation.cleanup();
|
||||||
auto tokens = byToken(buffer, config, &cache).array();
|
auto tokens = byToken(buffer, config, &cache).array();
|
||||||
auto depths = generateDepthInfo(tokens);
|
auto depths = generateDepthInfo(tokens);
|
||||||
auto tokenFormatter = TokenFormatter!OutputRange(tokens, depths, output,
|
auto tokenFormatter = TokenFormatter!OutputRange(buffer, tokens, depths, output,
|
||||||
&astInformation, formatterConfig);
|
&astInformation, formatterConfig);
|
||||||
tokenFormatter.format();
|
tokenFormatter.format();
|
||||||
}
|
}
|
||||||
|
|
@ -74,9 +74,10 @@ struct TokenFormatter(OutputRange)
|
||||||
* astInformation = information about the AST used to inform formatting
|
* astInformation = information about the AST used to inform formatting
|
||||||
* decisions.
|
* decisions.
|
||||||
*/
|
*/
|
||||||
this(const(Token)[] tokens, immutable short[] depths, OutputRange output,
|
this(const ubyte[] rawSource, const(Token)[] tokens, immutable short[] depths,
|
||||||
ASTInformation* astInformation, Config* config)
|
OutputRange output, ASTInformation* astInformation, Config* config)
|
||||||
{
|
{
|
||||||
|
this.rawSource = rawSource;
|
||||||
this.tokens = tokens;
|
this.tokens = tokens;
|
||||||
this.depths = depths;
|
this.depths = depths;
|
||||||
this.output = output;
|
this.output = output;
|
||||||
|
|
@ -105,6 +106,9 @@ private:
|
||||||
/// Output to write output to
|
/// Output to write output to
|
||||||
OutputRange output;
|
OutputRange output;
|
||||||
|
|
||||||
|
/// Used for skipping parts of the file with `dfmt off` and `dfmt on` comments
|
||||||
|
const ubyte[] rawSource;
|
||||||
|
|
||||||
/// Tokens being formatted
|
/// Tokens being formatted
|
||||||
const Token[] tokens;
|
const Token[] tokens;
|
||||||
|
|
||||||
|
|
@ -234,8 +238,43 @@ private:
|
||||||
writeToken();
|
writeToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string commentText(size_t i)
|
||||||
|
{
|
||||||
|
import std.string : strip;
|
||||||
|
assert(tokens[i].type == tok!"comment");
|
||||||
|
string commentText = tokens[i].text;
|
||||||
|
if (commentText[0 ..2] == "//")
|
||||||
|
commentText = commentText[2 .. $];
|
||||||
|
else
|
||||||
|
commentText = commentText[2 .. $ - 2];
|
||||||
|
return commentText.strip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipFormatting()
|
||||||
|
{
|
||||||
|
size_t dfmtOff = index;
|
||||||
|
size_t dfmtOn = index;
|
||||||
|
foreach (i; dfmtOff + 1.. tokens.length)
|
||||||
|
{
|
||||||
|
dfmtOn = i;
|
||||||
|
if (tokens[i].type != tok!"comment")
|
||||||
|
continue;
|
||||||
|
immutable string commentText = commentText(i);
|
||||||
|
if (commentText == "dfmt on")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write(cast(string) rawSource[tokens[dfmtOff].index .. tokens[dfmtOn].index]);
|
||||||
|
index = dfmtOn;
|
||||||
|
}
|
||||||
|
|
||||||
void formatComment()
|
void formatComment()
|
||||||
{
|
{
|
||||||
|
if (commentText(index) == "dfmt off")
|
||||||
|
{
|
||||||
|
skipFormatting();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
immutable bool currIsSlashSlash = tokens[index].text[0 .. 2] == "//";
|
immutable bool currIsSlashSlash = tokens[index].text[0 .. 2] == "//";
|
||||||
immutable prevTokenEndLine = index == 0 ? size_t.max : tokenEndLine(tokens[index - 1]);
|
immutable prevTokenEndLine = index == 0 ? size_t.max : tokenEndLine(tokens[index - 1]);
|
||||||
immutable size_t currTokenLine = tokens[index].line;
|
immutable size_t currTokenLine = tokens[index].line;
|
||||||
|
|
@ -279,7 +318,7 @@ private:
|
||||||
|
|
||||||
void formatModuleOrImport()
|
void formatModuleOrImport()
|
||||||
{
|
{
|
||||||
auto t = current.type;
|
immutable t = current.type;
|
||||||
writeToken();
|
writeToken();
|
||||||
if (currentIs(tok!"("))
|
if (currentIs(tok!"("))
|
||||||
{
|
{
|
||||||
|
|
@ -302,7 +341,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (t == tok!"import" && !currentIs(tok!"import") && !currentIs(tok!"}")
|
else if (t == tok!"import" && !currentIs(tok!"import") && !currentIs(tok!"}")
|
||||||
&& !(currentIs(tok!"public") && peekIs(tok!"import")))
|
&& !(currentIs(tok!"public") && peekIs(tok!"import")))
|
||||||
{
|
{
|
||||||
simpleNewline();
|
simpleNewline();
|
||||||
currentLineLength = 0;
|
currentLineLength = 0;
|
||||||
|
|
@ -313,6 +352,13 @@ private:
|
||||||
newline();
|
newline();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (currentIs(tok!":"))
|
||||||
|
{
|
||||||
|
if (config.dfmt_selective_import_space)
|
||||||
|
write(" ");
|
||||||
|
writeToken();
|
||||||
|
write(" ");
|
||||||
|
}
|
||||||
else if (currentIs(tok!","))
|
else if (currentIs(tok!","))
|
||||||
{
|
{
|
||||||
// compute length until next ',' or ';'
|
// compute length until next ',' or ';'
|
||||||
|
|
@ -418,12 +464,22 @@ private:
|
||||||
|
|
||||||
void formatColon()
|
void formatColon()
|
||||||
{
|
{
|
||||||
if (astInformation.caseEndLocations.canFindIndex(current.index)
|
import dfmt.editorconfig : OptionalBoolean;
|
||||||
|| astInformation.attributeDeclarationLines.canFindIndex(current.line))
|
|
||||||
|
immutable bool isCase = astInformation.caseEndLocations.canFindIndex(current.index);
|
||||||
|
immutable bool isAttribute = astInformation.attributeDeclarationLines.canFindIndex(current.line);
|
||||||
|
if (isCase || isAttribute)
|
||||||
{
|
{
|
||||||
writeToken();
|
writeToken();
|
||||||
if (!currentIs(tok!"{"))
|
if (!currentIs(tok!"{"))
|
||||||
|
{
|
||||||
|
if (isCase && !indents.topIs(tok!"case") && config.dfmt_align_switch_statements == OptionalBoolean.f)
|
||||||
|
indents.push(tok!"case");
|
||||||
|
else if (isAttribute && !indents.topIs(tok!"@") && config.dfmt_outdent_attributes == OptionalBoolean.f)
|
||||||
|
indents.push(tok!"@");
|
||||||
newline();
|
newline();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (peekBackIs(tok!"identifier") && (peekBack2Is(tok!"{", true)
|
else if (peekBackIs(tok!"identifier") && (peekBack2Is(tok!"{", true)
|
||||||
|| peekBack2Is(tok!"}", true) || peekBack2Is(tok!";", true)
|
|| peekBack2Is(tok!"}", true) || peekBack2Is(tok!";", true)
|
||||||
|
|
@ -441,7 +497,10 @@ private:
|
||||||
else if (isBlockHeader(1) && !peekIs(tok!"if"))
|
else if (isBlockHeader(1) && !peekIs(tok!"if"))
|
||||||
{
|
{
|
||||||
writeToken();
|
writeToken();
|
||||||
write(" ");
|
if (config.dfmt_compact_labeled_statements)
|
||||||
|
write(" ");
|
||||||
|
else
|
||||||
|
newline();
|
||||||
}
|
}
|
||||||
else if (linebreakHints.canFindIndex(index))
|
else if (linebreakHints.canFindIndex(index))
|
||||||
{
|
{
|
||||||
|
|
@ -492,7 +551,7 @@ private:
|
||||||
{
|
{
|
||||||
if (currentIs(tok!"{"))
|
if (currentIs(tok!"{"))
|
||||||
indents.popTempIndents();
|
indents.popTempIndents();
|
||||||
indentLevel = indents.indentSize;
|
indentLevel = indents.indentLevel;
|
||||||
newline();
|
newline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -539,9 +598,9 @@ private:
|
||||||
{
|
{
|
||||||
indents.popWrapIndents();
|
indents.popWrapIndents();
|
||||||
if (indents.length && isTempIndent(indents.top))
|
if (indents.length && isTempIndent(indents.top))
|
||||||
indentLevel = indents.indentSize - 1;
|
indentLevel = indents.indentLevel - 1;
|
||||||
else
|
else
|
||||||
indentLevel = indents.indentSize;
|
indentLevel = indents.indentLevel;
|
||||||
|
|
||||||
if (!peekBackIsSlashSlash())
|
if (!peekBackIsSlashSlash())
|
||||||
{
|
{
|
||||||
|
|
@ -555,7 +614,7 @@ private:
|
||||||
{
|
{
|
||||||
writeToken();
|
writeToken();
|
||||||
indents.popTempIndents();
|
indents.popTempIndents();
|
||||||
indentLevel = indents.indentSize - 1;
|
indentLevel = indents.indentLevel - 1;
|
||||||
}
|
}
|
||||||
indents.push(tok!"{");
|
indents.push(tok!"{");
|
||||||
if (!currentIs(tok!"{"))
|
if (!currentIs(tok!"{"))
|
||||||
|
|
@ -629,7 +688,7 @@ private:
|
||||||
|| astInformation.conditionalWithElseLocations.canFindIndex(current.index);
|
|| astInformation.conditionalWithElseLocations.canFindIndex(current.index);
|
||||||
immutable bool c = b
|
immutable bool c = b
|
||||||
|| astInformation.conditionalStatementLocations.canFindIndex(current.index);
|
|| astInformation.conditionalStatementLocations.canFindIndex(current.index);
|
||||||
immutable bool shouldPushIndent = c && !(currentIs(tok!"if") && indents.topIsWrap());
|
immutable bool shouldPushIndent = c && !(currentIs(tok!"if") && indents.topIsWrap());
|
||||||
if (currentIs(tok!"out") && !peekBackIs(tok!"}"))
|
if (currentIs(tok!"out") && !peekBackIs(tok!"}"))
|
||||||
newline();
|
newline();
|
||||||
if (shouldPushIndent)
|
if (shouldPushIndent)
|
||||||
|
|
@ -1015,7 +1074,6 @@ private:
|
||||||
|
|
||||||
if (hasCurrent)
|
if (hasCurrent)
|
||||||
{
|
{
|
||||||
bool switchLabel = false;
|
|
||||||
if (currentIs(tok!"else"))
|
if (currentIs(tok!"else"))
|
||||||
{
|
{
|
||||||
auto i = indents.indentToMostRecent(tok!"if");
|
auto i = indents.indentToMostRecent(tok!"if");
|
||||||
|
|
@ -1026,35 +1084,31 @@ private:
|
||||||
}
|
}
|
||||||
else if (currentIs(tok!"identifier") && peekIs(tok!":"))
|
else if (currentIs(tok!"identifier") && peekIs(tok!":"))
|
||||||
{
|
{
|
||||||
while ((peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
|
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
|
||||||
&& indents.length && isTempIndent(indents.top()))
|
indents.popTempIndents();
|
||||||
{
|
|
||||||
indents.pop();
|
|
||||||
}
|
|
||||||
immutable l = indents.indentToMostRecent(tok!"switch");
|
immutable l = indents.indentToMostRecent(tok!"switch");
|
||||||
if (l != -1)
|
if (l != -1 && config.dfmt_align_switch_statements == OptionalBoolean.t)
|
||||||
{
|
|
||||||
indentLevel = l;
|
indentLevel = l;
|
||||||
switchLabel = true;
|
else if (config.dfmt_compact_labeled_statements == OptionalBoolean.f
|
||||||
}
|
|| !isBlockHeader(2) || peek2Is(tok!"if"))
|
||||||
else if (!isBlockHeader(2) || peek2Is(tok!"if"))
|
|
||||||
{
|
{
|
||||||
immutable l2 = indents.indentToMostRecent(tok!"{");
|
immutable l2 = indents.indentToMostRecent(tok!"{");
|
||||||
indentLevel = l2 == -1 ? indentLevel : l2;
|
indentLevel = l2 != -1 ? l2 : indents.indentLevel - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
indentLevel = indents.indentSize;
|
indentLevel = indents.indentLevel;
|
||||||
}
|
}
|
||||||
else if (currentIs(tok!"case") || currentIs(tok!"default"))
|
else if (currentIs(tok!"case") || currentIs(tok!"default"))
|
||||||
{
|
{
|
||||||
while (indents.length && (peekBackIs(tok!"}", true)
|
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
|
||||||
|| peekBackIs(tok!";", true)) && isTempIndent(indents.top()))
|
|
||||||
{
|
{
|
||||||
indents.pop();
|
indents.popTempIndents();
|
||||||
|
if (indents.topIs(tok!"case"))
|
||||||
|
indents.pop();
|
||||||
}
|
}
|
||||||
immutable l = indents.indentToMostRecent(tok!"switch");
|
immutable l = indents.indentToMostRecent(tok!"switch");
|
||||||
if (l != -1)
|
if (l != -1)
|
||||||
indentLevel = l;
|
indentLevel = config.dfmt_align_switch_statements == OptionalBoolean.t ? l : indents.indentLevel;
|
||||||
}
|
}
|
||||||
else if (currentIs(tok!"{"))
|
else if (currentIs(tok!"{"))
|
||||||
{
|
{
|
||||||
|
|
@ -1062,13 +1116,15 @@ private:
|
||||||
if (peekBackIsSlashSlash())
|
if (peekBackIsSlashSlash())
|
||||||
{
|
{
|
||||||
indents.popTempIndents();
|
indents.popTempIndents();
|
||||||
indentLevel = indents.indentSize;
|
indentLevel = indents.indentLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (currentIs(tok!"}"))
|
else if (currentIs(tok!"}"))
|
||||||
{
|
{
|
||||||
indents.popTempIndents();
|
indents.popTempIndents();
|
||||||
if (indents.top == tok!"{")
|
while (indents.topIs(tok!"case") || indents.topIs(tok!"@"))
|
||||||
|
indents.pop();
|
||||||
|
if (indents.topIs(tok!"{"))
|
||||||
{
|
{
|
||||||
indentLevel = indents.indentToMostRecent(tok!"{");
|
indentLevel = indents.indentToMostRecent(tok!"{");
|
||||||
indents.pop();
|
indents.pop();
|
||||||
|
|
@ -1085,22 +1141,30 @@ private:
|
||||||
if (indents.topIs(tok!"]"))
|
if (indents.topIs(tok!"]"))
|
||||||
{
|
{
|
||||||
indents.pop();
|
indents.pop();
|
||||||
indentLevel = indents.indentSize;
|
indentLevel = indents.indentLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (astInformation.attributeDeclarationLines.canFindIndex(current.line))
|
else if (astInformation.attributeDeclarationLines.canFindIndex(current.line))
|
||||||
{
|
{
|
||||||
immutable l = indents.indentToMostRecent(tok!"{");
|
if (config.dfmt_outdent_attributes == OptionalBoolean.t)
|
||||||
if (l != -1)
|
{
|
||||||
indentLevel = l;
|
immutable l = indents.indentToMostRecent(tok!"{");
|
||||||
|
if (l != -1)
|
||||||
|
indentLevel = l;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (indents.topIs(tok!"@"))
|
||||||
|
indents.pop();
|
||||||
|
indentLevel = indents.indentLevel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (indents.topIsTemp() && (peekBackIsOneOf(true, tok!"}", tok!";") && indents.top != tok!";"))
|
while (indents.topIsTemp() && (peekBackIsOneOf(true, tok!"}", tok!";")
|
||||||
{
|
&& indents.top != tok!";"))
|
||||||
indents.pop();
|
indents.pop();
|
||||||
}
|
indentLevel = indents.indentLevel;
|
||||||
indentLevel = indents.indentSize;
|
|
||||||
}
|
}
|
||||||
indent();
|
indent();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,33 @@ module dfmt.indentation;
|
||||||
|
|
||||||
import std.d.lexer;
|
import std.d.lexer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: true if the given token type is a wrap indent type
|
||||||
|
*/
|
||||||
bool isWrapIndent(IdType type) pure nothrow @nogc @safe
|
bool isWrapIndent(IdType type) pure nothrow @nogc @safe
|
||||||
{
|
{
|
||||||
return type != tok!"{" && type != tok!":" && type != tok!"]" && isOperator(type);
|
return type != tok!"{" && type != tok!"case" && type != tok!"@"
|
||||||
|
&& type != tok!"]" && isOperator(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: true if the given token type is a wrap indent type
|
||||||
|
*/
|
||||||
bool isTempIndent(IdType type) pure nothrow @nogc @safe
|
bool isTempIndent(IdType type) pure nothrow @nogc @safe
|
||||||
{
|
{
|
||||||
return type != tok!"{";
|
return type != tok!"{" && type != tok!"case" && type != tok!"@";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stack for managing indent levels.
|
||||||
|
*/
|
||||||
struct IndentStack
|
struct IndentStack
|
||||||
{
|
{
|
||||||
int indentToMostRecent(IdType item)
|
/**
|
||||||
|
* Modifies the indent stack to match the state that it had at the most
|
||||||
|
* recent appearance of the given token type.
|
||||||
|
*/
|
||||||
|
int indentToMostRecent(IdType item) const
|
||||||
{
|
{
|
||||||
size_t i = index;
|
size_t i = index;
|
||||||
while (true)
|
while (true)
|
||||||
|
|
@ -47,44 +61,69 @@ struct IndentStack
|
||||||
return tempIndentCount;
|
return tempIndentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the given indent type on to the stack.
|
||||||
|
*/
|
||||||
void push(IdType item) pure nothrow
|
void push(IdType item) pure nothrow
|
||||||
{
|
{
|
||||||
index = index == 255 ? index : index + 1;
|
index = index == 255 ? index : index + 1;
|
||||||
arr[index] = item;
|
arr[index] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops the top indent from the stack.
|
||||||
|
*/
|
||||||
void pop() pure nothrow
|
void pop() pure nothrow
|
||||||
{
|
{
|
||||||
index = index == 0 ? index : index - 1;
|
index = index == 0 ? index : index - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops all wrapping indents from the top of the stack.
|
||||||
|
*/
|
||||||
void popWrapIndents() pure nothrow @safe @nogc
|
void popWrapIndents() pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
while (index > 0 && isWrapIndent(arr[index]))
|
while (index > 0 && isWrapIndent(arr[index]))
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops all temporary indents from the top of the stack.
|
||||||
|
*/
|
||||||
void popTempIndents() pure nothrow @safe @nogc
|
void popTempIndents() pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
while (index > 0 && isTempIndent(arr[index]))
|
while (index > 0 && isTempIndent(arr[index]))
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: `true` if the top of the indent stack is the given indent type.
|
||||||
|
*/
|
||||||
bool topIs(IdType type) const pure nothrow @safe @nogc
|
bool topIs(IdType type) const pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
return index > 0 && arr[index] == type;
|
return index > 0 && arr[index] == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: `true` if the top of the indent stack is a temporary indent
|
||||||
|
*/
|
||||||
bool topIsTemp()
|
bool topIsTemp()
|
||||||
{
|
{
|
||||||
return index > 0 && index < arr.length && isTempIndent(arr[index]);
|
return index > 0 && index < arr.length && isTempIndent(arr[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: `true` if the top of the indent stack is a wrapping indent
|
||||||
|
*/
|
||||||
bool topIsWrap()
|
bool topIsWrap()
|
||||||
{
|
{
|
||||||
return index > 0 && index < arr.length && isWrapIndent(arr[index]);
|
return index > 0 && index < arr.length && isWrapIndent(arr[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: `true` if the top of the indent stack is one of the given token
|
||||||
|
* types.
|
||||||
|
*/
|
||||||
bool topIsOneOf(IdType[] types...) const pure nothrow @safe @nogc
|
bool topIsOneOf(IdType[] types...) const pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
if (index <= 0)
|
if (index <= 0)
|
||||||
|
|
@ -101,23 +140,9 @@ struct IndentStack
|
||||||
return arr[index];
|
return arr[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
int indentSize(size_t k = size_t.max) const pure nothrow @safe @nogc
|
int indentLevel() const pure nothrow @safe @nogc @property
|
||||||
{
|
{
|
||||||
if (index == 0)
|
return indentSize();
|
||||||
return 0;
|
|
||||||
immutable size_t j = k == size_t.max ? index : k - 1;
|
|
||||||
int size = 0;
|
|
||||||
foreach (i; 1 .. j + 1)
|
|
||||||
{
|
|
||||||
if ((i + 1 <= index && arr[i] != tok!"]" && !isWrapIndent(arr[i])
|
|
||||||
&& isTempIndent(arr[i]) && (!isTempIndent(arr[i + 1])
|
|
||||||
|| arr[i + 1] == tok!"switch")))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int length() const pure nothrow @property
|
int length() const pure nothrow @property
|
||||||
|
|
@ -126,6 +151,31 @@ struct IndentStack
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
|
|
||||||
IdType[256] arr;
|
IdType[256] arr;
|
||||||
|
|
||||||
|
int indentSize(size_t k = size_t.max) const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
return 0;
|
||||||
|
immutable size_t j = k == size_t.max ? index : k - 1;
|
||||||
|
int size = 0;
|
||||||
|
foreach (i; 1 .. j + 1)
|
||||||
|
{
|
||||||
|
if (i + 1 <= index)
|
||||||
|
{
|
||||||
|
if (arr[i] == tok!"]")
|
||||||
|
continue;
|
||||||
|
immutable bool currentIsTemp = isTempIndent(arr[i]);
|
||||||
|
immutable bool nextIsTemp = isTempIndent(arr[i + 1]);
|
||||||
|
immutable bool nextIsSwitch = arr[i + 1] == tok!"switch";
|
||||||
|
if (currentIsTemp && (!nextIsTemp || nextIsSwitch))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,22 +30,26 @@ else
|
||||||
import dfmt.editorconfig : OptionalBoolean;
|
import dfmt.editorconfig : OptionalBoolean;
|
||||||
import std.exception : enforceEx;
|
import std.exception : enforceEx;
|
||||||
enforceEx!GetOptException(value == "true" || value == "false", "Invalid argument");
|
enforceEx!GetOptException(value == "true" || value == "false", "Invalid argument");
|
||||||
|
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case "align_switch_statements":
|
case "align_switch_statements":
|
||||||
optConfig.dfmt_align_switch_statements = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
optConfig.dfmt_align_switch_statements = optVal;
|
||||||
break;
|
break;
|
||||||
case "outdent_attributes":
|
case "outdent_attributes":
|
||||||
optConfig.dfmt_outdent_attributes = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
optConfig.dfmt_outdent_attributes = optVal;
|
||||||
break;
|
|
||||||
case "outdent_labels":
|
|
||||||
optConfig.dfmt_outdent_labels = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
|
||||||
break;
|
break;
|
||||||
case "space_after_cast":
|
case "space_after_cast":
|
||||||
optConfig.dfmt_space_after_cast = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
optConfig.dfmt_space_after_cast = optVal;
|
||||||
break;
|
break;
|
||||||
case "split_operator_at_line_end":
|
case "split_operator_at_line_end":
|
||||||
optConfig.dfmt_split_operator_at_line_end = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
optConfig.dfmt_split_operator_at_line_end = optVal;
|
||||||
|
break;
|
||||||
|
case "selective_import_space":
|
||||||
|
optConfig.dfmt_selective_import_space = optVal;
|
||||||
|
break;
|
||||||
|
case "compact_labeled_statements":
|
||||||
|
optConfig.dfmt_compact_labeled_statements = optVal;
|
||||||
break;
|
break;
|
||||||
default: assert(false, "Invalid command-line switch");
|
default: assert(false, "Invalid command-line switch");
|
||||||
}
|
}
|
||||||
|
|
@ -64,9 +68,10 @@ else
|
||||||
"max_line_length", &optConfig.max_line_length,
|
"max_line_length", &optConfig.max_line_length,
|
||||||
"soft_max_line_length", &optConfig.dfmt_soft_max_line_length,
|
"soft_max_line_length", &optConfig.dfmt_soft_max_line_length,
|
||||||
"outdent_attributes", &handleBooleans,
|
"outdent_attributes", &handleBooleans,
|
||||||
"outdent_labels", &handleBooleans,
|
|
||||||
"space_after_cast", &handleBooleans,
|
"space_after_cast", &handleBooleans,
|
||||||
|
"selective_import_space", &handleBooleans,
|
||||||
"split_operator_at_line_end", &handleBooleans,
|
"split_operator_at_line_end", &handleBooleans,
|
||||||
|
"compact_labeled_statements", &handleBooleans,
|
||||||
"tab_width", &optConfig.tab_width);
|
"tab_width", &optConfig.tab_width);
|
||||||
}
|
}
|
||||||
catch (GetOptException e)
|
catch (GetOptException e)
|
||||||
|
|
@ -144,7 +149,7 @@ else
|
||||||
|
|
||||||
private void printHelp()
|
private void printHelp()
|
||||||
{
|
{
|
||||||
writeln(`dfmt 0.3.6
|
writeln(`dfmt 0.4.0-beta
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--help | -h Print this help message
|
--help | -h Print this help message
|
||||||
|
|
@ -161,9 +166,10 @@ Formatting Options:
|
||||||
--soft_max_line_length
|
--soft_max_line_length
|
||||||
--max_line_length
|
--max_line_length
|
||||||
--outdent_attributes
|
--outdent_attributes
|
||||||
--outdent_labels
|
|
||||||
--space_after_cast
|
--space_after_cast
|
||||||
--split_operator_at_line_end`);
|
--selective_import_space
|
||||||
|
--split_operator_at_line_end
|
||||||
|
--compact_labeled_statements`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string createFilePath(bool readFromStdin, string fileName)
|
private string createFilePath(bool readFromStdin, string fileName)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Label:
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
version (none)
|
||||||
|
{
|
||||||
|
// Comment
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
Label: while (1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Label2:
|
||||||
|
doStuff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
switch (a)
|
||||||
|
{
|
||||||
|
case a:
|
||||||
|
doStuff();
|
||||||
|
doOtherStuff();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
import std.stdio: stderr;
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
void main(string[] args)
|
||||||
|
{
|
||||||
|
// dfmt off
|
||||||
|
getopt(args,
|
||||||
|
"optionOne", &optionOne,
|
||||||
|
"optionTwo", &optionTwo,
|
||||||
|
"optionThree", &optionThree);
|
||||||
|
// dfmt on
|
||||||
|
|
||||||
|
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
class SomeClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
private:
|
||||||
|
int z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void doStuff();
|
||||||
|
|
@ -2,7 +2,7 @@ argsFile=$1.args
|
||||||
if [ -e ${argsFile} ]; then
|
if [ -e ${argsFile} ]; then
|
||||||
args=$(cat ${argsFile})
|
args=$(cat ${argsFile})
|
||||||
fi
|
fi
|
||||||
echo ${args}
|
echo "Args:" ${args}
|
||||||
dfmt --brace_style=allman ${args} $1.d > allman/$1.d.ref
|
dfmt --brace_style=allman ${args} $1.d > allman/$1.d.ref
|
||||||
dfmt --brace_style=otbs ${args} $1.d > otbs/$1.d.ref
|
dfmt --brace_style=otbs ${args} $1.d > otbs/$1.d.ref
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
--compact_labeled_statements=false
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Label:
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
--align_switch_statements=false
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
version (none)
|
||||||
|
{
|
||||||
|
// Comment
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
Label: while (1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Label2:
|
||||||
|
doStuff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
switch (a)
|
||||||
|
{
|
||||||
|
case a:
|
||||||
|
doStuff();
|
||||||
|
doOtherStuff();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
--selective_import_space=false
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
import std.stdio : stderr;
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
void main(string[] args)
|
||||||
|
{
|
||||||
|
// dfmt off
|
||||||
|
getopt(args,
|
||||||
|
"optionOne", &optionOne,
|
||||||
|
"optionTwo", &optionTwo,
|
||||||
|
"optionThree", &optionThree);
|
||||||
|
// dfmt on
|
||||||
|
|
||||||
|
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
--outdent_attributes=false
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
class SomeClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
private:
|
||||||
|
int z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void doStuff();
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
unittest {
|
||||||
|
Label:
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
unittest {
|
||||||
|
switch (x) {
|
||||||
|
case 0:
|
||||||
|
version (none) {
|
||||||
|
// Comment
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
switch (x) {
|
||||||
|
case 0: {
|
||||||
|
Label: while (1) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Label2:
|
||||||
|
doStuff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
doStuff();
|
||||||
|
doOtherStuff();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
import std.stdio: stderr;
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
void main(string[] args) {
|
||||||
|
// dfmt off
|
||||||
|
getopt(args,
|
||||||
|
"optionOne", &optionOne,
|
||||||
|
"optionTwo", &optionTwo,
|
||||||
|
"optionThree", &optionThree);
|
||||||
|
// dfmt on
|
||||||
|
|
||||||
|
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
class SomeClass {
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
private:
|
||||||
|
int z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void doStuff();
|
||||||
Loading…
Reference in New Issue