1
- 'use babel'
2
1
// TODO: docstrings
2
+ // TODO: replace getHeadBufferPosition with getBufferRowRange? - getHeadBufferPosition isn't public API
3
+ // TODO: make sure returned range from getRanges is not undefined
3
4
4
- import { forLines } from './scopes'
5
+ import { forLines } from "./scopes"
6
+ import { TextEditor , Selection } from "atom"
5
7
6
- export function getLine ( ed , l ) {
8
+ interface LineInfo {
9
+ scope : readonly string [ ]
10
+ line : string
11
+ }
12
+
13
+ export function getLine ( editor : TextEditor , l : number ) : LineInfo {
7
14
return {
8
- scope : ed . scopeDescriptorForBufferPosition ( [ l , 0 ] ) . scopes ,
9
- line : ed . getTextInBufferRange ( [ [ l , 0 ] , [ l , Infinity ] ] )
15
+ scope : editor . scopeDescriptorForBufferPosition ( [ l , 0 ] ) . getScopesArray ( ) , // was .scopes
16
+ line : editor . getTextInBufferRange ( [
17
+ [ l , 0 ] ,
18
+ [ l , Infinity ]
19
+ ] )
10
20
}
11
21
}
12
22
13
- function isBlank ( { line, scope} , allowDocstrings = false ) {
23
+ function isBlank ( { line, scope } : LineInfo , allowDocstrings = false ) {
14
24
for ( const s of scope ) {
15
25
if ( / \b c o m m e n t \b / . test ( s ) || ( ! allowDocstrings && / \b d o c s t r i n g \b / . test ( s ) ) ) {
16
26
return true
17
27
}
18
28
}
19
- return / ^ \s * ( # .* ) ? $ / . test ( line ) ;
29
+ return / ^ \s * ( # .* ) ? $ / . test ( line )
20
30
}
21
- function isEnd ( { line, scope } ) {
22
- if ( isStringEnd ( { line, scope } ) ) {
31
+
32
+ function isEnd ( lineInfo : LineInfo ) {
33
+ if ( isStringEnd ( lineInfo ) ) {
23
34
return true
24
35
}
25
- return / ^ ( e n d \b | \) | \] | \} ) / . test ( line ) ;
36
+ return / ^ ( e n d \b | \) | \] | \} ) / . test ( lineInfo . line )
26
37
}
27
- function isStringEnd ( { line , scope } ) {
28
- scope = scope . join ( ' ' )
29
- return / \b s t r i n g \. m u l t i l i n e \. e n d \b / . test ( scope ) ||
30
- ( / \b s t r i n g \. e n d \b / . test ( scope ) && / \b b a c k t i c k \b / . test ( scope ) ) ;
38
+
39
+ function isStringEnd ( lineInfo : LineInfo ) {
40
+ const scope = lineInfo . scope . join ( " " )
41
+ return / \b s t r i n g \. m u l t i l i n e \. e n d \b / . test ( scope ) || ( / \b s t r i n g \. e n d \b / . test ( scope ) && / \b b a c k t i c k \b / . test ( scope ) )
31
42
}
32
- function isCont ( { line, scope } ) {
33
- scope = scope . join ( ' ' )
34
- if ( / \b s t r i n g \b / . test ( scope ) && ! ( / \b p u n c t u a t i o n \. d e f i n i t i o n \. s t r i n g \b / . test ( scope ) ) ) {
43
+
44
+ function isCont ( lineInfo : LineInfo ) {
45
+ const scope = lineInfo . scope . join ( " " )
46
+ if ( / \b s t r i n g \b / . test ( scope ) && ! / \b p u n c t u a t i o n \. d e f i n i t i o n \. s t r i n g \b / . test ( scope ) ) {
35
47
return true
36
48
}
37
49
38
- return line . match ( / ^ ( e l s e | e l s e i f | c a t c h | f i n a l l y ) \b / ) ;
50
+ return lineInfo . line . match ( / ^ ( e l s e | e l s e i f | c a t c h | f i n a l l y ) \b / )
39
51
}
40
- function isStart ( lineInfo ) {
41
- return ! ( / ^ \s / . test ( lineInfo . line ) || isBlank ( lineInfo ) || isEnd ( lineInfo ) || isCont ( lineInfo ) ) ;
52
+
53
+ function isStart ( lineInfo : LineInfo ) {
54
+ return ! ( / ^ \s / . test ( lineInfo . line ) || isBlank ( lineInfo ) || isEnd ( lineInfo ) || isCont ( lineInfo ) )
42
55
}
43
56
44
- function walkBack ( ed , row ) {
45
- while ( ( row > 0 ) && ! isStart ( getLine ( ed , row ) ) ) {
57
+ function walkBack ( editor : TextEditor , row : number ) {
58
+ while ( row > 0 && ! isStart ( getLine ( editor , row ) ) ) {
46
59
row --
47
60
}
48
61
return row
49
62
}
50
63
51
- function walkForward ( ed , start ) {
64
+ function walkForward ( editor : TextEditor , start : number ) {
52
65
let end = start
53
66
let mark = start
54
- while ( mark < ed . getLastBufferRow ( ) ) {
67
+ while ( mark < editor . getLastBufferRow ( ) ) {
55
68
mark ++
56
- const lineInfo = getLine ( ed , mark )
69
+ const lineInfo = getLine ( editor , mark )
57
70
58
71
if ( isStart ( lineInfo ) ) {
59
72
break
@@ -62,10 +75,7 @@ function walkForward (ed, start) {
62
75
// An `end` only counts when there still are unclosed blocks (indicated by `forLines`
63
76
// returning a non-empty array).
64
77
// If the line closes a multiline string we also take that as ending the block.
65
- if (
66
- ! ( forLines ( ed , start , mark - 1 ) . length === 0 ) ||
67
- isStringEnd ( lineInfo )
68
- ) {
78
+ if ( ! ( forLines ( editor , start , mark - 1 ) . length === 0 ) || isStringEnd ( lineInfo ) ) {
69
79
end = mark
70
80
}
71
81
} else if ( ! ( isBlank ( lineInfo ) || isStart ( lineInfo ) ) ) {
@@ -75,76 +85,90 @@ function walkForward (ed, start) {
75
85
return end
76
86
}
77
87
78
- function getRange ( ed , row ) {
79
- const start = walkBack ( ed , row )
80
- const end = walkForward ( ed , start )
88
+ function getRange ( editor : TextEditor , row : number ) : [ [ number , number ] , [ number , number ] ] | undefined {
89
+ const start = walkBack ( editor , row )
90
+ const end = walkForward ( editor , start )
81
91
if ( start <= row && row <= end ) {
82
- return [ [ start , 0 ] , [ end , Infinity ] ]
92
+ return [
93
+ [ start , 0 ] ,
94
+ [ end , Infinity ]
95
+ ]
96
+ } else {
97
+ return undefined // TODO
83
98
}
84
99
}
85
100
86
- function getSelection ( ed , sel ) {
87
- const { start, end} = sel . getBufferRange ( )
88
- const range = [ [ start . row , start . column ] , [ end . row , end . column ] ]
89
- while ( isBlank ( getLine ( ed , range [ 0 ] [ 0 ] ) , true ) && ( range [ 0 ] [ 0 ] <= range [ 1 ] [ 0 ] ) ) {
101
+ function getSelection ( editor : TextEditor , selection : Selection ) {
102
+ const { start, end } = selection . getBufferRange ( )
103
+ const range = [
104
+ [ start . row , start . column ] ,
105
+ [ end . row , end . column ]
106
+ ]
107
+ while ( isBlank ( getLine ( editor , range [ 0 ] [ 0 ] ) , true ) && range [ 0 ] [ 0 ] <= range [ 1 ] [ 0 ] ) {
90
108
range [ 0 ] [ 0 ] ++
91
109
range [ 0 ] [ 1 ] = 0
92
110
}
93
- while ( isBlank ( getLine ( ed , range [ 1 ] [ 0 ] ) , true ) && ( range [ 1 ] [ 0 ] >= range [ 0 ] [ 0 ] ) ) {
111
+ while ( isBlank ( getLine ( editor , range [ 1 ] [ 0 ] ) , true ) && range [ 1 ] [ 0 ] >= range [ 0 ] [ 0 ] ) {
94
112
range [ 1 ] [ 0 ] --
95
113
range [ 1 ] [ 1 ] = Infinity
96
114
}
97
115
return range
98
116
}
99
117
100
- export function moveNext ( ed , sel , range ) {
118
+ export function moveNext ( editor : TextEditor , selection : Selection , range : [ [ number , number ] , [ number , number ] ] ) {
101
119
// Ensure enough room at the end of the buffer
102
120
const row = range [ 1 ] [ 0 ]
103
121
let last
104
- while ( ( last = ed . getLastBufferRow ( ) ) < ( row + 2 ) ) {
105
- if ( ( last !== row ) && ! isBlank ( getLine ( ed , last ) ) ) {
122
+ while ( ( last = editor . getLastBufferRow ( ) ) < row + 2 ) {
123
+ if ( last !== row && ! isBlank ( getLine ( editor , last ) ) ) {
106
124
break
107
125
}
108
- sel . setBufferRange ( [ [ last , Infinity ] , [ last , Infinity ] ] )
109
- sel . insertText ( '\n' )
126
+ selection . setBufferRange ( [
127
+ [ last , Infinity ] ,
128
+ [ last , Infinity ]
129
+ ] )
130
+ selection . insertText ( "\n" )
110
131
}
111
132
// Move the cursor
112
133
let to = row + 1
113
- while ( ( to < ed . getLastBufferRow ( ) ) && isBlank ( getLine ( ed , to ) ) ) {
134
+ while ( to < editor . getLastBufferRow ( ) && isBlank ( getLine ( editor , to ) ) ) {
114
135
to ++
115
136
}
116
- to = walkForward ( ed , to )
117
- return sel . setBufferRange ( [ [ to , Infinity ] , [ to , Infinity ] ] )
137
+ to = walkForward ( editor , to )
138
+ return selection . setBufferRange ( [
139
+ [ to , Infinity ] ,
140
+ [ to , Infinity ]
141
+ ] )
118
142
}
119
143
120
- function getRanges ( ed ) {
121
- const ranges = ed . getSelections ( ) . map ( sel => {
144
+ function getRanges ( editor : TextEditor ) {
145
+ const ranges = editor . getSelections ( ) . map ( selection => {
122
146
return {
123
- selection : sel ,
124
- range : sel . isEmpty ( ) ?
125
- getRange ( ed , sel . getHeadBufferPosition ( ) . row ) :
126
- getSelection ( ed , sel )
147
+ selection : selection ,
148
+ range : selection . isEmpty ( )
149
+ ? getRange ( editor , selection . getHeadBufferPosition ( ) . row )
150
+ : getSelection ( editor , selection )
127
151
}
128
152
} )
129
153
return ranges . filter ( ( { range } ) => {
130
- return range && ed . getTextInBufferRange ( range ) . trim ( )
154
+ return range && editor . getTextInBufferRange ( range ) . trim ( )
131
155
} )
132
156
}
133
157
134
- export function get ( ed ) {
135
- return getRanges ( ed ) . map ( ( { range, selection } ) => {
158
+ export function get ( editor : TextEditor ) {
159
+ return getRanges ( editor ) . map ( ( { range, selection } ) => {
136
160
return {
137
161
range,
138
162
selection,
139
163
line : range [ 0 ] [ 0 ] ,
140
- text : ed . getTextInBufferRange ( range )
164
+ text : editor . getTextInBufferRange ( range )
141
165
}
142
166
} )
143
167
}
144
168
145
- export function getLocalContext ( editor , row ) {
169
+ export function getLocalContext ( editor : TextEditor , row : number ) {
146
170
const range = getRange ( editor , row )
147
- const context = range ? editor . getTextInBufferRange ( range ) : ''
171
+ const context = range ? editor . getTextInBufferRange ( range ) : ""
148
172
// NOTE:
149
173
// backend code expects startRow to be number for most cases, e.g.: `row = row - startRow`
150
174
// so let's just return `0` when there is no local context
@@ -156,10 +180,10 @@ export function getLocalContext (editor, row) {
156
180
}
157
181
}
158
182
159
- export function select ( ed = atom . workspace . getActiveTextEditor ( ) ) {
160
- if ( ! ed ) return
161
- return ed . mutateSelectedText ( selection => {
162
- const range = getRange ( ed , selection . getHeadBufferPosition ( ) . row )
183
+ export function select ( editor = atom . workspace . getActiveTextEditor ( ) ) {
184
+ if ( ! editor ) return
185
+ return editor . mutateSelectedText ( selection => {
186
+ const range = getRange ( editor , selection . getHeadBufferPosition ( ) . row )
163
187
if ( range ) {
164
188
selection . setBufferRange ( range )
165
189
}
0 commit comments