DO IT
WITH CFML
Building Tools with CommandBox
Matthew Clemente
box server start
server.json
.CFConfig.json
box.json

180+ config items!
All the server settings!
Complete package control
What is CommandBox?




Let's Check the Docs
- Command Line Interface (CLI)
- Package Manager
- Embedded CFML Server
- Read Eval Print Loop (REPL)
CommandBox is...
>Command Line_

Powerful

Obscure Incantations


grep
sed
xargs
awk
uniq
Dangerous

>Command Line_


box
server
start
CLI
command
namespace
HELP!




Tab-Completion

Tab-Completion

Example: Removing a Directory
execute
Executes a CFML file and outputs whatever the template outputs using cfoutput or the buffer.

execute

Helpful Commands
tokenReplace
utils
propertyFile
env
checksum
Command Line Tools
- Task Runners
- Watchers
- Custom Commands
- CommandBox Modules
this would be so much easier with ColdFusion?
Have you ever thought...

#!/bin/sh # credit: https://medium.com/@basi/docker-environment-variables-expanded-from-secrets-8fa70617b3bc : ${ENV_SECRETS_DIR:=/run/secrets} env_secret_debug() { if [ ! -z "$ENV_SECRETS_DEBUG" ]; then echo -e "\033[1m$@\033[0m" fi } # usage: env_secret_expand VAR # ie: env_secret_expand 'XYZ_DB_PASSWORD' # (will check for "$XYZ_DB_PASSWORD" variable value for a placeholder that defines the # name of the docker secret to use instead of the original value. For example: # XYZ_DB_PASSWORD=<<SECRET:my-db.secret>> env_secret_expand() { var="$1" eval val=\$$var if secret_name=$(expr match "$val" "<<SECRET:\([^}]\+\)>>$"); then secret="${ENV_SECRETS_DIR}/${secret_name}" elif [[ ${var:(-5)} = '_FILE' ]]; then suffix=${var:(-5)} secret=$val fi if [ $secret ]; then env_secret_debug "Secret file for $var: $secret" if [ -f "$secret" ]; then val=$(cat "${secret}") if [ $suffix ]; then echo "Expanding from _FILE suffix" var=$(echo $var| cut -d'_' -f 1); fi export "$var"="$val" env_secret_debug "Expanded variable: $var=$val" else export "$var"="" env_secret_debug "Secret file does not exist! $secret" fi fi # reset unset secret; unset secret_name; unset var; unset suffix; unset val; } env_secrets_expand() { for env_var in $(printenv | cut -f1 -d"=") do env_secret_expand $env_var done if [ ! -z "$ENV_SECRETS_DEBUG" ]; then echo -e "\n\033[1mExpanded environment variables\033[0m" printenv fi } env_secrets_expand
Easier in ColdFusion

Task Runners

Streamline jobs in CFML with a defined API, minimal boilerplate, and helpful tooling.
?
Ready to create your first task
Ready to create your first task
?

Seriously, it's just two words.

Seriously, it's just two words.

task create --open

Print Helper
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
// all the examples from the docs component { function run() { print.line( 'I like Spam.' ); print.line(); print.magenta( 'I sound like a toner cartridge' ); print.greenText( "You wouldn't like me when I'm angry" ); print.Blue( 'UHF ' ); print.blackOnWhiteText( 'Inverse!' ); print.greenOnRedLine( "Christmas?" ); print.color221( 'I will print PaleVioletRed1' ); print.boldText( "Don't make me turn this car around!" ); print.underscoredLine( "Have I made my point?" ); print.boldText( "Header" ) .indentedLine( "Detail 1" ) .indentedLine( "Detail 2" ); print.redOnWhiteLine( 'Ready the cannons!' ); print.boldRedOnBlueText( "Test dirt, don't wash." ); print.boldBlinkingUnderscoredBlueTextOnRedBackground( "That's just cruel" ); print.text( 'status', ( dayofweek(now()) == 5 ? 'green' : 'red' ) ); print.whiteOnRedLine( 'ERROR' ) .line() .redLine( 'oops' ) .line(); } }
component { function wizard() { var name = ask( message="Name of recipient: ", defaultResponse="Friend" ); var savePdf = confirm( "Do you want to save a PDF version?" ); var quote = multiselect() .setQuestion( 'What quote should be included? ' ) .setOptions( [ { value='What have you learned?', selected=true }, { value='Lost time is never found again.' }, { value='Time flies like an arrow; fruit flies like a banana.' } ] ) .setRequired( true ) .ask(); var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# left in #year(now())#. #quote#'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } } }
component { function wizard() { var name = ask( message="Name of recipient: ", defaultResponse="Friend" ); var savePdf = confirm( "Do you want to save a PDF version?" ); var quote = multiselect() .setQuestion( 'What quote should be included? ' ) .setOptions( [ { value='What have you learned?', selected=true }, { value='Lost time is never found again.' }, { value='Time flies like an arrow; fruit flies like a banana.' } ] ) .setRequired( true ) .ask(); var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# left in #year(now())#. #quote#'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } } }
component { function wizard() { var name = ask( message="Name of recipient: ", defaultResponse="Friend" ); var savePdf = confirm( "Do you want to save a PDF version?" ); var quote = multiselect() .setQuestion( 'What quote should be included? ' ) .setOptions( [ { value='What have you learned?', selected=true }, { value='Lost time is never found again.' }, { value='Time flies like an arrow; fruit flies like a banana.' } ] ) .setRequired( true ) .ask(); var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# left in #year(now())#. #quote#'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } } }
component { function wizard() { var name = ask( message="Name of recipient: ", defaultResponse="Friend" ); var savePdf = confirm( "Do you want to save a PDF version?" ); var quote = multiselect() .setQuestion( 'What quote should be included? ' ) .setOptions( [ { value='What have you learned?', selected=true }, { value='Lost time is never found again.' }, { value='Time flies like an arrow; fruit flies like a banana.' } ] ) .setRequired( true ) .ask(); var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# left in #year(now())#. #quote#'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } } }
component { function wizard() { var name = ask( message="Name of recipient: ", defaultResponse="Friend" ); var savePdf = confirm( "Do you want to save a PDF version?" ); var quote = multiselect() .setQuestion( 'What quote should be included? ' ) .setOptions( [ { value='What have you learned?', selected=true }, { value='Lost time is never found again.' }, { value='Time flies like an arrow; fruit flies like a banana.' } ] ) .setRequired( true ) .ask(); var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# left in #year(now())#. #quote#'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } } }
Interactivity
task create motivate wizard --open
Passing Arguments
function report( string name = 'Friend', boolean savePdf = false ) { var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# days left in #year(now())#. What have you learned?'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } }
function report( string name = 'Friend', boolean savePdf = false ) { var days = now().daysinyear()-now().dayofyear(); var message = 'Hello #name#, there are #days# days left in #year(now())#. What have you learned?'; print.greenLine( message ); if( savePdf ){ cfDocument(format="PDF", filename="motivate-#name#.pdf", overwrite="true") { writeOutput(message); }; } }
Parameters
- Positional

- Named
- Boolean Flags



component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ var csvs = globber( resolvePath( '' ) & '*.csv' ).matches(); if( !csvs.len() ) { print.boldRedLine( 'No CSV Files found' ); return; } var line = ''; for( var csv in csvs ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } }
Task Example
Use Cases
- Scheduled jobs
- One-off tasks
- CI/CD

Watchers
Trigger code in response to specific file changes within a watched folder.

component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ watch() .paths( '/*.csv' ) .inDirectory( resolvePath( '' ) ) .withDelay( 5000 ) .onChange( function( paths ){ print.line( 'Added: #paths.added.toList()#' ) .line( 'Removed: #paths.removed.toList()#' ) .line( 'Changed: #paths.changed.toList()#' ) .toConsole(); var line = ''; for( var csv in paths.added ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } ) .start(); } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ watch() .paths( '/*.csv' ) .inDirectory( resolvePath( '' ) ) .withDelay( 5000 ) .onChange( function( paths ){ print.line( 'Added: #paths.added.toList()#' ) .line( 'Removed: #paths.removed.toList()#' ) .line( 'Changed: #paths.changed.toList()#' ) .toConsole(); var line = ''; for( var csv in paths.added ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } ) .start(); } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ watch() .paths( '/*.csv' ) .inDirectory( resolvePath( '' ) ) .withDelay( 5000 ) .onChange( function( paths ){ print.line( 'Added: #paths.added.toList()#' ) .line( 'Removed: #paths.removed.toList()#' ) .line( 'Changed: #paths.changed.toList()#' ) .toConsole(); var line = ''; for( var csv in paths.added ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } ) .start(); } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ watch() .paths( '/*.csv' ) .inDirectory( resolvePath( '' ) ) .withDelay( 5000 ) .onChange( function( paths ){ print.line( 'Added: #paths.added.toList()#' ) .line( 'Removed: #paths.removed.toList()#' ) .line( 'Changed: #paths.changed.toList()#' ) .toConsole(); var line = ''; for( var csv in paths.added ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } ) .start(); } }
component { property name='progressableDownloader' inject='ProgressableDownloader'; property name='progressBar' inject='ProgressBar'; function run( boolean doZip = false ){ watch() .paths( '/*.csv' ) .inDirectory( resolvePath( '' ) ) .withDelay( 5000 ) .onChange( function( paths ){ print.line( 'Added: #paths.added.toList()#' ) .line( 'Removed: #paths.removed.toList()#' ) .line( 'Changed: #paths.changed.toList()#' ) .toConsole(); var line = ''; for( var csv in paths.added ) { var dateSlug = formatterUtil.slugify( dateFormat( now(), 'long' ) ); var exportName = getFileFromPath( csv ).listFirst( '.' ).lcase(); var exportFolder = dateSlug & '-' & exportName; var collectionDir = getCWD() & exportFolder; command( 'mkdir' ) .params( exportFolder ) .append( 'log.txt' ) .run(); cfloop( file=csv, item='line' ) { var imageUrl = line.listlast().replace( '"', '', 'all' ); var imageName = imageurl.listlast( '/' ); var imageDestination = collectionDir & '/' & imageName & '.jpg'; if( !isValid( 'url', imageUrl ) ) continue; progressableDownloader.download( imageUrl, imageDestination, ( status ) => progressBar.update( argumentCollection = status ) ); command( 'imageToASCII' ) .params( imageDestination ) .overwrite( collectionDir & '/' & imageName & '.txt' ) .run(); } fileMove( csv, collectionDir ); if( doZip ) { cfzip( source=collectionDir, file='#collectionDir#.zip', overwrite='true' ); } } } ) .start(); } }
Watcher Example
Custom Commands
Reusable packages of code that contain command CFCs to extend CommandBox functionality.

./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands └── Hello.cfc
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands └── Hello.cfc
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands └── Hello.cfc
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands └── Hello.cfc
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands └── Hello.cfc
Structure
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands ├── Hello.cfc └── say └── Hello.cfc └── Goodbye.cfc
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands ├── Hello.cfc └── say └── Hello.cfc └── Goodbye.cfc
./YourCommandModule ├── ModuleConfig.cfc ├── box.json └── commands ├── Hello.cfc └── say └── Hello.cfc └── Goodbye.cfc
Structure
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
mkdir exampleCommand --cd && touch ModuleConfig.cfc && package init && package set name="Example Command" && package set slug="commandbox-example" && package set type="commandbox-modules" && mkdir commands --cd && touch date.cfc && cd ../ && !code .
Command Creation
Module Location
-
~/.CommandBox/cfml/system/modules
-
~/.CommandBox/cfml/system/modules_app
-
~/.CommandBox/cfml/modules
package link package unlink
Package Link
Creates a symlink in the core CommandBox modules directory.
Help and Completion
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.options Chickens,Turkeys,Flamingos,Vultures,Penguins */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } }
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.options Chickens,Turkeys,Flamingos,Vultures,Penguins */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } }
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.options Chickens,Turkeys,Flamingos,Vultures,Penguins */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } }
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.options Chickens,Turkeys,Flamingos,Vultures,Penguins */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } }
Help and Completion
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.options Chickens,Turkeys,Flamingos,Vultures,Penguins */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } }
touch ./commands/exclaim.cfc --open
Help and Completion
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.optionsUdf listBirds */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } function listBirds( string paramSoFar, struct passedNamedParameters ) { return [ "Albatrosses", "Auklets", "Bitterns", "Blackbirds", "Bluebirds", "Buntings", "Cardinals", "Catbirds", "Chickadees", "Chickens", "Cowbirds", "Cranes", "Crows", "Cuckoos", "Doves", "Ducks", "Eagles", "Egrets", "Falcons", "Finchs", "Flamingos", "Goldfinches", "Geese", "Gulls", "Hawks", "Herons", "Hummingbirds", "Ibises", "Jays", "Kestrels", "Kingfishers", "Larks", "Loons", "Magpies", "Mallards", "Mockingbirds", "Orioles", "Ospreys", "Owls", "Pelicans", "Penguins", "Pheasants", "Pigeons", "Puffins", "Quail", "Ravens", "Roadrunners", "Robins", "Sandpipers", "Sapsuckers", "Sparrows", "Starlings", "Storks", "Swallows", "Swans", "Turkeys", "Vultures", "Warblers", "Woodpeckers", "Wrens" ]; } }
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.optionsUdf listBirds */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } function listBirds( string paramSoFar, struct passedNamedParameters ) { return [ "Albatrosses", "Auklets", "Bitterns", "Blackbirds", "Bluebirds", "Buntings", "Cardinals", "Catbirds", "Chickadees", "Chickens", "Cowbirds", "Cranes", "Crows", "Cuckoos", "Doves", "Ducks", "Eagles", "Egrets", "Falcons", "Finchs", "Flamingos", "Goldfinches", "Geese", "Gulls", "Hawks", "Herons", "Hummingbirds", "Ibises", "Jays", "Kestrels", "Kingfishers", "Larks", "Loons", "Magpies", "Mallards", "Mockingbirds", "Orioles", "Ospreys", "Owls", "Pelicans", "Penguins", "Pheasants", "Pigeons", "Puffins", "Quail", "Ravens", "Roadrunners", "Robins", "Sandpipers", "Sapsuckers", "Sparrows", "Starlings", "Storks", "Swallows", "Swans", "Turkeys", "Vultures", "Warblers", "Woodpeckers", "Wrens" ]; } }
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.optionsUdf listBirds */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } function listBirds( string paramSoFar, struct passedNamedParameters ) { return [ "Albatrosses", "Auklets", "Bitterns", "Blackbirds", "Bluebirds", "Buntings", "Cardinals", "Catbirds", "Chickadees", "Chickens", "Cowbirds", "Cranes", "Crows", "Cuckoos", "Doves", "Ducks", "Eagles", "Egrets", "Falcons", "Finchs", "Flamingos", "Goldfinches", "Geese", "Gulls", "Hawks", "Herons", "Hummingbirds", "Ibises", "Jays", "Kestrels", "Kingfishers", "Larks", "Loons", "Magpies", "Mallards", "Mockingbirds", "Orioles", "Ospreys", "Owls", "Pelicans", "Penguins", "Pheasants", "Pigeons", "Puffins", "Quail", "Ravens", "Roadrunners", "Robins", "Sandpipers", "Sapsuckers", "Sparrows", "Starlings", "Storks", "Swallows", "Swans", "Turkeys", "Vultures", "Warblers", "Woodpeckers", "Wrens" ]; } }
/** * Craft your own avian exclamation, like Ben Nadel. * This is how you call it: * * {code:bash} * exclaim bird=chickens * {code} * **/ component { /** * @bird.hint Type of bird to use as an exclamation * @bird.optionsUdf listBirds */ function run( required string bird ) { print.line() .boldCyanLine( ' Oh my sweet #bird#! ' ) .line().toConsole(); } function listBirds( string paramSoFar, struct passedNamedParameters ) { return [ "Albatrosses", "Auklets", "Bitterns", "Blackbirds", "Bluebirds", "Buntings", "Cardinals", "Catbirds", "Chickadees", "Chickens", "Cowbirds", "Cranes", "Crows", "Cuckoos", "Doves", "Ducks", "Eagles", "Egrets", "Falcons", "Finchs", "Flamingos", "Goldfinches", "Geese", "Gulls", "Hawks", "Herons", "Hummingbirds", "Ibises", "Jays", "Kestrels", "Kingfishers", "Larks", "Loons", "Magpies", "Mallards", "Mockingbirds", "Orioles", "Ospreys", "Owls", "Pelicans", "Penguins", "Pheasants", "Pigeons", "Puffins", "Quail", "Ravens", "Roadrunners", "Robins", "Sandpipers", "Sapsuckers", "Sparrows", "Starlings", "Storks", "Swallows", "Swans", "Turkeys", "Vultures", "Warblers", "Woodpeckers", "Wrens" ]; } }
// ModuleConfig.cfc component { function configure(){ settings = { 'bird': 'chickens', 'exclamation': true } } }
// ModuleConfig.cfc component { function configure(){ settings = { 'bird': 'chickens', 'exclamation': true } } }
Settings
component { // property name='settings' inject='commandbox:moduleSettings:moduleName'; property name='settings' inject='commandbox:moduleSettings:commandbox-example'; function run(){ print.line( settings ).toConsole(); return; } }
Settings
config set modules.commandbox-example.bird="eagles" config set modules.commandbox-example.exclamation=false config show modules.commandbox-example
Settings
Digging into the APIs
ForgeBox
CommandBox Modules

box install commandbox-bullet-train

box install cfdocs

box install commandbox-cfformat

box install commandbox-update-check
Code Quality Commands
Go
Build
Something.
DO IT
WITH CFML
Building Tools with CommandBox
Matthew Clemente
DO IT WITH CFML Building Tools with CommandBox Matthew Clemente blog.mattclemente.com @mjclemente @mjclemente @mjclemente84
Do It with CFML: Building Your Own Tools with CommandBox
By mjclemente
Do It with CFML: Building Your Own Tools with CommandBox
Presentation for Into the Box 2020
- 3,502