Skip to content

Commit

Permalink
cleanup pass + loader example + README update
Browse files Browse the repository at this point in the history
  • Loading branch information
bjouhier committed Mar 31, 2012
1 parent 8030598 commit 919bb7e
Show file tree
Hide file tree
Showing 15 changed files with 137 additions and 262 deletions.
1 change: 0 additions & 1 deletion .npmignore

This file was deleted.

13 changes: 5 additions & 8 deletions API.md
Expand Up @@ -351,9 +351,9 @@ Flows Module

The `streamline/lib/util/flows` module contains some handy utilities for streamline code

## Array utilities
## Array utilities (obsolete)

The following functions are async equivalents of the ES5 Array methods (`forEach`, `map`, `filter`, ...)
This API is obsolete. Use `array.forEach_`, `array.map_`, ... instead.

* `flows.each(_, array, fn, [thisObj])`
applies `fn` sequentially to the elements of `array`.
Expand Down Expand Up @@ -382,9 +382,9 @@ The following functions are async equivalents of the ES5 Array methods (`forEach

Note: this function _changes_ the original array (and returns it)

## Object utility
## Object utility (obsolete)

The following function can be used to iterate through object properties:
This API is obsolete. Use `Object.keys(obj).forEach_` instead.

* `flows.eachKey(_, obj, fn)`
calls `fn(_, key, obj[key])` for every `key` in `obj`.
Expand Down Expand Up @@ -419,7 +419,4 @@ Utility functions:
`nextTick` function for both browser and server.
Aliased to `process.nextTick` on the server side.
* `result = flows.apply(_, fn, thisObj, args, [index])`
Helper to apply `Function.apply` to streamline functions.
Equivalent to `result = fn.apply(thisObj, argsWith_)` where `argsWith_` is
a modified argument list in which the callback has been inserted at `index`
(at the end of the argument list if `index` is not specified).
Obsolete. Use `fn.apply_` instead.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -7,4 +7,5 @@ Aseem Kishore <aseem.kishore@gmail.com>
Daniel Ennis <aikar@aikar.co>
Marcel Laverdet <marcel@laverdet.com> (https://github.com/laverdet/)
Evan Worley
anodos (https://github.com/anodos)
Alan Gutierrez <alan@prettyrobots.com>
181 changes: 69 additions & 112 deletions README.md
@@ -1,6 +1,6 @@
## streamline.js
# streamline.js

`streamline.js` is a small tool to simplify asynchronous Javascript programming.
`streamline.js` is a language tool to simplify asynchronous Javascript programming.

Instead of writing hairy code like:

Expand Down Expand Up @@ -29,53 +29,7 @@ And streamline is not limited to a subset of Javascript.
You can use all the flow control features of Javascript in your asynchronous code: conditionals,
loops, `try/catch/finally` blocks, anonymous functions, `this`, etc.

Streamline also provides _futures_, and comes with a small optional library of helper functions (see Goodies section below).

# Generation options

Streamline gives you the choice between generating regular callback-based asynchronous code,
or generating code that takes advantage of the [fibers library](https://github.com/laverdet/node-fibers).

The _callback_ option produces code that does not have any special runtime dependencies. You may even use it
to generate asynchronous code for the browser.

The _fibers_ option produces simpler code but requires that you install
the fibers library (easy: `npm install fibers`).
This option gives superior development experience: line numbers are always preserved in the transformed code;
you can step with the debugger through asynchronous calls without having to go through complex callbacks, etc.
It may also generate more efficient code (to be confirmed by benchmarks).

The _fibers_ option can be activated by passing `--fibers` to the `node-streamline` command or by
setting the `fibers` option when registering streamline
(see the `register(options)` function in `streamline/lib/compiler/register` or the `streamline/module` API).

# Interoperability with standard node.js code

You can call standard node functions from streamline code. For example the `fs.readFile` function:

```javascript
function lineCount(path, _) {
return fs.readFile(path, "utf8", _).split('\n').length;
}
```
You can also call streamline functions as if they were standard node functions. For example:

```javascript
lineCount("README.md", function(err, result) {
if (err) return console.error("ERROR: " + err.message);
console.log("README has " + result + " lines.");
});
```
And you can mix streamline functions, classical callback based code and synchrononous functions in the same file.
Streamline will only transform the functions that have the special `_` parameter.

Note: this works with both transformation options.
Even if you use the _fibers_ option, you can seamlessly call standard callback based node APIs
and the asynchronous functions that you create with streamline have the standard node callback signature.

# On-line demo

You can test `streamline.js` directly with the [on-line demo](http://sage.github.com/streamlinejs/examples/streamlineMe/streamlineMe.html)
Streamline also provides _futures_, and additional builtin functions for asynchronous programming.

# Installation

Expand All @@ -86,12 +40,12 @@ npm install streamline -g
```

The `-g` option installs it _globally_.
You can also install it _locally_, without `-g` but then the `node-streamline` and `coffee-streamline`
You can also install it _locally_, without `-g` but then the `_node` and `_coffee`
commands will not be in your default PATH.

Note: If you encounter a permission error when installing on UNIX systems, you should retry with `sudo`.

The global installation option makes `node-streamline` globally accessible but it does not expose the Javascript support
The global installation option makes `_node` globally accessible but it does not expose the Javascript support
modules (`runtime.js`, `flows.js`, etc.) globally.
If you need these modules anywhere in your development tree,
for example because you use streamline in shell scripts (see below),
Expand All @@ -102,98 +56,101 @@ cd $myworkdir
npm link streamline
```

If you want to use the _fibers_ option, you must also install the fibers library:
If you want to use the _fibers_ option (see below), you must also install the fibers library:

```sh
npm install fibers [-g]
```

# Creating and running streamline modules

The easiest way to write streamline code is to put the following line at the top of your module:
# Hello World

``` javascript
if (!require('streamline/module')(module)) return;
```
Streamline modules have `._js` or `._coffee` extensions and you run them with the `_node` or `_coffee`
loader.

Then you can use the `_` marker anywhere in your module:
Javascripters:

```javascript
function lineCount(path, _) {
return fs.readFile(path, "utf8", _).split('\n').length;
}
``` sh
echo "console.log('hello ...');" > hello._js
echo "setTimeout(_, 1000);" >> hello._js
echo "console.log('... world');" >> hello._js
_node hello
```

You can run your module with `node-streamline`:
Coffeescripters:

```sh
node-streamline myModule
``` sh
echo "console.log 'hello ...'" > hello._coffee
echo "setTimeout _, 1000" >> hello._coffee
echo "console.log '... world'" >> hello._coffee
_coffee hello
```

The code will be automatically transformed and the transformed files will be cached under `~/.streamline`.
You can also create standalone shell utilities:

You can also run your module with `node`:

```sh
node myModule
``` sh
echo "#!/usr/bin/env _node" > hello.sh
cat hello._js >> hello.sh
chmod +x hello.sh
./hello.sh
```

If you run with `node`, streamline will create (and delete) a temporary copy of your source file.
So you need r/w access to the module's directory.
Note that only the main module will be copied, the streamline modules that are _required_ by the main module
won't be copied so you don't need r/w access to all directories.

# Coffeescript
or:

Coffeescript is no different. You just need the following line at the top of your module:

```coffeescript
return if not require('streamline/module')(module)
``` sh
echo "#!/usr/bin/env _coffee" > hello.sh
cat hello._coffee >> hello.sh
chmod +x hello.sh
./hello.sh
```

And then you can run your module with:

```sh
coffee-streamline myModule
```
You can also create your own loader and run your program with `node` or `coffee`.
See the [loader example](http://sage.github.com/streamlinejs/examples/loader/loader.md)

or just, if you have r/w access to the module's directory (see `node` above):
# Generation options

```sh
coffee myModule
```
Streamline gives you the choice between generating regular callback-based asynchronous code,
or generating code that takes advantage of the [fibers library](https://github.com/laverdet/node-fibers).

# Shell scripts
The _callback_ option produces code that does not have any special runtime dependencies. You may even use it
to generate asynchronous code for the browser.

You can also use streamline to write shell scripts that call asynchronous node APIs.
You just need the following line at the top of your script:
The _fibers_ option produces simpler code but requires that you install
the fibers library (easy: `npm install fibers`).
This option gives superior development experience: line numbers are always preserved in the transformed code;
you can step with the debugger through asynchronous calls without having to go through complex callbacks, etc.
It may also generate more efficient code (to be confirmed by benchmarks).

```sh
#!/usr/bin/env node-streamline
```
The _fibers_ option can be activated by passing `--fibers` to the `_node` command or by
setting the `fibers` option when registering streamline
(see the `register(options)` function in `streamline/lib/compiler/register`).

# Interoperability with standard node.js code

For example:
You can call standard node functions from streamline code. For example the `fs.readFile` function:

```sh
#!/usr/bin/env node-streamline
console.log("waiting 1 second");
setTimeout(_, 1000);
console.log("done!");
```javascript
function lineCount(path, _) {
return fs.readFile(path, "utf8", _).split('\n').length;
}
```
You can also call streamline functions as if they were standard node functions. For example:

Note: you must install streamline with the `-g` option and you must `npm link` it at the top of your
development tree to make this work smoothly (see installation section above).

# Compilation setup (old style)
```javascript
lineCount("README.md", function(err, result) {
if (err) return console.error("ERROR: " + err.message);
console.log("README has " + result + " lines.");
});
```
And you can mix streamline functions, classical callback based code and synchrononous functions in the same file.
Streamline will only transform the functions that have the special `_` parameter.

You can also set up your modules to have the streamline source and the transformed Javascript side by side in
the same directory. To do this, you must append an underscore to your module's base name: `myModule_.js`.
Note: this works with both transformation options.
Even if you use the _fibers_ option, you can seamlessly call standard callback based node APIs
and the asynchronous functions that you create with streamline have the standard node callback signature.

This was the original setup. It is nice if you want to see the transformed code but it pollutes the directories
with extra files and it becomes messy when you start testing with both callback and fibers mode.
The callback output is called `myModule.js` and the fibers' output is called `myModule--fibers.js`.
# On-line demo

The [Compilers wiki page](https://github.com/Sage/streamlinejs/wiki/Compilers) gives details on this mode.
You can test `streamline.js` directly with the [on-line demo](http://sage.github.com/streamlinejs/examples/streamlineMe/streamlineMe.html)

# Browser-side use

Expand Down
1 change: 1 addition & 0 deletions bin/coffee-streamline
@@ -1,5 +1,6 @@
#!/usr/bin/env node

console.log("obsolete script: use _coffee instead.");
var coffee = require('coffee-script');
var path = require('path');
var fs = require('fs');
Expand Down
1 change: 1 addition & 0 deletions bin/node-streamline
@@ -1,3 +1,4 @@
#!/usr/bin/env node

console.log("obsolete script: use _node instead.");
require("streamline/lib/compiler/command").run();
3 changes: 3 additions & 0 deletions examples/loader/hello._js
@@ -0,0 +1,3 @@
console.log('hello ...');
setTimeout(_, 1000);
console.log('... world!');
22 changes: 22 additions & 0 deletions examples/loader/loader.js
@@ -0,0 +1,22 @@
/// !example
///
/// # Streamline loader example
///
/// The loader module must be a vanilla Javascript or CoffeeScript module
/// (`.js` or `.coffee` extension), not a streamline.js source because
/// it gets loaded before the extensions have been registered.
///
/// The loader module must register the streamline file extensions:
require('streamline/lib/compiler/register').register({
fibers: false,
cache: true,
verbose: true,
});
/// Once the extensions have been registered, the loader can require a streamline
/// module
require('./hello')
/// ## Running it
///
/// ``` sh
/// node streamline/examples/runner/runner
/// ```
30 changes: 30 additions & 0 deletions examples/loader/loader.md
@@ -0,0 +1,30 @@

# Streamline loader example

The loader module must be a vanilla Javascript or CoffeeScript module
(`.js` or `.coffee` extension), not a streamline.js source because
it gets loaded before the extensions have been registered.

The loader module must register the streamline file extensions:

``` javascript
require('streamline/lib/compiler/register').register({
fibers: false,
cache: true,
verbose: true,
});
```

Once the extensions have been registered, the loader can require a streamline
module

``` javascript
require('./hello')
```


## Running it

``` sh
node streamline/examples/runner/runner
```
19 changes: 0 additions & 19 deletions examples/misc/options_.coffee

This file was deleted.

7 changes: 0 additions & 7 deletions examples/misc/require.js

This file was deleted.

0 comments on commit 919bb7e

Please sign in to comment.