📄 vbformattingstrategy.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Markus Palme" email="MarkusPalme@gmx.de"/>
// <version value="$version"/>
// </file>
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using ICSharpCode.TextEditor.Document;
using ICSharpCode.TextEditor.Actions;
using ICSharpCode.TextEditor;
using ICSharpCode.Core.Properties;
using ICSharpCode.Core.Services;
namespace VBBinding.FormattingStrategy
{
/// <summary>
/// This class handles the auto and smart indenting in the textbuffer while
/// you type.
/// </summary>
public class VBFormattingStrategy : DefaultFormattingStrategy
{
ArrayList statements;
StringCollection keywords;
bool doCasing;
bool doInsertion;
public VBFormattingStrategy()
{
statements = new ArrayList();
statements.Add(new VBStatement("^if.*?then$", "^end ?if$", "End If", 1));
statements.Add(new VBStatement("\\bclass \\w+$", "^end class$", "End Class", 1));
statements.Add(new VBStatement("\\bnamespace \\w+$", "^end namespace$", "End Namespace", 1));
statements.Add(new VBStatement("\\bmodule \\w+$", "^end module$", "End Module", 1));
statements.Add(new VBStatement("\\bstructure \\w+$", "^end structure$", "End Structure", 1));
statements.Add(new VBStatement("^while ", "^end while$", "End While", 1));
statements.Add(new VBStatement("^select case", "^end select$", "End Select", 2));
statements.Add(new VBStatement("(?<!\\bmustoverride )\\bsub \\w+", "^end sub$", "End Sub", 1));
statements.Add(new VBStatement("(?<!\\bmustoverride (readonly |writeonly )?)\\bproperty \\w+", "^end property$", "End Property", 1));
statements.Add(new VBStatement("(?<!\\bmustoverride )\\bfunction \\w+", "^end function$", "End Function", 1));
statements.Add(new VBStatement("\\bfor .*?$", "^next( \\w+)?$", "Next", 1));
statements.Add(new VBStatement("^synclock .*?$", "^end synclock$", "End SyncLock", 1));
statements.Add(new VBStatement("^get$", "^end get$", "End Get", 1));
statements.Add(new VBStatement("^with \\w+$", "^end with$", "End With", 1));
statements.Add(new VBStatement("^set\\s*\\(.*?\\)$", "^end set$", "End Set", 1));
statements.Add(new VBStatement("^try$", "^end try$", "End Try", 1));
statements.Add(new VBStatement("^do .+?$", "^loop$", "Loop", 1));
statements.Add(new VBStatement("^do$", "^loop .+?$", "Loop While ", 1));
statements.Add(new VBStatement("\\benum .*?$", "^end enum$", "End Enum", 1));
keywords = new StringCollection();
keywords.AddRange(new string[] {
"AddHandler", "AddressOf", "Alias", "And", "AndAlso", "Ansi", "As", "Assembly",
"Auto", "Boolean", "ByRef", "Byte", "ByVal", "Call", "Case", "Catch",
"CBool", "CByte", "CChar", "CDate", "CDec", "CDbl", "Char", "CInt", "Class",
"CLng", "CObj", "Const", "CShort", "CSng", "CStr", "CType",
"Date", "Decimal", "Declare", "Default", "Delegate", "Dim", "DirectCast", "Do",
"Double", "Each", "Else", "ElseIf", "End", "Enum", "Erase", "Error",
"Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get",
"GetType", "GoSub", "GoTo", "Handles", "If", "Implements", "Imports", "In",
"Inherits", "Integer", "Interface", "Is", "Let", "Lib", "Like", "Long",
"Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass",
"Namespace", "New", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable", "Object",
"On", "Option", "Optional", "Or", "OrElse", "Overloads", "Overridable", "Overrides",
"ParamArray", "Preserve", "Private", "Property", "Protected", "Public", "RaiseEvent", "ReadOnly",
"ReDim", "Region", "REM", "RemoveHandler", "Resume", "Return", "Select", "Set", "Shadows",
"Shared", "Short", "Single", "Static", "Step", "Stop", "String", "Structure",
"Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TypeOf",
"Unicode", "Until", "Variant", "When", "While", "With", "WithEvents", "WriteOnly", "Xor"
});
}
/// <summary>
/// Define VB.net specific smart indenting for a line :)
/// </summary>
protected override int SmartIndentLine(TextArea textArea, int lineNr)
{
PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
doCasing = propertyService.GetProperty("VBBinding.TextEditor.EnableCasing", true);
IDocument document = textArea.Document;
if (lineNr <= 0)
return AutoIndentLine(textArea, lineNr);
LineSegment lineAbove = document.GetLineSegment(lineNr - 1);
string lineAboveText = document.GetText(lineAbove.Offset, lineAbove.Length).Trim();
LineSegment curLine = document.GetLineSegment(lineNr);
string oldLineText = document.GetText(curLine.Offset, curLine.Length);
string curLineText = oldLineText.Trim();
// remove comments
string texttoreplace = Regex.Replace(lineAboveText, "'.*$", "", RegexOptions.Singleline).Trim();
// remove string content
foreach (Match match in Regex.Matches(texttoreplace, "\"[^\"]*?\"")) {
texttoreplace = texttoreplace.Remove(match.Index, match.Length).Insert(match.Index, new String('-', match.Length));
}
string curLineReplace = Regex.Replace(curLineText, "'.*$", "", RegexOptions.Singleline).Trim();
// remove string content
foreach (Match match in Regex.Matches(curLineReplace, "\"[^\"]*?\"")) {
curLineReplace = curLineReplace.Remove(match.Index, match.Length).Insert(match.Index, new String('-', match.Length));
}
StringBuilder b = new StringBuilder(GetIndentation(textArea, lineNr - 1));
string indentString = Tab.GetIndentationString(document);
if (texttoreplace.IndexOf(':') > 0)
texttoreplace = texttoreplace.Substring(0, texttoreplace.IndexOf(':')).TrimEnd();
bool matched = false;
foreach (VBStatement statement in statements) {
if (statement.IndentPlus == 0) continue;
if (Regex.IsMatch(curLineReplace, statement.EndRegex, RegexOptions.IgnoreCase)) {
for (int i = 0; i < statement.IndentPlus; ++i) {
RemoveIndent(b);
}
if (doCasing && !statement.EndStatement.EndsWith(" "))
curLineText = statement.EndStatement;
matched = true;
}
if (Regex.IsMatch(texttoreplace, statement.StartRegex, RegexOptions.IgnoreCase)) {
for (int i = 0; i < statement.IndentPlus; ++i) {
b.Append(indentString);
}
matched = true;
}
if (matched)
break;
}
if (lineNr >= 2) {
if (texttoreplace.EndsWith("_")) {
// Line continuation
char secondLastChar = ' ';
for (int i = texttoreplace.Length - 2; i >= 0; --i) {
secondLastChar = texttoreplace[i];
if (!Char.IsWhiteSpace(secondLastChar))
break;
}
if (secondLastChar != '>') {
// is not end of attribute
LineSegment line2Above = document.GetLineSegment(lineNr - 2);
string lineAboveText2 = document.GetText(line2Above.Offset, line2Above.Length).Trim();
lineAboveText2 = Regex.Replace(lineAboveText2, "'.*$", "", RegexOptions.Singleline).Trim();
if (!lineAboveText2.EndsWith("_")) {
b.Append(indentString);
}
}
} else {
LineSegment line2Above = document.GetLineSegment(lineNr - 2);
string lineAboveText2 = document.GetText(line2Above.Offset, line2Above.Length).Trim();
lineAboveText2 = StripComment(lineAboveText2);
if (lineAboveText2.EndsWith("_")) {
char secondLastChar = ' ';
for (int i = texttoreplace.Length - 2; i >= 0; --i) {
secondLastChar = texttoreplace[i];
if (!Char.IsWhiteSpace(secondLastChar))
break;
}
if (secondLastChar != '>')
RemoveIndent(b);
}
}
}
if (IsElseConstruct(curLineText))
RemoveIndent(b);
if (IsElseConstruct(lineAboveText))
b.Append(indentString);
int indentLength = b.Length;
b.Append(curLineText);
if (b.ToString() != oldLineText)
textArea.Document.Replace(curLine.Offset, curLine.Length, b.ToString());
return indentLength;
}
bool IsElseConstruct(string line)
{
string t = StripComment(line).ToLower();
if (t.StartsWith("case ")) return true;
if (t == "else" || t.StartsWith("elseif ")) return true;
if (t == "catch" || t.StartsWith("catch ")) return true;
if (t == "finally") return true;
return false;
}
string StripComment(string text)
{
return Regex.Replace(text, "'.*$", "", RegexOptions.Singleline).Trim();
}
void RemoveIndent(StringBuilder b)
{
if (b.Length == 0) return;
if (b[b.Length - 1] == '\t') {
b.Remove(b.Length - 1, 1);
} else {
for (int j = 0; j < 4; ++j) {
if (b.Length == 0) return;
if (b[b.Length - 1] != ' ')
break;
b.Remove(b.Length - 1, 1);
}
}
}
public override int FormatLine(TextArea textArea, int lineNr, int cursorOffset, char ch)
{
PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
doCasing = propertyService.GetProperty("VBBinding.TextEditor.EnableCasing", true);
doInsertion = propertyService.GetProperty("VBBinding.TextEditor.EnableEndConstructs", true);
if (lineNr > 0) {
LineSegment curLine = textArea.Document.GetLineSegment(lineNr);
LineSegment lineAbove = lineNr > 0 ? textArea.Document.GetLineSegment(lineNr - 1) : null;
string curLineText = textArea.Document.GetText(curLine.Offset, curLine.Length);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -