@@ -29,35 +29,53 @@ extension TextView {
29
29
30
30
override public func selectWord( _ sender: Any ? ) {
31
31
let newSelections = selectionManager. textSelections. compactMap { ( textSelection) -> NSRange ? in
32
- guard textSelection. range. isEmpty,
33
- let char = textStorage. substring (
34
- from: NSRange ( location: textSelection. range. location, length: 1 )
35
- ) ? . first else {
36
- return nil
37
- }
38
- let charSet = CharacterSet ( charactersIn: String ( char) )
39
- let characterSet : CharacterSet
40
- if CharacterSet . codeIdentifierCharacters. isSuperset ( of: charSet) {
41
- characterSet = . codeIdentifierCharacters
42
- } else if CharacterSet . whitespaces. isSuperset ( of: charSet) {
43
- characterSet = . whitespaces
44
- } else if CharacterSet . newlines. isSuperset ( of: charSet) {
45
- characterSet = . newlines
46
- } else if CharacterSet . punctuationCharacters. isSuperset ( of: charSet) {
47
- characterSet = . punctuationCharacters
48
- } else {
49
- return nil
50
- }
51
- guard let start = textStorage
52
- . findPrecedingOccurrenceOfCharacter ( in: characterSet. inverted, from: textSelection. range. location) ,
53
- let end = textStorage
54
- . findNextOccurrenceOfCharacter ( in: characterSet. inverted, from: textSelection. range. max) else {
55
- return nil
32
+ guard textSelection. range. isEmpty else {
33
+ return nil
34
+ }
35
+ return findWordBoundary ( at: textSelection. range. location)
56
36
}
57
- return NSRange ( start: start, end: end)
58
- }
59
37
selectionManager. setSelectedRanges ( newSelections)
60
38
unmarkTextIfNeeded ( )
61
39
needsDisplay = true
62
40
}
41
+
42
+ /// Given a position, find the range of the word that exists at that position.
43
+ internal func findWordBoundary( at position: Int ) -> NSRange {
44
+ guard position >= 0 && position < textStorage. length,
45
+ let char = textStorage. substring (
46
+ from: NSRange ( location: position, length: 1 )
47
+ ) ? . first else {
48
+ return NSRange ( location: position, length: 0 )
49
+ }
50
+
51
+ let charSet = CharacterSet ( charactersIn: String ( char) )
52
+ let characterSet : CharacterSet
53
+
54
+ if CharacterSet . codeIdentifierCharacters. isSuperset ( of: charSet) {
55
+ characterSet = . codeIdentifierCharacters
56
+ } else if CharacterSet . whitespaces. isSuperset ( of: charSet) {
57
+ characterSet = . whitespaces
58
+ } else if CharacterSet . newlines. isSuperset ( of: charSet) {
59
+ characterSet = . newlines
60
+ } else if CharacterSet . punctuationCharacters. isSuperset ( of: charSet) {
61
+ characterSet = . punctuationCharacters
62
+ } else {
63
+ return NSRange ( location: position, length: 0 )
64
+ }
65
+
66
+ guard let start = textStorage. findPrecedingOccurrenceOfCharacter ( in: characterSet. inverted, from: position) ,
67
+ let end = textStorage. findNextOccurrenceOfCharacter ( in: characterSet. inverted, from: position) else {
68
+ return NSRange ( location: position, length: 0 )
69
+ }
70
+
71
+ return NSRange ( start: start, end: end)
72
+ }
73
+
74
+ /// Given a position, find the range of the entire line that exists at that position.
75
+ internal func findLineBoundary( at position: Int ) -> NSRange {
76
+ guard let linePosition = layoutManager. textLineForOffset ( position) else {
77
+ return NSRange ( location: position, length: 0 )
78
+ }
79
+ return linePosition. range
80
+ }
63
81
}
0 commit comments