#!/usr/bin/env perl

# Created on: 2008-01-26 16:49:28
# Create by:  freman
# $Id$
# $Revision$, $HeadURL$, $Date$
# $Revision$, $Source$, $Date$

use strict;
use warnings;
use version;
use Getopt::Long;
use Pod::Usage;
use Data::Dumper qw/Dumper/;
use English qw/ -no_match_vars /;
use List::MoreUtils qw/uniq/;
use Path::Class;
use Term::ANSIColor qw/colored/;
use YAML qw/LoadFile DumpFile/;

our $VERSION   = version->new('0.0.8');
my ($PROGNAME) = $PROGRAM_NAME =~ m{^.*/(.*?)$}mxs;
my $HOME       = $ENV{HOME};
my $SCREEN     = '/usr/bin/screen';

my %option = (
    task        => '',
    force_title => 1,
    verbose     => 0,
    man         => 0,
    help        => 0,
    VERSION     => 0,
);
my %ERROR = (
    COULD_NOT_LAUNCH_SCREEN => {
        message => "Unable to launch screen %s\n",
        code    => 10,
    },
    COULD_NOT_LAUNCH_SCREEN_PROTECTION => {
        message => "Unable to run protection screen '%s': %s\n",
        code    => 12,
    },
    COULD_NOT_WIPE_SESSION => {
        message => "Unable to launch screen to wipe '%s': %s\n",
        code    => 14,
    },
    COULD_NOT_REATTACH => {
        message => "Unable to launch screen to re-attach to '%s': %s\n",
        code    => 16,
    },
    COULD_NOT_FIND_SESSION => {
        message => "Could not find the screen session '%s'\n",
        code    => 18,
    },
    COULD_NOT_FIND_CONFIG => {
        message => "No config exists for %s\nTo create from template Use:\n \$ %s %s --create\n",
        code    => 20,
    },
    COULD_NOT_LAUNCH_SCREEN_TASK => {
        message => "Unable to launch screen for '%s': %s\n",
        code    => 30,
    },
    COULD_NOT_CREATE_CONFIG => {
        message => "Could not create '%s' config from template: %s\n",
        code    => 40,
    },
);
my %COLOURS = (
    'ATTACHED'    => 'green',
    'DETACHED'    => 'blue',
    'Not Started' => 'white',
    ''            => 'red',
);
my %SUFFIXES = (
    'ATTACHED'    => '*',
    'DETACHED'    => '/',
    'Not Started' => '',
    ''            => '',
);

if (!@ARGV) {
    pod2usage(-verbose => 1);
}

main();
exit 0;

sub error {
    my ( $name, @args ) = @_;
    print {*STDERR} sprintf $ERROR{$name}{message}, @args;
    exit $ERROR{$name}{code};
}

sub main {
    Getopt::Long::Configure('bundling');
    GetOptions(
        \%option,
        'task|t=s',
        'kill|k',
        'list|ls|l',
        'bw',
        'all|a',
        'exists|e!',
        'multiconnect|x',
        'create|c+',
        'chdir|d',
        'reconnect|r!',
        'force_title|force-title|f',
        'title_bar|title-bar|b=s',
        'protect|p',
        'short|S!',
        'server|s=s',
        'auto|A=s',
        'current|C=s',
        'remote_opt|remote-opt|o=s',
        'pre_cmd|pre-cmd|pre=s',
        'post_cmd|post-cmd|post=s',
        'test|T',
        'verbose|v+',
        'man',
        'help',
        'VERSION!',
    ) or pod2usage(2);
    my $task = $option{task} || $ARGV[0] || '';

    if ($option{VERSION}) {
        print "$PROGNAME Version = $VERSION\n";
        exit 1;
    }
    elsif ($option{man}) {
        pod2usage(-verbose => 2);
    }
    elsif ($option{help}) {
        pod2usage(-verbose => 1);
    }
    elsif ( $option{auto} ) {
        auto($option{auto}) ;
    }

    my %session = get_sessions();

    # Make upper and lower case versions of the task name
    # All filenames are lower case
    # All session names are upper case
    my $uc_task = uc $task;
    my $lc_task = lc $task;

    # task defaults
    my $config = config($lc_task);

    if ($option{'server'}) {
        my $mode  = shift @ARGV;
        my $reset = 'reset;';
        my $ssh   = 'ssh -t';
        if ( $option{list} ) {
            $mode  = '--list';
            $reset = '';
            $ssh   = 'ssh';
        }
        push @ARGV, $config->{remote_opt} if $config->{remote_opt};

        return print "$ssh @ARGV $option{server} '$reset devmode $mode'\n" if $option{test};
        return exec  "$ssh @ARGV $option{server} '$reset devmode $mode'";
    }
    elsif ($option{'list'}) {
        my $count = 0;

        if ( $option{verbose} || $option{all} ) {
            my @modes = grep { -f $_ && $_->basename !~ /^[.#]|[.]rc$/xms } dir("$ENV{HOME}", ".devmode")->children;
            for my $mode (@modes) {
                my $base = $mode->basename;
                $session{uc $base} ||= { state => 'Not Started' };
            }
        }

        SESSION:
        for my $session ( sort keys %session ) {
            # remove any sessions that look like they are named after their pid
            next SESSION if $session{$session}{pid} && $session =~ /^\d+$/ && $session == $session{$session}{pid};

            print ucfirst lc $session{$session}{state},
                ' ' x (14 - length $session{$session}{state}),
                $option{bw}
                ? lc $session
                : colored( lc $session, $COLOURS{ $session{$session}{state} || '' } ),
                "\n";
            $count++;
        }

        exit $count;
    }

    if ( $option{create} && !-f "$HOME/.devmode/$lc_task" ) {
        my $task = create_task( $task, $option{template} || 'rc', "$ENV{HOME}/.devmode/" );

        exec 'vim', $task;
    }

    if ($config) {
        for my $key ( keys %{ $config } ) {
            if ( !exists $option{$key} ) {
                $option{$key} = $config->{$key};
            }
        }
    }

    if ($option{'force_title'}) {
        force_title( $option{title_bar} || $task);
    }
    else {
        $option{short} = length $task > 8 if !exists $option{short};

        require Term::Title;
        Term::Title::set_titlebar(
            ( $option{short} ? '' : "Devmode " )
            . ( $option{title_bar} || $task )
        );
    }

    if ( $option{verbose} ) {
        print Dumper \%session;
    }

    if ( exists $session{$uc_task} ) {
        if ( $option{kill} ) {
            if ( $option{post_cmd} ) {
                system $option{post_cmd};
            }
            system "kill $session{$uc_task}{pid}";
            exit;
        }
        elsif ( $session{$uc_task}{state} eq 'DEAD' ) {
            warn "A previous session for '$task' was detected as dead, wiping and starting a new session\n";
            system "$SCREEN -wipe $uc_task > /dev/null 2>&1" or error( COULD_NOT_WIPE_SESSION => $task, $OS_ERROR );
        }
        else {
            my $task = "$session{$uc_task}{pid}.$uc_task";
            my $conn = $option{multiconnect} ? '-x' : '-d -R';
            warn "$SCREEN $conn $task" if $option{verbose} || $option{test};
            return if $option{test};
            exec "$SCREEN $conn $task" or error( COULD_NOT_REATTACH => $task, $OS_ERROR );
        }
    }
    elsif ( $option{reconnect} || $option{kill} ) {
        error( COULD_NOT_FIND_SESSION => $task );
    }

    system $option{pre_cmds} if $option{pre_cmds};

    my @screen_opts = (
        "-S $uc_task",
    );

    # Per session config?
    if (-e "$HOME/.devmode/$lc_task") {
        push @screen_opts, "-c $HOME/.devmode/$lc_task";

        if ($option{chdir}) {
            my $rc    = file("$HOME/.devmode/$lc_task")->slurp;
            my ($dir) = $rc =~ m{ ^ chdir \s+ (\S+?) $ }xms;

            if ( -d $dir ) {
                chdir $dir;
            }
        }
    }
    elsif ( $option{exits} ) {
        error( COULD_NOT_FIND_CONFIG => $task, $0, $task );
        die "No config exists for $task\nTo create from template Use:\n \$ $0 $task --create\n";
    }

    if ( $option{protect} ) {
        protect($lc_task);
    }

    if ( $option{pre_cmd} ) {
        system $option{pre_cmd};
    }

    my $cmd = "$SCREEN " . join (' ', @screen_opts);
    if ($option{test}) {
        warn $cmd;
        exit 0;
    }
    exec $cmd or error( COULD_NOT_LAUNCH_SCREEN_TASK => $task, $OS_ERROR );
}

sub get_sessions {
    my %session;

    # run screen to read in all the sessions
    open my $screen, "-|", "$SCREEN -ls" or error( COULD_NOT_LAUNCH_SCREEN => $OS_ERROR);

    # read each running session
    while ( my $session = <$screen> ) {
        if ( $session =~ /^\s+ (\d+) [.] ([\w-]+) \s+ (?: \( .*? \) \s+ )? \( (Attached|Dead|Detached) /xms ) {
            $session{$2} = {
                pid   => $1,
                name  => $2,
                state => uc($3),
            };
            $session{$1} = $session{$2}
        }
    }
    close $screen;

    return map { $_ => $session{$_} } grep { $_ ne $session{$_}{pid} } keys %session;

}

# runs a ssh-agent protecting screen session
sub protect {
    my ($task) = @_;
    my $protect_dir = "$ENV{HOME}/.devmode_prot";
    if ( !-d $protect_dir ) {
        mkdir $protect_dir;
    }

    my $protect_rc = file $protect_dir, $task;
    if ( !-f $protect_rc ) {
        create_task( $task, 'rcprot', $protect_dir );
    }

    for my $env ( keys %ENV ) {
        delete $ENV{$env} if $env =~ /ssh/i;
    }
    my $cmd = "$SCREEN -S PROT_$task -c $protect_rc";
    if ($option{test}) {
        warn $cmd;
        exit 0;
    }
    exec $cmd or error( COULD_NOT_LAUNCH_SCREEN_PROTECTION => $cmd, $OS_ERROR );
}

sub force_title {
    my ($task) = @_;

    require Term::Title;
    Term::Title::set_titlebar(
        ( $option{short} ? '' : "Devmode " )
        . ( $option{title_bar} || $task )
    );

    return;
}

sub create_task {
    my ( $task, $template, $out_dir ) = @_;

    require Template;
    require Template::Provider::FromDATA;

    # Create the provider
    my $provider = Template::Provider::FromDATA->new({
        CLASSES => __PACKAGE__,
    });

    # Add the provider to the config
    my $tt = Template->new({
        LOAD_TEMPLATES => [ $provider ],
        OUTPUT_PATH    => $out_dir,
    });

    my %data = (
        cwd     => file('.')->absolute->resolve,
        devmode => file($0)->absolute->resolve,
        task    => $task,
    );

    $tt->process( $template, \%data, lc $task ) or error( COULD_NOT_CREATE_CONFIG => $tt->error() );

    return "$out_dir/$task";
}

sub auto {
    my ($type) = @_;

    if ( $type eq 'ssh' ) {
        my @hosts
            = map {
                /(.*?)(?:#.*)?$/;
                my ($addr, @a) = split /\s+/, $1;
                @a;
            }
            grep {
                !/^\s*$/ && !/^\s*#/
            }
            map {
                /(.*)\n/;
                $1 || $_
            }
            file('/etc/hosts')->slurp;
        push @hosts,
            map {
                /(?:Host\s*)?(.*)/;
                $1;
            }
            grep {
                /^Host /
            }
            map {
                /(.*)\n/;
                $1 || $_
            }
            file("$ENV{HOME}/.ssh/config")->slurp;
        print join ' ', uniq sort @hosts;
        exit 0;
    }
    elsif ( $type eq 'full' ) {
        my @names;
        my @running;
        if ( $option{server} ) {
            @names = remote_cache($option{server});
        }
        else {
            @names
                = sort {
                    my $A = $a;
                    $A =~ s/(\d+)/sprintf "%05d", $1/egxms;
                    my $B = $b;
                    $B =~ s/(\d+)/sprintf "%05d", $1/egxms;
                    $A cmp $B;
                }
                map {
                    $_->basename
                }
                grep {
                    !/[.]rc$/ && !/^#/
                }
                dir($ENV{HOME}, '.devmode')->children;
            @running = `devmode --list --bw`;
        }

        if ( @running && !$option{bw} ) {
            my %running
                = map {
                    chomp;
                    my ($state, $mode) = split /\s+/, $_, 2;
                    ( $mode => $state );
                }
                @running;
            @names
                = map {
                    $running{$_} ? $_ . ( $SUFFIXES{ $running{$_} || '' } || '' ) : $_;
                }
                @names;
        }

        shift @ARGV;
        my $search = pop @ARGV;
        if ($search) {
            @names = grep { /$search/ } @names;
        }

        print join ' ', @names;
        exit 0;
    }

    exit 1;
}

sub remote_cache {
    my ($server)   = @_;
    my $cache      = {};
    my $cache_file = file('/tmp/devmode_remoter_cache');

    if ( -f $cache_file ) {
        $cache = LoadFile($cache_file);
    }

    # check the cache is fresh (1 day)
    if ( $cache->{$server} && $cache->{$server}{last} > time - 1 * 24 * 60 * 60 ) {
        return @{ $cache->{$server}{modes} };
    }

    $cache->{$server}{last} = time;
    $cache->{$server}{modes}
        = [
            grep {
                !/[.]rc$/ && !/^#/
            }
            map {
                m{^(?:.*/)(.*)};
                $1
            }
            split /\n/,
            '' . `ssh $option{server} '/bin/ls -1 ~/.devmode/[^.#]*'`
        ];

    DumpFile($cache_file, $cache);

    return @{ $cache->{$server}{modes} };
}

sub config {
    my ($base) = @_;
    my $base_config = "$HOME/.devmode/$base.rc";
    my $devmode     = "$HOME/.devmode.rc";
    my $config      = {};

    if ( -e $base_config ) {
        $config = eval { LoadFile($base_config) };

        # if no config found and we have an error assume that the file is old
        # format and try to require it and convert to YAML.
        if ( !$config && $@ ) {
            $config = require $base_config;
            DumpFile($base_config, $config);
        }
    }

    if ( -e $devmode ) {
        $config = { %{ LoadFile($devmode) }, %$config };
    }

    return $config
}

=head1 NAME

devmode - Wrapper for GNU screen to manage multiple screenrc files

=head1 VERSION

This documentation refers to devmode version 0.0.8.

=head1 SYNOPSIS

   devmode <task>

 OPTIONS:
  <task>       The name of a screen config found in the ~/.devmode/ directory
  -k --kill    Kill the task
  -l --list    List all running devmode tasks
  -a --all     Makes --list show even non-running sessions
  -e --exists  Only run screen if a devmode file exists by that name
  -x --multiconnect
               Connect to session with out disconnecting existing session
  -c --create  Creates a missing devmode task
  -d --chdir   Parse the config and change directory to the last chdir command
               found in there.
  -f --force-title
               Try harder to set the terminal title
  -t --template=name
               Uses this template name for creating the missing task. The
               default template is rc other templates can be stored in the
               $HOME/.devmode/templates/ directory
  -p --protect Run a surrounding screen session to protect the intended
               session from ssh-agent being lost when logging out of the
               of box. (experimental 256 colours doesn't work is sub screen)
  -s --server=str
               Use a remote server to connect to and run devmode. The server
               may include username@ to login with a particular user.
  -S --short   Don't show "Devmode" in the title bar

  -A --auto=str
               Allows a BASH command line completion mode helper mode to run
  -T --test    Don't run any external commands
     --VERSION Prints the version information
     --help    Prints this help information
     --man     Prints the full documentation for devmode

=head1 DESCRIPTION

C<devmode> makes managing screen sessions simpler by managing session names
and configuration files.

C<devmode> configuration files are stored in the $HOME/.devmode/ directory.
Templates for creating new configuration files can be placed in the directory
$HOME/.devmode/template/, the default template creates a session that always
opens to the directory that devmode was run from, it is aimed at working with
perl packages.

=head2 BASH auto-completion

 _devmode() {
     local cur prev opts
     COMPREPLY=()
     cur="${COMP_WORDS[COMP_CWORD]}"
     prev="${COMP_WORDS[COMP_CWORD-1]}"
     opts="--task -t --kill -k --list --ls -l --all -a --exists -e --multiconnect -x --create -c --chdir -d --reconnect -r --force_title -force-title -f --title_bar -title-bar -b --protect -p --short -S --server -s --auto -A --current -C --pre_cmd -pre-cmd --pre --post_cmd -post-cmd --post --test -T --verbose -v --man --help --VERSION"
     if [[ ${cur} == -* && ${COMP_CWORD} -eq 1 ]]; then
         COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
     elif [[ ${prev} == -s* ]]; then
         local hosts=$(devmode --auto ssh)
         COMPREPLY=($(compgen -W "${hosts}" -- ${cur}))
     else
         local sonames=$(devmode --auto full --current ${COMP_CWORD} ${COMP_WORDS[@]})
         COMPREPLY=($(compgen -W "${sonames}" -- ${cur}))
     fi
 }
 complete -F _devmode devmode

=head1 SUBROUTINES/METHODS

=head1 DIAGNOSTICS

=head1 CONFIGURATION AND ENVIRONMENT

The <Cdevmode> program uses 3 different types of configuration files:

=over 4

=item Screen

Stored in C<~/.devmode/[name]> are standard GNU Screen files.

=item mode

Each mode file can have a C,~/.devmode[mode].rc> to change default configuration.
It is stored in YAML format.

=item global

Stored inC<`/.devmode.rc> sets global defaults.
It is stored in YAML format.

=back

=head1 DEPENDENCIES

=head1 INCOMPATIBILITIES

=head1 BUGS AND LIMITATIONS

There are no known bugs in this module.

Please report problems to Ivan Wills (ivan.wills@gmail.com)

Patches are welcome.

=head1 AUTHOR

Shannon Wynter - (http://fremnet.net/contact) (original)
Ivan Wills  - (ivan.wills@gmail.com)

=head1 LICENSE AND COPYRIGHT

Copyright (c) 2007 Shannon Wynter, 2007-2013 Ivan Wills.
All rights reserved.

=cut

__DATA__

__rc__
[% TAGS <+ +> -%]
#
# Example of a user's .screenrc file
#

# This is how one can set a reattach password:
# password ODSJQf.4IJN7E    # "1234"

# no annoying audible bell, please
vbell off

# detach on hangup
autodetach on

# don't display the copyright page
startup_message off

# emulate .logout message
pow_detach_msg "Screen session of \$LOGNAME \$:cr:\$:nl:ended."

# advertise hardstatus support to $TERMCAP
# termcapinfo  * '' 'hs:ts=\E_:fs=\E\\:ds=\E_\E\\'

# make the shell in every window a login shell
#shell -$SHELL

# autoaka testing
# shellaka '> |tcsh'
# shellaka '$ |sh'

# set every new windows hardstatus line to somenthing descriptive
# defhstatus "screen: ^En (^Et)"

defscrollback 5000

# don't kill window after the process died
# zombie "^["
zombie kr


################
#
# xterm tweaks
#

#xterm understands both im/ic and doesn't have a status line.
#Note: Do not specify im and ic in the real termcap/info file as
#some programs (e.g. vi) will not work anymore.
termcap  xterm hs@:cs=\E[%i%d;%dr:im=\E[4h:ei=\E[4l
terminfo xterm hs@:cs=\E[%i%p1%d;%p2%dr:im=\E[4h:ei=\E[4l

#80/132 column switching must be enabled for ^AW to work
#change init sequence to not switch width
termcapinfo  xterm Z0=\E[?3h:Z1=\E[?3l:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l

# Make the output buffer large for (fast) xterms.
termcapinfo xterm* OL=10000

# tell screen that xterm can switch to dark background and has function
# keys.
termcapinfo xterm 'VR=\E[?5h:VN=\E[?5l'
termcapinfo xterm 'k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~'
termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[H:kN=\E[6~'

# special xterm hardstatus: use the window title.
#termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'

#terminfo xterm 'vb=\E[?5h$<200/>\E[?5l'
termcapinfo xterm 'vi=\E[?25l:ve=\E[34h\E[?25h:vs=\E[34l'

# emulate part of the 'K' charset
termcapinfo   xterm 'XC=K%,%\E(B,[\304,\\\\\326,]\334,{\344,|\366,}\374,~\337'

# xterm-52 tweaks:
# - uses background color for delete operations
termcapinfo xterm ut

################
#
# wyse terminals
#

#wyse-75-42 must have flow control (xo = "terminal uses xon/xoff")
#essential to have it here, as this is a slow terminal.
termcapinfo wy75-42 xo:hs@

# New termcap sequences for cursor application mode.
termcapinfo wy* CS=\E[?1h:CE=\E[?1l:vi=\E[?25l:ve=\E[?25h:VR=\E[?5h:VN=\E[?5l:cb=\E[1K:CD=\E[1J

################
#
# other terminals
#

#make hp700 termcap/info better
termcapinfo  hp700 'Z0=\E[?3h:Z1=\E[?3l:hs:ts=\E[62"p\E[0$~\E[2$~\E[1$}:fs=\E[0}\E[61"p:ds=\E[62"p\E[1$~\E[61"p:ic@'

# Extend the vt100 desciption by some sequences.
termcap  vt100* ms:AL=\E[%dL:DL=\E[%dM:UP=\E[%dA:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC
terminfo vt100* ms:AL=\E[%p1%dL:DL=\E[%p1%dM:UP=\E[%p1%dA:DO=\E[%p1%dB:LE=\E[%p1%dD:RI=\E[%p1%dC

# 256 colour stuff
# terminfo and termcap for nice 256 color terminal
# allow bold colors - necessary for some reason
attrcolor b ".I"
# tell screen how to set colors. AB = background, AF=foreground
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
# erase background with current bg color
#defbce "on"


################
#
# keybindings
#

#remove some stupid / dangerous key bindings
bind k
bind ^k
bind .
bind ^\
bind \\
bind ^h
bind h
#make them better
bind 'K' kill
bind 'I' login on
bind 'O' login off
bind '}' history

# Yet another hack:
# Prepend/append register [/] to the paste if ^a^] is pressed.
# This lets me have autoindent mode in vi.
register [ "\033:se noai\015a"
register ] "\033:se ai\015a"
bind ^] paste [.]

################
#
# default windows
#

# screen -t local 0
# screen -t mail 1 elm
# screen -t 40 2 rlogin faui40

# caption always "%3 %t%? @%u%?%? [%h]%?"
# hardstatus alwaysignore
# hardstatus alwayslastline "%w"

# run any cmds before starting the screen session
# eg cd via chdir
# choose a program to run automaticall in that window by appending to the end of the command
#
# eg:
# chdir /var/log/apache
# screen -t 'logs' 1 tail -f error_log
#
chdir <+ cwd +>
screen -t '> cmds'	1
screen -t '> cmds'	2
screen -t '> code'	3
screen -t '> code'	4 #deep -N10 -fbd data=1 /tmp/<+ task +>_\*.log
screen -t '> code'	5 itail /www/logs/error.log /www/logs/access.log
chdir <+ cwd +>/db
screen -t '> psql'	6
chdir <+ cwd +>
screen -t '> root'	7 sudo -s
#screen -t '> tail'	8
#screen -t '> code'	9
#screen -t '> code'	10
#screen -t '> code'	11
#screen -t '> code'	12
#screen -t '> code'	13
#screen -t '> code'	14
#screen -t '> code'	15
#screen -t '> code'	16
#screen -t '> code'	17
#screen -t '> code'	18
#screen -t '> code'	19
#screen -t '> code'	20
#screen -t '> code'	21
#screen -t '> code'	22

# see 'Input Translation' section for key names
bindkey 0   select 0
bindkey OP  select 1
bindkey OQ  select 2
bindkey OR  select 3
bindkey OS  select 4
bindkey -k k5 select 5
bindkey -k k6 select 6
bindkey -k k7 select 7
bindkey -k k8 select 8
bindkey -k k9 select 9
bindkey -k k; select 10
bindkey -k F1 select 11
bindkey -k F2 select 12
bindkey 3   select 13
bindkey 4   select 14
bindkey 5   select 15
bindkey 6   select 16
bindkey 7   select 17
bindkey 8   select 18
bindkey 9   select 19
bindkey 0   select 20
bindkey 1   select 21
bindkey 2   select 22

hardstatus on
hardstatus alwayslastline
#hardstatus string "%{..k}%-t%{.rK}%n %t%{-}%+w %=%{..K} %H %{..K} %Y-%m-%d %c "
#hardstatus alwayslastline "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%< %=[%c, %D, %d/%m/%y]"
#hardstatus alwayslastline "%-w%?%F%{.R.}%?%n %t%+w [%H %l] [%0c] [%Y-%m-%d]"
hardstatus alwayslastline "%{+b}%{.kw}[<+ task +>] %-w%{.kc}%n %t%{-}%+w %=%{b}%H%{d} - %{y}%l%{d} - %{r}%Y-%m-%d %0c"
#caption always "%{=}%?%{r}%H %L=%{+b}%?%{b}%-Lw%47L>%?%{w}%n*%f %t %?%{b}%+Lw%?%{g}%-31=%c %l %Y-%m-%d"

escape ^Aa

__rcprot__
[% TAGS <+ +> -%]
vbell off
autodetach on
startup_message off
pow_detach_msg "Screen session of \$LOGNAME \$:cr:\$:nl:ended."
defscrollback 0
termcap  xterm hs@:cs=\E[%i%d;%dr:im=\E[4h:ei=\E[4l
terminfo xterm hs@:cs=\E[%i%p1%d;%p2%dr:im=\E[4h:ei=\E[4l
termcapinfo  xterm Z0=\E[?3h:Z1=\E[?3l:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l
termcapinfo xterm* OL=10000
termcapinfo xterm 'VR=\E[?5h:VN=\E[?5l'
termcapinfo xterm 'k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~'
termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[H:kN=\E[6~'
termcapinfo xterm 'vi=\E[?25l:ve=\E[34h\E[?25h:vs=\E[34l'
termcapinfo   xterm 'XC=K%,%\E(B,[\304,\\\\\326,]\334,{\344,|\366,}\374,~\337'
termcapinfo xterm ut
termcapinfo wy75-42 xo:hs@
termcapinfo wy* CS=\E[?1h:CE=\E[?1l:vi=\E[?25l:ve=\E[?25h:VR=\E[?5h:VN=\E[?5l:cb=\E[1K:CD=\E[1J
termcapinfo  hp700 'Z0=\E[?3h:Z1=\E[?3l:hs:ts=\E[62"p\E[0$~\E[2$~\E[1$}:fs=\E[0}\E[61"p:ds=\E[62"p\E[1$~\E[61"p:ic@'
termcap  vt100* ms:AL=\E[%dL:DL=\E[%dM:UP=\E[%dA:DO=\E[%dB:LE=\E[%dD:RI=\E[%dC
terminfo vt100* ms:AL=\E[%p1%dL:DL=\E[%p1%dM:UP=\E[%p1%dA:DO=\E[%p1%dB:LE=\E[%p1%dD:RI=\E[%p1%dC
attrcolor b ".I"
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
bind k
bind ^k
bind .
bind ^\
bind \\
bind ^h
bind h
#make them better
bind 'K' kill
bind 'I' login on
bind 'O' login off
bind '}' history
register [ "\033:se noai\015a"
register ] "\033:se ai\015a"
bind ^] paste [.]
escape ^Qq

screen 0 bash -c 'ssh-agent; <+ devmode +> <+ task +>'