lilalo

changeset 109:3cd466f35ad6

* Добавлено разбиения журнала на блоки
* Оптимизирована генерация всплывающих подсказок
* В заголовке указывается дата
* Переделано взаимодействие с mywi: код mywi интегрирован в lilalo
* Изменён способ вывода таблицы, теперь она лушче показывается в Opera и IE
* Изменён формат diff'а, теперь diff -u
author igor
date Wed Feb 13 02:41:57 2008 +0200 (2008-02-13)
parents 0d49f33696b3
children 2fc1f3f08760
files README install l3-cgi-lite l3-frontend l3bashrc l3config.pm
line diff
     1.1 --- a/README	Sun Nov 12 17:34:47 2006 +0200
     1.2 +++ b/README	Wed Feb 13 02:41:57 2008 +0200
     1.3 @@ -1,3 +1,24 @@
     1.4 +
     1.5 +LiLaLo - Live Lab Log
     1.6 +
     1.7 +(c) Игорь Чубин, 2004-2008
     1.8 +
     1.9 +Лицензия, по которой распространяется 
    1.10 +приведена в файле LICENSE
    1.11 +в данном дистрибутиве
    1.12 +
    1.13 +
    1.14 +Дополнительную информацию о программе
    1.15 +можно найти на странице:
    1.16 +
    1.17 +    http://xgu.ru/wiki/LiLaLo
    1.18 +
    1.19 +
    1.20 +
    1.21 +-----------------------------------------------------------------
    1.22 +
    1.23 +
    1.24 +
    1.25  АТРИБУТЫ cline
    1.26  СПИСОК ПОЛЕЙ, ХАРАКТЕРИЗУЮЩИХ КОМАНДНУЮ СТРОКУ
    1.27  
     2.1 --- a/install	Sun Nov 12 17:34:47 2006 +0200
     2.2 +++ b/install	Wed Feb 13 02:41:57 2008 +0200
     2.3 @@ -25,6 +25,7 @@
     2.4  url_perl_modules=${url_lilalo}/
     2.5  perl_modules="Term-VT102 Text-Iconv"
     2.6  
     2.7 +apt_get_install_this="perl make libmodule-build-perl libc6-dev gcc"
     2.8  
     2.9  wget=wget
    2.10  uname -a | grep -qi bsd && wget=fetch
    2.11 @@ -34,6 +35,25 @@
    2.12  redC='\033[0;31m'
    2.13  greenC='\033[0;32m'
    2.14  
    2.15 +apt_get_install_deps()
    2.16 +{
    2.17 +    if which apt-get >& /dev/null
    2.18 +    then 
    2.19 +        apt-get install -y $apt_get_install_this
    2.20 +    else
    2.21 +        echo "Please install this dependencies manually:"
    2.22 +        echo $apt_get_install_this
    2.23 +        echo "Have you installed this already (y/n)?"
    2.24 +        echo y | read answer
    2.25 +        if echo $answer | grep -q ^[yY]
    2.26 +        then
    2.27 +            true
    2.28 +        else
    2.29 +            echo Please install the dependencies and rerun the script
    2.30 +            exit 1
    2.31 +        fi
    2.32 +    fi
    2.33 +}
    2.34  
    2.35  
    2.36  step()
    2.37 @@ -141,6 +161,7 @@
    2.38  temp_dir=/tmp/lilalo-install-temp-$$
    2.39  mkdir -p ${temp_dir}
    2.40  cd ${temp_dir}
    2.41 +step "Installing dependencies" apt_get_install_deps
    2.42  step "Downloading l3bashrc" ${wget} ${url_l3bashrc} 
    2.43  step "Downloading l3-agent" '${wget} ${url_l3agent}; ${wget} ${url_l3config}'
    2.44  step "Downloading perl modules for l3-agent" '{ for i in ${perl_modules}; do ${wget} ${url_perl_modules}/$i.tar.gz; done; }'
     3.1 --- a/l3-cgi-lite	Sun Nov 12 17:34:47 2006 +0200
     3.2 +++ b/l3-cgi-lite	Wed Feb 13 02:41:57 2008 +0200
     3.3 @@ -17,14 +17,26 @@
     3.4  sub print_footer;
     3.5  sub nav_bar;
     3.6  
     3.7 +sub count_command_lines($);
     3.8 +
     3.9  my $print="";
    3.10  my $path = $ENV{PATH_INFO};
    3.11  remove_extra_slashes_from($path);
    3.12  
    3.13 +
    3.14 +my $commands_to_show_at_a_go = $l3config::Config{"commands_to_show_at_a_go"};
    3.15 +my $start_from_command = "100";
    3.16 +my $this_page_number=0;
    3.17 +if ($path =~ s/:(.*)//) {
    3.18 +    $this_page_number = $1;
    3.19 +    $start_from_command = $this_page_number*$commands_to_show_at_a_go;
    3.20 +}
    3.21 +
    3.22  my $real_path = $l3config::Config{"backend_datadir"} ;
    3.23  my $cgi_path = $l3config::Config{"cgi_path"} ;
    3.24  my $style_files = $l3config::Config{"frontend_files"} ;
    3.25  my $frontend_css = $l3config::Config{"frontend_css"} ;
    3.26 +
    3.27  my $data_file = "data.xml";
    3.28  
    3.29  path_is_correct($path)
    3.30 @@ -51,12 +63,12 @@
    3.31  
    3.32      unless ( -e "$real_path/$data_file"
    3.33               && -e "$real_path/index.html" 
    3.34 -             && (stat("$real_path/index.html"))[9] > (stat("$real_path/$data_file"))[9] ) {
    3.35 +             && (stat("$real_path/index.html"))[9] > (stat("$real_path/$data_file"))[9] && 0!=0 ) {
    3.36  
    3.37 -        my $l3_frontend = "/home/devi/cvs/lilalo/l3-frontend --backend_datafile $real_path/$data_file --output $real_path/index.html";
    3.38 +        my $l3_frontend = "/home/devi/cvs/lilalo/l3-frontend --backend_datafile $real_path/$data_file --output $real_path/index.html --start_from_command $start_from_command ";
    3.39          system($l3_frontend) == 0
    3.40              or error("Файл журнала найден, но возникла ошибка при его обработке:<br/> $!");
    3.41 -        $print .= "(перегенирован)<br/>";
    3.42 +        #$print .= "(перегенирован)<br/>";
    3.43      }
    3.44  
    3.45      {
    3.46 @@ -169,6 +181,28 @@
    3.47          $current_path .= "/$path_part";
    3.48          $nav_bar .= "/<a href='$current_path'>$path_part</a>";
    3.49      }
    3.50 +    my $pages=int(count_command_lines("$real_path/$data_file")/$commands_to_show_at_a_go)+1;
    3.51 +    my $i=1;
    3.52 +    while ($i<$pages) {
    3.53 +        if ($i==$this_page_number) {
    3.54 +            $nav_bar .= " <b>:$i</b>";
    3.55 +        } 
    3.56 +        else {
    3.57 +            $nav_bar .= " <a href='$current_path:$i'>:$i</a>";
    3.58 +        }
    3.59 +        $i++;
    3.60 +    }
    3.61      return "<table class='nav_bar' cellpadding='0' cellspacing='0' width='100%'><tr><td>$nav_bar</td></tr></table>";
    3.62  }
    3.63  
    3.64 +sub count_command_lines($)
    3.65 +#
    3.66 +# Считает количество строк в файле с данными
    3.67 +# Грязный временный хак
    3.68 +#
    3.69 +{
    3.70 +    my $filename= $_[0];
    3.71 +    return int(`grep '<command>' $filename |wc -l`);
    3.72 +#    return $filename;
    3.73 +}
    3.74 +
     4.1 --- a/l3-frontend	Sun Nov 12 17:34:47 2006 +0200
     4.2 +++ b/l3-frontend	Wed Feb 13 02:41:57 2008 +0200
     4.3 @@ -1,6 +1,6 @@
     4.4  #!/usr/bin/perl -w
     4.5  
     4.6 -use IO::Socket;
     4.7 +use POSIX qw(strftime);
     4.8  use lib '.';
     4.9  use l3config;
    4.10  use utf8;
    4.11 @@ -9,9 +9,10 @@
    4.12  our @Command_Lines_Index;
    4.13  our %Commands_Description;
    4.14  our %Args_Description;
    4.15 -our $Mywi_Socket;
    4.16  our %Sessions;
    4.17  
    4.18 +our $debug_output="";      # Используйте эту переменную, если нужно передать отладочную информацию
    4.19 +
    4.20  our %filter;
    4.21  our $filter_url;
    4.22  sub init_filter;
    4.23 @@ -26,12 +27,17 @@
    4.24  our %Elements_Visibility;
    4.25  # ^^^
    4.26  
    4.27 +our $First_Command=$0;
    4.28 +our $Last_Command=40;
    4.29 +
    4.30  our %Stat;
    4.31  our %frequency_of_command; # Сколько раз в журнале встречается какая команда
    4.32  our $table_number=1;
    4.33 +our %tigra_hints;
    4.34  
    4.35  my %mywi_cache_for;         # Кэш для экономии обращений к mywi
    4.36  
    4.37 +sub count_frequency_of_commands;
    4.38  sub make_comment;
    4.39  sub make_new_entries_table;
    4.40  sub load_command_lines_from_xml;
    4.41 @@ -53,6 +59,20 @@
    4.42  sub print_stat_html;
    4.43  sub print_header_html;
    4.44  sub print_footer_html;
    4.45 +sub tigra_hints_generate;
    4.46 +
    4.47 +#### mywi
    4.48 +# 
    4.49 +sub mywi_init;
    4.50 +sub load_mywitxt;
    4.51 +sub mywi_process_query($);
    4.52 +#
    4.53 +sub add_to_log($$);
    4.54 +sub parse_query;
    4.55 +sub search_in_txt;
    4.56 +sub add_to_log($$);
    4.57 +sub mywi_guess($);
    4.58 +#
    4.59  
    4.60  main();
    4.61  
    4.62 @@ -65,8 +85,8 @@
    4.63      $Config{frontend_ico_path}=$Config{frontend_css};
    4.64      $Config{frontend_ico_path}=~s@/[^/]*$@@;
    4.65      init_filter();
    4.66 +    mywi_init();
    4.67  
    4.68 -    open_mywi_socket();
    4.69      load_command_lines_from_xml($Config{"backend_datafile"});
    4.70      load_sessions_from_xml($Config{"backend_datafile"});
    4.71      sort_command_lines;
    4.72 @@ -77,7 +97,6 @@
    4.73      else {
    4.74          print_all_html($Config{"output"});
    4.75      }
    4.76 -    close_mywi_socket;
    4.77  }
    4.78  
    4.79  sub init_filter
    4.80 @@ -150,46 +169,75 @@
    4.81      
    4.82  }
    4.83  
    4.84 -
    4.85 -
    4.86 -
    4.87 -#
    4.88 -# Подпрограммы для работы с mywi
    4.89 -#
    4.90 -
    4.91 -sub open_mywi_socket
    4.92 +sub mywrap($)
    4.93  {
    4.94 -    $Mywi_Socket = IO::Socket::INET->new(
    4.95 -                PeerAddr => $Config{mywi_server},
    4.96 -                PeerPort => $Config{mywi_port},
    4.97 -                Proto    => "tcp",
    4.98 -                Type     => SOCK_STREAM);
    4.99 +return '<div class="t"><div class="b"><div class="l"><div class="r"><div class="bl"><div class="br"><div class="tl"><div class="tr">'.$_[0].
   4.100 +'</div></div></div></div></div></div></div></div>';
   4.101  }
   4.102  
   4.103 -sub close_mywi_socket
   4.104 +sub tigra_hints_generate
   4.105  {
   4.106 -    close ($Mywi_Socket) if $Mywi_Socket ;
   4.107 +    my $tigra_hints_items="";
   4.108 +    for my $hint_id (keys %tigra_hints) {
   4.109 +        $tigra_hints{$hint_id} =~ s@\n@<br/>@gs;
   4.110 +        $tigra_hints{$hint_id} =~ s@ - @ — @gs;
   4.111 +        $tigra_hints{$hint_id} =~ s@'@\\'@gs;
   4.112 +#        $tigra_hints_items .= "'$hint_id' : mywrap('".$tigra_hints{$hint_id}."'),";
   4.113 +        $tigra_hints_items .= "'$hint_id' : '".mywrap($tigra_hints{$hint_id})."',";
   4.114 +    }
   4.115 +    $tigra_hints_items =~ s/,$//; 
   4.116 +    return <<TIGRA;
   4.117 +
   4.118 +var HINTS_CFG = {
   4.119 +	'top'        : 5, // a vertical offset of a hint from mouse pointer
   4.120 +	'left'       : 5, // a horizontal offset of a hint from mouse pointer
   4.121 +	'css'        : 'hintsClass', // a style class name for all hints, TD object
   4.122 +	'show_delay' : 500, // a delay between object mouseover and hint appearing
   4.123 +	'hide_delay' : 2000, // a delay between hint appearing and hint hiding
   4.124 +	'wise'       : true,
   4.125 +	'follow'     : true,
   4.126 +	'z-index'    : 0 // a z-index for all hint layers
   4.127 +},
   4.128 +
   4.129 +HINTS_CFG_NEW = {
   4.130 +    'wise'       : true, // don't go off screen, don't overlap the object in the document
   4.131 +    'margin'     : 10, // minimum allowed distance between the hint and the window edge (negative values accepted)
   4.132 +    'gap'        : 20, // minimum allowed distance between the hint and the origin (negative values accepted)
   4.133 +    'align'      : 'bctl', // align of the hint and the origin (by first letters origin's top|middle|bottom left|center|right to hint's top|middle|bottom left|center|right)
   4.134 +    'css'        : 'hintsClass', // a style class name for all hints, applied to DIV element (see style section in the header of the document)
   4.135 +    'show_delay' : 0, // a delay between initiating event (mouseover for example) and hint appearing
   4.136 +    'hide_delay' : 200, // a delay between closing event (mouseout for example) and hint disappearing
   4.137 +    'follow'     : true, // hint follows the mouse as it moves
   4.138 +    'z-index'    : 100, // a z-index for all hint layers
   4.139 +    'IEfix'      : false, // fix IE problem with windowed controls visible through hints (activate if select boxes are visible through the hints)
   4.140 +    'IEtrans'    : ['blendTrans(DURATION=.3)', null], // [show transition, hide transition] - nice transition effects, only work in IE5+
   4.141 +    'opacity'    : 90 // opacity of the hint in %%
   4.142 +},
   4.143 +
   4.144 +HINTS_ITEMS = {
   4.145 +    $tigra_hints_items
   4.146 +};
   4.147 +var myHint = new THints (HINTS_CFG, HINTS_ITEMS);
   4.148 +
   4.149 +
   4.150 +function mywrap (s_) {
   4.151 +return '<div class="t"><div class="b"><div class="l"><div class="r"><div class="bl"><div class="br"><div class="tl"><div class="tr">'+s_+
   4.152 +'</div></div></div></div></div></div></div></div>';
   4.153 +
   4.154 +}
   4.155 +TIGRA
   4.156 +$a=<<TIGRA;
   4.157 +TIGRA
   4.158  }
   4.159  
   4.160  
   4.161 -sub mywi_client
   4.162 +sub count_frequency_of_commands
   4.163  {
   4.164 -    return "";
   4.165 -    my $query = $_[0];
   4.166 -    my $mywi;
   4.167 -
   4.168 -    open_mywi_socket;
   4.169 -    if ($Mywi_Socket) {
   4.170 -        binmode ":utf8", $Mywi_Socket;
   4.171 -        local $| = 1;
   4.172 -        local $/ = "";
   4.173 -        print $Mywi_Socket $query."\n";
   4.174 -        $mywi = <$Mywi_Socket>;
   4.175 -        utf8::decode($mywi);
   4.176 -        $mywi = "" if $mywi =~ /nothing app/;
   4.177 +    my $cline = $_[0];
   4.178 +    my @commands = keys %{extract_from_cline("commands", $cline)};
   4.179 +    for my $command (@commands) {
   4.180 +        $frequency_of_command{$command}++;
   4.181      }
   4.182 -    close_mywi_socket;
   4.183 -    return $mywi;
   4.184  }
   4.185  
   4.186  sub make_comment
   4.187 @@ -206,9 +254,9 @@
   4.188      # Commands
   4.189      for my $command (@commands) {
   4.190          $command =~ s/'//g;
   4.191 -        $frequency_of_command{$command}++;
   4.192 +        #$frequency_of_command{$command}++;
   4.193          if (!$Commands_Description{$command}) {
   4.194 -            $mywi_cache_for{$command} ||= mywi_client($command) || "";
   4.195 +            $mywi_cache_for{$command} ||= mywi_process_query($command) || "";
   4.196              my $mywi = join ("\n", grep(/\([18]|sh|script\)/, split(/\n/, $mywi_cache_for{$command})));
   4.197              $mywi =~ s/\s+/ /;
   4.198              if ($mywi !~ /^\s*$/) {
   4.199 @@ -330,8 +378,16 @@
   4.200  sub process_command_lines
   4.201  {
   4.202  
   4.203 +
   4.204 +    my $current_command=0;
   4.205 +
   4.206  COMMAND_LINE_PROCESSING:
   4.207      for my $i (@Command_Lines_Index) {
   4.208 +        
   4.209 +        $current_command++;
   4.210 +        next if $current_command < $Config{"start_from_command"};
   4.211 +        last if $current_command > $Config{"start_from_command"} + $Config{"commands_to_show_at_a_go"};
   4.212 +
   4.213          my $cl = \$Command_Lines[$i];
   4.214  
   4.215          next if !$cl;
   4.216 @@ -361,11 +417,15 @@
   4.217          }
   4.218  
   4.219          my $hint;
   4.220 +        count_frequency_of_commands($$cl->{"cline"});
   4.221          $hint = make_comment($$cl->{"cline"});
   4.222 +
   4.223          if ($hint) {
   4.224              $$cl->{hint} = $hint;
   4.225          }
   4.226 -#        $$cl->{hint}="";
   4.227 +        $tigra_hints{$$cl->{"time"}} = $hint;
   4.228 +
   4.229 +        $$cl->{hint}="";
   4.230  
   4.231  # Выводим <head_lines> верхних строк
   4.232  # и <tail_lines> нижних строк,
   4.233 @@ -491,6 +551,8 @@
   4.234      my $last_session="";
   4.235      my $last_day=q();
   4.236      my $last_wday=q();
   4.237 +    my $first_command_of_the_day_unix_time=q();
   4.238 +    my $human_readable_time=q();
   4.239      my $in_range=0;
   4.240  
   4.241      my $current_command=0;
   4.242 @@ -517,6 +579,10 @@
   4.243          my $cl=$Command_Lines[$Command_Lines_Index[$current_command++]];
   4.244          next unless $cl;
   4.245  
   4.246 +        next if $current_command < $Config{"start_from_command"};
   4.247 +        last if $current_command > $Config{"start_from_command"} + $Config{"commands_to_show_at_a_go"};
   4.248 +
   4.249 +
   4.250  # Пропускаем команды, с одинаковым временем
   4.251  # Это не совсем правильно.
   4.252  # Возможно, что это команды, набираемые с помощью <completion>
   4.253 @@ -592,6 +658,7 @@
   4.254  
   4.255          my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time});
   4.256  
   4.257 +
   4.258          # Добавляем спереди 0 для удобочитаемости
   4.259          $min  = "0".$min  if $min  =~ /^.$/;
   4.260          $hour = "0".$hour if $hour =~ /^.$/;
   4.261 @@ -603,6 +670,9 @@
   4.262  
   4.263  # DAY CHANGE
   4.264          if ( $last_day ne $day) {
   4.265 +            $prev_unix_time=$first_command_of_the_day_unix_time;
   4.266 +            $first_command_of_the_day_unix_time = $cl->{time};
   4.267 +            $human_readable_time = strftime "%D", localtime($prev_unix_time);
   4.268              if ($last_day) {
   4.269  
   4.270  # Вычисляем разность множеств.
   4.271 @@ -610,7 +680,9 @@
   4.272  #   @new_commands = keys %frequency_of_command - @known_commands;
   4.273  
   4.274  
   4.275 -                $result .= "<h3 id='day$last_day'>".$Day_Name[$last_wday]."</h3>";
   4.276 +# Выводим предыдущий день
   4.277 +
   4.278 +                $result .= "<h3 id='day_on_sec_$prev_unix_time'>".$Day_Name[$last_wday]." ($human_readable_time)</h3>";
   4.279                  for my $entry_class (sort keys %new_entries_of) {
   4.280                      my $table_caption = "Таблица ".$table_number++.".".$Day_Name[$last_wday]
   4.281                                          .". Новые ".$new_entries_of{$entry_class};
   4.282 @@ -623,7 +695,12 @@
   4.283                  $result .= $this_day_result;
   4.284              }
   4.285  
   4.286 -            push @toc, "<a href='#day$day'>".$Day_Name[$wday]."</a>\n";
   4.287 +# Добавляем текущий день в оглавление
   4.288 +
   4.289 +            $human_readable_time = strftime "%D", localtime($first_command_of_the_day_unix_time);
   4.290 +            push @toc, "<a href='#day_on_sec_$first_command_of_the_day_unix_time'>".$Day_Name[$wday]." ($human_readable_time)</a>\n";
   4.291 +
   4.292 +
   4.293              $last_day=$day;
   4.294              $last_wday=$wday;
   4.295              $this_day_result = q();
   4.296 @@ -672,8 +749,8 @@
   4.297              $cline = "<span class='without_hint'>$cline</span>";
   4.298          }
   4.299  
   4.300 -        $this_day_result .= "<table cellpadding='0' cellspacing='0'><tr><td>\n<div class='cblock_$cl->{class}'>\n";
   4.301 -        $this_day_result .= "<div class='cline'>\n" . $cline ;      #cline
   4.302 +        $this_day_result .= "<DIV class='fixed_div'><table cellpadding='0' cellspacing='0'><tr><td>\n<div class='cblock_$cl->{class}'>\n";
   4.303 +        $this_day_result .= "<div class='cline' onmouseover=\"myHint.show('".$cl->{time}."')\" onmouseout=\"myHint.hide()\">\n" . $cline ;      #cline
   4.304          $this_day_result .= "<span title='Код завершения ".$cl->{"err"}."'>\n"
   4.305                           .  "<img src='".$Config{frontend_ico_path}."/error.png'/>\n"
   4.306                           .  "</span>\n" if $cl->{"err"};
   4.307 @@ -716,11 +793,15 @@
   4.308  
   4.309          # Вывод очередной команды окончен
   4.310          $this_day_result .= "</div>\n";                     # cblock
   4.311 -        $this_day_result .= "</td></tr></table>\n"
   4.312 +        $this_day_result .= "</td></tr></table></DIV>\n"
   4.313                           .  "</div>\n";                     # command
   4.314      }
   4.315      last: {
   4.316 -        $result .= "<h3 id='day$last_day'>".$Day_Name[$last_wday]."</h3>";
   4.317 +        $prev_unix_time=$first_command_of_the_day_unix_time;
   4.318 +        $first_command_of_the_day_unix_time = $cl->{time};
   4.319 +        $human_readable_time = strftime "%D", localtime($prev_unix_time);
   4.320 +
   4.321 +        $result .= "<h3 id='day_on_sec_$prev_unix_time'>".$Day_Name[$last_wday]." ($human_readable_time)</h3>";
   4.322  
   4.323          for my $entry_class (keys %new_entries_of) {
   4.324              my $table_caption = "Таблица ".$table_number++.".".$Day_Name[$last_wday]
   4.325 @@ -1120,7 +1201,8 @@
   4.326      my ($command_lines,$toc)  = print_command_lines_html;
   4.327      my $files_section         = print_files_html;
   4.328  
   4.329 -    $result = print_header_html($toc);
   4.330 +    $result = $debug_output;
   4.331 +    $result .= print_header_html($toc);
   4.332  
   4.333  
   4.334  #    $result.= join " <br/>", keys %Sessions;
   4.335 @@ -1195,9 +1277,11 @@
   4.336  
   4.337  
   4.338      # Управляющая форма отключена
   4.339 -    # Она слишеком сильно мешает, нужно что-то переделать
   4.340 +    # Она слишком сильно мешает, нужно что-то переделать
   4.341      $control_form = "";
   4.342  
   4.343 +    my $tigra_hints_array=tigra_hints_generate;
   4.344 +
   4.345      my $result;
   4.346      $result = <<HEADER;
   4.347      <html>
   4.348 @@ -1207,23 +1291,51 @@
   4.349      <title>$title</title>
   4.350      </head>
   4.351      <body>
   4.352 -    <script>
   4.353 +    <!--<script>
   4.354      $Html_JavaScript
   4.355 -    </script>
   4.356 +    </script>-->
   4.357  
   4.358  <!-- vvv Tigra Hints vvv -->
   4.359  <script language="JavaScript" src="/tigra/hints.js"></script>
   4.360 -<script language="JavaScript" src="/tigra/hints_cfg.js"></script>
   4.361 +<!--<script language="JavaScript" src="/tigra/hints_cfg.js"></script>-->
   4.362 +<script>$tigra_hints_array</script>
   4.363  <style>
   4.364  /* a class for all Tigra Hints boxes, TD object */
   4.365      .hintsClass
   4.366 -        {text-align: center; font-family: Verdana, Arial, Helvetica; padding: 0px 0px 0px 0px;}
   4.367 +        {text-align: left; font-size:80%; font-family: Verdana, Arial, Helvetica; background-color:#ffffee; padding: 0px 0px 0px 0px;}
   4.368  /* this class is used by Tigra Hints wrappers */
   4.369      .row
   4.370          {background: white;}
   4.371 +
   4.372 +
   4.373 +    .bl2 {border: 1px solid #e68200; background:url(/tigra/block/bl2.gif) 0 100% no-repeat; text-align:left}
   4.374 +    .bl {background:url(/tigra/block/bl2.gif) 0 100% no-repeat; text-align:left}
   4.375 +    .br {background:url(/tigra/block/br2.gif) 100% 100% no-repeat}
   4.376 +    .tl {background:url(/tigra/block/tl2.gif) 0 0 no-repeat}
   4.377 +    .tr {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat; padding:10px}
   4.378 +    .tr2 {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat}
   4.379 +    .t {background:url(/tigra/block/dot2.gif) 0 0 repeat-x}
   4.380 +    .b {background:url(/tigra/block/dot2.gif) 0 100% repeat-x}
   4.381 +    .l {background:url(/tigra/block/dot2.gif) 0 0 repeat-y}
   4.382 +    .r {background:url(/tigra/block/dot2.gif) 100% 0 repeat-y}
   4.383 +
   4.384 +
   4.385  </style>
   4.386  <!-- ^^^ Tigra Hints ^^^ -->
   4.387  
   4.388 +<!--
   4.389 +    .bl2 {border: 1px solid #e68200; background:url(/tigra/block/bl2.gif) 0 100% no-repeat; width:20em; text-align:center}
   4.390 +    .bl {background:url(/tigra/block/bl2.gif) 0 100% no-repeat; width:20em; text-align:center}
   4.391 +    .br {background:url(/tigra/block/br2.gif) 100% 100% no-repeat}
   4.392 +    .tl {background:url(/tigra/block/tl2.gif) 0 0 no-repeat}
   4.393 +    .tr {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat; padding:10px}
   4.394 +    .tr2 {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat}
   4.395 +    .t {background:url(/tigra/block/dot2.gif) 0 0 repeat-x; width:20em}
   4.396 +    .b {background:url(/tigra/block/dot2.gif) 0 100% repeat-x}
   4.397 +    .l {background:url(/tigra/block/dot2.gif) 0 0 repeat-y}
   4.398 +    .r {background:url(/tigra/block/dot2.gif) 100% 0 repeat-y}
   4.399 +-->
   4.400 +
   4.401  
   4.402      <div class='edit_link'>
   4.403      [ <a href='?action=edit&$filter_url'>править</a> ]
   4.404 @@ -1824,3 +1936,199 @@
   4.405                  $Search_Machines{$sm}->{"icon"}."' border='0'/></a>";
   4.406  }
   4.407  
   4.408 +
   4.409 +
   4.410 +
   4.411 +########################################################################################
   4.412 +#
   4.413 +# mywi
   4.414 +#
   4.415 +# 
   4.416 +#
   4.417 +#
   4.418 +#
   4.419 +#
   4.420 +#
   4.421 +
   4.422 +
   4.423 +
   4.424 +sub mywi_init
   4.425 +{
   4.426 +    our $MyWiFile = "/home/devi/mywi/mywi.txt";
   4.427 +    our $MyWiLog = "/home/devi/mywi/mywi.log";
   4.428 +    our $section="";
   4.429 +
   4.430 +    our @MywiTXT;       # Массив текстовых записей mywi
   4.431 +    our %MywiHASH;      # Хэш массивов записей
   4.432 +    our %Query;
   4.433 +
   4.434 +    load_mywitxt($MyWiFile, \@MywiTXT, \%MywiHASH);
   4.435 +}
   4.436 +
   4.437 +sub mywi_process_query($)
   4.438 +#
   4.439 +# Сделать подсказку по заданному запросу
   4.440 +# $_[0] - тема для подсказки
   4.441 +# 
   4.442 +# Возвращает:
   4.443 +#   строку-подсказку
   4.444 +#
   4.445 +{
   4.446 +    my $query = shift;
   4.447 +    parse_query($query, \%Query);
   4.448 +    $result = search_in_txt(\%Query, \@MywiTXT, \%MywiHASH);
   4.449 +
   4.450 +    if (!$result) {
   4.451 +        #add_to_log(\%Query, $MyWiLog);
   4.452 +        return "$query nothing appropriate.  Logged. ".join (";",%Query);
   4.453 +    }   
   4.454 +
   4.455 +    return $result;
   4.456 +}
   4.457 +
   4.458 +####################################################################################
   4.459 +#                                   private section
   4.460 +####################################################################################
   4.461 +
   4.462 +sub load_mywitxt
   4.463 +#
   4.464 +# Загрузить файл с записями Mywi_TXT
   4.465 +# в массив
   4.466 +# $_[0] - указатель на массив для загрузки
   4.467 +# $_[1] - имя файла для загрузки
   4.468 +# 
   4.469 +{
   4.470 +    my $MyWiFile = $_[0];
   4.471 +    my $MywiTXT = $_[1];
   4.472 +    my $MywiHASH = $_[2];
   4.473 +    
   4.474 +    open (MW, "$MyWiFile") or die "Can't open $MyWiFile for reading";
   4.475 +    binmode MW, ":utf8";
   4.476 +    @{$MywiTXT} = <MW>;
   4.477 +    close (MWF);
   4.478 +
   4.479 +    for my $mywi_line (@{$MywiTXT}) {
   4.480 +        my $topic = $mywi_line;
   4.481 +        $topic =~ s@\s*\(.*\n@@;
   4.482 +        push @{$$MywiHASH{"$topic"}}, $mywi_line;
   4.483 +#        $MywiHASH{"$topic"} .= $mywi_line;
   4.484 +    }
   4.485 +}
   4.486 +
   4.487 +sub parse_query
   4.488 +#
   4.489 +# Строка запроса:
   4.490 +#   [format:]topic[(section)]
   4.491 +# Элементы format и topic являются не обязательными
   4.492 +#
   4.493 +# $_[0] - строка запроса
   4.494 +# $_[1] - ссылка на хэш запроса
   4.495 +#
   4.496 +{
   4.497 +    my $query_string = shift;
   4.498 +    my $query_hash = shift;
   4.499 +
   4.500 +    %{$query_hash} = (
   4.501 +        "format"    =>  "txt",
   4.502 +        "section"   =>  "",
   4.503 +        "topic" =>  "",
   4.504 +    );
   4.505 +
   4.506 +    if ($query_string =~ s/^([^:]*)://) {
   4.507 +        $query_hash->{"format"} = $1 || "txt";
   4.508 +    }
   4.509 +    if ($query_string =~ s/\(([^(]*)\)$//) {
   4.510 +        $query_hash->{"section"} = $1 || "";
   4.511 +    }
   4.512 +    $query_hash->{"topic"} = $query_string;
   4.513 +}
   4.514 +
   4.515 +
   4.516 +sub search_in_txt
   4.517 +#
   4.518 +# Выполнить поиск в текстовой базе 
   4.519 +# по известному запросу
   4.520 +# $_[0] -- ссылка на хэш запроса
   4.521 +# $_[1] -- ссылка на массив текстовых записей
   4.522 +# $_[2] -- ссылка на хэш массивов текстовых записей
   4.523 +# Результат:
   4.524 +#   найденная текстовая запись в заданном формате
   4.525 +#
   4.526 +{
   4.527 +    my %Query = %{$_[0]};
   4.528 +    my %MywiHASH = %{$_[2]};
   4.529 +
   4.530 +    my $topic = $Query{"topic"};
   4.531 +    my $section = $Query{"section"};
   4.532 +    my $result = "";
   4.533 +
   4.534 +    return join("\n",@{$MywiHASH{"$topic"}})."\n";
   4.535 +
   4.536 +    for my $l (@{$$_[2]{$topic}}) {
   4.537 +#    for my $l (@{$_[1]}) {
   4.538 +        my $line = $l;
   4.539 +        if (
   4.540 +            ($section and $line =~ /^\s*\Q$topic\E\s*\($section*\)\s*-/ )
   4.541 +            or (not $section and $line =~ /^\s*\Q$topic\E\s*(\([^)]*\)?)\s*-/) ) {
   4.542 +            $line =~ s/^.* -//mg if ($Config{"short"});
   4.543 +            $result .= "<para>$line</para>";
   4.544 +        }
   4.545 +    }
   4.546 +    return $result;
   4.547 +}
   4.548 +
   4.549 +
   4.550 +sub add_to_log($$)
   4.551 +#
   4.552 +# Если в базе отсутствует информация по данной теме, 
   4.553 +# сделать предположение доступным способом
   4.554 +# и добавить его в базу
   4.555 +# или просто сделать отметку о необходимости 
   4.556 +# расширения базы
   4.557 +#
   4.558 +# Добавить запись в журнал
   4.559 +# $_[0] - запись (ссылка на хэш)
   4.560 +# $_[1] - имя файла-журнала
   4.561 +#
   4.562 +{
   4.563 +    my $query = $_[0];
   4.564 +    my $MyWiLog = $_[1];
   4.565 +
   4.566 +    open (MWF, ">>:utf8", $MyWiLog) or die "Can't open $MyWiLog for writing";
   4.567 +    my $my_guess = mywi_guess($query);
   4.568 +    print MWF "$my_guess\n";
   4.569 +    close(MWF);
   4.570 +}
   4.571 +
   4.572 +sub mywi_guess($)
   4.573 +# Сформировать исходную строку для журнала по заданному запросу
   4.574 +# Если секция принадлежит 0..9, в качестве основы для результирующего текста использовать whatis
   4.575 +# $_[0] - запись (ссылка на хэш)
   4.576 +# 
   4.577 +# Возвращает:
   4.578 +#   строку-предположение
   4.579 +{
   4.580 +    my %query = %{$_[0]};
   4.581 +
   4.582 +    my $topic = $query{"topic"};
   4.583 +    my $section = $query{"section"};
   4.584 +    
   4.585 +    my $result = "$topic($section)";
   4.586 +    if (!$section or $section =~ /^[1-9]$/)
   4.587 +    {
   4.588 +        # Запрос из категории 1-9
   4.589 +        # Об этом может знать whatis
   4.590 +        $result = `LANG=C whatis -- "$topic"`;
   4.591 +        if ($result =~ /nothing appropriate/i) {
   4.592 +            $result = $topic;
   4.593 +            $result .= "($section)" if $section;
   4.594 +        }
   4.595 +        else {
   4.596 +            1 while ($result =~ s/(\s+)-(\s+)/$1+$2/sg);
   4.597 +            $result =~ s/\s+\(/(/;
   4.598 +            chomp $result;
   4.599 +        }
   4.600 +    }   
   4.601 +    return $result;
   4.602 +}
   4.603 +
     5.1 --- a/l3bashrc	Sun Nov 12 17:34:47 2006 +0200
     5.2 +++ b/l3bashrc	Wed Feb 13 02:41:57 2008 +0200
     5.3 @@ -151,11 +151,9 @@
     5.4                  old_file=\"/tmp/l3-saved-\$\$.\$RANDOM.\$RANDOM\"
     5.5                  /bin/cp -- \"\$1\" \"\$old_file\" 2> /dev/null
     5.6                  $editor_file \"\$@\" || ERR=\$?
     5.7 -                [ -e \"\$old_file\" ] && diff \"\$old_file\" \"\$1\" > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
     5.8 -                if [ "$?" == 2 ] 
     5.9 -                then 
    5.10 -                    diff /dev/null \"\$1\"  > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
    5.11 -                fi
    5.12 +                [ -e \"\$old_file\" ] \
    5.13 +                 && diff -u \"\$old_file\" \"\$1\" > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null \
    5.14 +                 || diff -u /dev/null \"\$1\"  > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
    5.15                  /bin/rm \"\$old_file\" 2> /dev/null
    5.16                  return \$ERR
    5.17              fi
    5.18 @@ -238,8 +236,26 @@
    5.19              grep ^l3cd= ~/.l3rc | sed s/[^=]*=//
    5.20          ;;
    5.21          *) 
    5.22 -            echo /usr/local/bin/l3
    5.23 +            cat <<EOF
    5.24 +l3 [command]:
    5.25 +
    5.26 +    cd new_context   - change current lilalo context
    5.27 +    pwd              - show current lilalo context
    5.28 +    on               - switch writing on (NOT IMPLEMENTED YET)
    5.29 +    off              - switch writing off (NOT IMPLEMENTED YET)
    5.30 +
    5.31 +EOF
    5.32          ;;
    5.33      esac
    5.34  }
    5.35  
    5.36 +l3cd()
    5.37 +{
    5.38 +    l3 cd "$@"
    5.39 +}
    5.40 +
    5.41 +l3pwd()
    5.42 +{
    5.43 +    l3 pwd
    5.44 +}
    5.45 +
     6.1 --- a/l3config.pm	Sun Nov 12 17:34:47 2006 +0200
     6.2 +++ b/l3config.pm	Wed Feb 13 02:41:57 2008 +0200
     6.3 @@ -145,6 +145,8 @@
     6.4      "cgi2file"          => "",
     6.5  
     6.6      "year"              =>  "2006",
     6.7 +    "commands_to_show_at_a_go" => "100",
     6.8 +    "start_from_command" => "0",
     6.9  );
    6.10  
    6.11  sub read_config_file