Code Coverage Statistics for Source File
C:\Users\Marcus\Documents\MyCode\2007\SharpSelectWord\SharpSelectWord\Src\SingleWordSelection.cs
|
Sequence Point Coverage
100,0%
96 of 96
|
Branch Coverage
N/A
0 of 0
|
Lines
252
|
Highlight:
Uncovered Code
Covered Code
| L | V | Source |
|---|---|---|
1 |
// SharpSelectWord is a addin to SharpDevelop that can select text. |
|
2 |
// Copyright (C) 2007 Marcus Holmgren |
|
3 |
// |
|
4 |
// This library is free software; you can redistribute it and/or |
|
5 |
// modify it under the terms of the GNU Lesser General Public |
|
6 |
// License as published by the Free Software Foundation; either |
|
7 |
// version 2.1 of the License, or (at your option) any later version. |
|
8 |
// |
|
9 |
// This library is distributed in the hope that it will be useful, |
|
10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 |
// Lesser General Public License for more details. |
|
13 |
// |
|
14 |
// You should have received a copy of the GNU Lesser General Public |
|
15 |
// License along with this library; if not, write to the Free Software |
|
16 |
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 |
||
18 |
||
19 |
using System; |
|
20 |
using ICSharpCode.TextEditor; |
|
21 |
using ICSharpCode.TextEditor.Document; |
|
22 |
||
23 |
namespace MarcusHolmgren.SharpDevelop.SelectWord |
|
24 |
{ |
|
25 |
/// <summary> |
|
26 |
/// Purpose of the SingleWordSelection class is to select the first word positioned closest to the current cursor position. |
|
27 |
/// </summary> |
|
28 |
public sealed class SingleWordSelection : ISelection |
|
29 |
{ |
|
30 |
private readonly IDocument itsDocument; |
|
31 |
private TextLocation itsStartPosition; |
|
32 |
private TextLocation itsEndPosition; |
|
33 |
private int itsOffset; |
|
34 |
private int itsEndOffset; |
|
35 |
private string itsSelectedText; |
|
36 |
||
37 |
/// <summary> |
|
38 |
/// Initialize a new instance of the SingleWordSelection class. |
|
39 |
/// </summary> |
|
40 |
/// <param name="document">IDocument object.</param> |
|
41 |
/// <param name="offset">Current position for the cursor.</param> |
|
42 |
/// <exception cref="ArgumentNullException">If parameter document is not provided an ArgumentNullException is throw.</exception> |
|
43 |
28 |
public SingleWordSelection(IDocument document, int offset) |
44 |
{ |
|
45 |
28 |
if (document == null) |
46 |
1 |
throw new ArgumentNullException("document"); |
47 |
||
48 |
27 |
itsDocument = document; |
49 |
||
50 |
27 |
if (offset < 0) itsOffset = 0; |
51 |
23 |
else if (offset >= document.TextLength) itsOffset = document.TextLength - 1; |
52 |
17 |
else itsOffset = offset; |
53 |
||
54 |
27 |
itsEndOffset = itsOffset; |
55 |
||
56 |
27 |
FindSelection(); |
57 |
} |
|
58 |
||
59 |
||
60 |
public bool ContainsOffset(int offset) |
|
61 |
{ |
|
62 |
14 |
return itsOffset != offset; |
63 |
14 |
} |
64 |
||
65 |
public TextLocation StartPosition |
|
66 |
{ |
|
67 |
48 |
get { return itsStartPosition; } |
68 |
23 |
set { itsStartPosition = value; } |
69 |
} |
|
70 |
||
71 |
public TextLocation EndPosition |
|
72 |
{ |
|
73 |
44 |
get { return itsEndPosition; } |
74 |
23 |
set { itsEndPosition = value; } |
75 |
} |
|
76 |
||
77 |
public int Offset |
|
78 |
{ |
|
79 |
135 |
get { return itsOffset; } |
80 |
} |
|
81 |
||
82 |
public int EndOffset |
|
83 |
{ |
|
84 |
49 |
get { return itsEndOffset; } |
85 |
} |
|
86 |
||
87 |
public int Length |
|
88 |
{ |
|
89 |
13 |
get { return IsEmpty ? 0 : SelectedText.Length; } |
90 |
} |
|
91 |
||
92 |
public bool IsRectangularSelection |
|
93 |
{ |
|
94 |
13 |
get { return false; } |
95 |
} |
|
96 |
||
97 |
public bool IsEmpty |
|
98 |
{ |
|
99 |
27 |
get { return string.IsNullOrEmpty(itsSelectedText) ? true : false; } |
100 |
} |
|
101 |
||
102 |
public string SelectedText |
|
103 |
{ |
|
104 |
39 |
get{ return itsSelectedText; } |
105 |
} |
|
106 |
||
107 |
||
108 |
public bool ContainsPosition(TextLocation position) |
|
109 |
{ |
|
110 |
13 |
System.Diagnostics.Debug.WriteLine("ContainsPosition"); |
111 |
//if (itsStartPosition.Line == position.Line) |
|
112 |
||
113 |
13 |
return false; |
114 |
13 |
} |
115 |
||
116 |
/// <summary> |
|
117 |
/// Navigates the current offset and locates the closest word. |
|
118 |
/// </summary> |
|
119 |
private void FindSelection() |
|
120 |
{ |
|
121 |
27 |
if (itsDocument.TextLength > 0) |
122 |
{ |
|
123 |
23 |
if (NotPositionedAtSingleCharacter()) |
124 |
{ |
|
125 |
21 |
SetStartingLocation(); |
126 |
21 |
SetStartOffset(); |
127 |
21 |
SetEndOffset(); |
128 |
} |
|
129 |
||
130 |
23 |
itsSelectedText = itsDocument.GetText(Offset, EndOffset - Offset); |
131 |
} |
|
132 |
27 |
} |
133 |
||
134 |
/// <summary> |
|
135 |
/// Check if the cursor is positioned inside a single character quote. |
|
136 |
/// </summary> |
|
137 |
/// <returns>True if cursor is positioned at a single character, otherwise false.</returns> |
|
138 |
private bool NotPositionedAtSingleCharacter() |
|
139 |
{ |
|
140 |
const char SingleQuote = '\''; |
|
141 |
23 |
bool isSingleCharacter = false; |
142 |
23 |
if (itsDocument.GetCharAt(Offset) == SingleQuote && (Offset - 2) > 0) |
143 |
{ |
|
144 |
3 |
if (itsDocument.GetCharAt(Offset - 2) == SingleQuote) |
145 |
{ |
|
146 |
1 |
itsOffset--; |
147 |
1 |
isSingleCharacter = true; |
148 |
} |
|
149 |
} |
|
150 |
20 |
else if ((Offset - 1) > 0 && itsDocument.GetCharAt(Offset - 1) == SingleQuote) |
151 |
{ |
|
152 |
1 |
if ((EndOffset + 1) < itsDocument.TextLength && itsDocument.GetCharAt(EndOffset + 1) == SingleQuote) |
153 |
{ |
|
154 |
1 |
itsEndOffset++; |
155 |
1 |
isSingleCharacter = true; |
156 |
} |
|
157 |
} |
|
158 |
||
159 |
23 |
if (isSingleCharacter) |
160 |
{ |
|
161 |
2 |
StartPosition = itsDocument.OffsetToPosition(Offset); |
162 |
2 |
EndPosition = itsDocument.OffsetToPosition(EndOffset); |
163 |
} |
|
164 |
||
165 |
23 |
return !isSingleCharacter; |
166 |
23 |
} |
167 |
||
168 |
/// <summary> |
|
169 |
/// Reposition starting offset if the cursor is positioned at the end of a word. |
|
170 |
/// </summary> |
|
171 |
private void SetStartingLocation() |
|
172 |
{ |
|
173 |
21 |
char firstChar = itsDocument.GetCharAt(itsOffset); |
174 |
21 |
if (firstChar == ' ' || firstChar == '.' || firstChar == '(') |
175 |
{ |
|
176 |
5 |
char secondChar = itsDocument.GetCharAt(itsOffset - 1); |
177 |
5 |
if (itsOffset > 0 && secondChar != ' ' || secondChar != '.' || secondChar != '(') |
178 |
5 |
itsOffset--; |
179 |
} |
|
180 |
21 |
} |
181 |
||
182 |
/// <summary> |
|
183 |
/// Navigate the document from the current cursor position and locates the ending position of the word. |
|
184 |
/// </summary> |
|
185 |
private void SetEndOffset() |
|
186 |
{ |
|
187 |
21 |
int temp = itsOffset; |
188 |
||
189 |
bool ok; |
|
190 |
do |
|
191 |
{ |
|
192 |
136 |
char c = itsDocument.GetCharAt(temp); |
193 |
136 |
ok = ValidCharacter(c); |
194 |
||
195 |
136 |
if (ok && temp < itsDocument.TextLength - 1) |
196 |
115 |
temp++; |
197 |
21 |
else ok = false; |
198 |
} |
|
199 |
136 |
while (ok); |
200 |
||
201 |
21 |
itsEndOffset = temp; |
202 |
21 |
EndPosition = itsDocument.OffsetToPosition(temp); |
203 |
21 |
} |
204 |
||
205 |
/// <summary> |
|
206 |
/// Navigate the document from the current cursor position and locates the starting position of the word. |
|
207 |
/// </summary> |
|
208 |
private void SetStartOffset() |
|
209 |
{ |
|
210 |
21 |
int temp = itsOffset; |
211 |
||
212 |
21 |
if (itsDocument.GetCharAt(temp) == '\"') temp--; |
213 |
||
214 |
bool ok; |
|
215 |
do |
|
216 |
{ |
|
217 |
80 |
char c = itsDocument.GetCharAt(temp); |
218 |
80 |
ok = ValidCharacter(c); |
219 |
||
220 |
80 |
if (ok && temp > 0) temp--; |
221 |
else |
|
222 |
{ |
|
223 |
21 |
if (!ok && temp > -1 && temp < itsDocument.TextLength - 1) |
224 |
17 |
temp++; |
225 |
21 |
ok = false; |
226 |
} |
|
227 |
} |
|
228 |
80 |
while (ok); |
229 |
||
230 |
21 |
itsOffset = temp; |
231 |
21 |
StartPosition = itsDocument.OffsetToPosition(temp); |
232 |
21 |
} |
233 |
||
234 |
/// <summary> |
|
235 |
/// Validates a character. |
|
236 |
/// </summary> |
|
237 |
/// <param name="input">Character to validate.</param> |
|
238 |
/// <returns>True if the input character is valid, otherwise false.</returns> |
|
239 |
private static bool ValidCharacter(char input) |
|
240 |
{ |
|
241 |
216 |
bool result = true; |
242 |
216 |
char[] invalidChars = new char[] { ' ', '\n', '\r', '\t', '(', ')', '{', '}', '[', ']', '<', '>', '"', '.', ',', ';', ':' }; |
243 |
||
244 |
3888 |
foreach (char c in invalidChars) |
245 |
{ |
|
246 |
3672 |
if (input == c) |
247 |
38 |
result = false; |
248 |
} |
|
249 |
216 |
return result; |
250 |
} |
|
251 |
} |
|
252 |
} |