Skip to content

Commit

Permalink
'sh' block: now support:
Browse files Browse the repository at this point in the history
* write-formula: this specify a variable name (aka a *formula*) which will be populated by each line of the output
  of this shell block, the formula is used as a list
* splitter: this specify a splitter for the 'write' argument, by default '\n' is the splitter
* silence: dispell all output to stdout
* amnesia: dispell all output to log files
  • Loading branch information
Cédric Ronvel committed Sep 10, 2014
1 parent 4b539c0 commit f448682
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ log/jshint.log: log/npm-dev-install.log lib/spellcast.js test/spellcast-test.js

# Mocha BDD STDOUT test
log/mocha.log: log/npm-dev-install.log lib/spellcast.js test/spellcast-test.js
${MOCHA} test/spellcast-test.js -R list | tee log/mocha.log ; exit $${PIPESTATUS[0]}
${MOCHA} test/spellcast-test.js -R spec | tee log/mocha.log ; exit $${PIPESTATUS[0]}

# README
README.md: documentation.md bdd-spec.md
Expand Down
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ Full BDD spec generated by Mocha:
echo
delayed-echo
bob blihblih one
scroll line: one
scroll line: three
scroll line: two
scroll line: one
scroll line: three
scroll line: two
one more time: one
one more time: two
one more time: three
Expand Down Expand Up @@ -74,7 +80,7 @@ cleanup( function() {
} ) ;
```

should substitute variable (aka formula) accordingly.
should substitute variable (aka formula) accordingly in 'sh' block.

```js
cleanup( function() {
Expand All @@ -90,6 +96,22 @@ cleanup( function() {
} ) ;
```

should write a new formula with the output of an 'sh' block.

```js
cleanup( function() {

var book = new spellcast.Book( fs.readFileSync( 'spellbook' ).toString() ) ;

book.cast( 'write-formula' , function( error )
{
expect( error ).not.ok() ;
expect( getCastedLog( 'write-formula' ) ).to.be( 'scroll line: one\nscroll line: three\nscroll line: two\nscroll line: one\nscroll line: three\nscroll line: two\n' ) ;
done() ;
} ) ;
} ) ;
```

<a name="foreach-block"></a>
# 'foreach' block
should .
Expand Down
24 changes: 23 additions & 1 deletion bdd-spec.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
echo
delayed-echo
bob blihblih one
scroll line: one
scroll line: three
scroll line: two
scroll line: one
scroll line: three
scroll line: two
one more time: one
one more time: two
one more time: three
Expand Down Expand Up @@ -56,7 +62,7 @@ cleanup( function() {
} ) ;
```

should substitute variable (aka formula) accordingly.
should substitute variable (aka formula) accordingly in 'sh' block.

```js
cleanup( function() {
Expand All @@ -72,6 +78,22 @@ cleanup( function() {
} ) ;
```

should write a new formula with the output of an 'sh' block.

```js
cleanup( function() {

var book = new spellcast.Book( fs.readFileSync( 'spellbook' ).toString() ) ;

book.cast( 'write-formula' , function( error )
{
expect( error ).not.ok() ;
expect( getCastedLog( 'write-formula' ) ).to.be( 'scroll line: one\nscroll line: three\nscroll line: two\nscroll line: one\nscroll line: three\nscroll line: two\n' ) ;
done() ;
} ) ;
} ) ;
```

<a name="foreach-block"></a>
# 'foreach' block
should .
Expand Down
17 changes: 15 additions & 2 deletions format.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@

# Variable substitution

Variables aka formula are defined in the 'formula' block.
Variables aka *formula* are defined in the *formula* block.

A formula only consists of a string, no other type are supported ATM.
A *formula* only consists of a string, no other type are supported ATM.

Once a formula is defined, it can be used with the syntax `${variableName}`, where 'variableName' is the name
of the variable.

When a variable is encountered, it is substituted by its string value.

TODOC: list formula



# References
Expand All @@ -36,8 +38,19 @@ This block defines formula, i.e. variables and values used for substitution.
* parallel: this shell block will execute each command in parallel mode, if a number is passed, this is the maximum
of commands running in parallel
* ignore: if a command return a non-zero status, it will continue nontheless
* write-formula: this specify a variable name (aka a *formula*) which will be populated by each line of the output
of this shell block, the formula is used as a list
* splitter: this specify a splitter for the 'write' argument, by default '\n' is the splitter
* silence: dispell all output to stdout
* amnesia: dispell all output to log files

Each child of this block is a shell command to execute.



## foreach <formula>

TODOC: everything about foreach



74 changes: 45 additions & 29 deletions lib/spellcast.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@

/*
TODO:
* turn arguments using hyphen in spellbooks into camelCase (e.g. write-formula should be writeFormula in code)
* automatically check versus the 'spellbook' file (just like if 'spellbook' was added to all 'summon' block)
* escape formula variable substitution
* new blocks:
- spellbook
- wand
- zap
- ssh : like sh but remotely
* find the right regexp for split(/,/) because '\,' should not split
*/


Expand Down Expand Up @@ -661,31 +663,50 @@ spellcast.Book.prototype.castSummon = function castSummon( summon , castExecutio

spellcast.Book.prototype.castShell = function castShell( shell , castExecution , callback )
{
var plan ;
var plan , splitter , self = this ;

plan = async
.foreach( shell.shellCommands , this.execShellCommand.bind( this , castExecution ) )
.map( shell.shellCommands , this.execShellCommand.bind( this , castExecution , shell.args ) )
.nice( 0 ) ;

//console.log( shell ) ;

if ( shell.args.parallel )
{
if ( shell.args.parallel === true ) { plan.parallel( shell.args.parallel ) ; }
else { plan.parallel( parseInt( shell.args.parallel ) ) ; }
}
if ( ! shell.args.parallel ) { plan.parallel( false ) ; }
else if ( shell.args.parallel === true ) { plan.parallel() ; }
else { plan.parallel( parseInt( shell.args.parallel ) ) ; }

if ( ! shell.args.ignore ) { plan.fatal( true ) ; }

plan.exec( callback ) ;
if ( shell.args['write-formula'] && typeof shell.args['write-formula'] !== 'string' ) { delete shell.args['write-formula'] ; }


// Let's exec the plan and process the final outcome!

plan.exec( function( error , outputMap ) {

if ( error ) { callback( error ) ; return ; }

if ( shell.args['write-formula'] )
{
splitter = shell.args.splitter || '\n' ;
self.formula[ shell.args['write-formula'] ] = outputMap.join( '' ).trim().split( splitter ) ;

/*
console.log( "outputMap:" , outputMap[0] ) ;
console.log( "full output:" , output ) ;
*/
}

callback() ;
} ) ;
//plan.exec( function() { console.log( 'castShell: Done!' ) ; callback() ; } ) ;
} ;



spellcast.Book.prototype.execShellCommand = function execShellCommand( castExecution , shellCommand , callback )
spellcast.Book.prototype.execShellCommand = function execShellCommand( castExecution , args , shellCommand , callback )
{
var child , onStdout , onStderr , onStdin , onceExit , onIgnoredError ;
var child , onStdout , onStderr , onStdin , onceExit , onIgnoredError , output = '' ;

//console.log( 'Exec command: ' , shellCommand ) ;

Expand All @@ -705,41 +726,36 @@ spellcast.Book.prototype.execShellCommand = function execShellCommand( castExecu

// For some reason, 'exit' can be triggered before some 'data' event, so we have to delay removeListener() a bit
setTimeout( function() {

child.stdout.removeListener( 'data' , onStdout ) ;
child.stderr.removeListener( 'data' , onStderr ) ;
} , 200 ) ;

// If there is an 'write-formula' arguments, we must trigger the callback in this timeout event,
// if not we take the risk that we will miss some output and we don't want that
if ( args['write-formula'] ) { callback( status , output ) ; }

} , 0 ) ;

callback( status ) ;
// If there isn't an 'write-formula' arguments, then we can trigger the callback now
if ( ! args['write-formula'] ) { callback( status ) ; }
} ;

onStdout = function( chunk ) {
// Send the command's stdout to the process stdout and the output file
process.stdout.write( chunk ) ;
//castExecution.outputFile.write( 'Stdout:\n' ) ;
castExecution.outputFile.write( chunk ) ;
//castExecution.outputFile.write( '\n' ) ;
if ( ! args.silence ) { process.stdout.write( chunk ) ; }
if ( ! args.amnesia ) { castExecution.outputFile.write( chunk ) ; }
if ( args['write-formula'] ) { output += chunk ; }
} ;

onStderr = function( chunk ) {
// Send the command's stderr to the process stderr and the output file
process.stderr.write( chunk ) ;

//castExecution.outputFile.write( 'Stderr:\n' ) ;
castExecution.outputFile.write( chunk ) ;
//castExecution.outputFile.write( '\n' ) ;
if ( ! args.silence ) { process.stderr.write( chunk ) ; }
if ( ! args.amnesia ) { castExecution.outputFile.write( chunk ) ; }
} ;

onStdin = function( chunk ) {
// Send the process stdin to the command's stdin
child.stdin.write( chunk ) ;

// tmp:
/*
console.log( 'Received STDIN:' , chunk.toString() ) ;
castExecution.outputFile.write( 'Stdin:\n' ) ;
castExecution.outputFile.write( chunk ) ;
castExecution.outputFile.write( '\n' ) ;
*/
} ;

// Prevent message sent to command that ignore them, then emit ECONNRESET when finished
Expand Down
1 change: 1 addition & 0 deletions test/ls/one
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
one
1 change: 1 addition & 0 deletions test/ls/three
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
three
1 change: 1 addition & 0 deletions test/ls/two
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
two
10 changes: 9 additions & 1 deletion test/spellbook
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@ formula
sh
echo end: ${list}


.write-formula
sh amnesia silence write-formula:scroll
ls ls/
ls ls/

foreach scroll
sh
echo scroll line: ${scroll}




Expand Down
17 changes: 16 additions & 1 deletion test/spellcast-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ describe( "'sh' block" , function() {
} ) ;
} ) ;

it( "should substitute variable (aka formula) accordingly" , function( done ) {
it( "should substitute variable (aka formula) accordingly in 'sh' block" , function( done ) {

cleanup( function() {

Expand All @@ -137,6 +137,21 @@ describe( "'sh' block" , function() {
} ) ;
} ) ;

it( "should write a new formula with the output of an 'sh' block" , function( done ) {

cleanup( function() {

var book = new spellcast.Book( fs.readFileSync( 'spellbook' ).toString() ) ;

book.cast( 'write-formula' , function( error )
{
expect( error ).not.ok() ;
expect( getCastedLog( 'write-formula' ) ).to.be( 'scroll line: one\nscroll line: three\nscroll line: two\nscroll line: one\nscroll line: three\nscroll line: two\n' ) ;
done() ;
} ) ;
} ) ;
} ) ;

/*
it( "should launch editor" , function( done ) {
Expand Down

0 comments on commit f448682

Please sign in to comment.