📄 miscactions.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <version value="$version"/>
// </file>
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.TextEditor.Actions
{
public class Tab : AbstractEditAction
{
public static string GetIndentationString(IDocument document)
{
StringBuilder indent = new StringBuilder();
if (document.TextEditorProperties.ConvertTabsToSpaces) {
indent.Append(new String(' ', document.TextEditorProperties.TabIndent));
} else {
indent.Append('\t');
}
return indent.ToString();
}
void InsertTabs(IDocument document, ISelection selection, int y1, int y2)
{
int redocounter = 0;
string indentationString = GetIndentationString(document);
for (int i = y2; i >= y1; --i) {
LineSegment line = document.GetLineSegment(i);
if (i == y2 && i == selection.EndPosition.Y && selection.EndPosition.X == 0) {
continue;
}
// this bit is optional - but useful if you are using block tabbing to sort out
// a source file with a mixture of tabs and spaces
// string newLine = document.GetText(line.Offset,line.Length);
// document.Replace(line.Offset,line.Length,newLine);
// ++redocounter;
document.Insert(line.Offset, indentationString);
++redocounter;
}
if (redocounter > 0) {
document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
}
}
void InsertTabAtCaretPosition(TextArea textArea)
{
switch (textArea.Caret.CaretMode) {
case CaretMode.InsertMode:
textArea.InsertString(GetIndentationString(textArea.Document));
break;
case CaretMode.OverwriteMode:
string indentStr = GetIndentationString(textArea.Document);
textArea.ReplaceChar(indentStr[0]);
if (indentStr.Length > 1) {
textArea.InsertString(indentStr.Substring(1));
}
break;
}
textArea.SetDesiredColumn();
}
/// <remarks>
/// Executes this edit action
/// </remarks>
/// <param name="textArea">The <see cref="ItextArea"/> which is used for callback purposes</param>
public override void Execute(TextArea textArea)
{
if (textArea.Document.ReadOnly) {
return;
}
if (textArea.SelectionManager.HasSomethingSelected) {
foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) {
int startLine = selection.StartPosition.Y;
int endLine = selection.EndPosition.Y;
if (startLine != endLine) {
textArea.BeginUpdate();
InsertTabs(textArea.Document, selection, startLine, endLine);
textArea.Document.UpdateQueue.Clear();
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, startLine, endLine));
textArea.EndUpdate();
} else {
InsertTabAtCaretPosition(textArea);
break;
}
}
textArea.Document.CommitUpdate();
textArea.AutoClearSelection = false;
} else {
InsertTabAtCaretPosition(textArea);
}
}
}
public class ShiftTab : AbstractEditAction
{
void RemoveTabs(IDocument document, ISelection selection, int y1, int y2)
{
int redocounter = 0;
for (int i = y2; i >= y1; --i) {
LineSegment line = document.GetLineSegment(i);
if (i == y2 && line.Offset == selection.EndOffset) {
continue;
}
if (line.Length > 0) {
/**** TextPad Strategy:
/// first convert leading whitespace to tabs (controversial! - not all editors work like this)
string newLine = TextUtilities.LeadingWhiteSpaceToTabs(document.GetText(line.Offset,line.Length),document.Properties.GetProperty("TabIndent", 4));
if(newLine.Length > 0 && newLine[0] == '\t') {
document.Replace(line.Offset,line.Length,newLine.Substring(1));
++redocounter;
}
else if(newLine.Length > 0 && newLine[0] == ' ') {
/// there were just some leading spaces but less than TabIndent of them
int leadingSpaces = 1;
for(leadingSpaces = 1; leadingSpaces < newLine.Length && newLine[leadingSpaces] == ' '; leadingSpaces++) {
/// deliberately empty
}
document.Replace(line.Offset,line.Length,newLine.Substring(leadingSpaces));
++redocounter;
}
/// else
/// there were no leading tabs or spaces on this line so do nothing
/// MS Visual Studio 6 strategy:
****/
// string temp = document.GetText(line.Offset,line.Length);
if (line.Length > 0) {
int charactersToRemove = 0;
if(document.GetCharAt(line.Offset) == '\t') { // first character is a tab - just remove it
charactersToRemove = 1;
} else if(document.GetCharAt(line.Offset) == ' ') {
int leadingSpaces = 1;
int tabIndent = document.TextEditorProperties.TabIndent;
for (leadingSpaces = 1; leadingSpaces < line.Length && document.GetCharAt(line.Offset + leadingSpaces) == ' '; leadingSpaces++) {
// deliberately empty
}
if(leadingSpaces >= tabIndent) {
// just remove tabIndent
charactersToRemove = tabIndent;
}
else if(line.Length > leadingSpaces && document.GetCharAt(line.Offset + leadingSpaces) == '\t') {
// remove the leading spaces and the following tab as they add up
// to just one tab stop
charactersToRemove = leadingSpaces+1;
}
else {
// just remove the leading spaces
charactersToRemove = leadingSpaces;
}
}
if (charactersToRemove > 0) {
document.Remove(line.Offset,charactersToRemove);
++redocounter;
}
}
}
}
if (redocounter > 0) {
document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
}
}
/// <remarks>
/// Executes this edit action
/// </remarks>
/// <param name="textArea">The <see cref="ItextArea"/> which is used for callback purposes</param>
public override void Execute(TextArea textArea)
{
if (textArea.SelectionManager.HasSomethingSelected) {
foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) {
int startLine = selection.StartPosition.Y;
int endLine = selection.EndPosition.Y;
textArea.BeginUpdate();
RemoveTabs(textArea.Document, selection, startLine, endLine);
textArea.Document.UpdateQueue.Clear();
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, startLine, endLine));
textArea.EndUpdate();
}
textArea.AutoClearSelection = false;
} else {
// Pressing Shift-Tab with nothing selected the cursor will move back to the
// previous tab stop. It will stop at the beginning of the line. Also, the desired
// column is updated to that column.
LineSegment line = textArea.Document.GetLineSegmentForOffset(textArea.Caret.Offset);
string startOfLine = textArea.Document.GetText(line.Offset,textArea.Caret.Offset - line.Offset);
int tabIndent = textArea.Document.TextEditorProperties.TabIndent;
int currentColumn = textArea.Caret.Column;
int remainder = currentColumn % tabIndent;
if (remainder == 0) {
textArea.Caret.DesiredColumn = Math.Max(0, currentColumn - tabIndent);
} else {
textArea.Caret.DesiredColumn = Math.Max(0, currentColumn - remainder);
}
textArea.SetCaretToDesiredColumn(textArea.Caret.Line);
}
}
}
public class ToggleComment : AbstractEditAction
{
int firstLine;
int lastLine;
void RemoveCommentAt(IDocument document, string comment, ISelection selection, int y1, int y2)
{
int redocounter = 0;
firstLine = y1;
lastLine = y2;
for (int i = y2; i >= y1; --i) {
LineSegment line = document.GetLineSegment(i);
if (selection != null && i == y2 && line.Offset == selection.Offset + selection.Length) {
--lastLine;
continue;
}
string lineText = document.GetText(line.Offset, line.Length);
if (lineText.Trim().StartsWith(comment)) {
document.Remove(line.Offset + lineText.IndexOf(comment), comment.Length);
++redocounter;
}
}
if (redocounter > 0) {
document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
}
}
void SetCommentAt(IDocument document, string comment, ISelection selection, int y1, int y2)
{
int redocounter = 0;
firstLine = y1;
lastLine = y2;
for (int i = y2; i >= y1; --i) {
LineSegment line = document.GetLineSegment(i);
if (selection != null && i == y2 && line.Offset == selection.Offset + selection.Length) {
--lastLine;
continue;
}
string lineText = document.GetText(line.Offset, line.Length);
document.Insert(line.Offset, comment);
++redocounter;
}
if (redocounter > 0) {
document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
}
}
bool ShouldComment(IDocument document, string comment, ISelection selection, int startLine, int endLine)
{
for (int i = endLine; i >= startLine; --i) {
LineSegment line = document.GetLineSegment(i);
if (selection != null && i == endLine && line.Offset == selection.Offset + selection.Length) {
--lastLine;
continue;
}
string lineText = document.GetText(line.Offset, line.Length);
if (!lineText.Trim().StartsWith(comment)) {
return true;
}
}
return false;
}
/// <remarks>
/// Executes this edit action
/// </remarks>
/// <param name="textArea">The <see cref="ItextArea"/> which is used for callback purposes</param>
public override void Execute(TextArea textArea)
{
if (textArea.Document.ReadOnly) {
return;
}
string comment = null;
if (textArea.Document.HighlightingStrategy.Properties["LineComment"] != null) {
comment = textArea.Document.HighlightingStrategy.Properties["LineComment"].ToString();
}
if (comment == null || comment.Length == 0) {
return;
}
if (textArea.SelectionManager.HasSomethingSelected) {
bool shouldComment = true;
foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) {
if (!ShouldComment(textArea.Document, comment, selection, selection.StartPosition.Y, selection.EndPosition.Y)) {
shouldComment = false;
break;
}
}
foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) {
textArea.BeginUpdate();
if (shouldComment) {
SetCommentAt(textArea.Document, comment, selection, selection.StartPosition.Y, selection.EndPosition.Y);
} else {
RemoveCommentAt(textArea.Document, comment, selection, selection.StartPosition.Y, selection.EndPosition.Y);
}
textArea.Document.UpdateQueue.Clear();
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, firstLine, lastLine));
textArea.EndUpdate();
}
textArea.Document.CommitUpdate();
textArea.AutoClearSelection = false;
} else {
textArea.BeginUpdate();
int caretLine = textArea.Caret.Line;
if (ShouldComment(textArea.Document, comment, null, caretLine, caretLine)) {
SetCommentAt(textArea.Document, comment, null, caretLine, caretLine);
} else {
RemoveCommentAt(textArea.Document, comment, null, caretLine, caretLine);
}
textArea.Document.UpdateQueue.Clear();
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, caretLine));
textArea.EndUpdate();
}
}
}
public class IndentSelection : AbstractEditAction
{
/// <remarks>
/// Executes this edit action
/// </remarks>
/// <param name="textArea">The <see cref="ItextArea"/> which is used for callback purposes</param>
public override void Execute(TextArea textArea)
{
if (textArea.Document.ReadOnly) {
return;
}
textArea.BeginUpdate();
if (textArea.SelectionManager.HasSomethingSelected) {
foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) {
textArea.Document.FormattingStrategy.IndentLines(textArea, selection.StartPosition.Y, selection.EndPosition.Y);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -