#!/usr/bin/perl use strict; BEGIN { eval { require Gantry::Server; }; if ( $@ ) { my $msg = "\n You need to install Gantry, rerun Bigtop's Build.PL,\n" . " and reinstall Bigtop before using tentmaker.\n\n"; die $msg; } } use File::Spec; use Getopt::Long; use Gantry::Server; use IO::Prompt; use Bigtop::TentMaker qw{ -Engine=CGI -TemplateEngine=TT }; use Bigtop::TentMakerPath; use Bigtop::ScriptHelp::Style; $SIG{ INT } = \&trap_int; my $port = 8080; my $new_app_name; my $add_bigtop_file; my $style; GetOptions( 'port|p=s' => \$port, 'new|n=s' => \$new_app_name, 'add|a=s' => \$add_bigtop_file, 'style|s=s' => \$style, 'help|h' => \&help, ); my $action_flags = 0; $action_flags++ if $new_app_name; $action_flags++ if $add_bigtop_file; if ( $action_flags > 1 ) { die "--new and --add are incompatible\n"; } if ( $new_app_name and not Bigtop::ScriptHelp::valid_ident( $new_app_name ) ) { die "--new requires valid package name, '$new_app_name' is invalid.\n"; } if ( $add_bigtop_file and not -f $add_bigtop_file ) { die "--add requires valid input file,\n" . " couldn't read '$add_bigtop_file': $!\n"; } # You could do this with a Damianism: #my $file = ( $new_app_name ) ? '' # : ( $add_bigtop_file ) ? $add_bigtop_file # : shift || ''; # set the file name my $file; if ( $new_app_name ) { $file = ''; } elsif ( $add_bigtop_file ) { $file = $add_bigtop_file; } else { $file = shift || ''; } my $template_path = File::Spec->catfile( Bigtop::TentMakerPath->get_template_path(), 'tenttemplates' ); my $cgi = Gantry::Engine::CGI->new( { config => { root => $template_path, file => $file, }, locations => { '/', 'Bigtop::TentMaker' } } ); my $server = Gantry::Server->new( $port ); $server->set_engine_object( $cgi ); my $space = ' '; my $ascii_art = join $space, @ARGV; $ascii_art =~ s/^\s+//; $ascii_art =~ s/\s+$//; my $script_help_style = Bigtop::ScriptHelp::Style->get_style( $style ); eval { Bigtop::TentMaker->take_performance_hit( $script_help_style, $file, $ascii_art, $new_app_name ); }; if ( $@ and $file =~ /^\d+$/ ) { die "usage: tentmaker [--port 8089] [options] [file]\n"; } elsif ( $@ ) { die "$@\n"; } $server->run(); sub trap_int { # see if there are changes exit unless Bigtop::TentMaker->dirty(); @ARGV = (); # IO::Prompt uses @ARGV, don't let it my $response = ''; my $prompt = "\n\nYou hit CTRL-C, would you like to save changes? "; while ( length $response == 0 ) { $response = prompt $prompt; $response =~ s/\W+|\s+//gms; $response =~ s/A//; $prompt = "\nPlease answer yes or no. "; } if ( $response =~ /^y/i ) { my $file = Bigtop::TentMaker->get_file() || 'tmp.bigtop'; open my $OUTPUT, '>', $file or die "I couldn't write the changes\n"; print $OUTPUT Bigtop::TentMaker->deparsed(); close $OUTPUT; print STDERR "Saved $file\n"; } exit; } sub help { print <<"EO_HELP"; If you already have a bigtop file and don't need new tables: tentmaker filename.bigtop If you already have a bigtop file but need new tables: tentmaker -a filename.bigtop 'new_table->old_table' If you are starting from scratch: tentmaker -n AppName [ 'table_list->including_relationships' ] If you don't want port 8080: add -p your_port_number to any of the above (for example): tentmaker -p 8192 filename.bigtop EO_HELP exit; } =head1 NAME tentmaker - browser based bigtop file editor =head1 USAGE tentmaker [ --port=8192 ] [ file ] Or, to name a new app with optional table layout: tentmaker --new AppName style_info Or, to augment an existing bigtop file: tentmaker --add file.bigtop style_info See L below for what style_info can be. =head1 DESCRIPTION This script is a simple web server. Tell it what file you want to edit (or start from scratch) and an optional port (defaults to 8080). Point your browser to that port and edit away. =head1 OPTIONS =over 4 =item --port (or -p) Specifies a port for the server. Defaults to 8080. =item --new (or -n) Allows you to specify the name of the app and optionally its table relationships. Requires a name for the app. The rest of the command line arguments are depend on what style you use, see L. Normally this flag uses the default bigtop file from L. For your convenience, you can see it in examples/default.bigtop. To override it, copy that file to bigtopdef in the directory where you invoke tentmaker -n, or to .bigtopdef in your home directory. Edit the file to your heart's content. The result must be a valid bigtop file, with one exception. The file you create will be used as a template toolkit template. But, only three things are available for subsitution: =over 4 =item app_name The name of the app from the command line. =item no_colon_name The app name, where all ::'s are replaced with underscores. =item short_name Everything after the last :: in the app_name in lower case. =back For example see examples/def.bigtop.tt. =item --add (or -a) Allows you to augment an existing bigtop file prior to editing it. Requires a bigtop file name. The rest of the command line arguments as the same as for -n, see L. =item --style (or -s) Defaults to Original. Specifies which Bigtop::ScriptHelp::Style:: module will handle extra command line arguements and standard input. See your Style module's docs for details. =back =head1 STYLES Any command line arguments not consumed by the options above are passed to your style backend. If you don't use -s, the Original style is used. If you do use -s, whatever style you choose is used. All styles live in the Bigtop::ScriptHelp::Style:: namespace. See their individual docs for what they know how to do. This section used to be called "ASCII ART," the code which supported that got factored out and became the default style C. See it for details on ASCII art. =head1 AUTHOR Phil Crow =head1 COPYRIGHT and LICENSE Copyright (C) 2006 by Phil Crow This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available. =cut