@@ -431,9 +431,9 @@ export default class ASTCapabilities {
431431 var d = dmp . diff_main ( oldText , newText ) ;
432432 // d.inspect()
433433 var index = 0 ;
434- let firstChangeStep = true
434+ let firstChangeStep = true ;
435435 // prune diffs
436- const onlySpaces = str => str . trim ( ) . length === 0
436+ const onlySpaces = str => str . trim ( ) . length === 0 ;
437437 // d = d.filter(([changeType, text]) => changeType === 0 || !onlySpaces(text));
438438 // d.inspect()
439439 for ( let [ changeType , text ] of d ) {
@@ -459,6 +459,105 @@ export default class ASTCapabilities {
459459 return index ;
460460 }
461461
462+ /*MD ## Slurping and Barfing MD*/
463+ slurpOrBarf ( { slurp = false , barf = false , forward } ) {
464+ const cm = this . codeProvider . codeMirror ;
465+ var getScrollInfo = ( ) => {
466+ return cm . getScrollInfo ( ) ;
467+ } ;
468+
469+ var setScrollInfo = scrollInfo => {
470+ cm . scrollIntoView ( {
471+ left : scrollInfo . left ,
472+ top : scrollInfo . top ,
473+ right : scrollInfo . left + scrollInfo . width ,
474+ bottom : scrollInfo . top + scrollInfo . height
475+ } ) ;
476+ } ;
477+
478+ const scrollInfo = getScrollInfo ( ) ;
479+ const selections = cm . listSelections ( ) ;
480+
481+ const res = this . sourceCode . transformAsAST ( ( { types : t } ) => ( {
482+ visitor : {
483+ Program : programPath => {
484+ let path = this . getInnermostPathContainingSelection ( programPath , range ( selections . first ) ) ;
485+ let innerBlock = path . find ( p => {
486+
487+ if ( ! p . isBlock ( ) ) {
488+ return false ;
489+ }
490+ if ( barf && p . get ( 'body' ) . length === 0 ) {
491+ // nothing to barf
492+ return false ;
493+ }
494+ return true ;
495+ } ) ;
496+
497+ if ( ! innerBlock ) {
498+ if ( barf ) {
499+ lively . warn ( 'nothing to barf' ) ;
500+ } else {
501+ lively . warn ( 'no innerBlock found' ) ;
502+ }
503+ return ;
504+ }
505+
506+ let outerStatement = innerBlock . find ( p => {
507+ if ( ! ( p . parentPath && p . parentPath . isBlock ( ) ) ) {
508+ return false ;
509+ }
510+ if ( slurp ) {
511+ if ( forward && ! p . getNextSibling ( ) . node ) {
512+ return false ;
513+ }
514+ if ( ! forward && ! p . getPrevSibling ( ) . node ) {
515+ return false ;
516+ }
517+ }
518+ return true ;
519+ } ) ;
520+
521+ if ( slurp ) {
522+ if ( forward ) {
523+ const pathToSlurp = outerStatement . getNextSibling ( ) ;
524+ innerBlock . pushContainer ( 'body' , pathToSlurp . node ) ;
525+ pathToSlurp . remove ( ) ;
526+ } else {
527+ const pathToSlurp = outerStatement . getPrevSibling ( ) ;
528+ innerBlock . unshiftContainer ( 'body' , pathToSlurp . node ) ;
529+ pathToSlurp . remove ( ) ;
530+ }
531+ }
532+ if ( barf ) {
533+ if ( forward ) {
534+ const pathToBarf = innerBlock . get ( 'body' ) . last ;
535+ outerStatement . insertAfter ( pathToBarf . node ) ;
536+ pathToBarf . remove ( ) ;
537+ } else {
538+ const pathToBarf = innerBlock . get ( 'body' ) . first ;
539+ outerStatement . insertBefore ( pathToBarf . node ) ;
540+ pathToBarf . remove ( ) ;
541+ }
542+ }
543+ }
544+ }
545+ } ) ) ;
546+
547+ this . sourceCode = res . code ;
548+
549+ cm . setSelections ( selections ) ;
550+ setScrollInfo ( scrollInfo ) ;
551+ }
552+
553+ slurp ( forward ) {
554+ this . slurpOrBarf ( { slurp : true , forward } ) ;
555+ }
556+
557+ barf ( forward ) {
558+ this . slurpOrBarf ( { barf : true , forward } ) ;
559+ }
560+
462561 /*MD ## Navigation MD*/
463562 /**
464563 * Get the root path
@@ -1731,7 +1830,7 @@ export default class ASTCapabilities {
17311830 let exitedEarly = false ;
17321831
17331832 const pathLocationsToSelect = [ ] ;
1734- debugger
1833+ debugger ;
17351834 let transformed = this . sourceCode . transformAsAST ( ( { types : t , template } ) => ( {
17361835 visitor : {
17371836 Program : programPath => {
0 commit comments