= Groovy guide

This section teaches about advanced Groovy usage in CRaSH.

[[commands_as_script]]
== Commands as a script

The <<developers>> covered how to write a CRaSH command as a Groovy/Java class. The Groovy language
also supports simple scripts. A simple script that returns a string is a valid command:

[source,java]
----
return "Hello World";
----

The +out+ implicit variable can be used to send a message to the console:

[source,java]
----
out.println("Hello World");
----

It can be even Groovier:

[source,groovy]
----
out << "Hello World"
----

== Inter command API

Groovy provides powerful support for invoking nested commands, allowing to reuse any CRaSH
commands inside your commands, obviously such nested commands don't have be Groovy commands.
Let's study how a command can reuse existing commands:

[source,groovy]
.dbscript.groovy
----
jdbc.connect username:root, password:crash, "jdbc:derby:memory:EmbeddedDB;create=true"
jdbc.execute "create table derbyDB(num int, addr varchar(40))"
jdbc.execute "insert into derbyDB values (1956,'Webster St.')"
jdbc.execute "insert into derbyDB values (1910,'Union St.')"
jdbc.execute "select * from derbyDb"
jdbc.close
----

This script is written in Groovy and use Groovy DSL capabilities, the first statement can be
analyzed:

* the +jdbc.connect+ statement is decomposed into two steps
** the +jdbc+ is resolved as the command itself
** the +connect+ invokes the connect command
* the +username+ and +password+ are considered as command options
* the SQL statement +"jdbc:derby:memory:EmbeddedDB;create=true"+ is the main argument of the command

This syntax is quite powerful (and explained more in depth in <<groovy_repl>> section)
is equivalent to the command line:

----
% jdbc connect --username root --password crash jdbc:derby:memory:EmbeddedDB;create=true
----

The rest of the script is fairly easy to understand, here is the output of the script execution:

----
% dbscript
Connected to data base : jdbc:derby:memory:EmbeddedDB;create=true
Query executed successfully
Query executed successfully
Query executed successfully
NUM                  ADDR
1956                 Webster St.
1910                 Union St.
Connection closed
----

[groovy_repl]
== The Groovy REPL

The _Read–eval–print loop_ known as _REPL_ is the interactive evaluation of CRaSH. Since CRaSH 1.3, the REPL evaluation
can be switch to the Groovy language.

The Groovy REPL is switched via the _repl_ directive:

----
% repl groovy
Using repl groovy
----

=== Evaluating commands

Simple commands are invoked by calling them just like a function:

.Invoking a simple command the Groovy way
----
% repl groovy
Using repl groovy
% help()
Try one of these commands with the -h or --help switch:

NAME          DESCRIPTION
cls           clear screen
egrep         search file(s) for lines that match a pattern
env           display the term env
...
----

Typing a command name evalutes to a Groovy closure, allowing to call the command just like a function.

NOTE: to switch back to the script REPL, you need to use the Groovy syntax +repl("script")+ as +repl+
is a command itself

.Typing a command evaluates to a closure
----
% cmd = help
help
% cmd()
----

Sub commands can be invoked by resolving a new closure from the initial command:

.Invoking a sub command the Groovy way
----
% thread.ls()
----

Which is equivalent to

.Sub commands are also evaluated to closures
----
% cmd = thread
thread
% cmd2 = cmd.ls
thread.ls
% cmd2()
...
----

=== Passing options and arguments

Command options and command arguments are passed as invocation parameters:

* options are used as a map or named parameters
* arguments are the other invocation parameters

.Passing options as named parameters
----
% thread(h:true)
usage: thread COMMAND [ARGS]

The most commonly used thread commands are:
   stop             stop vm threads
   interrupt        interrupt vm threads
   top              thread top
   ls               list the vm threads
   dump             dump vm threads

% thread.ls(h:true)
usage: thread ls [-n | --name] [-g | --group] [-s | --state]

   [-n | --name]  Filter the threads with a glob expression on their name
   [-g | --group] Filter the threads with a glob expression on their group
   [-s | --state] Filter the threads by their status (new,runnable,blocked,waiting,timed_waiting,terminated)
----

.Passing an argument
----
% system.propget("file.encoding")
UTF-8
----

Passing options and arguments at the same time is easy to do, however the options should be the first method parameters:

.Passing an options and arguments
----
% jul.send(m:"hello", "the.category")
Aug 12, 2013 11:22:50 AM org.codehaus.groovy.reflection.CachedMethod invoke
INFO: hello
----

=== Options and arguments binding

Options and arguments can also be bound on a closure:

.Binding options to a command
----
% (thread.ls { h=true })()
...
% cmd = thread.ls { h=true }
thread.ls { h=true }
% cmd();
...
----

.Binding arguments to a command
----
% (system.propget { "file.encoding" })()
...
% cmd = system.propget { "file.encoding" }
system.propget { ["file.encoding"] }
% cmd();
...
----

Of course it is possible to bind options and arguments too, the arguments needs to be passed as last parameters:

.Passing an options and arguments
----
% (jul.send { m="hello"; "the category" })()
...
% cmd = jul.send { m="hello"; "the category" }
jul.send { m="hello"; ["the category"] }
% cmd()
...
----

=== Command pipeline

The object pipeline can be used in the Groovy REPL using the +|+ (pipe) operator. When a command closure is combined with a
 pipe, it returns a new closure that will invoke the pipeline construction.

.Assembling a command pipe
----
% (system.propls | egrep { "java.*" })()
java.runtime.name                        Java(TM) SE Runtime Environment
java.vm.version                          23.7-b01
java.vm.vendor                           Oracle Corporation
...
% cmd = system.propls | egrep { "java.*" }
system.propls | egrep { ["java.*"] }
% cmd()
...
----

A pipeline can also contain Groovy closures in addition of the existing commands

.Using a Groovy closure in a pipe
----
% (thread.ls | { Thread thread -> [id:thread.id, name:thread.name] })()
id name
------------------------------------
2  Reference Handler
3  Finalizer
...
% cmd = thread.ls | { Thread thread -> [id:thread.id, name:thread.name] }
thread.ls | Script14$_run_closure1@47da4d19
% cmd()
...
----

In this example, the closure takes the threads argument and transforms them to a serie of maps that are displayed then as a table
by CRaSH.
