@@ -29,35 +29,53 @@ extension TextView {
2929
3030 override public func selectWord( _ sender: Any ? ) {
3131 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)
5636 }
57- return NSRange ( start: start, end: end)
58- }
5937 selectionManager. setSelectedRanges ( newSelections)
6038 unmarkTextIfNeeded ( )
6139 needsDisplay = true
6240 }
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+ }
6381}
0 commit comments