?? csharpformattingstrategy.cs
字號:
case '}':
case '{':
return textArea.Document.FormattingStrategy.IndentLine(textArea, lineNr);
case '\n':
if (lineNr <= 0) {
return IndentLine(textArea, lineNr);
}
string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove);
//// curLine might have some text which should be added to indentation
curLineText = "";
if (curLine.Length > 0) {
curLineText = textArea.Document.GetText(curLine);
}
LineSegment nextLine = lineNr + 1 < textArea.Document.TotalNumberOfLines ? textArea.Document.GetLineSegment(lineNr + 1) : null;
string nextLineText = lineNr + 1 < textArea.Document.TotalNumberOfLines ? textArea.Document.GetText(nextLine) : "";
int addCursorOffset = 0;
if (lineAboveText.Trim().StartsWith("#region") && NeedEndregion(textArea.Document)) {
textArea.Document.Insert(curLine.Offset, "#endregion");
return IndentLine(textArea, lineNr) + "#endregion".Length;
}
if (lineAbove.HighlightSpanStack != null && !lineAbove.HighlightSpanStack.IsEmpty) {
if (!lineAbove.HighlightSpanStack.Peek().StopEOL) { // case for /* style comments
int index = lineAboveText.IndexOf("/*");
if (index > 0) {
StringBuilder indentation = new StringBuilder(GetIndentation(textArea, lineNr - 1));
for (int i = indentation.Length; i < index; ++ i) {
indentation.Append(' ');
}
//// adding curline text
textArea.Document.Replace(curLine.Offset, curLine.Length, indentation.ToString() + " * " + curLineText);
return indentation.Length + 3 + curLineText.Length;
}
index = lineAboveText.IndexOf("*");
if (index > 0) {
StringBuilder indentation = new StringBuilder(GetIndentation(textArea, lineNr - 1));
for (int i = indentation.Length; i < index; ++ i) {
indentation.Append(' ');
}
//// adding curline if present
textArea.Document.Replace(curLine.Offset, curLine.Length, indentation.ToString() + "* " + curLineText);
return indentation.Length + 2 + curLineText.Length;
}
} else { // don't handle // lines, because they're only one lined comments
int indexAbove = lineAboveText.IndexOf("///");
int indexNext = nextLineText.IndexOf("///");
if (indexAbove > 0 && (indexNext != -1 || indexAbove + 4 < lineAbove.Length)) {
StringBuilder indentation = new StringBuilder(GetIndentation(textArea, lineNr - 1));
for (int i = indentation.Length; i < indexAbove; ++ i) {
indentation.Append(' ');
}
//// adding curline text if present
textArea.Document.Replace(curLine.Offset, curLine.Length, indentation.ToString() + "/// " + curLineText);
textArea.Document.UndoStack.UndoLast(2);
return indentation.Length + 4 /*+ curLineText.Length*/;
}
if (IsInNonVerbatimString(lineAboveText, curLineText)) {
textArea.Document.Insert(lineAbove.Offset + lineAbove.Length,
"\" +");
curLine = textArea.Document.GetLineSegment(lineNr);
textArea.Document.Insert(curLine.Offset, "\"");
textArea.Document.UndoStack.UndoLast(3);
addCursorOffset = 1;
}
}
}
int result = IndentLine(textArea, lineNr) + addCursorOffset;
if (textArea.TextEditorProperties.AutoInsertCurlyBracket) {
string oldLineText = TextUtilities.GetLineAsString(textArea.Document, lineNr - 1);
if (oldLineText.EndsWith("{")) {
if (NeedCurlyBracket(textArea.Document.TextContent)) {
textArea.Document.Insert(curLine.Offset + curLine.Length, "\n}");
IndentLine(textArea, lineNr + 1);
}
}
}
return result;
}
return 0;
}
/// <summary>
/// Checks if the cursor is inside a non-verbatim string.
/// This method is used to check if a line break was inserted in a string.
/// The text editor has already broken the line for us, so we just need to check
/// the two lines.
/// </summary>
/// <param name="start">The part before the line break</param>
/// <param name="end">The part after the line break</param>
/// <returns>
/// True, when the line break was inside a non-verbatim-string, so when
/// start does not contain a comment, but a non-even number of ", and
/// end contains a non-even number of " before the first comment.
/// </returns>
bool IsInNonVerbatimString(string start, string end)
{
bool inString = false;
bool inChar = false;
for (int i = 0; i < start.Length; ++i) {
char c = start[i];
if (c == '"' && !inChar) {
if (!inString && i > 0 && start[i - 1] == '@')
return false; // no string line break for verbatim strings
inString = !inString;
} else if (c == '\'' && !inString) {
inChar = !inChar;
}
if (!inString && i > 0 && start[i - 1] == '/' && (c == '/' || c == '*'))
return false;
if (inString && start[i] == '\\')
++i;
}
if (!inString) return false;
// we are possibly in a string, or a multiline string has just ended here
// check if the closing double quote is in end
for (int i = 0; i < end.Length; ++i) {
char c = end[i];
if (c == '"' && !inChar) {
if (!inString && i > 0 && end[i - 1] == '@')
break; // no string line break for verbatim strings
inString = !inString;
} else if (c == '\'' && !inString) {
inChar = !inChar;
}
if (!inString && i > 0 && end[i - 1] == '/' && (c == '/' || c == '*'))
break;
if (inString && end[i] == '\\')
++i;
}
// return true if the string was closed properly
return !inString;
}
#endregion
#region SearchBracket helper functions
static int ScanLineStart(IDocument document, int offset)
{
for (int i = offset - 1; i > 0; --i) {
if (document.GetCharAt(i) == '\n')
return i + 1;
}
return 0;
}
/// <summary>
/// Gets the type of code at offset.<br/>
/// 0 = Code,<br/>
/// 1 = Comment,<br/>
/// 2 = String<br/>
/// Block comments and multiline strings are not supported.
/// </summary>
static int GetStartType(IDocument document, int linestart, int offset)
{
bool inString = false;
bool inChar = false;
bool verbatim = false;
for(int i = linestart; i < offset; i++) {
switch (document.GetCharAt(i)) {
case '/':
if (!inString && !inChar && i + 1 < document.TextLength) {
if (document.GetCharAt(i + 1) == '/') {
return 1;
}
}
break;
case '"':
if (!inChar) {
if (inString && verbatim) {
if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') {
++i; // skip escaped quote
inString = false; // let the string go on
} else {
verbatim = false;
}
} else if (!inString && i > 0 && document.GetCharAt(i - 1) == '@') {
verbatim = true;
}
inString = !inString;
}
break;
case '\'':
if (!inString) inChar = !inChar;
break;
case '\\':
if ((inString && !verbatim) || inChar)
++i; // skip next character
break;
}
}
return (inString || inChar) ? 2 : 0;
}
#endregion
#region SearchBracketBackward
public override int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket)
{
if (offset + 1 >= document.TextLength) return -1;
// this method parses a c# document backwards to find the matching bracket
// first try "quick find" - find the matching bracket if there is no string/comment in the way
int quickResult = base.SearchBracketBackward(document, offset, openBracket, closingBracket);
if (quickResult >= 0) return quickResult;
// we need to parse the line from the beginning, so get the line start position
int linestart = ScanLineStart(document, offset + 1);
// we need to know where offset is - in a string/comment or in normal code?
// ignore cases where offset is in a block comment
int starttype = GetStartType(document, linestart, offset + 1);
if (starttype != 0) {
return -1; // start position is in a comment/string
}
// I don't see any possibility to parse a C# document backwards...
// We have to do it forwards and push all bracket positions on a stack.
Stack bracketStack = new Stack();
bool blockComment = false;
bool lineComment = false;
bool inChar = false;
bool inString = false;
bool verbatim = false;
for(int i = 0; i <= offset; ++i) {
char ch = document.GetCharAt(i);
switch (ch) {
case '\r':
case '\n':
lineComment = false;
inChar = false;
if (!verbatim) inString = false;
break;
case '/':
if (blockComment) {
Debug.Assert(i > 0);
if (document.GetCharAt(i - 1) == '*') {
blockComment = false;
}
}
if (!inString && !inChar && i + 1 < document.TextLength) {
if (!blockComment && document.GetCharAt(i + 1) == '/') {
lineComment = true;
}
if (!lineComment && document.GetCharAt(i + 1) == '*') {
blockComment = true;
}
}
break;
case '"':
if (!(inChar || lineComment || blockComment)) {
if (inString && verbatim) {
if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') {
++i; // skip escaped quote
inString = false; // let the string go
} else {
verbatim = false;
}
} else if (!inString && offset > 0 && document.GetCharAt(i - 1) == '@') {
verbatim = true;
}
inString = !inString;
}
break;
case '\'':
if (!(inString || lineComment || blockComment)) {
inChar = !inChar;
}
break;
case '\\':
if ((inString && !verbatim) || inChar)
++i; // skip next character
break;
default :
if (ch == openBracket) {
if (!(inString || inChar || lineComment || blockComment)) {
bracketStack.Push(i);
}
} else if (ch == closingBracket) {
if (!(inString || inChar || lineComment || blockComment)) {
if (bracketStack.Count > 0)
bracketStack.Pop();
}
}
break;
}
}
if (bracketStack.Count > 0) return (int)bracketStack.Pop();
return -1;
}
#endregion
#region SearchBracketForward
public override int SearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket)
{
bool inString = false;
bool inChar = false;
bool verbatim = false;
bool lineComment = false;
bool blockComment = false;
if (offset < 0) return -1;
// first try "quick find" - find the matching bracket if there is no string/comment in the way
int quickResult = base.SearchBracketForward(document, offset, openBracket, closingBracket);
if (quickResult >= 0) return quickResult;
// we need to parse the line from the beginning, so get the line start position
int linestart = ScanLineStart(document, offset);
// we need to know where offset is - in a string/comment or in normal code?
// ignore cases where offset is in a block comment
int starttype = GetStartType(document, linestart, offset);
if (starttype != 0) return -1; // start position is in a comment/string
int brackets = 1;
while (offset < document.TextLength) {
char ch = document.GetCharAt(offset);
switch (ch) {
case '\r':
case '\n':
lineComment = false;
inChar = false;
if (!verbatim) inString = false;
break;
case '/':
if (blockComment) {
Debug.Assert(offset > 0);
if (document.GetCharAt(offset - 1) == '*') {
blockComment = false;
}
}
if (!inString && !inChar && offset + 1 < document.TextLength) {
if (!blockComment && document.GetCharAt(offset + 1) == '/') {
lineComment = true;
}
if (!lineComment && document.GetCharAt(offset + 1) == '*') {
blockComment = true;
}
}
break;
case '"':
if (!(inChar || lineComment || blockComment)) {
if (inString && verbatim) {
if (offset + 1 < document.TextLength && document.GetCharAt(offset + 1) == '"') {
++offset; // skip escaped quote
inString = false; // let the string go
} else {
verbatim = false;
}
} else if (!inString && offset > 0 && document.GetCharAt(offset - 1) == '@') {
verbatim = true;
}
inString = !inString;
}
break;
case '\'':
if (!(inString || lineComment || blockComment)) {
inChar = !inChar;
}
break;
case '\\':
if ((inString && !verbatim) || inChar)
++offset; // skip next character
break;
default :
if (ch == openBracket) {
if (!(inString || inChar || lineComment || blockComment)) {
++brackets;
}
} else if (ch == closingBracket) {
if (!(inString || inChar || lineComment || blockComment)) {
--brackets;
if (brackets == 0) {
return offset;
}
}
}
break;
}
++offset;
}
return -1;
}
#endregion
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -