Rotor
Rotor is a build system for Elixir projects. Use it to compile things, run commands or do anything that needs to be run when files change.
Wreckers don’t call for backup, they call for cleanup ~!
Example: Compile CoffeeScript files whenever they change
paths = ["assets/libs/*.coffee", "assets/*.coffee"]
Rotor.watch :coffee_assets, paths, fn(changed_files, all_files)->
read_files(all_files)
|> coffee
|> concat
|> write_to("priv/static/assets/app.js")
end
touch a file that’s in the path provided and watch the Rotor function being run.
The above example uses the coffee_rotor.
NOTE: Rotor is not a replacement for mix. It is intended to be used as your sidekick during development.
Features
- Works with any web framework or even plain mix projects
- Easy to use
- Extendable with simple functions
- Can be configured to run commands or code or go to the moon.
- Inspired by gulp
Usage
A set of paths you want to watch is called a watch group. Each watch group has the following
- name
- a list of paths to watch
-
a function, which we’ll call the rotor function, that is run everytime any of the files in the paths changes. It should accept 2 arguments
- changed_files - a list of maps, each containing info about changed files
- all_files - a list of maps, each containing info about all files that matched the path
Adding watch groups
# With default options
Rotor.watch(name, files, rotor_function)
# With options
Rotor.watch(name, files, rotor_function, options)
The rotor function is passed info about the list of files that match the paths specified. The rotor function calls other little functions called rotors, that run certain tasks.
paths = ["assets/javascripts/libs/*.js", "assets/javascripts/*.js"]
Rotor.watch :javascripts, paths, fn(changed_files, all_files)->
read_files(all_files)
|> concat
|> write_to("priv/static/assets/app.js")
endThe fourth argument is options. It accepts a map. The following are valid options:
manual- defaults to false. If set to true, paths will only be polled whenRotor.run/1orRotor.run_async/1is called.interval- defaults to 2500 milliseconds (2.5 seconds). This is the interval at which files are checked for changes.
Manually running rotors
If you want files to be polled only when you say so (and not at intervals). Then pass the manual option as true when adding a group. Then use one of the following functions to trigger a poll.
Rotor.run(group_name)- will poll paths and run the Rotor function synchronouslyRotor.run_async(group_name)- will poll paths and run the Rotor function asynchronously
Rotors
Rotor ships with a few simple rotors in the Rotor.Basic module.
read_files(files)- reads contents of files, and returns files with a property calledcontentscopy_files(files, destination_dir)- copies files to destination_dirconcat(files)- concats contents of files and returns a stringwrite_to(contents, output_path)- writes the contents to the file path specified in output path
You can also write your own. Check the “Writing custom rotors” section below.
Other stuff
To remove a watch group
Rotor.stop_watching(group_name)To list groups
Rotor.groupsTo run a watch group’s rotor functions forcefully
Rotor.run(group_name)
Examples
paths = ["assets/stylesheets/libs/*.css", "assets/stylesheets/*.css"]
Rotor.watch :stylesheets, paths, fn(changed_files, all_files)->
read_files(all_files)
|> concat
|> write_to("app.css")
end
paths = ["assets/images/*", "assets/fonts/*"]
Rotor.watch :images_and_fonts, paths, fn(changed_files, all_files)->
copy_files(files, "priv/static/assets")
endWriting custom rotors
Rotors are just functions that accept data and do something.
Checkout coffee_rotor, which provides a rotor to compile CoffeeScript files.
License
Copyright © 2014, Akash Manohar J, under the MIT License