/**
* Copyright (C) 2015 drrb
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.drrb.rust.netbeans.formatting;
import com.github.drrb.rust.netbeans.parsing.NetbeansRustParser;
import com.github.drrb.rust.netbeans.parsing.NetbeansRustParser.NetbeansRustParserResult;
import static java.lang.Character.isWhitespace;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.csl.api.Formatter;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.editor.indent.spi.Context;
import org.netbeans.spi.lexer.MutableTextInput;
import org.openide.util.Exceptions;
/**
*
*/
public class RustFormatter implements Formatter {
@Override
public void reformat(Context context, ParserResult compilationInfo) {
NetbeansRustParserResult parseResult = (NetbeansRustParser.NetbeansRustParserResult) compilationInfo;
final BaseDocument document = (BaseDocument) context.document();
final RustDocumentFormatter formatter = new RustDocumentFormatter(this, parseResult, document, context);
document.runAtomic(new Runnable() {
@Override
public void run() {
// Not sure why, but setActive(false)/(true) makes the formatting a lot faster
MutableTextInput mti = (MutableTextInput) document.getProperty(MutableTextInput.class);
try {
mti.tokenHierarchyControl().setActive(false);
formatter.format();
} finally {
mti.tokenHierarchyControl().setActive(true);
}
}
});
}
@Override
public void reindent(Context context) {
try {
int lineStart = context.lineStartOffset(context.startOffset());
int previousLineEnd = lineStart - 1;
int previousLineStart = context.lineStartOffset(previousLineEnd);
int previousLineIndent = context.lineIndent(previousLineStart);
Document document = context.document();
char lastCharOfPreviousLine = lastNonWhiteCharacter(previousLineStart, previousLineEnd, document);
int targetIndent;
if (lastCharOfPreviousLine == '{') {
targetIndent = previousLineIndent + indentSize();
} else {
targetIndent = previousLineIndent;
}
context.modifyIndent(lineStart, targetIndent);
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
}
private static char lastNonWhiteCharacter(int lineStart, int lineEnd, Document document) throws BadLocationException {
for (int i = lineEnd; i > lineStart; i--) {
char character = document.getText(i - 1, 1).charAt(0);
if (!isWhitespace(character)) {
return character;
}
}
return ' ';
}
@Override
public boolean needsParserResult() {
return true;
}
@Override
public int indentSize() {
return 4;
}
@Override
public int hangingIndentSize() {
return 8;
}
}