@@ -29,8 +29,8 @@ define(function (require) {
29
29
30
30
var angular = require ( 'angular' ) ;
31
31
32
- return [ '$scope' , 'DataflowUtils' , '$modal' , '$state' , 'TaskAppService' , 'TaskDslValidatorService' , '$cookieStore' ,
33
- function ( $scope , utils , $modal , $state , taskAppService , validatorService , $cookieStore ) {
32
+ return [ '$scope' , 'DataflowUtils' , '$modal' , '$state' , 'TaskAppService' , 'TaskDslValidatorService' , '$cookieStore' , 'TaskContentAssistService' ,
33
+ function ( $scope , utils , $modal , $state , taskAppService , validatorService , $cookieStore , contentAssistService ) {
34
34
35
35
var editor ;
36
36
@@ -242,21 +242,80 @@ define(function (require) {
242
242
$scope . dsl = contents ;
243
243
} ;
244
244
245
- $scope . hint = {
246
- async : 'true' ,
247
- hint : function ( cm , callback ) { // jshint ignore:line
248
- // TODO: calculate completion proposals and return results as shown below
245
+ function isDelimiter ( c ) {
246
+ return c && c === ' ' ;
247
+ }
249
248
250
- // See https://codemirror.net/doc/manual.html#addons hint/show-hint.js section
249
+ /**
250
+ * The suggestions provided by rest api are very long and include the whole command typed
251
+ * from the start of the line. This function determines the start of the 'interesting' part
252
+ * at the end of the prefix, so that we can use it to chop-off the suggestion there.
253
+ */
254
+ function interestingPrefixStart ( prefix , completions ) {
255
+ var cursor = prefix . length ;
256
+ if ( completions . every ( function ( completion ) {
257
+ return isDelimiter ( completion [ cursor ] ) ;
258
+ } ) ) {
259
+ return cursor ;
260
+ }
261
+ return prefix . lastIndexOf ( ' ' ) ;
262
+ }
251
263
252
- // return callback({
253
- // list: listOfStrings
254
- // from: {line: startLine, ch:startCharIndex},
255
- // to: {line: endLine, ch:endCharIndex}
256
- // });
264
+ var taskProposalComputer = function ( cm , callback ) { // jshint ignore:line
265
+ var cursor = cm . getDoc ( ) . getCursor ( ) ;
266
+ var startOfLine = { line : cursor . line , ch : 0 } ;
267
+ var prefix = cm . getDoc ( ) . getRange ( startOfLine , cursor ) ;
268
+
269
+ // Handle content assist for the name if not yet specified or followed by equals:
270
+ var equalsIndex = prefix . indexOf ( '=' ) ;
271
+ if ( equalsIndex === - 1 ) {
272
+ var trimmed = prefix . trim ( ) ;
273
+ if ( trimmed . length !== 0 ) {
274
+ // Suggest they follow the name with an '='
275
+ return callback ( { list :[ trimmed + '=' ] , from :{ line :cursor . line , ch :0 } , to :cursor } ) ;
276
+ } else {
277
+ return callback ( { list :[ 'task' + ( cursor . line + 1 ) + '=' ] , from :{ line :cursor . line , ch :0 } , to :cursor } ) ;
278
+ }
279
+ }
280
+ var textAfterEquals = prefix . substring ( equalsIndex + 1 ) ;
281
+ contentAssistService . getProposals ( textAfterEquals ) . then ( function ( completions ) {
282
+ // Example:
283
+ // [{"text":"spark-yarn","explanation":"Choose a task app"},
284
+ // {"text":"spark-cluster","explanation":"Choose a task app"},
285
+ // {"text":"timestamp","explanation":"Choose a task app"},
286
+ // {"text":"spark-client","explanation":"Choose a task app"}]
287
+ var chopAt = interestingPrefixStart ( textAfterEquals , completions ) ;
288
+ if ( chopAt === - 1 ) {
289
+ chopAt = 0 ;
290
+ }
291
+ // If all the proposals are options adjust the chopAt
292
+ var areAllOptions = true ;
293
+ for ( var c = 0 ; c < completions . length ; c ++ ) {
294
+ var longCompletion = completions [ c ] ;
295
+ var text = typeof longCompletion === 'string' ?longCompletion : longCompletion . text ;
296
+ if ( ! text . substring ( textAfterEquals . length ) . startsWith ( ' --' ) ) {
297
+ areAllOptions = false ;
298
+ break ;
299
+ }
300
+ }
301
+ if ( areAllOptions ) {
302
+ chopAt = textAfterEquals . length ;
303
+ }
304
+ return callback ( {
305
+ list :completions . map ( function ( longCompletion ) {
306
+ var text = typeof longCompletion === 'string' ?longCompletion : longCompletion . text ;
307
+ return text . substring ( chopAt ) ;
308
+ } ) ,
309
+ from :{ line :cursor . line , ch :chopAt + equalsIndex + 1 } ,
310
+ to :cursor
311
+ } ) ;
312
+ } ) ;
313
+ } ;
314
+ taskProposalComputer . async = true ;
257
315
258
- utils . $log . info ( 'Task DSL Content Assist Invoked!' ) ;
259
- }
316
+ $scope . hint = {
317
+ async : 'true' ,
318
+ hint : taskProposalComputer
260
319
} ;
261
320
262
321
$scope . nextError = function ( ) {
0 commit comments