blob: 26a45727c20216e724aa994fc2c8ebfdf73c9942 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2017 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.tcl.internal.ui.text;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.tcl.internal.ui.TclUI;
import org.eclipse.dltk.tcl.ui.TclPreferenceConstants;
import org.eclipse.dltk.tcl.ui.text.TclPartitions;
import org.eclipse.dltk.ui.CodeFormatterConstants;
import org.eclipse.dltk.ui.PreferenceConstants;
import org.eclipse.dltk.ui.text.util.AutoEditUtils;
import org.eclipse.dltk.utils.CharacterStack;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.rules.FastPartitioner;
/**
* Auto indent strategy sensitive to brackets.
*/
public class TclAutoEditStrategy extends DefaultIndentLineAutoEditStrategy {
private final IPreferenceStore preferenceStore;
private final String fPartitioning;
private boolean closeStrings() {
return preferenceStore
.getBoolean(PreferenceConstants.EDITOR_CLOSE_STRINGS);
}
private boolean closeBrackets() {
return preferenceStore
.getBoolean(PreferenceConstants.EDITOR_CLOSE_BRACKETS);
}
private boolean closeBraces() {
return preferenceStore
.getBoolean(PreferenceConstants.EDITOR_CLOSE_BRACES);
}
/*
* Switch smart mode on/off
*/
private boolean isSmartMode() {
return preferenceStore
.getBoolean(PreferenceConstants.EDITOR_SMART_INDENT);
}
/**
* Calculates real length of string. So any char except \t has length 1, \t
* has length getTabWidth.
*
* @param str
* string to process
* @return length
*/
public int getPhysicalLength(String str) {
int res = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '\t')
res += getTabSize();
else
res++;
}
return res;
}
private int getTabSize() {
return preferenceStore
.getInt(CodeFormatterConstants.FORMATTER_TAB_SIZE);
}
private int getIndentSize() {
return preferenceStore
.getInt(CodeFormatterConstants.FORMATTER_INDENTATION_SIZE);
}
private String getTabStyle() {
return preferenceStore
.getString(CodeFormatterConstants.FORMATTER_TAB_CHAR);
}
private boolean isSmartPasteMode1() {
return preferenceStore.getInt(
TclPreferenceConstants.EDITOR_SMART_PASTE_MODE) == TclPreferenceConstants.EDITOR_SMART_PASTE_MODE_SIMPLE;
}
private boolean isSmartPasteMode2() {
return preferenceStore.getInt(
TclPreferenceConstants.EDITOR_SMART_PASTE_MODE) == TclPreferenceConstants.EDITOR_SMART_PASTE_MODE_FULL;
}
public TclAutoEditStrategy(IPreferenceStore store, String part) {
preferenceStore = store;
fPartitioning = part;
}
private boolean isLineDelimiter(IDocument document, String text) {
String[] delimiters = document.getLegalLineDelimiters();
if (delimiters != null)
return TextUtilities.equals(delimiters, text) > -1;
return false;
}
/**
* Returns the leading whitespaces.
*
* @param document
* - the document being parsed
* @param line
* - the line being searched
* @return the leading whitespace
* @throws BadLocationException
* in case <code>line</code> is invalid in the document
*/
private String getLineIndent(IDocument document, int line)
throws BadLocationException {
if (line > -1) {
int start = document.getLineOffset(line);
int end = start + document.getLineLength(line);
int whiteend = findEndOfWhiteSpace(document, start, end);
return document.get(start, whiteend - start);
}
return ""; //$NON-NLS-1$
}
/**
* Returns the leading whitespaces and tabs.
*
* @param line
* - the line being searched
* @return the leading whitespace
*/
public String getLineIndent(String line) {
int end = line.length();
int whiteend = end;
int offset = 0;
while (offset < end) {
char c = line.charAt(offset);
if (c != ' ' && c != '\t') {
whiteend = offset;
break;
}
offset++;
}
return line.substring(0, whiteend);
}
/*
* Block is and opening char seq. and closing char seq. Each block have it's
* own indent
*/
private static abstract class TclBlock {
private int offset;
public char openingPeer;
public char closingPeer;
public String indent;
protected TclBlock(int o) {
offset = o;
}
public int getOffset() {
return offset;
}
}
private class RoundBracketBlock extends TclBlock {
public RoundBracketBlock(int offset) {
super(offset);
openingPeer = '(';
closingPeer = ')';
if (!getTabStyle().equals(CodeFormatterConstants.TAB))
indent = " ";
else
indent = "\t";
}
}
private class BracketBlock extends TclBlock {
public BracketBlock(int offset) {
super(offset);
openingPeer = '[';
closingPeer = ']';
if (!getTabStyle().equals(CodeFormatterConstants.TAB))
indent = " ";
else
indent = "\t";
}
}
private class BraceBlock extends TclBlock {
public BraceBlock(int offset) {
super(offset);
openingPeer = '{';
closingPeer = '}';
if (!getTabStyle().equals(CodeFormatterConstants.SPACE))
indent = "\t";
else {
indent = AutoEditUtils.getNSpaces(getIndentSize());
}
}
}
/**
* Return pair to brace. Ex. '(' for ')', e.t.c.
*
* @param b
* input brace
* @return peer brace
*/
private char getBracePair(char b) {
switch (b) {
case '(':
return ')';
case ')':
return '(';
case '[':
return ']';
case ']':
return '[';
case '{':
return '}';
case '}':
return '{';
case '\"':
return '\"';
case '\'':
return '\'';
}
return b;
}
private static final int MAX_BACK_SCAN_SIZE = 16384;
/**
* Determines type of last opening block. For example, for such line <code>
* proc () {
* </code> function will return new BraceBlockType. And for
* <code>proc(){}</code> function will return null
*
* @param d
* document containing the line
* @param line
* number of the start search offset
* @return an object of appropriate block type
* @throws BadLocationException
*/
private TclBlock getLastOpenBlockType(IDocument d, int start)
throws BadLocationException {
// IRegion lineReg = d.getLineInformation(line);
final CharacterStack blocks = new CharacterStack();
// String lineStr = d.get(lineReg.getOffset(), lineReg.getLength());
ITypedRegion lastRegion = null;
int lastLine = -1;
int lastLineOffset = -1;
String lastLineStr = Util.EMPTY_STRING;
final int stopPosition = Math.max(start - MAX_BACK_SCAN_SIZE, 0);
int offset = start;
while (offset > stopPosition) {
offset--;
// skip screening
int bslashes = 0;
while (offset - bslashes > 0
&& d.getChar(offset - bslashes - 1) == '\\')
bslashes++;
if (bslashes % 2 == 1) {
offset -= bslashes;
continue;
}
// skip comment lines
if (lastLineOffset < 0 || offset < lastLineOffset) {
lastLine = d.getLineOfOffset(offset);
lastLineOffset = d.getLineOffset(lastLine);
lastLineStr = d.get(lastLineOffset, d.getLineLength(lastLine))
.trim();
}
if (lastLineStr.length() != 0 && lastLineStr.charAt(0) == '#') {
offset = lastLineOffset;
continue;
}
// skip strings
if (lastRegion == null || offset < lastRegion.getOffset()) {
lastRegion = TextUtilities.getPartition(d, fPartitioning,
offset, true);
}
if (lastRegion.getType() == TclPartitions.TCL_STRING) {
offset = lastRegion.getOffset();
offset--;
}
char c = d.getChar(offset);
boolean insideFig = false;
if (blocks.size() > 0 && blocks.peek() == '}')
insideFig = true;
// ommit everything inside {}
if (c != '{' && c != '}' && insideFig)
continue;
switch (c) {
case '(':
if (0 == blocks.size())
return new RoundBracketBlock(offset);
if (blocks.pop() != ')')
return new RoundBracketBlock(offset);
break;
case '[':
if (0 == blocks.size())
return new BracketBlock(offset);
if (blocks.pop() != ']')
return new BracketBlock(offset);
break;
case '{':
if (0 == blocks.size())
return new BraceBlock(offset);
if (blocks.pop() != '}')
return new BraceBlock(offset);
break;
case ')':
case ']':
case '}':
blocks.push(c);
break;
}
}
return null;
}
/**
* Find line with number <=line, that is Tcl code line (not comment)
*
* @param d
* the document to search in
* @param line
* number of starting line
* @return number of code line or -1 if no such line found
*/
private int getLastCodeLine(IDocument d, int line) {
int res = line;
try {
while (res > -1) {
IRegion reg = d.getLineInformation(res);
String str = d.get(reg.getOffset(), reg.getLength()).trim();
if (!str.startsWith("#") && str.length() > 0)
return res;
res--;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
return res;
}
private String getDocumentLine(IDocument d, int line)
throws BadLocationException {
int start = d.getLineOffset(line);
int length = d.getLineLength(line);
return d.get(start, length);
}
private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) {
if (c.offset == -1 || d.getLength() == 0)
return;
try {
TclDocumentScanner scanner = new TclDocumentScanner(d,
fPartitioning, IDocument.DEFAULT_CONTENT_TYPE);
int pos = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
int line = d.getLineOfOffset(pos);
int curLine = d.getLineOfOffset(c.offset);
String curLineStr = getDocumentLine(d, curLine);
String resultIndent = "";
String lastIndent = "";
TclBlock block = null;
boolean needPeer = false;
// if we need to jump into middle of block without inserting peer
// brace
boolean dummyPeer = false;
block = getLastOpenBlockType(d, c.offset);
if (curLineStr.trim().endsWith("\\")) {
resultIndent = getLineIndent(d, line - 1);
} else if (block == null) {
int lastCodeLine = getLastCodeLine(d, line);
// no code above us, just copy last indent
if (-1 == lastCodeLine) {
resultIndent = getLineIndent(d, line - 1);
} else {
// if our line is inside brackets, get line with opening
// bracket
block = getLastOpenBlockType(d,
d.getLineOffset(lastCodeLine));
if (block != null) {
int peer = scanner.findOpeningPeer(
d.getLineOffset(lastCodeLine),
block.openingPeer, block.closingPeer);
if (peer != TclDocumentScanner.NOT_FOUND) {
lastCodeLine = d.getLineOfOffset(peer);
}
}
resultIndent = getLineIndent(d, lastCodeLine);
}
} else {
int lastCodeLine = d.getLineOfOffset(block.getOffset());
lastIndent = getLineIndent(d, lastCodeLine);
resultIndent = lastIndent + block.indent;
int cPos = pos;
while ((d.getChar(cPos) == ' ' || d.getChar(cPos) == '\t')) {
if (cPos == d.getLength() - 1)
break;
cPos++;
}
if (block.closingPeer == d.getChar(cPos)) {
dummyPeer = true;
}
// find closing peer, if exists
int peerOffset = scanner.findClosingPeer(pos, block.openingPeer,
block.closingPeer);
// if not fount peer, we need it
if (peerOffset == TclDocumentScanner.NOT_FOUND)
needPeer = true;
}
// process line indent
resultIndent = remakeIndent(resultIndent);
IRegion reg = d.getLineInformation(line);
int lineEnd = reg.getOffset() + reg.getLength();
int contentStart = findEndOfWhiteSpace(d, c.offset, lineEnd);
c.length = Math.max(contentStart - c.offset, 0);
if (block instanceof BraceBlock && !preferenceStore
.getBoolean(PreferenceConstants.EDITOR_CLOSE_BRACES))
needPeer = false;
if ((block instanceof BracketBlock
|| block instanceof RoundBracketBlock)
&& !preferenceStore.getBoolean(
PreferenceConstants.EDITOR_CLOSE_BRACKETS))
needPeer = false;
if (needPeer || dummyPeer) {
StringBuffer buf = new StringBuffer(c.text);
buf.append(resultIndent);
c.shiftsCaret = false;
c.caretOffset = c.offset + buf.length();
if (lineEnd - contentStart > 0 && !dummyPeer) {
c.length = lineEnd - c.offset;
buf.append(d.get(contentStart, lineEnd - contentStart)
.toCharArray());
}
buf.append("\n"); // may be we should we default line delimeter?
buf.append(lastIndent);
if (!dummyPeer)
buf.append(block.closingPeer);
c.text = buf.toString();
} else {
StringBuffer buf = new StringBuffer(c.text);
buf.append(resultIndent);
c.text = buf.toString();
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
private void smartIndentAfterOpeningBracket(IDocument d,
DocumentCommand c) {
if (c.offset == -1)
return;
try {
if (d.getChar(c.offset - 1) == '\\')
return;
} catch (BadLocationException e1) {
}
if ('\"' == c.text.charAt(0) && !closeStrings())
return;
if ('\'' == c.text.charAt(0) && !closeStrings())
return;
if (!closeBrackets()
&& ('[' == c.text.charAt(0) || '(' == c.text.charAt(0)))
return;
if (!closeBraces() && ('{' == c.text.charAt(0)))
return;
try {
char ch = c.text.charAt(0);
switch (ch) {
case '\"':
case '\'':
// if we close existing quote, do nothing
if ('\"' == ch && c.offset > 0
&& "\"".equals(d.get(c.offset - 1, 1)))
return;
if ('\'' == ch && c.offset > 0
&& "\'".equals(d.get(c.offset - 1, 1)))
return;
if (c.offset != d.getLength()
&& ch == d.get(c.offset, 1).charAt(0))
c.text = "";
else {
c.text += c.text;
c.length = 0;
}
c.shiftsCaret = false;
c.caretOffset = c.offset + 1;
break;
case '(':
case '{':
case '[':
boolean needPeer = false;
TclDocumentScanner scanner = new TclDocumentScanner(d,
fPartitioning, IDocument.DEFAULT_CONTENT_TYPE);
// find closing peer, if exists
int peerOffset = scanner.findClosingPeer(c.offset, ch,
getBracePair(ch));
// if not fount peer, we need it
if (peerOffset == TclDocumentScanner.NOT_FOUND)
needPeer = true;
// check partition
if (getRegionType(d,
c.offset) != IDocument.DEFAULT_CONTENT_TYPE)
return;
if (!needPeer)
return;
if (c.offset != d.getLength()
&& ch == d.get(c.offset, 1).charAt(0))
return;
// add closing peer
c.text = c.text + getBracePair(ch);
c.length = 0;
c.shiftsCaret = false;
c.caretOffset = c.offset + 1;
break;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
private void smartIndentAfterClosingBracket(IDocument d,
DocumentCommand c) {
if (c.offset == -1 || d.getLength() == 0)
return;
try {
char bracket = c.text.charAt(0);
// if we already have bracket we should jump over it
if (c.offset != d.getLength()
&& bracket == d.get(c.offset, 1).charAt(0)
&& (getRegionType(d,
c.offset) == IDocument.DEFAULT_CONTENT_TYPE)) {
if ((bracket == '}' && closeBraces())
|| ((bracket == ')' || bracket == ']')
&& closeBrackets())) {
c.text = "";
c.shiftsCaret = false;
c.caretOffset = c.offset + 1;
return;
}
}
TclDocumentScanner scanner = new TclDocumentScanner(d);
int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
int line = d.getLineOfOffset(p);
int start = d.getLineOffset(line);
int whiteend = findEndOfWhiteSpace(d, start, c.offset);
// shift only when line does not contain any text up to the closing
// bracket
if (whiteend == c.offset) {
// determine block type
TclBlock block = null;
switch (c.text.charAt(0)) {
case ']':
block = new BracketBlock(0);
break;
case '}':
block = new BraceBlock(0);
break;
case ')':
block = new RoundBracketBlock(0);
break;
}
if (block == null)
return;
// evaluate the line with the opening bracket that matches out
// closing bracket
int reference = scanner.findOpeningPeer(p, block.openingPeer,
block.closingPeer);
int indLine = d.getLineOfOffset(reference);
if (indLine != -1 && indLine != line) {
// take the indent of the found line
StringBuffer replaceText = new StringBuffer();
// add the rest of the current line including the just added
// close bracket
replaceText.append(getLineIndent(d, indLine));
replaceText.append(c.text);
// modify document command
c.length += c.offset - start;
c.offset = start;
c.text = replaceText.toString();
}
}
} catch (BadLocationException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
private boolean smartIndentJump(IDocument d, DocumentCommand c) {
if (c.offset == -1 || d.getLength() == 0)
return false;
try {
TclDocumentScanner scanner = new TclDocumentScanner(d,
fPartitioning, IDocument.DEFAULT_CONTENT_TYPE);
int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
int curLine = d.getLineOfOffset(c.offset);
String curLineStr = getDocumentLine(d, curLine);
int line = d.getLineOfOffset(p);
int start = d.getLineOffset(line);
String resultIndent = "";
String lastIndent = "";
TclBlock block;
// DUPLICATION: this code is identical to code in
// smartInsertAfterNewLine
block = getLastOpenBlockType(d, c.offset);
if (curLineStr.trim().endsWith("\\")) {
resultIndent = getLineIndent(d, line - 1);
} else if (block == null) {
int lastCodeLine = getLastCodeLine(d, line);
// if our line is inside brackets, get line with opening bracket
block = getLastOpenBlockType(d, d.getLineOffset(curLine));
if (block != null) {
int peer = scanner.findOpeningPeer(d.getLineOffset(curLine),
block.openingPeer, block.closingPeer);
if (peer != TclDocumentScanner.NOT_FOUND) {
lastCodeLine = d.getLineOfOffset(peer);
}
}
// no code above us, just copy last indent
if (-1 == lastCodeLine) {
resultIndent = getLineIndent(d, line - 1);
} else {
resultIndent = getLineIndent(d, lastCodeLine);
}
} else {
int lastCodeLine = d.getLineOfOffset(block.getOffset());
lastIndent = getLineIndent(d, lastCodeLine);
resultIndent = lastIndent + block.indent;
}
if (c.offset >= start + resultIndent.length())
return false; // we already in the place
String currentIndent = getLineIndent(d, line);
if (!currentIndent.startsWith(resultIndent))
return false; // we have no place to jump
c.length = 0;
c.shiftsCaret = false;
c.text = "";
c.caretOffset = d.getLineOffset(line) + resultIndent.length();
} catch (BadLocationException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Installs a partitioner with <code>document</code>.
*
* @param document
* the document
*/
private static void installStuff(Document document) {
String[] types = new String[] { TclPartitions.TCL_STRING,
TclPartitions.TCL_COMMENT, IDocument.DEFAULT_CONTENT_TYPE };
FastPartitioner partitioner = new FastPartitioner(
new TclPartitionScanner(), types);
partitioner.connect(document);
document.setDocumentPartitioner(TclPartitions.TCL_PARTITIONING,
partitioner);
}
/**
* Removes a partitioner with <code>document</code>.
*
* @param document
* the document
*/
private static void removeStuff(Document document) {
document.setDocumentPartitioner(TclPartitions.TCL_PARTITIONING, null);
}
/**
* Reindents c.text when pasting(simply indents all to common level).
*
* @param d
* @param c
*/
private void smartPasteSimple(IDocument d, DocumentCommand c) {
try {
String content = d.get(0, c.offset) + c.text;
Document temp = new Document(content);
int line = d.getLineOfOffset(c.offset);
int start = d.getLineOffset(line);
int relativeIndent = 0;
int sline = line + 1;
String commonIndent = getLineIndent(d, line);
int back = -1;
if (d.get(start, c.offset - start).trim().length() == 0) { // we are
// inserting
// lines
// block
// TODO: recalc common indent
// try to detect cutten line
int i;
int depth = 0;
myloop: for (i = 0; i < c.text.length(); i++) {
switch (c.text.charAt(i)) {
case '(':
case '{':
case '[':
depth++;
break;
case ')':
case ']':
case '}':
depth--;
break;
case '\n':
break myloop;
}
}
if (depth == 0 && i != c.text.length() && getRegionType(temp,
c.offset + i) != TclPartitions.TCL_STRING) {
String first = getLineIndent(c.text.substring(0, i));
String second = getLineIndent(temp, line + 1);
temp.replace(start, c.offset - start + first.length(),
second);
} else
temp.replace(start, c.offset - start, "");
back = c.offset - start;
relativeIndent = getPhysicalLength(getLineIndent(temp, line));
sline = line;
}
while (true) {
try {
getDocumentLine(temp, sline);
} catch (BadLocationException e) {
break; // signal of the end of lines
}
String currentIndent = getLineIndent(temp, sline);
int newIndentLen = getPhysicalLength(commonIndent)
+ getPhysicalLength(currentIndent) - relativeIndent;
String newIndent = generateIndent(newIndentLen); // may be do
// here
temp.replace(temp.getLineOffset(sline), currentIndent.length(),
newIndent);
sline++;
}
if (back > 0) {
c.offset = start;
c.text = temp.get(start, temp.getLength() - start);
c.length += back;
} else {
c.text = temp.get(c.offset, temp.getLength() - c.offset);
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
private String generateIndent(int newIndentLen) {
String res = "";
if (!getTabStyle().equals(CodeFormatterConstants.SPACE)) {
int ts = getTabSize();
while (newIndentLen >= ts) {
res += "\t";
newIndentLen -= ts;
}
}
if (getTabStyle().equals(CodeFormatterConstants.TAB)) {
if (newIndentLen > 0)
res += "\t";
} else {
for (int i = 0; i < newIndentLen; i++)
res += " ";
}
return res;
}
private String remakeIndent(String indent) {
int len = getPhysicalLength(indent);
return generateIndent(len);
}
private void smartPaste2(IDocument d, DocumentCommand cmd) {
try {
String content = d.get(0, cmd.offset) + cmd.text;
Document temp = new Document(content);
installStuff(temp);
List<TclBlock> blocks = new ArrayList<>();
int figs = 0; // count of braces
int newOffset = cmd.offset;
int cmdLine = d.getLineOfOffset(cmd.offset);
int cmdLineStart = d.getLineOffset(cmdLine);
int startLine = d.getLineOfOffset(cmd.offset) + 1;
if (d.get(cmdLineStart, cmd.offset - cmdLineStart).trim()
.length() == 0) {
// we are inserting lines block
startLine--;
newOffset = cmdLineStart;
}
int offset = 0;
while (offset < temp.getLength()) {
ITypedRegion region = TextUtilities.getPartition(temp,
fPartitioning, offset, true);
if (region.getType() != IDocument.DEFAULT_CONTENT_TYPE
&& figs == 0) {
offset = region.getOffset() + region.getLength();
continue;
}
char c = temp.getChar(offset);
if (c == '\\') {
offset += 2;
continue;
}
switch (c) {
case ')':
case ']':
case '}':
if (c == '}')
figs--;
if (blocks.size() > 0) {
blocks.remove(blocks.size() - 1);
}
break;
}
int line = temp.getLineOfOffset(offset);
String currentIndent = getLineIndent(temp, line);
// if may start reindenting
if (line >= startLine && offset == temp.getLineOffset(line)
+ currentIndent.length()) {
StringBuffer newIndentBuf = new StringBuffer();
for (TclBlock b : blocks) {
newIndentBuf.append(b.indent);
}
String newIndent = newIndentBuf.toString();
temp.replace(temp.getLineOffset(line),
currentIndent.length(), newIndent);
offset = temp.getLineOffset(line) + newIndent.length();
}
switch (c) {
case '(':
blocks.add(new RoundBracketBlock(offset));
break;
case '[':
blocks.add(new BracketBlock(offset));
break;
case '{':
figs++;
blocks.add(new BraceBlock(offset));
break;
}
offset++;
}
cmd.text = temp.get(newOffset, temp.getLength() - newOffset);
cmd.offset = newOffset;
removeStuff(temp);
} catch (BadLocationException e) {
TclUI.error("Error in TclAutoEditStrategy.smartPaste2", e); //$NON-NLS-1$
}
}
/**
* get partition covering offset
*
* @param d
* @param offset
* @return
* @throws BadLocationException
*/
private String getRegionType(IDocument d, int offset)
throws BadLocationException {
ITypedRegion region = TextUtilities.getPartition(d, fPartitioning,
offset, true);
return region.getType();
}
/*
* @see
* org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(org
* .eclipse.jface.text.IDocument, org.eclipse.jface.text.DocumentCommand)
*/
@Override
public void customizeDocumentCommand(IDocument d, DocumentCommand c) {
if (c.doit == false)
return;
if (c.length == 0 && c.text != null && isLineDelimiter(d, c.text)) {
if (isSmartMode())
smartIndentAfterNewLine(d, c);
else {
super.customizeDocumentCommand(d, c);
return;
}
} else if (c.length <= 1 && c.text.length() == 1) {
switch (c.text.charAt(0)) {
case '}':
case ']':
case ')':
smartIndentAfterClosingBracket(d, c);
break;
// case '\"':
// double quote is handled in TclBracketInserter
case '(':
case '{':
case '[':
smartIndentAfterOpeningBracket(d, c);
break;
case '\t':
boolean jumped = false;
if (preferenceStore
.getBoolean(PreferenceConstants.EDITOR_SMART_TAB)) {
jumped = smartIndentJump(d, c);
}
if (!jumped) { // process tab key using format options
if (getTabStyle().equals(CodeFormatterConstants.SPACE)) {
c.text = "";
int ts = getTabSize();
for (int i = 0; i < ts; i++) {
c.text += " ";
}
}
}
break;
}
} else if (c.text.length() >= 1 && isSmartPasteMode1()) {
smartPasteSimple(d, c); //
} else if (c.text.length() >= 1 && isSmartPasteMode2()) {
smartPaste2(d, c);
}
}
}