From 3214feb89ffca3e8432805c048b3879d0146b0c0 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 13 Aug 2016 13:45:12 -0400 Subject: start working on a simple repl --- bin/chartrepl | 7 ++ lib/Chart/Clicker/SQL/REPL.pm | 146 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100755 bin/chartrepl create mode 100644 lib/Chart/Clicker/SQL/REPL.pm diff --git a/bin/chartrepl b/bin/chartrepl new file mode 100755 index 0000000..10da400 --- /dev/null +++ b/bin/chartrepl @@ -0,0 +1,7 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use Chart::Clicker::SQL::REPL; + +Chart::Clicker::SQL::REPL->new->run; diff --git a/lib/Chart/Clicker/SQL/REPL.pm b/lib/Chart/Clicker/SQL/REPL.pm new file mode 100644 index 0000000..dca39f9 --- /dev/null +++ b/lib/Chart/Clicker/SQL/REPL.pm @@ -0,0 +1,146 @@ +package Chart::Clicker::SQL::REPL; +use Moose; +use 5.020; +use feature 'signatures', 'postderef'; +no warnings 'experimental::signatures'; +no warnings 'experimental::postderef'; + +use Browser::Open; +use File::HomeDir; +use File::Spec; +use File::Temp; +use Module::Runtime; +use Path::Class; +use Term::ReadLine; + +use Chart::Clicker::SQL; + +has sql => ( + is => 'rw', + isa => 'Chart::Clicker::SQL', + predicate => 'initialized', +); + +has history_file => ( + is => 'ro', + isa => 'Str', + default => sub { + my $filename = File::Spec->catfile( + File::HomeDir->my_data, + '.ccsql_history' + ); + file($filename)->touch; + return $filename; + }, +); + +has rl => ( + is => 'ro', + isa => 'Term::ReadLine', + lazy => 1, + default => sub ($self) { + my $rl = Term::ReadLine->new(__PACKAGE__); + for my $line (file($self->history_file)->slurp(chomp => 1)) { + $rl->addhistory($line); + } + return $rl; + }, +); + +has chart_options => ( + is => 'ro', + isa => 'HashRef', + default => sub { + { + width => 1000, + height => 600, + set_renderer => Chart::Clicker::Renderer::Line->new, + } + }, +); + +has last_query => ( + is => 'rw', + isa => 'Str', + predicate => 'has_last_query', +); + +sub dsn ($self, $dsn) { + $self->sql(Chart::Clicker::SQL->new(dsn => $dsn)); +} + +sub select ($self, $query) { + $query = "select $query"; + $self->last_query($query); + $self->_draw; +} + +sub _draw ($self) { + if (!$self->initialized) { + warn "not initialized"; + return; + } + if (!$self->has_last_query) { + warn "no active query"; + return; + } + my $chart = $self->sql->render($self->last_query); + $self->_configure_chart($chart); + my ($fh, $filename) = File::Temp::tempfile(SUFFIX => '.png', UNLINK => 1); + $chart->draw; + $fh->write($chart->rendered_data); + $fh->flush; + Browser::Open::open_browser("file://$filename"); +} + +sub size ($self, $size) { + my ($width, $height) = split ' ', $size; + $self->chart_options->{width} = $width; + $self->chart_options->{height} = $height; +} + +sub title ($self, $title) { + $self->chart_options->{title} = $title; +} + +for my $renderer (qw(Line StackedLine Bar StackedBar Area StackedArea Point)) { + __PACKAGE__->meta->add_method(lc($renderer) => sub ($self, $args) { + my $renderer_class = "Chart::Clicker::Renderer::$renderer"; + Module::Runtime::require_module($renderer_class); + $self->chart_options->{set_renderer} = $renderer_class->new; + $self->_draw; + }) +} + +sub _configure_chart ($self, $chart) { + $chart->get_context('default')->range_axis->tick_division_type("LinearRounded"); + for my $opt (keys $self->chart_options->%*) { + $chart->$opt($self->chart_options->{$opt}) + if $chart->can($opt); + } +} + +sub run ($self) { + while (1) { + if (defined(my $input = $self->rl->readline("> "))) { + next unless length($input); + chomp($input); + last if $input eq 'exit'; + my ($command, $args) = split(' ', $input, 2); + $self->$command($args); + } + else { + print "\n"; + last; + } + } +} + +sub DEMOLISH ($self, $igd) { + $self->rl->WriteHistory($self->history_file); +} + +__PACKAGE__->meta->make_immutable; +no Moose; + +1; -- cgit v1.2.3