Browse Source

Extend selection - moved to separate file.

pull/15/head
mkonicek 15 years ago
parent
commit
bb888bf171
  1. 1
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  2. 74
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  3. 96
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ExtendSelection.cs

1
src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj

@ -94,6 +94,7 @@ @@ -94,6 +94,7 @@
<Compile Include="Src\CodeEditorView.cs" />
<Compile Include="Src\ContextActionsRenderer.cs" />
<Compile Include="Src\ExpressionHighlightRenderer.cs" />
<Compile Include="Src\ExtendSelection.cs" />
<Compile Include="Src\NewLineConsistencyCheck.cs" />
<Compile Include="Src\SharpDevelopTextEditor.cs" />
<Compile Include="Src\Commands\FoldingCommands.cs" />

74
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -393,80 +393,8 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -393,80 +393,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
base.OnKeyUp(e);
if (e.Handled) return;
if (e.Key == Key.W && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) {
// Select AST Node
var editorLang = EditorContext.GetEditorLanguage(this.Adapter);
if (editorLang == null) return;
var parser = ParserFactory.CreateParser(editorLang.Value, new StringReader(this.Text));
parser.ParseMethodBodies = true;
parser.Lexer.SkipAllComments = false; // f
parser.Parse();
var parsedCU = parser.CompilationUnit;
if (parsedCU == null) return;
//var caretLocation = new Location(this.Adapter.Caret.Column, this.Adapter.Caret.Line);
var selectionStart = this.Adapter.Document.OffsetToPosition(this.SelectionStart);
var selectionEnd = this.Adapter.Document.OffsetToPosition(this.SelectionStart + this.SelectionLength);
foreach (var node in parsedCU.Children) {
// fix StartLocation / EndLocation
node.AcceptVisitor(new ICSharpCode.NRefactory.Visitors.SetRegionInclusionVisitor(), null);
}
Ast.INode currentNode = parsedCU.Children.Select(
n => EditorContext.FindInnermostNodeContainingSelection(n, selectionStart, selectionEnd)).Where(n => n != null).FirstOrDefault();
if (currentNode == null) return;
// whole node already selected -> expand selection
if (currentNode.StartLocation == selectionStart && currentNode.EndLocation == selectionEnd) {
var commentsBlankLines = parser.Lexer.SpecialTracker.CurrentSpecials;
// if there is a comment block immediately before selection, or behind selection on the same line, add it to selection
var comments = commentsBlankLines.Where(s => s is Comment).Cast<Comment>().ToList();
int commentIndex = comments.FindIndex(c => c.EndPosition.Line == currentNode.StartLocation.Line);
if (commentIndex >= 0 && IsWhitespaceBetween(this.Adapter.Document, comments[commentIndex].EndPosition, selectionStart)) {
while (commentIndex >= 0 && comments[commentIndex].EndPosition.Line == selectionStart.Line)
{
var comment = comments[commentIndex];
selectionStart = comment.StartPosition;
if (comment.CommentStartsLine)
selectionStart.Column = 1;
commentIndex--;
}
}
else {
// if the extended selection would contain blank lines, extend the selection only to the blank lines/comments on both sides (use siblings)
// if the selection contains blank lines or comments on both sides, dont do this
var parent = currentNode.Parent;
// it can happen that parent region exactly matches child region - in this case we need to advance even to the next parent
// bc otherwise the selection would never move
while (parent != null && parent.StartLocation == selectionStart && parent.EndLocation == selectionEnd) {
parent = parent.Parent;
}
if (parent == null)
return;
selectionStart = parent.StartLocation;
selectionEnd = parent.EndLocation;
ExtendSelection.Run(this.Adapter);
}
} else {
// select current node
selectionStart = currentNode.StartLocation;
selectionEnd = currentNode.EndLocation;
}
int startOffset, endOffset;
try {
startOffset = this.Adapter.Document.PositionToOffset(selectionStart);
endOffset = this.Adapter.Document.PositionToOffset(selectionEnd);
} catch(ArgumentOutOfRangeException) {
return;
}
this.Select(startOffset, endOffset - startOffset);
}
}
bool IsWhitespaceBetween(IDocument document, Location startPos, Location endPos)
{
int startOffset = document.PositionToOffset(startPos);
int endOffset = document.PositionToOffset(endPos);
return string.IsNullOrWhiteSpace(document.GetText(startOffset, endOffset - startOffset));
}
#endregion

96
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ExtendSelection.cs

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using System.Linq;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
using Ast = ICSharpCode.NRefactory.Ast;
namespace ICSharpCode.AvalonEdit.AddIn
{
/// <summary>
/// Description of ExtendSelection.
/// </summary>
public class ExtendSelection
{
public static void Run(ITextEditor editor)
{
var editorLang = EditorContext.GetEditorLanguage(editor);
if (editorLang == null) return;
var parser = ParserFactory.CreateParser(editorLang.Value, editor.Document.CreateReader());
if (parser == null) return;
parser.ParseMethodBodies = true;
parser.Lexer.SkipAllComments = false;
parser.Parse();
var parsedCU = parser.CompilationUnit;
if (parsedCU == null) return;
var selectionStart = editor.Document.OffsetToPosition(editor.SelectionStart);
var selectionEnd = editor.Document.OffsetToPosition(editor.SelectionStart + editor.SelectionLength);
foreach (var node in parsedCU.Children) {
// fix StartLocation / EndLocation
node.AcceptVisitor(new ICSharpCode.NRefactory.Visitors.SetRegionInclusionVisitor(), null);
}
Ast.INode currentNode = parsedCU.Children.Select(
n => EditorContext.FindInnermostNodeContainingSelection(n, selectionStart, selectionEnd)).Where(n => n != null).FirstOrDefault();
if (currentNode == null) return;
// whole node already selected -> expand selection
if (currentNode.StartLocation == selectionStart && currentNode.EndLocation == selectionEnd) {
var commentsBlankLines = parser.Lexer.SpecialTracker.CurrentSpecials;
// if there is a comment block immediately before selection, or behind selection on the same line, add it to selection
var comments = commentsBlankLines.Where(s => s is Comment).Cast<Comment>().ToList();
int commentIndex = comments.FindIndex(c => c.EndPosition.Line == currentNode.StartLocation.Line);
if (commentIndex >= 0 && IsWhitespaceBetween(editor.Document, comments[commentIndex].EndPosition, selectionStart)) {
while (commentIndex >= 0 && comments[commentIndex].EndPosition.Line == selectionStart.Line)
{
var comment = comments[commentIndex];
selectionStart = comment.StartPosition;
if (comment.CommentStartsLine)
selectionStart.Column = 1;
commentIndex--;
}
}
else {
// if the extended selection would contain blank lines, extend the selection only to the blank lines/comments on both sides (use siblings)
// if the selection contains blank lines or comments on both sides, dont do this
var parent = currentNode.Parent;
// it can happen that parent region exactly matches child region - in this case we need to advance even to the next parent
// bc otherwise the selection would never move
while (parent != null && parent.StartLocation == selectionStart && parent.EndLocation == selectionEnd) {
parent = parent.Parent;
}
if (parent == null)
return;
selectionStart = parent.StartLocation;
selectionEnd = parent.EndLocation;
}
} else {
// select current node
selectionStart = currentNode.StartLocation;
selectionEnd = currentNode.EndLocation;
}
int startOffset, endOffset;
try {
startOffset = editor.Document.PositionToOffset(selectionStart);
endOffset = editor.Document.PositionToOffset(selectionEnd);
} catch(ArgumentOutOfRangeException) {
return;
}
editor.Select(startOffset, endOffset - startOffset);
}
static bool IsWhitespaceBetween(IDocument document, Location startPos, Location endPos)
{
int startOffset = document.PositionToOffset(startPos);
int endOffset = document.PositionToOffset(endPos);
return string.IsNullOrWhiteSpace(document.GetText(startOffset, endOffset - startOffset));
}
}
}
Loading…
Cancel
Save