App-Chart

 view release on metacpan or  search on metacpan

chart  view on Meta::CPAN

#!perl -w

# Copyright 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2018, 2024 Kevin Ryde

# This file is part of Chart.
#
# Chart is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3, or (at your option) any later version.
#
# Chart is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with Chart.  If not, see <http://www.gnu.org/licenses/>.

use 5.010;
use strict;
use warnings;

# BEGIN {
#   use Carp; # 0.22 needs this pre-loaded for the prototypes
#   $ENV{'LIST_MOREUTILS_PP'} = 1;
# }
use File::Spec;
use Getopt::Long;
use Glib 1.200; # for strerror()
use Encode;
use Encode::Locale 0.02;  # version 0.02 for console_in,console_out
use List::Util qw(min max);
use Locale::Messages;
use Locale::TextDomain 'App-Chart';

use App::Chart;
$|=1;

# uncomment this to run the ### lines
# use Smart::Comments;

if (@ARGV >= 1 && ($ARGV[0] eq '--subprocess' || $ARGV[0] eq '--emacs')) {
  binmode (STDOUT, ':utf8') or die;
  binmode (STDERR, ':utf8') or die;

} else {
  # locale encoding conversion on the tty, wide-chars everywhere internally
  require Encode::Locale;
  require PerlIO::encoding;
  unless (binmode(STDIN, ":encoding(console_in)")
          && binmode(STDOUT, ":encoding(console_out)")) {
    warn "Cannot set :encoding on stdin/out: $!\n";
  }
  # Not sure coding on STDERR is a good idea, could loop trying to print.
  # binmode(STDERR, ":encoding(console_out)")

  # Old code:
  #
  # # version 0.06 for bug fix of a struct size for perl 5.10 (there's some
  # # fragile duplication)
  # require Encode;           # Encode::PERLQQ
  # require PerlIO::locale; PerlIO::locale->VERSION(0.06);
  # { no warnings 'once';
  #   local $PerlIO::encoding::fallback = Encode::PERLQQ; # \x{1234} style
  #   (binmode (STDOUT, ':locale') && binmode (STDERR, ':locale'))
  #     or die "Cannot set :encoding on stdout/stderr: $!\n";
  # }
  # Makefile: 'PerlIO::locale' => '0.06',
  # , libperlio-locale-perl (>= 0.06)
}

my $option_output;
my $option_mode;
my @args;

{
  # callback option arg in perl 5.8 is a string, but in 5.10 it's a
  # Getopt::Long::Callback object, must stringize to get the plain name
  my $set_mode = sub {
    my ($opt) = @_;
    if ($option_mode) {
      print STDERR __x("chart: already got mode option --{mode}\n",
                       mode => $option_mode);
      exit 1;
    }
    $option_mode = "$opt";
  };
  my $set_output = sub {
    my ($opt) = @_;
    if ($option_output) {
      print STDERR __x("chart: already got output option --{output}\n",
                       output => $option_output);
      exit 1;
    }
    $option_output = "$opt";
  };
  my $add_symlist = sub {
    my ($opt) = @_;
    my $key = "$opt";
    if ($key eq 'favorites') { $key = 'favourites'; }
    require App::Chart::Gtk2::Symlist;
    push @args, App::Chart::Gtk2::Symlist->new_from_key ($key);
  };
  my $help = sub {
    print __("chart [--options] [SYMBOL...]\n");
    my @opts =
      (['-h, --help',    __('Print this help')],
       ['-v, --version', __('Print Chart version')],
       ['--verbose',     __('Print extra messages')],
       ['--download',    __('Download data for selected symbols, don\'t run the GUI')],
       ['--ticker',      __('Run just the stock ticker, on selected symbols')],
       ['--all',         __('Select all symbols')],
       ['--alerts',      __('Select alerts list symbols')],
       ['--favourites',  __('Select favourites list symbols')],
       ['--display=DPY',
        __("X display to use (default DISPLAY environment variable)")],
       ['--<gtk-options>', __('Standard Gtk options')]);
    my $width = 2 + max (map { length ($_->[0]) } @opts);
    foreach (@opts) {
      printf "%-*s%s\n", $width, $_->[0], $_->[1];
    }
    print "\n";
    print __"When running the GUI, the SYMBOL argument is an initial chart to show\n(can be a partial match, as in the open dialog).\n";
    print __"When running download or ticker, the SYMBOL... arguments select specific\nsymbols to show or download (must be full symbols, no partial matches).\n";
    exit 0;
  };

  GetOptions (require_order => 1,
              'help|?' => $help,
              version => sub {
                print "chart version $App::Chart::VERSION\n";
                exit 0;
              },
              all        => $add_symlist,
              favourites => $add_symlist,
              favorites  => $add_symlist,
              historical => $add_symlist,
              alerts     => $add_symlist,
              '<>'       => sub { my ($value) = @_;
                                  # stringize to avoid Getopt::Long object
                                  push @args, "$value";
                                },
              download   => $set_mode,
              ticker     => $set_mode,
              watchlist  => $set_mode,
              subprocess => $set_mode,  # undocumented
              emacs      => $set_mode,  # undocumented
              vacuum     => $set_mode,  # undocumented yet

              'verbose:i' => sub {
                my ($opt, $value) = @_;
                if ($value==0) {
                  $App::Chart::option{'verbose'}++;
                } else {
                  $App::Chart::option{'verbose'} = $value;
                }
              },
              'all-status' => $set_output,  # undocumented

              'lwp-debug' => sub {
                require LWP::Debug;
                LWP::Debug::level('+');
              },
             )
    or exit 1;
}

# $filename is in filesystem charset bytes.
#
# The file should end with some non-undef value, since otherwise it's
# indistinguishable from undef for the various do/require errors.
#
sub initfile {
  my ($filename) = @_;
  if (! -e $filename) { return; }
  $! = 0;
  my $ret = do $filename;
  if (! defined $ret) {
    my $display_filename = Glib::filename_display_name($filename);
    if ($@) {
      my $err = $@;
      unless (utf8::is_utf8($err)) { $err = Encode::decode('locale',$err); }
      print __x("chart: error in {filename}\n{error}\n  (starting anyway)\n",
                filename => $display_filename,
                error => $err);
    } elsif ($! != 0) {
      my $err = Glib::strerror($!);
      print __x("chart: cannot read {filename}: {error}\n  (starting anyway)\n",
                filename => $display_filename,
                error => $err);
    } else {
      print __x("chart: {filename} didn't end with a true value\n",
                filename => $display_filename);
    }
  }
}

$option_mode   ||= 'gui';
$option_output ||= 'tty';

unshift @INC, File::Spec->catdir (App::Chart::chart_directory(), 'lib');
initfile (File::Spec->catfile (App::Chart::chart_directory(), 'init.pl'));

if ($option_mode eq 'gui') {
  # default is the gui
  require App::Chart::Gtk2::Main;
  App::Chart::Gtk2::Main->main (\@args);

} elsif ($option_mode eq 'download') {
  require App::Chart::Download;
  App::Chart::Download->command_line_download ($option_output, \@args);

} elsif ($option_mode eq 'subprocess') {
  require App::Chart::SubprocessMain;
  App::Chart::SubprocessMain->main ();

} elsif ($option_mode eq 'vacuum') {
  require App::Chart::Vacuum;
  App::Chart::Vacuum->command_line_vacuum ($option_output, \@args);

} elsif ($option_mode eq 'emacs') {
  require App::Chart::EmacsMain;
  App::Chart::EmacsMain->main ();

} elsif ($option_mode eq 'watchlist') {
  require App::Chart::Gtk2::WatchlistDialog;
  App::Chart::Gtk2::WatchlistDialog->main (\@args);

} elsif ($option_mode eq 'ticker') {
  require App::Chart::Gtk2::TickerMain;
  App::Chart::Gtk2::TickerMain->main (\@args);
}

exit 0;

__END__

=for stopwords Gtk BHP BHP.AX bh wildcards Wildcards filenames tty ie watchlist Watchlist --watchlist SQLite Ryde

=head1 NAME

chart -- Stock and commodity price charting and downloading



( run in 1.143 second using v1.01-cache-2.11-cpan-ceb78f64989 )