view release on metacpan or search on metacpan
Changes
lib/App/FQStat.pm
lib/App/FQStat/Actions.pm
lib/App/FQStat/Colors.pm
lib/App/FQStat/Config.pm
lib/App/FQStat/Debug.pm
lib/App/FQStat/Drawing.pm
lib/App/FQStat/Input.pm
lib/App/FQStat/Menu.pm
lib/App/FQStat/PAR.pm
lib/App/FQStat/Scanner.pm
lib/App/FQStat/System.pm
Makefile.PL
MANIFEST This list of files
README
script/fqstat.pl
t/App-FQStat.t
META.yml Module meta-data (added by MakeMaker)
lib/App/FQStat.pm view on Meta::CPAN
use strict;
use warnings;
use App::FQStat::Actions;
use App::FQStat::System;
use App::FQStat::Config;
use App::FQStat::Colors;
use App::FQStat::Scanner;
use App::FQStat::Input;
use App::FQStat::Drawing;
use App::FQStat::Menu;
use App::FQStat::PAR;
use App::FQStat::Debug ();
1;
__END__
=head1 NAME
lib/App/FQStat/Actions.pm view on Meta::CPAN
warnenter if ::DEBUG;
cls();
my $heading = get_color("menu_normal");
my $h = get_color("warning");
my $r = RESET;
print <<"HERE";
${heading} fqstat v$App::FQStat::VERSION - Interactive front-end for qstat $r
Commands:
${h}'h' ${r} Show this (H)elp screen
${h}'q' ${r} (Q)uit
${h}F10 ${r} Show Menu
${h}F5 ${r} Refresh data from qstat and redraw
${h}'S' ${r} Toggle Summary Mode
${h}Up- / Down-Arrow${r} Scroll up/down if possible
${h}Page-Up / -Down ${r} Scroll one page up/down if possible
${h}Pos1 / End ${r} Jump to beginning / end
${h}Space / Enter ${r} Show detailed job info
${h}'u' ${r} Enter (U)ser name whose jobs to display
${h}'H' ${r} (H)ightlight a user's jobs
${h}'i' ${r} Set the desired update (I)nterval
lib/App/FQStat/Drawing.pm view on Meta::CPAN
# draws the first, title line
sub draw_title_line {
warnenter if ::DEBUG > 1;
locate(1,1);
my $line;
my $summary_mode = $::SummaryMode;
if ($::MenuMode) {
print get_color("menu_normal");
$line = App::FQStat::Menu::get_menu_title_line();
}
elsif ($summary_mode) {
lock($::Interval);
my $progress = ::PROGRESS_INDICATORS()->[$::ProgressIndicator];
$progress = ' ' if not defined $progress;
$line = sprintf(
'fqstat v%.1f %s Jobs:%i Upd:%.1fs [S]witch [F10] Menu ' . get_color('header_highlight') . 'Summary Mode' . RESET . ', Nodes:%i',
$App::FQStat::VERSION||0,
$progress,
scalar(@{$::Records})||0,
$::Interval||0,
$::NoActiveNodes||0,
);
}
else {
lock($::RecordsReversed);
lock($::Interval);
lib/App/FQStat/Drawing.pm view on Meta::CPAN
# reversed list indicator
my $status = get_color('reverse_indicator').'[';
if ($::RecordsReversed) { $status .= 'R' }
if ($status =~ /\[$/) { $status = '' }
else { $status .= ']'.RESET.' ' }
my $progress = ::PROGRESS_INDICATORS()->[$::ProgressIndicator];
$progress = ' ' if not defined $progress;
$line = sprintf(
'fqstat v%.1f %s %s%sJobs:%i Upd:%.1fs [h]elp [F10] Menu (c) S. Mueller, Nodes:%i',
$App::FQStat::VERSION||0,
$progress,
$status||'',
(defined($::User) ? "User:$::User " : ""),
scalar(@{$::Records})||0,
$::Interval||0,
$::NoActiveNodes||0,
);
}
::GetTermSize();
$line = substr($line, 0, $::Termsize[0]) if $::Termsize[0] < length($line);
printline($line);
print RESET if $::MenuMode;
}
# draws the column header line
sub draw_header_line {
warnenter if ::DEBUG > 1;
my @highlight = @_;
my %highlight = map {($_ => 1)} @highlight;
# Header Line
locate(2,1);
lib/App/FQStat/Drawing.pm view on Meta::CPAN
draw_title_line(); # first line
draw_header_line(); # second line
my $summary_mode = $::SummaryMode;
if ($summary_mode) {
draw_summary();
} else {
draw_job_display(); # list of jobs
}
if ($::MenuMode) {
App::FQStat::Menu::draw_menu();
}
locate(1,1);
}
# Draws the job summary
sub draw_summary {
warnenter if ::DEBUG;
# before there's any jobs, warn the user that the
lib/App/FQStat/Menu.pm view on Meta::CPAN
package App::FQStat::Menu;
# App::FQStat is (c) 2007-2009 Steffen Mueller
#
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
use strict;
use warnings;
use Term::ANSIScreen qw/RESET :cursor/;
use App::FQStat::Debug;
use App::FQStat::Config qw(get_config);
use App::FQStat::Colors qw(get_color);
use base 'Exporter';
our %EXPORT_TAGS = (
'all' => [qw(
)],
);
our @EXPORT_OK = @{$EXPORT_TAGS{'all'}};
our @Menus = (
{ width => 11, name => 'Display', entries => [
{ name => 'Summary', action => \&App::FQStat::Actions::toggle_summary_mode },
{ name => 'Summ.Clust.', action => \&App::FQStat::Actions::toggle_summary_name_clustering },
{ name => 'Refresh', action => sub { App::FQStat::Drawing::update_display(1) } },
{ name => 'Sort', action => \&App::FQStat::Actions::select_sort_field },
{ name => 'Reverse', action => \&App::FQStat::Actions::toggle_reverse_sort },
{ name => 'Interval', action => \&App::FQStat::Actions::set_user_interval },
{ name => 'Highl. User', action => \&App::FQStat::Actions::update_highlighted_user_name },
{ name => 'Job Details', action => \&App::FQStat::Actions::show_job_details, },
{ name => 'Job Log', action => \&App::FQStat::Actions::show_job_log, },
lib/App/FQStat/Menu.pm view on Meta::CPAN
], },
{ width => 5, name => 'Help', entries => [
{ name => 'Help', action => \&App::FQStat::Actions::show_manual, },
{ name => 'About', action => \&App::FQStat::Actions::show_manual, },
], },
{ width => 6, name => 'Config', entries => [
{ name => 'Edit', action => \&App::FQStat::Config::edit_configuration, },
{ name => 'Reset', action => \&App::FQStat::Config::reset_configuration, },
], },
{ width => 4, name => 'Quit', entries => [
{ name => 'Menu', action => \&App::FQStat::Menu::close_menu, },
{ name => 'Quit', action => \&main::cleanup_and_exit, },
], },
{
width => 8, name => 'Colors', entries => \&App::FQStat::Colors::get_color_scheme_menu_entries,
nEntries => \&App::FQStat::Colors::get_n_color_scheme_entries,
},
);
# Set cumulative width
{
my $width = 0;
foreach my $menu (@Menus) {
$menu->{startx} = $width+1;
$width += $menu->{width} + 2;
}
}
sub enter_menu {
warnenter if ::DEBUG > 0;
$::MenuMode = 1;
$::MenuNumber = 0;
$::MenuEntryNumber = 0;
App::FQStat::Drawing::update_display(@_);
}
sub close_menu {
warnenter if ::DEBUG > 0;
$::MenuMode = 0;
App::FQStat::Drawing::update_display(@_);
}
sub toggle_menu {
warnenter if ::DEBUG > 0;
$::MenuMode = ($::MenuMode ? 0 : 1);
$::MenuNumber = 0;
$::MenuEntryNumber = 0;
App::FQStat::Drawing::update_display(@_);
}
sub get_menu_title_line {
warnenter if ::DEBUG > 1;
my $line;
foreach my $menu_no (0..$#Menus) {
my $menu = $Menus[$menu_no];
my $name = $menu->{name};
$line .= " " . $name;
$line .= " " x ($menu->{width} - length($name) + ($menu_no != $#Menus ? 1 : 0));
}
return $line;
}
sub draw_menu {
warnenter if ::DEBUG > 0;
my $width = 1;
my $menu = $Menus[$::MenuNumber];
my $thisEntries = $menu->{entries};
$thisEntries = $thisEntries->() if ref($thisEntries) eq 'CODE';
my $startx = $menu->{startx};
draw_menubox($startx, $startx + $menu->{width}+2, $menu->{name}, $thisEntries, $::MenuEntryNumber);
locate(1, 1);
}
sub draw_menubox {
warnenter if ::DEBUG > 1;
my ($x1, $x2, $title, $entries, $selentry) = @_;
locate(1, $x1);
my $width = $x2-$x1;
lib/App/FQStat/Menu.pm view on Meta::CPAN
print $thiscolor . $name . RESET;
$y++;
}
#locate($y, $x1);
#print $color . (" "x($width)) . RESET;
}
sub menu_up {
warnenter if ::DEBUG > 1;
return if not $::MenuMode;
if ($::MenuEntryNumber == 0) {
my $max_entry = menu_entries() - 1;
$::MenuEntryNumber = $max_entry;
}
else {
$::MenuEntryNumber--;
}
return 1;
}
sub menu_down {
warnenter if ::DEBUG > 1;
return if not $::MenuMode;
my $max_entry = menu_entries() - 1;
if ($::MenuEntryNumber == $max_entry) {
$::MenuEntryNumber = 0;
}
else {
$::MenuEntryNumber++;
}
return 1;
}
sub menu_right {
warnenter if ::DEBUG > 1;
return if not $::MenuMode;
my $max_menu = @Menus - 1;
if ($::MenuNumber == $max_menu) {
$::MenuNumber = 0;
}
else {
$::MenuNumber++;
}
$::MenuEntryNumber = 0;
return 1;
}
sub menu_left {
warnenter if ::DEBUG > 1;
return if not $::MenuMode;
if ($::MenuNumber == 0) {
my $max_menu = @Menus - 1;
$::MenuNumber = $max_menu;
}
else {
$::MenuNumber--;
}
$::MenuEntryNumber = 0;
return 1;
}
sub menu_select {
warnenter if ::DEBUG > 1;
return if not $::MenuMode;
my $menu = $Menus[$::MenuNumber];
my $entries = $menu->{entries};
$entries = $entries->() if ref($entries) eq 'CODE';
my $entry = $entries->[$::MenuEntryNumber];
my $action = $entry->{action};
$::MenuMode = 0;
App::FQStat::Drawing::update_display();
return $action->($entry);
}
sub menu_entries {
return @{ $Menus[$::MenuNumber]->{entries} } if ref($Menus[$::MenuNumber]->{entries}) eq 'ARRAY';
my $nentries = $Menus[$::MenuNumber]->{nEntries};
$nentries = $nentries->() if defined($nentries) and ref($nentries) eq 'CODE';
return $nentries;
}
1;
script/fqstat.pl view on Meta::CPAN
ReadMode 3;
$|=1;
##############
# Declare globals
# action & key globals
use constant KEY_POLL_INTERVAL => 0.2; # blocking time for keyboard polling
our %Keys; # hash of key => action for main loop
our %ControlKeys; # hash of control key id => action for main loop
our %MenuKeys; # hash of key => action for menu
our %MenuControlKeys; # hash of control key id => action for menu
our %SummaryKeys;
our %SummaryControlKeys;
# twiddly globals
use constant PROGRESS_INDICATORS => ['-', '\\', '|', '/']; # progress indicator states
our $ProgressIndicator = 0; # progress indicator current state number
# displaying globals
our $Initialized = 0;
our @Termsize : shared; # holds terminal size
script/fqstat.pl view on Meta::CPAN
our $Interval : shared; # Effective data refreshing interval. Do not change. Is set to $UserInterval below
our $HighlightUser;
{
my $curuser = $ENV{USER};
if (defined $curuser) {
$HighlightUser = quotemeta($curuser);
}
}
# application mode globals
our $MenuMode = 0; # in menu or not
our $SummaryMode :shared = App::FQStat::Config::get("summary_mode") || 0; # in summary mode or not
# menu globals
our $MenuNumber = 0; # which menu (see @App::FQStat::Menu::Menus)
our $MenuEntryNumber = 0; # in which entry of that menu
# Displayed column descriptions
our %Columns = (
prio => { format => '%.5f', width => 7, name => 'Prio', key => 'prio', 'index' => F_prio, order => 'num_highlow' },
name => { format => '%-10s', width => 10, name => 'Name', key => 'name', 'index' => F_name, order => 'alpha' },
user => { format => '%-12s', width => 12, name => 'Owner', key => 'user', 'index' => F_user, order => 'alpha' },
id => { format => '%7u', width => 7, name => 'Id', key => 'id', 'index' => F_id, order => 'num' },
date => { format => '%-10s', width => 10, name => 'Date', key => 'date', 'index' => F_date, order => 'date' },
'time' => { format => '%-8s', width => 8, name => 'Time', key => 'time', 'index' => F_time, order => 'time' },
script/fqstat.pl view on Meta::CPAN
BEGIN {
%ControlKeys = (
'A' => sub { App::FQStat::Actions::scroll_up(1); 1 }, # up
'B' => sub { App::FQStat::Actions::scroll_down(1); 1 }, # down
'5' => sub { App::FQStat::Actions::scroll_up($Termsize[1]-4); 1 }, # pgup
'6' => sub { App::FQStat::Actions::scroll_down($Termsize[1]-4); 1 }, # pgdown
'H' => sub { App::FQStat::Actions::scroll_up(1e9); 1 }, # pos1 (640kb ought to be enough for everyone!)
'F' => sub { App::FQStat::Actions::scroll_down(1e9); 1 }, # end (640kb ought to be enough for everyone!)
'15' => sub { App::FQStat::Drawing::update_display(1) }, # F5
'21' => sub { App::FQStat::Menu::toggle_menu() }, # F10
);
%Keys = (
'q' => \&cleanup_and_exit,
'i' => \&App::FQStat::Actions::set_user_interval,
'H' => \&App::FQStat::Actions::update_highlighted_user_name,
'r' => \&App::FQStat::Actions::toggle_reverse_sort,
's' => \&App::FQStat::Actions::select_sort_field,
'u' => \&App::FQStat::Actions::update_user_name,
'k' => \&App::FQStat::Actions::kill_jobs,
script/fqstat.pl view on Meta::CPAN
'?' => \&App::FQStat::Actions::show_manual,
'c' => \&App::FQStat::Actions::clear_job_error_state,
'd' => \&App::FQStat::Actions::change_dependencies,
' ' => \&App::FQStat::Actions::show_job_details,
"\n" => \&App::FQStat::Actions::show_job_details,
'l' => \&App::FQStat::Actions::show_job_log,
'S' => \&App::FQStat::Actions::toggle_summary_mode,
);
# copy of the key maps for the menu
%MenuControlKeys = %ControlKeys;
delete $MenuControlKeys{$_} foreach qw(5 6 H F); # pg-up, pg-down, home, end
$MenuControlKeys{A} = \&App::FQStat::Menu::menu_up, # up-arrow
$MenuControlKeys{B} = \&App::FQStat::Menu::menu_down, # down-arrow
$MenuControlKeys{C} = \&App::FQStat::Menu::menu_right, # right-arrow
$MenuControlKeys{D} = \&App::FQStat::Menu::menu_left, # left-arrow
%MenuKeys = %Keys;
$MenuKeys{"\n"} = \&App::FQStat::Menu::menu_select, # Enter
$MenuKeys{" "} = \&App::FQStat::Menu::menu_select, # space
delete $MenuKeys{$_} foreach qw(S);
%SummaryKeys = map {($_ => $Keys{$_})} qw(q i h S);
$SummaryKeys{c} = \&App::FQStat::Actions::toggle_summary_name_clustering;
$SummaryKeys{s} = $SummaryKeys{S};
%SummaryControlKeys = map {($_ => $ControlKeys{$_})} qw(15 21);
}
my @OldTermSize = @Termsize;
sub main_loop {
warnenter if ::DEBUG;
my $Redraw = 1;
my $RedrawTime = time();
my $RedrawOffset = $DisplayOffset;
while (1) {
my $input = get_input_key();
if (defined $input) {
my ($KeysHash, $ControlKeysHash);
if ($MenuMode) {
$KeysHash = \%MenuKeys;
$ControlKeysHash = \%MenuControlKeys;
}
elsif ($SummaryMode) {
$KeysHash = \%SummaryKeys;
$ControlKeysHash = \%SummaryControlKeys;
}
else {
$KeysHash = \%Keys;
$ControlKeysHash = \%ControlKeys;
}