Shiny is a simple interpreted scripting language with aspects similar to Lua, Ruby and Perl. Anyone familiar with C derivative languages should find Shiny easy to pick up.
There is a minimal, mostly statically linked binary that runs on many Linux distros. To keep it small and fast, it lacks features like a full readline console and MySQL client support. For everything else, build from the source. See the different build options in the Makefile.
This is a little script I use to dump radio streams from an RSS feed supplied by my ISP.
#!/home/sean/bin/shiny unless find: args[2]? oops "missing find parameter" bye end # rss is pulled in by cron rss: io.slurp '/home/sean/.radio.rss' # grab the first channel only items: rss.alter ~^.*<channel>(.*)<\/channel>.*$~gsm action a end # extract an xml tag search: action txt, tag: in out if txt.match ~<%(tag)s>\s*(.*?)\s*</%(tag)s>~sm a else 'unknown' end end # cycle through radio stations searching name and description fields for items.find ~<item>(.*?)</item>~sm name: search { a 'title' } link: search { a 'link' } desc: search { a 'description' } if name.match ~%(find)s~i or desc.match ~%(find)s~i say "%s\n\t%s\n\t%s" name desc link end end
Variables can be any string that does not clash with a core key word. They must begin with a letter [a-zA-Z], optionally followed by letters, digits, or underscores [a-zA-Z0-9_]\*. The colon (:) is used to assign data to a variable. Data typing casting is dynamic.
> x: 3.14 > y: 'hello world'
Variables are created in the local scope by default, unless prefixed with one or more scope or object identifiers.
> global.x: 3.14
Numbers are all floating point (real). There is no internal distinction between integers and decimals. The common infix arithmetic can be used with C-like precedence:
> 1+2/3 1.67
A math library is available:
> x: -42 > math.abs x 42 > x.abs 42
For efficiency reasons, numbers are not true objects in Shiny, but they are treated as pseudo objects when assigned to a variable. The second dot (.) notation above implicity treats the math library methods as the x numeric variable's methods.
Numbers are passed by value.
More to come.
Strings may be specified using relatively standard single or double quote notation. Single quotes (') return a literal string unmodified except for any backslash (\) escaped single quotes. Double quotes (") replace most backslash (\) escape codes common to C type languages, and also perform automatic string formatting for percent sign (%) escape sequences, like those used by the C sprintf function.
> x: 'hello world' > y: "multi\nline\ntext" > z: "a formatted string with number '%d' and sub-string '%s'" 3.14 x
Like Numbers, Strings are pseudo objects. A string library is available to manipulate them.
> string.length x 11 > x.length 11
Strings are passed by value.
More to come.
Regular Expressions are used with various string library methods. They are specified using an ~pattern~flags notation, with Perl compatible syntax and modifier flags.
> x: 'hello world' > x.alter ~[aeiou]+~ '_' h_llo world > x.split ~\s+~ object 152684360 0: hello 1: world > if x.match ~hello~ 'yes!' else 'no!' end yes!
Sub-strings matched in parentheses during regex execution are exposed as variables in the local scope, and named a, b, c and so on.
> x.match ~(\w+)\s+(\w+)~ > a hello > b world
Regex are passed by value.
Actions are an executable data type filling the role of functions/procedures/routines, etc. They can be assigned to a variable name or passed around as nameless blocks of code. The global variable scope is just another object, so global words can be considered functions/routines/procedures too - they are all the same thing.
say_hi: action print 'hi!' end
Actions can import arguments with the in key word. Arguments are supplied to actions by placing them inline after the action call separated only by white space, without parentheses or commas.
say_hi_to: action print "hi %s!" in end say_hi_to 'tom'
Actions can return zero or one value with the out key word:
max_value: action a: in b: in out if a > b a else b end end print max_value 1 2
An action has a local variable scope. Variables in the local scope, the parent object scope, and the global scope are directly visible to an action by name. However, to write to a variable outside the local scope, a specific scope prefix must be used.
Actions are passed by reference.
Objects are closures. They use a prototype framework to create new objects either directly or by cloning. Any actions defined inside an object are automatically methods, which can reference their parent object with the this key word.
Create a raw object from the default super object prototype:
x: new object greet: 'hi' say_hi: action print greet end end x.say_hi
Create a object derived from another, either as a simple copy:
y: copy x
..or as an extendable copy (like inheritance):
y: new x greet: 'hello there' end y.say_hi
Objects can also be created and used as associative arrays, using JSON syntax:
array: { a: 1, b: 2, c: 'three' }
Object actions and variables can be referenced using the dot (.) notation, or with familiar square brackets ([]) array access notation. These are the same:
print y.greet print y['greet']
Objects are passed by reference.
More to come.
All control structures and code blocks end with the end key word.
if condition [or|and condition [...]] block else block end
while condition [or|and condition [...]] block end
for iterable key var block end
All control structures also return the last value generated in their code block. For example, this allows Shiny's normal if else end to act like the C ternary operator:
variable: if condition <true_value> else <false_value> end
(The above should look familiar to Python users!)
The key word print writes a single argument to stdout with a trailing line break.
The key word bye exits Shiny.
The key word type takes a single argument and returns the data type as a string.
> x: 42 > type x number
with allows an object's scope (remember, just a closure) to be re-entered directly after creation and without using a method, and a block of method calls to be made rapidly:
print with 'abcde' alter 'c' '_' upper 0 1 end
Ab_de
Above, with took the literal string object abcde, executed its alter and upper methods, and returned the modified result.
The io library exists to do simple I/O.
The time library exists to work with dates and times. All methods assume a YYYY-MM-DD HH:II:SS string format for dates. Shiny does not use Unix timestamps internally, so dates are not limited to the Unix epoch.
Or shell commands. Any string delimited by back ticks (`) is automatically executed in the system shell environment, and the result returned as a string. Back ticked strings perform all the same formating as double quoted (") strings.
> print `ls -al` total 52 -rw-r--r-- 1 sean sean 55 2008-11-30 02:28 Makefile -rw-r--r-- 1 sean sean 47379 2008-11-30 02:28 shiny.c
2013-01-04 eof