⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vbformattingstrategy.cs

📁 全功能c#编译器
💻 CS
📖 第 1 页 / 共 2 页
字号:
// <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 + -