Skip to content

dhamidi/proj

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Proj

Name

proj /prɔʣ/ – create files and directories based on templates.

Description

Proj is a tool born from the desire to automate the tedious tasks when starting to work on a website. Proj creates files and directories based on so called “templates” which define a directory structure and actions to perform after processing a template, such as initializing a git repository. Templates are general enough to be useful for any kind of task that benefits from any sort of scaffolding.

Proj tries to not break any things and does not overwrite any files by default. Single files can be overwritten in the target directory by explicitly saying so in the template. If anything goes wrong during the processing of a template, all files created so far are deleted in order to not leave the target directory in any inconsistent state.

Installation

  1. Put the contents of the lib directory into a location on your PERL5LIB.
  2. Copy bin/proj-create to a directory on your PATH.
  3. Copy examples to ~/.proj.d as a starting point for creating your own templates.
  4. Run proj-create static-site to create the skeleton for a static website in the current directory.

Usage

Templates are processed with proj-create:

proj-create [[-i|--include] INCLUDE] TEMPLATE [DEFINITION ...]

The option -i adds directory INCLUDE to the list of directories to search for templates. The -i option can be used more than once. TEMPLATE is the name of the template to create. DEFINITION is a key-value pair separated by an equal sign, e.g. title=Foo. All current environment variables and definitions are made available as variables within files processed by Template Toolkit.

By default, proj-create looks for templates in $HOME/.proj.d and the directories given in the environment variable PROJ_PATH. Multiple directories can be given in that variable by separating them with a colon (:).

Before running, proj-create evaluates the file $HOME/.proj.pl as perl code if it exists. Currently this is only useful for adding new handlers.

Templates

Templates are regular perl code that is evaluated when processing a template. Proj is instrumented by setting certain variables in the template, but any perl code can be used in a template. Each template requires an additional directory of the same name suffixed with .d to exist. This directory contains all the files referenced in the template.

$tree = [
  [ dir => html =>
      [ file => 'index.html' ]],
  [ dir => template =>
      [ file => 'default.html.tt' ]],
  [ dir => css =>
      [ file  => "devel.css" ],
      [ file  => "yaml" ],],
  [ dir => js =>
      [ http => 'code.jquery.com/jquery.min.js'],
      [ http => 'html5shim.googlecode.com/svn/trunk/html5.js'],
      [ http => 'code.jquery.com/jquery.js'],],
  [ dir => 'images' ],
  [ dir => 'perl'   ],
  [ dir => 'cgi-bin'],
  [ dir => 'log'    ],
  [ dir => 'tmp'    ],
  [ dir => 'conf',
    [ file => 'lighttpd.conf' ]],
];

$after = [
  'git init',
  'git add .',
  'git commit -m "initial commit"',
 ];

The following variables have a special meaning in templates:

$tree
this variable describes the directory structure that is to be created. Its value has to be an arrayref of entries, where each entry is of the form [ $HANDLER, @ARGS ]. $HANDLER names a function in the package Proj::Handler and @ARGS are the arguments passed to that function. If any coderefs in an entry are replaced by the value obtained by calling the referenced function without arguments.
$before, $after
these variables provide hooks for running code or shell commands before and after the structure defined in $tree has been created. Their values are arrayrefs of strings or coderefs. A string is taken as a shell command and executed with system, a coderef is called without arguments.

Templates are evaluated within the package Proj::Template, so any functions defined in that packed can be used in the template without importing any modules. One function, extends, is defined by default in that package. It takes a list (NB! not an arrayref) of template names and creates those in the current directory. This is mainly useful for extending templates (e.g. to customize shared templates for the local environment).

Handlers

The following handlers are defined by default for use in $tree entries:

dir $name @children
creates directory $name and processes child entries @children. The current directory is set to $name while processing @children.

Example:

$tree = [
  [ dir => 'foo',
    [file => 'bar']],
];
    
file $name \%options
creates file $name by copying it from the template directory. There are four locations relative to the template directory that are checked in order to find the source file for $name (where $CWD is the current directory relative to the template directory):
LocationExample
$name.ttbar.tt
$namebar
$PWD/$name.ttfoo/bar.tt
$PWD/$namefoo/bar

The first existing file is used. If the file name equal $name.tt, then the file will be processed as a Template Toolkit template.

If $options->{overwrite} is set to a true value, $name in the target directory will be overwritten if it exists.

http $url $filename
Uses LWP::Simple::mirror($url) in the template directory before copying the file named in $url to the target directory. If $filename is given, it will be used as the target file name instead.

Example:

[http => 'code.jquery.com/jquery.js']
    

Adding new handlers

It is possible to define own handlers with the function defhandler in the proj configuration file (~/.proj.pl). defhandler takes two arguments: the name of the new handler and a coderef to associate with that name. It is basically just syntactic sugar for installing functions into Proj::Handler.

A function installed with defhandler is called with a variable number of arguments. The first argument is always a instance of Proj, all other arguments are taken from the entry in $tree, excluding the handler name. The current working directory is set according to the location in $tree. If the handler creates any files that should be deleted in case of error, those file names should be registered with the _register(@filenames) method of the Proj instance. To abort the processing of the current template, use the _fail($message) method of the Proj instance. This exits the program with exit code 1 and removes all files created during this run.

A git handler that clones a repository if it doesn’t exist already and otherwise pulls the newest version could look like this:

# in file ~/.proj.pl
defhandler git => sub {
  my ($proj,$repo_url,$opts) = @_;

  my $repo_name = (split '/',$repo_url)[-1];

  if (-e $repo_name) {
    $proj->_diag("pull $repo_url");
    qx{pushd $repo_name; git pull; popd};
  }
  else {
    $proj->_diag("clone $repo_url");
    $opts ||= '';
    qx{git clone $opts $repo_url};
  }

};

Todo

  • add on-line help to proj-create
  • add comments to the code
  • add “sync” handler for just copying files/directories (maybe with rsync if available)
  • make the “http” handler operate on the current directory, not the template source directory
  • react to UNIX signals (e.g. clean up on SIGKILL or SIGINT)

Requires

Proj requires the following perl modules to be installed:

  • Template
  • LWP::Simple

Source Code

The source code for Proj can be found on github: http://github.com/dhamidi/proj.

License & Copyright

Copyright (C) 2013 Dario Hamidi <dario.hamidi@gmail.com>.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

About

create files and directories based on templates

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages