lilalo

annotate l3-frontend @ 150:822b36252d7f

Вывод больших фрагментов текста не теряется.

Большие фрагменты текста теперь не вырезаются бесследно.
Там, откуда они вырезаются, вставляются ссылки,
по которым можно посмотреть полную версию вывода.
Испытано на больших фрагментах текста,
содержащих до 5000 строк (фрагменты более 5000 строк по умолчанию
обрезаются административно; допустимые размеры задаются в l3config.pm).
Исправлены ошибки, из-за которых большие фрагменты
обрабатывались некорректно.
author igor@chub.in
date Tue Jun 23 01:15:02 2009 +0300 (2009-06-23)
parents 266dae9ce2a1
children 80691b40e6db
rev   line source
igor@121 1 #!/usr/bin/perl
devi@23 2
igor@109 3 use POSIX qw(strftime);
igor@115 4 use lib '/etc/lilalo';
devi@23 5 use l3config;
devi@88 6 use utf8;
devi@23 7
devi@23 8 our @Command_Lines;
devi@31 9 our @Command_Lines_Index;
devi@31 10 our %Commands_Description;
devi@31 11 our %Args_Description;
devi@32 12 our %Sessions;
igor@145 13 our %Uploads;
devi@89 14
igor@109 15 our $debug_output=""; # Используйте эту переменную, если нужно передать отладочную информацию
igor@109 16
devi@84 17 our %filter;
devi@89 18 our $filter_url;
devi@89 19 sub init_filter;
devi@23 20
devi@69 21 our %Files;
devi@69 22
devi@23 23 # vvv Инициализация переменных выполняется процедурой init_variables
devi@23 24 our @Day_Name;
devi@23 25 our @Month_Name;
devi@23 26 our @Of_Month_Name;
devi@23 27 our %Search_Machines;
devi@23 28 our %Elements_Visibility;
devi@23 29 # ^^^
devi@23 30
igor@109 31 our $First_Command=$0;
igor@109 32 our $Last_Command=40;
igor@109 33
devi@31 34 our %Stat;
devi@87 35 our %frequency_of_command; # Сколько раз в журнале встречается какая команда
devi@63 36 our $table_number=1;
igor@109 37 our %tigra_hints;
devi@31 38
devi@55 39 my %mywi_cache_for; # Кэш для экономии обращений к mywi
devi@55 40
igor@109 41 sub count_frequency_of_commands;
devi@23 42 sub make_comment;
devi@63 43 sub make_new_entries_table;
devi@23 44 sub load_command_lines_from_xml;
devi@32 45 sub load_sessions_from_xml;
igor@145 46 sub load_uploads;
devi@31 47 sub sort_command_lines;
devi@31 48 sub process_command_lines;
devi@23 49 sub init_variables;
devi@23 50 sub main;
devi@31 51 sub collapse_list($);
devi@23 52
devi@87 53 sub minutes_passed;
devi@87 54
devi@88 55 sub print_all_txt;
devi@88 56 sub print_all_html;
devi@89 57 sub print_edit_all_html;
devi@88 58 sub print_command_lines_html;
devi@89 59 sub print_command_lines_txt;
devi@88 60 sub print_files_html;
devi@88 61 sub print_stat_html;
devi@88 62 sub print_header_html;
devi@88 63 sub print_footer_html;
igor@109 64 sub tigra_hints_generate;
igor@109 65
igor@145 66
igor@109 67 #### mywi
igor@109 68 #
igor@109 69 sub mywi_init;
igor@109 70 sub load_mywitxt;
igor@109 71 sub mywi_process_query($);
igor@109 72 #
igor@109 73 sub add_to_log($$);
igor@109 74 sub parse_query;
igor@109 75 sub search_in_txt;
igor@109 76 sub add_to_log($$);
igor@109 77 sub mywi_guess($);
igor@109 78 #
devi@56 79
devi@23 80 main();
devi@23 81
devi@23 82 sub main
devi@23 83 {
devi@49 84 $| = 1;
devi@23 85
devi@49 86 init_variables();
devi@49 87 init_config();
devi@68 88 $Config{frontend_ico_path}=$Config{frontend_css};
devi@68 89 $Config{frontend_ico_path}=~s@/[^/]*$@@;
devi@89 90 init_filter();
igor@109 91 mywi_init();
devi@23 92
devi@49 93 load_command_lines_from_xml($Config{"backend_datafile"});
igor@145 94 load_uploads($Config{"upload_dir"});
devi@49 95 load_sessions_from_xml($Config{"backend_datafile"});
devi@49 96 sort_command_lines;
devi@49 97 process_command_lines;
devi@89 98 if (defined($filter{action}) && $filter{action} eq "edit") {
devi@89 99 print_edit_all_html($Config{"output"});
devi@89 100 }
devi@89 101 else {
devi@89 102 print_all_html($Config{"output"});
devi@89 103 }
devi@23 104 }
devi@23 105
devi@89 106 sub init_filter
devi@89 107 {
devi@89 108 if ($Config{filter}) {
devi@89 109 # Инициализация фильтра
igor@141 110 for (split /;;/,$Config{filter}) {
igor@141 111 my ($var, $val) = split /::/;
devi@89 112 $filter{$var} = $val || "";
devi@89 113 }
devi@89 114 }
igor@141 115 $filter_url = join (";;", map("$_::$filter{$_}", keys %filter));
devi@89 116 }
devi@89 117
devi@56 118 # extract_from_cline
devi@23 119
devi@56 120 # In: $what = commands | args
devi@56 121 # Out: return ссылка на хэш, содержащий результаты разбора
devi@56 122 # команда => позиция
devi@23 123
devi@31 124 # Разобрать командную строку $_[1] и возвратить хэш, содержащий
devi@31 125 # номер первого появление команды в строке:
devi@49 126 # команда => первая позиция
devi@56 127 sub extract_from_cline
devi@31 128 {
devi@49 129 my $what = $_[0];
devi@49 130 my $cline = $_[1];
devi@49 131 my @lists = split /\;/, $cline;
devi@49 132
devi@49 133
devi@56 134 my @command_lines = ();
devi@56 135 for my $command_list (@lists) {
devi@56 136 push(@command_lines, split(/\|/, $command_list));
devi@49 137 }
devi@31 138
devi@56 139 my %position_of_command;
devi@56 140 my %position_of_arg;
devi@49 141 my $i=0;
devi@56 142 for my $command_line (@command_lines) {
devi@56 143 $command_line =~ s@^\s*@@;
devi@56 144 $command_line =~ /\s*(\S+)\s*(.*)/;
devi@49 145 if ($1 && $1 eq "sudo" ) {
devi@56 146 $position_of_command{"$1"}=$i++;
devi@56 147 $command_line =~ s/\s*sudo\s+//;
devi@49 148 }
devi@56 149 if ($command_line !~ m@^\s*\S*/etc/@) {
devi@56 150 $command_line =~ s@^\s*\S+/@@;
devi@56 151 }
devi@56 152
devi@56 153 $command_line =~ /\s*(\S+)\s*(.*)/;
devi@56 154 my $command = $1;
devi@56 155 my $args = $2;
devi@56 156 if ($command && !defined $position_of_command{"$command"}) {
devi@56 157 $position_of_command{"$command"}=$i++;
devi@49 158 };
devi@56 159 if ($args) {
devi@49 160 my @args = split (/\s+/, $args);
devi@49 161 for my $a (@args) {
devi@56 162 $position_of_arg{"$a"}=$i++
devi@56 163 if !defined $position_of_arg{"$a"};
devi@49 164 };
devi@49 165 }
devi@49 166 }
devi@31 167
devi@49 168 if ($what eq "commands") {
devi@56 169 return \%position_of_command;
devi@49 170 } else {
devi@56 171 return \%position_of_arg;
devi@49 172 }
devi@49 173
devi@31 174 }
devi@31 175
igor@109 176 sub mywrap($)
devi@31 177 {
igor@109 178 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].
igor@109 179 '</div></div></div></div></div></div></div></div>';
devi@31 180 }
devi@31 181
igor@109 182 sub tigra_hints_generate
devi@31 183 {
igor@109 184 my $tigra_hints_items="";
igor@109 185 for my $hint_id (keys %tigra_hints) {
igor@109 186 $tigra_hints{$hint_id} =~ s@\n@<br/>@gs;
igor@109 187 $tigra_hints{$hint_id} =~ s@ - @ — @gs;
igor@109 188 $tigra_hints{$hint_id} =~ s@'@\\'@gs;
igor@109 189 # $tigra_hints_items .= "'$hint_id' : mywrap('".$tigra_hints{$hint_id}."'),";
igor@109 190 $tigra_hints_items .= "'$hint_id' : '".mywrap($tigra_hints{$hint_id})."',";
igor@109 191 }
igor@109 192 $tigra_hints_items =~ s/,$//;
igor@109 193 return <<TIGRA;
igor@109 194
igor@109 195 var HINTS_CFG = {
igor@109 196 'top' : 5, // a vertical offset of a hint from mouse pointer
igor@109 197 'left' : 5, // a horizontal offset of a hint from mouse pointer
igor@109 198 'css' : 'hintsClass', // a style class name for all hints, TD object
igor@109 199 'show_delay' : 500, // a delay between object mouseover and hint appearing
igor@109 200 'hide_delay' : 2000, // a delay between hint appearing and hint hiding
igor@109 201 'wise' : true,
igor@109 202 'follow' : true,
igor@109 203 'z-index' : 0 // a z-index for all hint layers
igor@109 204 },
igor@109 205
igor@109 206 HINTS_CFG_NEW = {
igor@109 207 'wise' : true, // don't go off screen, don't overlap the object in the document
igor@109 208 'margin' : 10, // minimum allowed distance between the hint and the window edge (negative values accepted)
igor@109 209 'gap' : 20, // minimum allowed distance between the hint and the origin (negative values accepted)
igor@109 210 '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)
igor@109 211 'css' : 'hintsClass', // a style class name for all hints, applied to DIV element (see style section in the header of the document)
igor@109 212 'show_delay' : 0, // a delay between initiating event (mouseover for example) and hint appearing
igor@109 213 'hide_delay' : 200, // a delay between closing event (mouseout for example) and hint disappearing
igor@109 214 'follow' : true, // hint follows the mouse as it moves
igor@109 215 'z-index' : 100, // a z-index for all hint layers
igor@109 216 'IEfix' : false, // fix IE problem with windowed controls visible through hints (activate if select boxes are visible through the hints)
igor@109 217 'IEtrans' : ['blendTrans(DURATION=.3)', null], // [show transition, hide transition] - nice transition effects, only work in IE5+
igor@109 218 'opacity' : 90 // opacity of the hint in %%
igor@109 219 },
igor@109 220
igor@109 221 HINTS_ITEMS = {
igor@109 222 $tigra_hints_items
igor@109 223 };
igor@109 224 var myHint = new THints (HINTS_CFG, HINTS_ITEMS);
igor@109 225
igor@109 226
igor@109 227 function mywrap (s_) {
igor@109 228 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_+
igor@109 229 '</div></div></div></div></div></div></div></div>';
igor@109 230
igor@109 231 }
igor@109 232 TIGRA
igor@109 233 $a=<<TIGRA;
igor@109 234 TIGRA
devi@31 235 }
devi@31 236
devi@31 237
igor@109 238 sub count_frequency_of_commands
devi@31 239 {
igor@109 240 my $cline = $_[0];
igor@109 241 my @commands = keys %{extract_from_cline("commands", $cline)};
igor@109 242 for my $command (@commands) {
igor@109 243 $frequency_of_command{$command}++;
devi@49 244 }
devi@31 245 }
devi@31 246
devi@23 247 sub make_comment
devi@23 248 {
devi@49 249 my $cline = $_[0];
devi@49 250 #my $files = $_[1];
devi@23 251
devi@55 252 my @comments;
devi@49 253 my @commands = keys %{extract_from_cline("commands", $cline)};
devi@49 254 my @args = keys %{extract_from_cline("args", $cline)};
devi@49 255 return if (!@commands && !@args);
devi@49 256 #return "commands=".join(" ",@commands)."; files=".join(" ",@files);
devi@23 257
devi@49 258 # Commands
devi@49 259 for my $command (@commands) {
devi@49 260 $command =~ s/'//g;
igor@109 261 #$frequency_of_command{$command}++;
devi@49 262 if (!$Commands_Description{$command}) {
igor@109 263 $mywi_cache_for{$command} ||= mywi_process_query($command) || "";
devi@63 264 my $mywi = join ("\n", grep(/\([18]|sh|script\)/, split(/\n/, $mywi_cache_for{$command})));
devi@49 265 $mywi =~ s/\s+/ /;
devi@49 266 if ($mywi !~ /^\s*$/) {
devi@49 267 $Commands_Description{$command} = $mywi;
devi@49 268 }
devi@49 269 else {
devi@49 270 next;
devi@49 271 }
devi@49 272 }
devi@23 273
devi@49 274 push @comments, $Commands_Description{$command};
devi@49 275 }
devi@49 276 return join("&#10;\n", @comments);
devi@49 277
devi@49 278 # Files
devi@49 279 for my $arg (@args) {
devi@49 280 $arg =~ s/'//g;
devi@49 281 if (!$Args_Description{$arg}) {
devi@49 282 my $mywi;
devi@49 283 $mywi = mywi_client ($arg);
devi@49 284 $mywi = join ("\n", grep(/\([5]\)/, split(/\n/, $mywi)));
devi@49 285 $mywi =~ s/\s+/ /;
devi@49 286 if ($mywi !~ /^\s*$/) {
devi@49 287 $Args_Description{$arg} = $mywi;
devi@49 288 }
devi@49 289 else {
devi@49 290 next;
devi@49 291 }
devi@49 292 }
devi@23 293
devi@49 294 push @comments, $Args_Description{$arg};
devi@49 295 }
devi@23 296
devi@23 297 }
devi@23 298
devi@23 299 =cut
devi@23 300 Процедура load_command_lines_from_xml выполняет загрузку разобранного lab-скрипта
devi@23 301 из XML-документа в переменную @Command_Lines
devi@23 302
devi@56 303 # In: $datafile имя файла
devi@56 304 # Out: @CommandLines загруженные командные строки
devi@56 305
devi@23 306 Предупреждение!
devi@23 307 Процедура не в состоянии обрабатывать XML-документ любой структуры.
devi@23 308 В действительности файл cache из которого загружаются данные
devi@23 309 просто напоминает XML с виду.
devi@23 310 =cut
devi@23 311 sub load_command_lines_from_xml
devi@23 312 {
devi@49 313 my $datafile = $_[0];
devi@23 314
devi@49 315 open (CLASS, $datafile)
devi@81 316 or die "Can't open file with xml lablog ",$datafile,"\n";
devi@49 317 local $/;
devi@89 318 binmode CLASS, ":utf8";
devi@49 319 $data = <CLASS>;
devi@49 320 close(CLASS);
devi@23 321
devi@49 322 for $command ($data =~ m@<command>(.*?)</command>@sg) {
devi@49 323 my %cl;
devi@49 324 while ($command =~ m@<([^>]*?)>(.*?)</\1>@sg) {
devi@49 325 $cl{$1} = $2;
devi@49 326 }
devi@49 327 push @Command_Lines, \%cl;
devi@49 328 }
devi@23 329 }
devi@23 330
devi@32 331 sub load_sessions_from_xml
devi@32 332 {
devi@49 333 my $datafile = $_[0];
devi@32 334
devi@89 335 open (CLASS, $datafile)
devi@81 336 or die "Can't open file with xml lablog ",$datafile,"\n";
devi@49 337 local $/;
devi@89 338 binmode CLASS, ":utf8";
devi@49 339 my $data = <CLASS>;
devi@49 340 close(CLASS);
devi@32 341
devi@84 342 my $i=0;
devi@84 343 for my $session ($data =~ m@<session>(.*?)</session>@msg) {
devi@84 344 my %session_hash;
devi@49 345 while ($session =~ m@<([^>]*?)>(.*?)</\1>@sg) {
devi@84 346 $session_hash{$1} = $2;
devi@49 347 }
devi@84 348 $Sessions{$session_hash{local_session_id}} = \%session_hash;
devi@49 349 }
devi@32 350 }
devi@32 351
igor@145 352 sub load_uploads($)
igor@145 353 {
igor@145 354 $dir=$_[0];
igor@145 355 for $i (glob("$dir/*.png")) {
igor@145 356 $i =~ s@.*/(([0-9-]+)_([0-9]+).*)@$1@;
igor@150 357 if (defined($Uploads{$2}{$3})) {
igor@150 358 $Uploads{$2}{$3} .= " ".$i;
igor@150 359 }
igor@150 360 else {
igor@150 361 $Uploads{$2}{$3}=$i;
igor@150 362 }
igor@145 363 }
igor@145 364 }
igor@145 365
igor@145 366 #for $key (sort keys %session) {
igor@145 367 # for $t (sort { $a <=> $b } keys %{ $session{$key} }) {
igor@145 368 # print $session{$key}{$t}."\n";
igor@145 369 # }
igor@145 370 #}
igor@145 371 #}
devi@32 372
devi@56 373 # sort_command_lines
devi@56 374 # In: @Command_Lines
devi@56 375 # Out: @Command_Lies_Index
devi@32 376
devi@31 377 sub sort_command_lines
devi@31 378 {
devi@31 379
devi@49 380 my @index;
devi@49 381 for (my $i=0;$i<=$#Command_Lines;$i++) {
devi@49 382 $index[$i]=$i;
devi@49 383 }
devi@31 384
devi@49 385 @Command_Lines_Index = sort {
devi@49 386 $Command_Lines[$index[$a]]->{"time"} <=> $Command_Lines[$index[$b]]->{"time"}
devi@49 387 } @index;
devi@31 388
devi@31 389 }
devi@31 390
devi@56 391 ##################
devi@56 392 # process_command_lines
devi@56 393 #
devi@56 394 # Обрабатываются командные строки @Command_Lines
devi@56 395 # Для каждой строки определяется:
devi@56 396 # class класс
devi@56 397 # note комментарий
devi@56 398 #
devi@56 399 # In: @Command_Lines_Index
devi@56 400 # In-Out: @Command_Lines
devi@56 401
devi@31 402 sub process_command_lines
devi@31 403 {
devi@89 404
igor@109 405
igor@109 406 my $current_command=0;
igor@115 407 my $prev_i;
igor@115 408
igor@115 409 my $tab_seq =0 ; # номер команды в последовательности tab-completion
igor@115 410 # отличен от нуля только для тех последовательностей,
igor@115 411 # где постоянно нажимается клавиша tab
igor@109 412
devi@89 413 COMMAND_LINE_PROCESSING:
devi@49 414 for my $i (@Command_Lines_Index) {
igor@109 415
igor@109 416 $current_command++;
igor@109 417 next if $current_command < $Config{"start_from_command"};
igor@109 418 last if $current_command > $Config{"start_from_command"} + $Config{"commands_to_show_at_a_go"};
igor@109 419
devi@56 420 my $cl = \$Command_Lines[$i];
devi@31 421
igor@115 422 # Запоминаем предыщуюу команду
igor@115 423 # Она нам потребуется, в частности, для ввода tab_seq рпи обработке tab_completion
igor@115 424 my $prev_cl;
igor@115 425 $prev_cl = \$Command_Lines[$prev_i] if defined($prev_i);
igor@115 426 $prev_i = $i;
igor@115 427
devi@56 428 next if !$cl;
devi@31 429
devi@89 430 for my $filter_key (keys %filter) {
devi@89 431 next COMMAND_LINE_PROCESSING
devi@89 432 if defined($$cl->{local_session_id})
devi@89 433 && defined($Sessions{$$cl->{local_session_id}}->{$filter_key})
devi@89 434 && $Sessions{$$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key};
devi@89 435 }
devi@89 436
devi@73 437 $$cl->{id} = $$cl->{"time"};
devi@73 438
devi@56 439 $$cl->{err} ||=0;
devi@56 440
igor@115 441
devi@56 442 # Класс команды
devi@56 443
devi@56 444 $$cl->{"class"} = $$cl->{"err"} eq 130 ? "interrupted"
devi@56 445 : $$cl->{"err"} eq 127 ? "mistyped"
devi@56 446 : $$cl->{"err"} ? "wrong"
devi@57 447 : "normal";
devi@56 448
devi@73 449 if ($$cl->{"cline"} &&
devi@73 450 $$cl->{"cline"} =~ /[^|`]\s*sudo/
devi@57 451 || $$cl->{"uid"} eq 0) {
devi@49 452 $$cl->{"class"}.="_root";
devi@49 453 }
devi@31 454
devi@91 455 my $hint;
igor@109 456 count_frequency_of_commands($$cl->{"cline"});
devi@91 457 $hint = make_comment($$cl->{"cline"});
igor@109 458
devi@91 459 if ($hint) {
devi@91 460 $$cl->{hint} = $hint;
devi@91 461 }
igor@109 462 $tigra_hints{$$cl->{"time"}} = $hint;
igor@109 463
igor@111 464 #$$cl->{hint}="";
devi@87 465
devi@87 466 # Выводим <head_lines> верхних строк
devi@87 467 # и <tail_lines> нижних строк,
devi@87 468 # если эти параметры существуют
devi@87 469 my $output="";
devi@87 470
devi@87 471 if ($$cl->{"last_command"} eq "cat" && !$$cl->{"err"} && !($$cl->{"cline"} =~ /</)) {
devi@87 472 my $filename = $$cl->{"cline"};
devi@87 473 $filename =~ s/.*\s+(\S+)\s*$/$1/;
devi@87 474 $Files{$filename}->{"content"} = $$cl->{"output"};
devi@87 475 $Files{$filename}->{"source_command_id"} = $$cl->{"id"}
devi@87 476 }
devi@87 477 my @lines = split '\n', $$cl->{"output"};
devi@87 478 if ((
devi@87 479 $Config{"head_lines"}
devi@87 480 || $Config{"tail_lines"}
devi@87 481 )
devi@87 482 && $#lines > $Config{"head_lines"} + $Config{"tail_lines"} ) {
devi@87 483 #
devi@87 484 for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) {
devi@87 485 $output .= $lines[$i]."\n";
devi@87 486 }
devi@87 487 $output .= $Config{"skip_text"}."\n";
devi@87 488
devi@87 489 my $start_line=$#lines-$Config{"tail_lines"}+1;
devi@87 490 for (my $i=$start_line; $i<= $#lines; $i++) {
devi@87 491 $output .= $lines[$i]."\n";
devi@87 492 }
devi@87 493 }
devi@87 494 else {
devi@87 495 $output = $$cl->{"output"};
devi@87 496 }
devi@87 497 $$cl->{short_output} = $output;
devi@56 498
igor@115 499 # Обработка команд с одинаковым временем
igor@115 500 # Скорее всего они набраны с помощью tab-completion
igor@115 501 if (defined($prev_cl)) {
igor@119 502 if ($$prev_cl->{time} == $$cl->{time} && $$prev_cl->{nonce} == $$cl->{nonce}) {
igor@115 503 $tab_seq++;
igor@115 504 }
igor@115 505 else {
igor@115 506 $tab_seq=0;
igor@115 507 };
igor@115 508 $$prev_cl->{tab_seq}=$tab_seq;
igor@115 509
igor@115 510 # Обработка команд с одинаковым номером в истории
igor@115 511 # Скорее всего они набраны с помощью Ctrl-C
igor@119 512 #if ($$prev_cl->{history} == $$cl->{history}) {
igor@119 513 # $$prev_cl->{break}=1;
igor@119 514 #}
igor@115 515 }
igor@115 516
igor@115 517
devi@56 518 #Обработка пометок
devi@56 519 # Если несколько пометок (notes) идут подряд,
devi@56 520 # они все объединяются
devi@31 521
devi@81 522 if ($$cl->{cline} =~ /l3shot/) {
devi@81 523 if ($$cl->{output} =~ m@Screenshot is written to.*/(.*)\.xwd@) {
igor@111 524 $$cl->{screenshot}="$1".$Config{l3shot_suffix};
igor@111 525 }
igor@111 526 }
igor@111 527 if ($$cl->{cline} =~ /l3upload/) {
igor@111 528 if ($$cl->{output} =~ m@Uploaded file name is (.*)@) {
devi@81 529 $$cl->{screenshot}="$1";
devi@81 530 }
devi@81 531 }
devi@81 532
devi@49 533 if ($$cl->{cline}=~ m@cat[^#]*#([\^=v])\s*(.*)@) {
devi@56 534
devi@56 535 my $note_operator = $1;
devi@56 536 my $note_title = $2;
devi@56 537
devi@56 538 if ($note_operator eq "=") {
devi@49 539 $$cl->{"class"} = "note";
devi@49 540 $$cl->{"note"} = $$cl->{"output"};
devi@49 541 $$cl->{"note_title"} = $2;
devi@49 542 }
devi@49 543 else {
devi@49 544 my $j = $i;
devi@56 545 if ($note_operator eq "^") {
devi@49 546 $j--;
devi@49 547 $j-- while ($j >=0 && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty}));
devi@49 548 }
devi@56 549 elsif ($note_operator eq "v") {
devi@49 550 $j++;
devi@49 551 $j++ while ($j <= @Command_Lines && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty}));
devi@49 552 }
devi@56 553 $Command_Lines[$j]->{note_title}=$note_title;
devi@56 554 $Command_Lines[$j]->{note}.=$$cl->{output};
devi@49 555 $$cl=0;
devi@49 556 }
devi@49 557 }
devi@49 558 elsif ($$cl->{cline}=~ /#([\^=v])(.*)/) {
devi@56 559
devi@56 560 my $note_operator = $1;
devi@56 561 my $note_text = $2;
devi@56 562
devi@56 563 if ($note_operator eq "=") {
devi@49 564 $$cl->{"class"} = "note";
devi@56 565 $$cl->{"note"} = $note_text;
devi@49 566 }
devi@49 567 else {
devi@49 568 my $j=$i;
devi@56 569 if ($note_operator eq "^") {
devi@49 570 $j--;
devi@49 571 $j-- while ($j >=0 && (!$Command_Lines[$j] || $Command_Lines[$j]->{tty} ne $$cl->{tty}));
devi@49 572 }
devi@56 573 elsif ($note_operator eq "v") {
devi@49 574 $j++;
devi@49 575 $j++ while ($j <= @Command_Lines && $Command_Lines[$j]->{tty} ne $$cl->{tty} || !$Command_Lines[$j]);
devi@49 576 }
devi@56 577 $Command_Lines[$j]->{note}.="$note_text\n";
devi@49 578 $$cl=0;
devi@49 579 }
devi@49 580 }
devi@88 581 if ($$cl->{"class"} eq "note") {
devi@87 582 my $note_html = $$cl->{note};
devi@88 583 $note_html = join ("\n", map ("<p>$_</p>", split (/-\n/, $note_html)));
devi@87 584 $note_html =~ s@(http:[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g;
devi@87 585 $note_html =~ s@(www\.[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g;
devi@87 586 $$cl->{"note_html"} = $note_html;
devi@87 587 }
devi@49 588 }
devi@31 589
devi@31 590 }
devi@31 591
devi@31 592
devi@23 593 =cut
devi@23 594 Процедура print_command_lines выводит HTML-представление
devi@23 595 разобранного lab-скрипта.
devi@23 596
devi@23 597 Разобранный lab-скрипт должен находиться в массиве @Command_Lines
devi@23 598 =cut
devi@23 599
devi@88 600 sub print_command_lines_html
devi@23 601 {
devi@23 602
devi@56 603 my @toc; # Оглавление
devi@49 604 my $note_number=0;
devi@23 605
devi@56 606 my $result = q();
devi@56 607 my $this_day_resut = q();
devi@49 608
devi@49 609 my $cl;
devi@49 610 my $last_tty="";
devi@80 611 my $last_session="";
devi@56 612 my $last_day=q();
devi@56 613 my $last_wday=q();
igor@109 614 my $first_command_of_the_day_unix_time=q();
igor@109 615 my $human_readable_time=q();
devi@49 616 my $in_range=0;
devi@23 617
devi@49 618 my $current_command=0;
devi@32 619
devi@57 620 my @known_commands;
devi@57 621
devi@56 622
devi@56 623
devi@56 624 $Stat{LastCommand} ||= 0;
devi@56 625 $Stat{TotalCommands} ||= 0;
devi@56 626 $Stat{ErrorCommands} ||= 0;
devi@56 627 $Stat{MistypedCommands} ||= 0;
devi@56 628
devi@63 629 my %new_entries_of = (
devi@64 630 "1 1" => "программы пользователя",
devi@64 631 "2 8" => "программы администратора",
devi@64 632 "3 sh" => "команды интерпретатора",
devi@64 633 "4 script"=> "скрипты",
devi@63 634 );
devi@63 635
devi@32 636 COMMAND_LINE:
devi@49 637 for my $k (@Command_Lines_Index) {
devi@31 638
devi@49 639 my $cl=$Command_Lines[$Command_Lines_Index[$current_command++]];
devi@49 640 next unless $cl;
igor@150 641 my $next_cl=$Command_Lines[$Command_Lines_Index[$current_command]];
devi@23 642
igor@109 643 next if $current_command < $Config{"start_from_command"};
igor@109 644 last if $current_command > $Config{"start_from_command"} + $Config{"commands_to_show_at_a_go"};
igor@109 645
igor@109 646
devi@32 647
devi@56 648 # Пропускаем строки, которые противоречат фильтру
devi@56 649 # Если у нас недостаточно информации о том, подходит строка под фильтр или нет,
devi@56 650 # мы её выводим
devi@56 651
devi@56 652 for my $filter_key (keys %filter) {
devi@84 653 next COMMAND_LINE
devi@84 654 if defined($cl->{local_session_id})
devi@84 655 && defined($Sessions{$cl->{local_session_id}}->{$filter_key})
devi@56 656 && $Sessions{$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key};
devi@49 657 }
devi@32 658
devi@64 659 # Набираем статистику
devi@64 660 # Хэш %Stat
devi@64 661
devi@64 662 $Stat{FirstCommand} = $cl->{time} unless $Stat{FirstCommand};
devi@64 663 if ($cl->{time} - $Stat{LastCommand} < $Config{stat_inactivity_interval}) {
devi@64 664 $Stat{TotalTime} += $cl->{time} - $Stat{LastCommand}
devi@64 665 }
devi@64 666 my $seconds_since_last_command = $cl->{time} - $Stat{LastCommand};
devi@87 667
devi@87 668 if ($Stat{LastCommand} > $cl->{time}) {
devi@87 669 $result .= "Время идёт вспять<br/>";
devi@87 670 };
devi@64 671 $Stat{LastCommand} = $cl->{time};
devi@64 672 $Stat{TotalCommands}++;
devi@64 673
devi@56 674 # Пропускаем строки, выходящие за границу "signature",
devi@56 675 # при условии, что границы указаны
devi@56 676 # Пропускаем неправильные/прерванные/другие команды
devi@49 677 if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) {
devi@49 678 $in_range=1;
devi@49 679 next;
devi@49 680 }
devi@49 681 if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) {
devi@49 682 $in_range=0;
devi@49 683 next;
devi@49 684 }
devi@56 685 next if ($Config{"from"} && $Config{"to"} && !$in_range)
devi@56 686 || ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ )
devi@56 687 || ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0)
devi@56 688 || ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130);
devi@49 689
devi@87 690
devi@87 691
devi@87 692
devi@87 693 #
devi@87 694 ##
devi@87 695 ## Начинается собственно вывод
devi@87 696 ##
devi@87 697 #
devi@87 698
devi@87 699 ### Сначала обрабатываем границы разделов
devi@87 700 ### Если тип команды "note", это граница
devi@87 701
devi@49 702 if ($cl->{class} eq "note") {
devi@57 703 $this_day_result .= "<tr><td colspan='6'>"
devi@57 704 . "<h4 id='note$note_number'>".$cl->{note_title}."</h4>" if $cl->{note_title}
devi@87 705 . "".$cl->{note_html}."<p/><p/></td></tr>";
devi@31 706
devi@49 707 if ($cl->{note_title}) {
devi@49 708 push @{$toc[@toc]},"<a href='#note$note_number'>".$cl->{note_title}."</a>";
devi@49 709 $note_number++;
devi@49 710 }
devi@49 711 next;
devi@49 712 }
devi@31 713
devi@49 714 my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time});
devi@31 715
igor@109 716
devi@49 717 # Добавляем спереди 0 для удобочитаемости
devi@56 718 $min = "0".$min if $min =~ /^.$/;
devi@49 719 $hour = "0".$hour if $hour =~ /^.$/;
devi@56 720 $sec = "0".$sec if $sec =~ /^.$/;
devi@23 721
devi@56 722 $class=$cl->{"class"};
devi@56 723 $Stat{ErrorCommands}++ if $class =~ /wrong/;
devi@56 724 $Stat{MistypedCommands}++ if $class =~ /mistype/;
devi@87 725
devi@56 726 # DAY CHANGE
devi@49 727 if ( $last_day ne $day) {
igor@109 728 $prev_unix_time=$first_command_of_the_day_unix_time;
igor@109 729 $first_command_of_the_day_unix_time = $cl->{time};
igor@109 730 $human_readable_time = strftime "%D", localtime($prev_unix_time);
devi@56 731 if ($last_day) {
devi@57 732
devi@57 733 # Вычисляем разность множеств.
devi@57 734 # Что-то вроде этого, если бы так можно было писать:
devi@87 735 # @new_commands = keys %frequency_of_command - @known_commands;
devi@57 736
devi@57 737
igor@109 738 # Выводим предыдущий день
igor@109 739
igor@109 740 $result .= "<h3 id='day_on_sec_$prev_unix_time'>".$Day_Name[$last_wday]." ($human_readable_time)</h3>";
devi@64 741 for my $entry_class (sort keys %new_entries_of) {
devi@87 742 my $table_caption = "Таблица ".$table_number++.".".$Day_Name[$last_wday]
devi@87 743 .". Новые ".$new_entries_of{$entry_class};
devi@87 744 my $new_commands_section = make_new_entries_table(
devi@87 745 $table_caption,
devi@87 746 $entry_class=~/[0-9]+\s+(.*)/,
devi@87 747 \@known_commands);
devi@63 748 }
devi@87 749 @known_commands = keys %frequency_of_command;
devi@56 750 $result .= $this_day_result;
devi@56 751 }
devi@56 752
igor@109 753 # Добавляем текущий день в оглавление
igor@109 754
igor@109 755 $human_readable_time = strftime "%D", localtime($first_command_of_the_day_unix_time);
igor@109 756 push @toc, "<a href='#day_on_sec_$first_command_of_the_day_unix_time'>".$Day_Name[$wday]." ($human_readable_time)</a>\n";
igor@109 757
igor@109 758
devi@49 759 $last_day=$day;
devi@56 760 $last_wday=$wday;
devi@56 761 $this_day_result = q();
devi@49 762 }
devi@87 763 else {
devi@87 764 $this_day_result .= minutes_passed($seconds_since_last_command);
devi@64 765 }
devi@23 766
devi@75 767 $this_day_result .= "<div class='command' id='command:".$cl->{"id"}."' >\n";
devi@56 768
devi@56 769 # CONSOLE CHANGE
devi@81 770 if ($cl->{"tty"} && $last_tty ne $cl->{"tty"} && 0) {
devi@56 771 my $tty = $cl->{"tty"};
devi@75 772 $this_day_result .= "<div class='ttychange'>"
devi@56 773 . $tty
devi@75 774 ."</div>";
devi@49 775 $last_tty=$cl->{"tty"};
devi@49 776 }
devi@23 777
devi@80 778 # Session change
devi@80 779 if ( $last_session ne $cl->{"local_session_id"}) {
devi@89 780 my $tty;
devi@89 781 if (defined $Sessions{$cl->{"local_session_id"}}->{"tty"}) {
igor@141 782 $this_day_result .= "<div class='ttychange'><a href='?filter=local_session_id::".$cl->{"local_session_id"}."'>"
devi@80 783 . $Sessions{$cl->{"local_session_id"}}->{"tty"}
devi@87 784 ."</a></div>";
devi@89 785 }
devi@80 786 $last_session=$cl->{"local_session_id"};
devi@80 787 }
devi@80 788
devi@56 789 # TIME
devi@87 790 if ($Config{"show_time"} =~ /^y/i) {
devi@87 791 $this_day_result .= "<div class='time'>$hour:$min:$sec</div>"
devi@87 792 }
devi@64 793
devi@56 794 # COMMAND
devi@56 795 my $cline;
igor@119 796 $prompt_hint = join ("&#10;",
igor@119 797 map("$_=$cl->{$_}",
igor@119 798 grep (!/^(output|short_output|diff)$/,
igor@119 799 sort(keys(%{$cl})))));
igor@119 800
igor@135 801 $cl->{"prompt"} =~ s/ $//;
igor@135 802 $cline = "<span title='$prompt_hint' class='prompt'><a href='#".$cl->{time}."' id='".$cl->{time}."'>".$cl->{"prompt"}."</a></span>"
igor@111 803 ."<span onmouseover=\"myHint.show('".$cl->{time}."')\" onmouseout=\"myHint.hide()\">".$cl->{"cline"}."</span>";
devi@49 804 $cline =~ s/\n//;
devi@32 805
devi@87 806 if ($cl->{"hint"}) {
igor@111 807 # $cline = "<span title='$cl->{hint}' class='with_hint'>$cline</span>" ;
igor@111 808 $cline = "<span class='with_hint'>$cline</span>" ;
devi@87 809 }
devi@87 810 else {
devi@87 811 $cline = "<span class='without_hint'>$cline</span>";
devi@87 812 }
devi@23 813
igor@109 814 $this_day_result .= "<DIV class='fixed_div'><table cellpadding='0' cellspacing='0'><tr><td>\n<div class='cblock_$cl->{class}'>\n";
igor@111 815 $this_day_result .= "<div class='cline'>" . $cline ; #cline
devi@75 816 $this_day_result .= "<span title='Код завершения ".$cl->{"err"}."'>\n"
devi@75 817 . "<img src='".$Config{frontend_ico_path}."/error.png'/>\n"
igor@115 818 . "</span>\n" if ($cl->{"err"} and not $cl->{tab_seq} and not $cl->{break});
igor@115 819 $this_day_result .= "<span title='Tab completion ".$cl->{tab_seq}."'>\n"
igor@115 820 . "<img src='".$Config{frontend_ico_path}."/tab.png'/>\n"
igor@115 821 . "</span>\n" if $cl->{tab_seq};
igor@115 822 $this_day_result .= "<span title='Ctrl-C pressed'>\n"
igor@115 823 . "<img src='".$Config{frontend_ico_path}."/break.png'/>\n"
igor@115 824 . "</span>\n" if ($cl->{break} and not $cl->{tab_seq});
devi@75 825 $this_day_result .= "</div>\n"; #cline
devi@56 826
devi@56 827 # OUTPUT
devi@49 828 my $last_command = $cl->{"last_command"};
devi@49 829 if (!(
devi@49 830 $Config{"suppress_editors"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"editors"}}) ||
devi@49 831 $Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) ||
devi@49 832 $Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}})
devi@49 833 )) {
devi@87 834 $this_day_result .= "<pre class='output'>\n" . $cl->{short_output} . "</pre>\n";
devi@87 835 }
devi@23 836
devi@56 837 # DIFF
devi@75 838 $this_day_result .= "<pre class='diff'>".$cl->{"diff"}."</pre>"
devi@75 839 if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"});
devi@81 840 # SHOT
igor@147 841
igor@150 842 #$this_day_result .= join(".", keys(%Uploads));
igor@150 843 #$this_day_result .= "PRIVET";
igor@146 844 for $t (sort { $a <=> $b } keys %{ $Uploads{$cl->{"local_session_id"}} }) {
igor@150 845 if (($t >= $cl->{"time"} and $t < $next_cl->{"time"}) or ($t >= $cl->{"time"} and not defined($next_cl))) {
igor@150 846 my @shots=split(/\s+/, $Uploads{$cl->{"local_session_id"}}{$t});
igor@150 847 for my $shot (@shots) {
igor@150 848 $this_day_result .= "<IMG src='"
igor@150 849 .$Config{l3shot_path}
igor@150 850 .$shot
igor@150 851 ."' alt ='screenshot id ".$shot
igor@150 852 ."'/><br/>"
igor@150 853 }
igor@150 854 }
igor@146 855 }
igor@145 856
igor@150 857 # Временно заблокировано
igor@150 858 # $this_day_result .= "<img src='"
igor@150 859 # .$Config{l3shot_path}
igor@150 860 # .$cl->{"screenshot"}
igor@150 861 # ."' alt ='screenshot id ".$cl->{"screenshot"}
igor@150 862 # ."'/>"
igor@150 863 # if ( $Config{"show_screenshots"} =~ /^y/i && $cl->{"screenshot"});
devi@56 864
devi@56 865 #NOTES
devi@49 866 if ( $Config{"show_notes"} =~ /^y/i && $cl->{"note"}) {
devi@49 867 my $note=$cl->{"note"};
devi@49 868 $note =~ s/\n/<br\/>\n/msg;
devi@52 869 if (not $note =~ s@(http:[a-zA-Z.0-9/_?%-]*)@<a href='$1'>$1</a>@g) {
devi@56 870 $note =~ s@(www\.[a-zA-Z.0-9/_?%-]*)@<a href='$1'>$1</a>@g;
devi@56 871 };
devi@75 872 $this_day_result .= "<div class='note'>";
devi@75 873 $this_day_result .= "<div class='note_title'>".$cl->{note_title}."</div>" if $cl->{note_title};
devi@75 874 $this_day_result .= "<div class='note_text'>".$note."</div>";
devi@75 875 $this_day_result .= "</div>\n";
devi@49 876 }
devi@23 877
devi@49 878 # Вывод очередной команды окончен
devi@75 879 $this_day_result .= "</div>\n"; # cblock
igor@109 880 $this_day_result .= "</td></tr></table></DIV>\n"
devi@75 881 . "</div>\n"; # command
devi@49 882 }
devi@57 883 last: {
igor@109 884 $prev_unix_time=$first_command_of_the_day_unix_time;
igor@109 885 $first_command_of_the_day_unix_time = $cl->{time};
igor@109 886 $human_readable_time = strftime "%D", localtime($prev_unix_time);
igor@109 887
igor@109 888 $result .= "<h3 id='day_on_sec_$prev_unix_time'>".$Day_Name[$last_wday]." ($human_readable_time)</h3>";
devi@23 889
devi@63 890 for my $entry_class (keys %new_entries_of) {
devi@87 891 my $table_caption = "Таблица ".$table_number++.".".$Day_Name[$last_wday]
devi@87 892 . ". Новые ".$new_entries_of{$entry_class};
devi@87 893 my $new_commands_section = make_new_entries_table(
devi@87 894 $table_caption,
devi@87 895 $entry_class=~/[0-9]+\s+(.*)/,
devi@87 896 \@known_commands);
devi@57 897 }
devi@87 898 @known_commands = keys %frequency_of_command;
devi@57 899 $result .= $this_day_result;
devi@57 900 }
devi@23 901
devi@56 902 return ($result, collapse_list (\@toc));
devi@31 903
devi@56 904 }
devi@56 905
devi@87 906 #############
devi@88 907 # make_new_entries_table
devi@87 908 #
devi@87 909 # Напечатать таблицу неизвестных команд
devi@87 910 #
devi@87 911 # In: $_[0] table_caption
devi@87 912 # $_[1] entries_class
devi@87 913 # @_[2..] known_commands
devi@87 914 # Out:
devi@87 915
devi@63 916 sub make_new_entries_table
devi@57 917 {
devi@87 918 my $table_caption;
devi@63 919 my $entries_class = shift;
devi@57 920 my @known_commands = @{$_[0]};
devi@87 921 my $result = "";
devi@56 922
devi@57 923 my %count;
devi@57 924 my @new_commands = ();
devi@87 925 for my $c (keys %frequency_of_command, @known_commands) {
devi@57 926 $count{$c}++
devi@57 927 }
devi@87 928 for my $c (keys %frequency_of_command) {
devi@57 929 push @new_commands, $c if $count{$c} != 2;
devi@57 930 }
devi@57 931
devi@57 932 my $new_commands_section;
devi@57 933 if (@new_commands){
devi@57 934 my $hint;
devi@87 935 for my $c (reverse sort { $frequency_of_command{$a} <=> $frequency_of_command{$b} } @new_commands) {
devi@57 936 $hint = make_comment($c);
devi@69 937 next unless $hint;
devi@57 938 my ($command, $hint) = $hint =~ m/(.*?) \s*- \s*(.*)/;
devi@64 939 next unless $command =~ s/\($entries_class\)//i;
devi@69 940 $new_commands_section .= "<tr><td valign='top'>$command</td><td>$hint</td></tr>";
devi@57 941 }
devi@57 942 }
devi@87 943 if ($new_commands_section) {
devi@87 944 $result .= "<table class='new_commands_table' width='700' cellspacing='0' cellpadding='0'>"
devi@87 945 . "<tr class='new_commands_caption'>"
devi@87 946 . "<td colspan='2' align='right'>$table_caption</td>"
devi@87 947 . "</tr>"
devi@87 948 . "<tr class='new_commands_header'>"
devi@87 949 . "<td width=100>Команда</td><td width=600>Описание</td>"
devi@87 950 . "</tr>"
devi@87 951 . $new_commands_section
devi@87 952 . "</table>"
devi@87 953 }
devi@87 954 return $result;
devi@57 955 }
devi@56 956
devi@87 957 #############
devi@88 958 # minutes_passed
devi@87 959 #
devi@87 960 #
devi@87 961 #
devi@87 962 # In: $_[0] seconds_since_last_command
devi@87 963 # Out: "minutes passed" text
devi@87 964
devi@87 965 sub minutes_passed
devi@87 966 {
devi@87 967 my $seconds_since_last_command = shift;
devi@87 968 my $result = "";
devi@87 969 if ($seconds_since_last_command > 7200) {
devi@87 970 my $hours_passed = int($seconds_since_last_command/3600);
devi@87 971 my $passed_word = $hours_passed % 10 == 1 ? "прошла"
devi@87 972 : "прошло";
devi@87 973 my $hours_word = $hours_passed % 10 == 1 ? "часа":
devi@87 974 "часов";
devi@87 975 $result .= "<div class='much_time_passed'>"
devi@87 976 . $passed_word." &gt;".$hours_passed." ".$hours_word
devi@87 977 . "</div>\n";
devi@87 978 }
devi@87 979 elsif ($seconds_since_last_command > 600) {
devi@87 980 my $minutes_passed = int($seconds_since_last_command/60);
devi@87 981
devi@87 982
devi@87 983 my $passed_word = $minutes_passed % 100 > 10
devi@87 984 && $minutes_passed % 100 < 20 ? "прошло"
devi@87 985 : $minutes_passed % 10 == 1 ? "прошла"
devi@87 986 : "прошло";
devi@87 987
devi@87 988 my $minutes_word = $minutes_passed % 100 > 10
devi@87 989 && $minutes_passed % 100 < 20 ? "минут" :
devi@87 990 $minutes_passed % 10 == 1 ? "минута":
devi@87 991 $minutes_passed % 10 == 0 ? "минут" :
devi@87 992 $minutes_passed % 10 > 4 ? "минут" :
devi@87 993 "минуты";
devi@87 994
devi@87 995 if ($seconds_since_last_command < 1800) {
devi@87 996 $result .= "<div class='time_passed'>"
devi@87 997 . $passed_word." ".$minutes_passed." ".$minutes_word
devi@87 998 . "</div>\n";
devi@87 999 }
devi@87 1000 else {
devi@87 1001 $result .= "<div class='much_time_passed'>"
devi@87 1002 . $passed_word." ".$minutes_passed." ".$minutes_word
devi@87 1003 . "</div>\n";
devi@87 1004 }
devi@87 1005 }
devi@87 1006 return $result;
devi@87 1007 }
devi@56 1008
devi@56 1009 #############
devi@88 1010 # print_all_txt
devi@56 1011 #
devi@88 1012 # Вывести журнал в текстовом формате
devi@56 1013 #
devi@56 1014 # In: $_[0] output_filename
devi@56 1015 # Out:
devi@56 1016
devi@89 1017 sub print_command_lines_txt
devi@88 1018 {
devi@56 1019
devi@88 1020 my $output_filename=$_[0];
devi@88 1021 my $note_number=0;
devi@88 1022
devi@88 1023 my $result = q();
devi@88 1024 my $this_day_resut = q();
devi@88 1025
devi@88 1026 my $cl;
devi@88 1027 my $last_tty="";
devi@88 1028 my $last_session="";
devi@88 1029 my $last_day=q();
devi@88 1030 my $last_wday=q();
devi@88 1031 my $in_range=0;
devi@88 1032
devi@88 1033 my $current_command=0;
devi@88 1034
devi@88 1035 my $cursor_position = 0;
devi@88 1036
devi@88 1037
devi@88 1038 if ($Config{filter}) {
devi@88 1039 # Инициализация фильтра
devi@88 1040 for (split /&/,$Config{filter}) {
igor@141 1041 my ($var, $val) = split /::/;
devi@88 1042 $filter{$var} = $val || "";
devi@88 1043 }
devi@88 1044 }
devi@88 1045
devi@88 1046
devi@88 1047 COMMAND_LINE:
devi@88 1048 for my $k (@Command_Lines_Index) {
devi@88 1049
devi@88 1050 my $cl=$Command_Lines[$Command_Lines_Index[$current_command++]];
devi@88 1051 next unless $cl;
devi@88 1052
devi@88 1053
devi@88 1054 # Пропускаем строки, которые противоречат фильтру
devi@88 1055 # Если у нас недостаточно информации о том, подходит строка под фильтр или нет,
devi@88 1056 # мы её выводим
devi@88 1057
devi@88 1058 for my $filter_key (keys %filter) {
devi@88 1059 next COMMAND_LINE
devi@88 1060 if defined($cl->{local_session_id})
devi@88 1061 && defined($Sessions{$cl->{local_session_id}}->{$filter_key})
devi@88 1062 && $Sessions{$cl->{local_session_id}}->{$filter_key} ne $filter{$filter_key};
devi@88 1063 }
devi@88 1064
devi@88 1065 # Пропускаем строки, выходящие за границу "signature",
devi@88 1066 # при условии, что границы указаны
devi@88 1067 # Пропускаем неправильные/прерванные/другие команды
devi@88 1068 if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) {
devi@88 1069 $in_range=1;
devi@88 1070 next;
devi@88 1071 }
devi@88 1072 if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) {
devi@88 1073 $in_range=0;
devi@88 1074 next;
devi@88 1075 }
devi@88 1076 next if ($Config{"from"} && $Config{"to"} && !$in_range)
devi@88 1077 || ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ )
devi@88 1078 || ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0)
devi@88 1079 || ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130);
devi@88 1080
devi@88 1081
devi@88 1082 #
devi@88 1083 ##
devi@88 1084 ## Начинается собственно вывод
devi@88 1085 ##
devi@88 1086 #
devi@88 1087
devi@88 1088 ### Сначала обрабатываем границы разделов
devi@88 1089 ### Если тип команды "note", это граница
devi@88 1090
devi@88 1091 if ($cl->{class} eq "note") {
devi@88 1092 $this_day_result .= " === ".$cl->{note_title}." === \n" if $cl->{note_title};
devi@88 1093 $this_day_result .= $cl->{note}."\n";
devi@88 1094 next;
devi@88 1095 }
devi@88 1096
devi@88 1097 my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time});
devi@88 1098
devi@88 1099 # Добавляем спереди 0 для удобочитаемости
devi@88 1100 $min = "0".$min if $min =~ /^.$/;
devi@88 1101 $hour = "0".$hour if $hour =~ /^.$/;
devi@88 1102 $sec = "0".$sec if $sec =~ /^.$/;
devi@88 1103
devi@88 1104 $class=$cl->{"class"};
devi@88 1105
devi@88 1106 # DAY CHANGE
devi@88 1107 if ( $last_day ne $day) {
devi@88 1108 if ($last_day) {
devi@88 1109 $result .= "== ".$Day_Name[$last_wday]." == \n";
devi@88 1110 $result .= $this_day_result;
devi@88 1111 }
devi@88 1112 $last_day = $day;
devi@88 1113 $last_wday = $wday;
devi@88 1114 $this_day_result = q();
devi@88 1115 }
devi@88 1116
devi@88 1117 # CONSOLE CHANGE
devi@88 1118 if ($cl->{"tty"} && $last_tty ne $cl->{"tty"} && 0) {
devi@88 1119 my $tty = $cl->{"tty"};
devi@88 1120 $this_day_result .= " #l3: ------- другая консоль ----\n";
devi@88 1121 $last_tty=$cl->{"tty"};
devi@88 1122 }
devi@88 1123
devi@88 1124 # Session change
devi@88 1125 if ( $last_session ne $cl->{"local_session_id"}) {
devi@88 1126 $this_day_result .= "# ------------------------------------------------------------"
devi@88 1127 . " l3: local_session_id=".$cl->{"local_session_id"}
devi@88 1128 . " ---------------------------------- \n";
devi@88 1129 $last_session=$cl->{"local_session_id"};
devi@88 1130 }
devi@88 1131
devi@88 1132 # TIME
devi@88 1133 my @nl_counter = split (/\n/, $result);
devi@88 1134 $cursor_position=length($result) - @nl_counter;
devi@88 1135
devi@88 1136 if ($Config{"show_time"} =~ /^y/i) {
devi@88 1137 $this_day_result .= "$hour:$min:$sec"
devi@88 1138 }
devi@88 1139
devi@88 1140 # COMMAND
devi@88 1141 $this_day_result .= " ".$cl->{"prompt"}.$cl->{"cline"}."\n";
devi@88 1142 if ($cl->{"err"}) {
devi@88 1143 $this_day_result .= " #l3: err=".$cl->{'err'}."\n";
devi@88 1144 }
devi@88 1145
devi@88 1146 # OUTPUT
devi@88 1147 my $last_command = $cl->{"last_command"};
devi@88 1148 if (!(
devi@88 1149 $Config{"suppress_editors"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"editors"}}) ||
devi@88 1150 $Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) ||
devi@88 1151 $Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}})
devi@88 1152 )) {
devi@88 1153 my $output = $cl->{short_output};
devi@88 1154 if ($output) {
devi@88 1155 $output =~ s/^/ |/mg;
devi@88 1156 }
devi@88 1157 $this_day_result .= $output;
devi@88 1158 }
devi@88 1159
devi@88 1160 # DIFF
devi@88 1161 if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"}) {
devi@88 1162 my $diff = $cl->{"diff"};
devi@88 1163 $diff =~ s/^/ |/mg;
devi@88 1164 $this_day_result .= $diff;
devi@88 1165 };
devi@88 1166 # SHOT
devi@88 1167 if ($Config{"show_screenshots"} =~ /^y/i && $cl->{"screenshot"}) {
devi@88 1168 $this_day_result .= " #l3: screenshot=".$cl->{'screenshot'}."\n";
devi@88 1169 }
devi@88 1170
devi@88 1171 #NOTES
devi@88 1172 if ( $Config{"show_notes"} =~ /^y/i && $cl->{"note"}) {
devi@88 1173 my $note=$cl->{"note"};
devi@88 1174 $note =~ s/\n/\n#^/msg;
devi@88 1175 $this_day_result .= "#^ == ".$cl->{note_title}." ==\n" if $cl->{note_title};
devi@88 1176 $this_day_result .= "#^ ".$note."\n";
devi@88 1177 }
devi@88 1178
devi@88 1179 }
devi@88 1180 last: {
devi@88 1181 $result .= "== ".$Day_Name[$last_wday]." == \n";
devi@88 1182 $result .= $this_day_result;
devi@88 1183 }
devi@88 1184
devi@89 1185 return $result;
devi@88 1186
devi@88 1187
devi@88 1188
devi@88 1189 }
devi@88 1190
devi@89 1191 #############
devi@89 1192 # print_edit_all_html
devi@89 1193 #
devi@89 1194 # Вывести страницу с текстовым представлением журнала для редактирования
devi@89 1195 #
devi@89 1196 # In: $_[0] output_filename
devi@89 1197 # Out:
devi@89 1198
devi@89 1199 sub print_edit_all_html
devi@89 1200 {
devi@89 1201 my $output_filename= shift;
devi@89 1202 my $result;
devi@89 1203 my $cursor_position = 0;
devi@89 1204
devi@89 1205 $result = print_command_lines_txt;
devi@93 1206 my $title = ">Журнал лабораторных работ. Правка";
devi@89 1207
devi@89 1208 $result =
devi@88 1209 "<html>"
devi@89 1210 ."<head>"
devi@89 1211 ."<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />"
devi@89 1212 ."<link rel='stylesheet' href='$Config{frontend_css}' type='text/css'/>"
devi@89 1213 ."<title>$title</title>"
devi@89 1214 ."</head>"
devi@88 1215 ."<script>"
devi@88 1216 .$SetCursorPosition_JS
devi@88 1217 ."</script>"
devi@88 1218 ."<body onLoad='setCursorPosition(document.all.mytextarea, $cursor_position, $cursor_position+10)'>"
devi@89 1219 ."<h1>Журнал лабораторных работ. Правка</h1>"
devi@89 1220 ."<form>"
devi@88 1221 ."<textarea rows='30' cols='100' wrap='off' id='mytextarea'>$result</textarea>"
devi@89 1222 ."<br/><input type='submit' value='Сохранить' label='label'/>"
devi@89 1223 ."</form>"
devi@89 1224 ."<p>Внимательно правим, потом сохраняем</p>"
devi@89 1225 ."<p>Строки, начинающиеся символами #l3: можно трогать, только если точно знаешь, что делаешь</p>"
devi@88 1226 ."</body>"
devi@89 1227 ."</html>";
devi@89 1228
devi@89 1229 if ($output_filename eq "-") {
devi@89 1230 print $result;
devi@88 1231 }
devi@88 1232 else {
devi@88 1233 open(OUT, ">", $output_filename)
devi@88 1234 or die "Can't open $output_filename for writing\n";
devi@89 1235 binmode ":utf8";
devi@89 1236 print OUT "$result";
devi@89 1237 close(OUT);
devi@89 1238 }
devi@89 1239 }
devi@89 1240
devi@89 1241 #############
devi@89 1242 # print_all_txt
devi@89 1243 #
devi@89 1244 # Вывести страницу с текстовым представлением журнала для редактирования
devi@89 1245 #
devi@89 1246 # In: $_[0] output_filename
devi@89 1247 # Out:
devi@89 1248
devi@89 1249 sub print_all_txt
devi@89 1250 {
devi@89 1251 my $result;
devi@89 1252
devi@89 1253 $result = print_command_lines_txt;
devi@89 1254
devi@89 1255 $result =~ s/&gt;/>/g;
devi@89 1256 $result =~ s/&lt;/</g;
devi@89 1257 $result =~ s/&amp;/&/g;
devi@89 1258
devi@89 1259 if ($output_filename eq "-") {
devi@89 1260 print $result;
devi@89 1261 }
devi@89 1262 else {
devi@89 1263 open(OUT, ">:utf8", $output_filename)
devi@89 1264 or die "Can't open $output_filename for writing\n";
devi@89 1265 print OUT "$result";
devi@88 1266 close(OUT);
devi@88 1267 }
devi@88 1268 }
devi@88 1269
devi@88 1270
devi@88 1271 #############
devi@88 1272 # print_all_html
devi@88 1273 #
devi@88 1274 #
devi@88 1275 #
devi@88 1276 # In: $_[0] output_filename
devi@88 1277 # Out:
devi@88 1278
devi@88 1279
devi@88 1280 sub print_all_html
devi@56 1281 {
devi@56 1282 my $output_filename=$_[0];
devi@56 1283
devi@56 1284 my $result;
devi@88 1285 my ($command_lines,$toc) = print_command_lines_html;
devi@88 1286 my $files_section = print_files_html;
devi@56 1287
igor@109 1288 $result = $debug_output;
igor@109 1289 $result .= print_header_html($toc);
devi@84 1290
devi@84 1291
devi@84 1292 # $result.= join " <br/>", keys %Sessions;
devi@84 1293 # for my $sess (keys %Sessions) {
devi@84 1294 # $result .= join " ", keys (%{$Sessions{$sess}});
devi@84 1295 # $result .= "<br/>";
devi@84 1296 # }
devi@84 1297
devi@56 1298 $result.= "<h2 id='log'>Журнал</h2>" . $command_lines;
devi@69 1299 $result.= "<h2 id='files'>Файлы</h2>" . $files_section if $files_section;
devi@89 1300 $result.= "<h2 id='stat'>Статистика</h2>" . print_stat_html;
devi@56 1301 $result.= "<h2 id='help'>Справка</h2>" . $Html_Help . "<br/>";
devi@56 1302 $result.= "<h2 id='about'>О программе</h2>". $Html_About. "<br/>";
devi@88 1303 $result.= print_footer_html;
devi@56 1304
devi@56 1305 if ($output_filename eq "-") {
devi@89 1306 binmode STDOUT, ":utf8";
devi@56 1307 print $result;
devi@56 1308 }
devi@56 1309 else {
devi@89 1310 open(OUT, ">:utf8", $output_filename)
devi@56 1311 or die "Can't open $output_filename for writing\n";
devi@56 1312 print OUT $result;
devi@56 1313 close(OUT);
devi@56 1314 }
devi@56 1315 }
devi@56 1316
devi@56 1317 #############
devi@88 1318 # print_header_html
devi@56 1319 #
devi@56 1320 #
devi@56 1321 #
devi@56 1322 # In: $_[0] Содержание
devi@56 1323 # Out: Распечатанный заголовок
devi@56 1324
devi@88 1325 sub print_header_html
devi@56 1326 {
devi@56 1327 my $toc = $_[0];
devi@56 1328 my $course_name = $Config{"course-name"};
devi@56 1329 my $course_code = $Config{"course-code"};
devi@56 1330 my $course_date = $Config{"course-date"};
devi@56 1331 my $course_center = $Config{"course-center"};
devi@56 1332 my $course_trainer = $Config{"course-trainer"};
devi@56 1333 my $course_student = $Config{"course-student"};
devi@56 1334
devi@56 1335 my $title = "Журнал лабораторных работ";
devi@56 1336 $title .= " -- ".$course_student if $course_student;
devi@56 1337 if ($course_date) {
devi@56 1338 $title .= " -- ".$course_date;
devi@56 1339 $title .= $course_code ? "/".$course_code
devi@56 1340 : "";
devi@56 1341 }
devi@56 1342 else {
devi@56 1343 $title .= " -- ".$course_code if $course_code;
devi@56 1344 }
devi@56 1345
devi@56 1346 # Управляющая форма
devi@69 1347 my $control_form .= "<div class='visibility_form' title='Выберите какие элементы должны быть показаны в журнале'>"
devi@69 1348 . "<span class='header'>Видимые элементы</span>"
devi@69 1349 . "<span class='window_controls'><a href='' onclick='' title='свернуть форму управления'>_</a> <a href='' onclick='' title='закрыть форму управления'>x</a></span>"
devi@69 1350 . "<div><form>\n";
devi@69 1351 for my $element (sort keys %Elements_Visibility)
devi@56 1352 {
devi@69 1353 my ($skip, @e) = split /\s+/, $element;
devi@56 1354 my $showhide = join "", map { "ShowHide('$_');" } @e ;
devi@69 1355 $control_form .= "<div><input type='checkbox' name='$e[0]' onclick=\"$showhide\" checked>".
devi@56 1356 $Elements_Visibility{$element}.
devi@69 1357 "</input></div>";
devi@56 1358 }
devi@69 1359 $control_form .= "</form>\n"
devi@69 1360 . "</div>\n";
devi@56 1361
devi@99 1362
devi@99 1363 # Управляющая форма отключена
igor@109 1364 # Она слишком сильно мешает, нужно что-то переделать
devi@99 1365 $control_form = "";
devi@99 1366
igor@109 1367 my $tigra_hints_array=tigra_hints_generate;
igor@109 1368
devi@56 1369 my $result;
devi@56 1370 $result = <<HEADER;
devi@56 1371 <html>
devi@56 1372 <head>
devi@56 1373 <meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
devi@56 1374 <link rel='stylesheet' href='$Config{frontend_css}' type='text/css'/>
devi@56 1375 <title>$title</title>
devi@56 1376 </head>
devi@56 1377 <body>
igor@109 1378 <!--<script>
devi@56 1379 $Html_JavaScript
igor@109 1380 </script>-->
devi@62 1381
devi@62 1382 <!-- vvv Tigra Hints vvv -->
devi@62 1383 <script language="JavaScript" src="/tigra/hints.js"></script>
igor@109 1384 <!--<script language="JavaScript" src="/tigra/hints_cfg.js"></script>-->
igor@109 1385 <script>$tigra_hints_array</script>
devi@62 1386 <style>
devi@62 1387 /* a class for all Tigra Hints boxes, TD object */
devi@62 1388 .hintsClass
igor@109 1389 {text-align: left; font-size:80%; font-family: Verdana, Arial, Helvetica; background-color:#ffffee; padding: 0px 0px 0px 0px;}
devi@62 1390 /* this class is used by Tigra Hints wrappers */
devi@62 1391 .row
devi@62 1392 {background: white;}
igor@109 1393
igor@109 1394
igor@109 1395 .bl2 {border: 1px solid #e68200; background:url(/tigra/block/bl2.gif) 0 100% no-repeat; text-align:left}
igor@109 1396 .bl {background:url(/tigra/block/bl2.gif) 0 100% no-repeat; text-align:left}
igor@109 1397 .br {background:url(/tigra/block/br2.gif) 100% 100% no-repeat}
igor@109 1398 .tl {background:url(/tigra/block/tl2.gif) 0 0 no-repeat}
igor@109 1399 .tr {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat; padding:10px}
igor@109 1400 .tr2 {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat}
igor@109 1401 .t {background:url(/tigra/block/dot2.gif) 0 0 repeat-x}
igor@109 1402 .b {background:url(/tigra/block/dot2.gif) 0 100% repeat-x}
igor@109 1403 .l {background:url(/tigra/block/dot2.gif) 0 0 repeat-y}
igor@109 1404 .r {background:url(/tigra/block/dot2.gif) 100% 0 repeat-y}
igor@109 1405
igor@109 1406
devi@62 1407 </style>
devi@62 1408 <!-- ^^^ Tigra Hints ^^^ -->
devi@62 1409
igor@109 1410 <!--
igor@109 1411 .bl2 {border: 1px solid #e68200; background:url(/tigra/block/bl2.gif) 0 100% no-repeat; width:20em; text-align:center}
igor@109 1412 .bl {background:url(/tigra/block/bl2.gif) 0 100% no-repeat; width:20em; text-align:center}
igor@109 1413 .br {background:url(/tigra/block/br2.gif) 100% 100% no-repeat}
igor@109 1414 .tl {background:url(/tigra/block/tl2.gif) 0 0 no-repeat}
igor@109 1415 .tr {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat; padding:10px}
igor@109 1416 .tr2 {background:url(/tigra/block/tr2.gif) 100% 0 no-repeat}
igor@109 1417 .t {background:url(/tigra/block/dot2.gif) 0 0 repeat-x; width:20em}
igor@109 1418 .b {background:url(/tigra/block/dot2.gif) 0 100% repeat-x}
igor@109 1419 .l {background:url(/tigra/block/dot2.gif) 0 0 repeat-y}
igor@109 1420 .r {background:url(/tigra/block/dot2.gif) 100% 0 repeat-y}
igor@109 1421 -->
igor@109 1422
devi@62 1423
devi@89 1424 <div class='edit_link'>
igor@141 1425 [ <a href='?filter=action::edit;;$filter_url'>править</a> ]
devi@89 1426 </div>
devi@89 1427 <h1 onmouseover="myHint.show('1')" onmouseout="myHint.hide()" class='lined_header'>Журнал лабораторных работ</h1>
devi@56 1428 HEADER
devi@56 1429 if ( $course_student
devi@56 1430 || $course_trainer
devi@56 1431 || $course_name
devi@56 1432 || $course_code
devi@56 1433 || $course_date
devi@56 1434 || $course_center) {
devi@56 1435 $result .= "<p>";
devi@56 1436 $result .= "Выполнил $course_student<br/>" if $course_student;
devi@56 1437 $result .= "Проверил $course_trainer <br/>" if $course_trainer;
devi@56 1438 $result .= "Курс " if $course_name
devi@56 1439 || $course_code
devi@56 1440 || $course_date;
devi@56 1441 $result .= "$course_name " if $course_name;
devi@56 1442 $result .= "($course_code)" if $course_code;
devi@56 1443 $result .= ", $course_date<br/>" if $course_date;
devi@56 1444 $result .= "Учебный центр $course_center <br/>" if $course_center;
devi@84 1445 $result .= "Фильтр ".join(" ", map("$filter{$_}=$_", keys %filter))."<br/>" if %filter;
devi@56 1446 $result .= "</p>";
devi@56 1447 }
devi@56 1448
devi@56 1449 $result .= <<HEADER;
devi@56 1450 <table width='100%'>
devi@56 1451 <tr>
devi@56 1452 <td width='*'>
devi@56 1453
devi@56 1454 <table border=0 id='toc' class='toc'>
devi@56 1455 <tr>
devi@56 1456 <td>
devi@56 1457 <div class='toc_title'>Содержание</div>
devi@56 1458 <ul>
devi@56 1459 <li><a href='#log'>Журнал</a></li>
devi@56 1460 <ul>$toc</ul>
devi@69 1461 <li><a href='#files'>Файлы</a></li>
devi@56 1462 <li><a href='#stat'>Статистика</a></li>
devi@56 1463 <li><a href='#help'>Справка</a></li>
devi@56 1464 <li><a href='#about'>О программе</a></li>
devi@56 1465 </ul>
devi@56 1466 </td>
devi@56 1467 </tr>
devi@56 1468 </table>
devi@56 1469
devi@56 1470 </td>
devi@56 1471 <td valign='top' width=200>$control_form</td>
devi@56 1472 </tr>
devi@56 1473 </table>
devi@56 1474 HEADER
devi@56 1475
devi@56 1476 return $result;
devi@56 1477 }
devi@56 1478
devi@56 1479
devi@56 1480 #############
devi@88 1481 # print_footer_html
devi@56 1482 #
devi@56 1483 #
devi@56 1484 #
devi@56 1485 #
devi@56 1486 #
devi@56 1487
devi@88 1488 sub print_footer_html
devi@56 1489 {
devi@102 1490 return "</body>\n</html>\n";
devi@56 1491 }
devi@56 1492
devi@56 1493
devi@56 1494
devi@56 1495
devi@56 1496 #############
devi@88 1497 # print_stat_html
devi@56 1498 #
devi@56 1499 #
devi@56 1500 #
devi@56 1501 # In:
devi@56 1502 # Out:
devi@56 1503
devi@88 1504 sub print_stat_html
devi@56 1505 {
devi@49 1506 %StatNames = (
devi@56 1507 FirstCommand => "Время первой команды журнала",
devi@56 1508 LastCommand => "Время последней команды журнала",
devi@56 1509 TotalCommands => "Количество командных строк в журнале",
devi@56 1510 ErrorsPercentage => "Процент команд с ненулевым кодом завершения, %",
devi@57 1511 MistypesPercentage => "Процент синтаксически неверно набранных команд, %",
devi@56 1512 TotalTime => "Суммарное время работы с терминалом <sup><font size='-2'>*</font></sup>, час",
devi@56 1513 CommandsPerTime => "Количество командных строк в единицу времени, команда/мин",
devi@56 1514 CommandsFrequency => "Частота использования команд",
devi@56 1515 RareCommands => "Частота использования этих команд < 0.5%",
devi@49 1516 );
devi@49 1517 @StatOrder = (
devi@49 1518 FirstCommand,
devi@49 1519 LastCommand,
devi@49 1520 TotalCommands,
devi@49 1521 ErrorsPercentage,
devi@56 1522 MistypesPercentage,
devi@49 1523 TotalTime,
devi@49 1524 CommandsPerTime,
devi@49 1525 CommandsFrequency,
devi@49 1526 RareCommands,
devi@49 1527 );
devi@31 1528
devi@49 1529 # Подготовка статистики к выводу
devi@49 1530 # Некоторые значения пересчитываются!
devi@49 1531 # Дальше их лучше уже не использовать!!!
devi@31 1532
devi@87 1533 my %CommandsFrequency = %frequency_of_command;
devi@37 1534
devi@49 1535 $Stat{TotalTime} ||= 0;
devi@49 1536 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Stat{FirstCommand} || 0);
devi@49 1537 $Stat{FirstCommand} = sprintf "%02i:%02i:%02i %04i-%2i-%2i", $hour, $min, $sec, $year+1900, $mon+1, $mday;
devi@49 1538 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Stat{LastCommand} || 0);
devi@49 1539 $Stat{LastCommand} = sprintf "%02i:%02i:%02i %04i-%2i-%2i", $hour, $min, $sec, $year+1900, $mon+1, $mday;
devi@56 1540 if ($Stat{TotalCommands}) {
devi@56 1541 $Stat{ErrorsPercentage} = sprintf "%5.2f", $Stat{ErrorCommands}*100/$Stat{TotalCommands};
devi@56 1542 $Stat{MistypesPercentage} = sprintf "%5.2f", $Stat{MistypedCommands}*100/$Stat{TotalCommands};
devi@56 1543 }
devi@49 1544 $Stat{CommandsPerTime} = sprintf "%5.2f", $Stat{TotalCommands}*60/$Stat{TotalTime}
devi@49 1545 if $Stat{TotalTime};
devi@49 1546 $Stat{TotalTime} = sprintf "%5.2f", $Stat{TotalTime}/60/60;
devi@31 1547
devi@49 1548 my $total_commands=0;
devi@49 1549 for $command (keys %CommandsFrequency){
devi@49 1550 $total_commands += $CommandsFrequency{$command};
devi@49 1551 }
devi@49 1552 if ($total_commands) {
devi@49 1553 for $command (reverse sort {$CommandsFrequency{$a} <=> $CommandsFrequency{$b}} keys %CommandsFrequency){
devi@49 1554 my $command_html;
devi@49 1555 my $percentage = sprintf "%5.2f",$CommandsFrequency{$command}*100/$total_commands;
devi@49 1556 if ($percentage < 0.5) {
devi@49 1557 my $hint = make_comment($command);
devi@49 1558 $command_html = "$command";
devi@56 1559 $command_html = "<span title='$hint' class='with_hint'>$command_html</span>" if $hint;
devi@56 1560 $command_html = "<span class='without_hint'>$command_html</span>" if not $hint;
devi@49 1561 my $command_html = "<tt>$command_html</tt>";
devi@49 1562 $Stat{RareCommands} .= $command_html."<sub><font size='-2'>".$CommandsFrequency{$command}."</font></sub> , ";
devi@49 1563 }
devi@49 1564 else {
devi@49 1565 my $hint = make_comment($command);
devi@49 1566 $command_html = "$command";
devi@56 1567 $command_html = "<span title='$hint' class='with_hint'>$command_html</span>" if $hint;
devi@56 1568 $command_html = "<span class='without_hint'>$command_html</span>" if not $hint;
devi@49 1569 my $command_html = "<tt>$command_html</tt>";
devi@49 1570 $percentage = sprintf "%5.2f",$percentage;
devi@49 1571 $Stat{CommandsFrequency} .= "<tr><td>".$command_html."</td><td>".$CommandsFrequency{$command}."</td>".
devi@49 1572 "<td>|".("="x int($CommandsFrequency{$command}*100/$total_commands))."| $percentage%</td></tr>";
devi@49 1573 }
devi@49 1574 }
devi@49 1575 $Stat{CommandsFrequency} = "<table>".$Stat{CommandsFrequency}."</table>";
devi@49 1576 $Stat{RareCommands} =~ s/, $// if $Stat{RareCommands};
devi@49 1577 }
devi@31 1578
devi@56 1579 my $result = q();
devi@49 1580 for my $stat (@StatOrder) {
devi@56 1581 next unless $Stat{"$stat"};
devi@56 1582 $result .= "<tr valign='top'><td width='300'>".$StatNames{"$stat"}."</td><td>".$Stat{"$stat"}."</td></tr>"
devi@49 1583 }
devi@56 1584 $result = "<table>$result</table>"
devi@56 1585 . "<font size='-2'>____<br/>*) Интервалы неактивности длительностью "
devi@56 1586 . ($Config{stat_inactivity_interval}/60)
devi@56 1587 . " минут и более не учитываются</font></br>";
devi@31 1588
devi@56 1589 return $result;
devi@23 1590 }
devi@23 1591
devi@23 1592
devi@31 1593 sub collapse_list($)
devi@31 1594 {
devi@49 1595 my $res = "";
devi@49 1596 for my $elem (@{$_[0]}) {
devi@49 1597 if (ref $elem eq "ARRAY") {
devi@49 1598 $res .= "<ul>".collapse_list($elem)."</ul>";
devi@49 1599 }
devi@49 1600 else
devi@49 1601 {
devi@49 1602 $res .= "<li>".$elem."</li>";
devi@49 1603 }
devi@49 1604 }
devi@49 1605 return $res;
devi@31 1606 }
devi@31 1607
devi@23 1608
devi@88 1609 sub print_files_html
devi@69 1610 {
devi@69 1611 my $result = qq();
devi@69 1612 my @toc;
devi@69 1613 for my $file (sort keys %Files) {
devi@73 1614 my $div_id = "file:$file";
devi@69 1615 $div_id =~ s@/@_@g;
devi@69 1616 push @toc, "<a href='#$div_id'>$file</a>";
devi@69 1617 $result .= "<div class='filename' id='$div_id'>".$file."</div>\n"
devi@73 1618 . "<div class='file_navigation'><a href='#command:".$Files{$file}->{source_command_id}."'>"."&gt;"."</a></div>"
devi@73 1619 . "<div class='filedata'><pre>".$Files{$file}->{content}."</pre></div>";
devi@69 1620 }
devi@89 1621 if ($result) {
devi@89 1622 return "<div class='files_toc'>".collapse_list(\@toc)."</div>".$result;
devi@89 1623 }
devi@89 1624 else {
devi@89 1625 return "";
devi@89 1626 }
devi@69 1627 }
devi@23 1628
devi@23 1629
devi@23 1630 sub init_variables
devi@23 1631 {
devi@23 1632 $Html_Help = <<HELP;
devi@49 1633 Для того чтобы использовать LiLaLo, не нужно знать ничего особенного:
devi@49 1634 всё происходит само собой.
devi@49 1635 Однако, чтобы ведение и последующее использование журналов
devi@49 1636 было как можно более эффективным, желательно иметь в виду следующее:
devi@56 1637 <ol>
devi@49 1638 <li><p>
devi@49 1639 В журнал автоматически попадают все команды, данные в любом терминале системы.
devi@49 1640 </p></li>
devi@49 1641 <li><p>
devi@49 1642 Для того чтобы убедиться, что журнал на текущем терминале ведётся,
devi@49 1643 и команды записываются, дайте команду w.
devi@49 1644 В поле WHAT, соответствующем текущему терминалу,
devi@49 1645 должна быть указана программа script.
devi@49 1646 </p></li>
devi@49 1647 <li><p>
devi@57 1648 Команды, при наборе которых были допущены синтаксические ошибки,
devi@57 1649 выводятся перечёркнутым текстом:
devi@57 1650 <table>
devi@57 1651 <tr class='command'>
devi@57 1652 <td class='script'>
devi@69 1653 <pre class='_mistyped_cline'>
devi@57 1654 \$ l s-l</pre>
devi@69 1655 <pre class='_mistyped_output'>bash: l: command not found
devi@57 1656 </pre>
devi@57 1657 </td>
devi@57 1658 </tr>
devi@57 1659 </table>
devi@57 1660 <br/>
devi@57 1661 </p></li>
devi@57 1662 <li><p>
devi@49 1663 Если код завершения команды равен нулю,
devi@49 1664 команда была выполнена без ошибок.
devi@49 1665 Команды, код завершения которых отличен от нуля, выделяются цветом.
devi@31 1666 <table>
devi@31 1667 <tr class='command'>
devi@31 1668 <td class='script'>
devi@69 1669 <pre class='_wrong_cline'>
devi@57 1670 \$ test 5 -lt 4</pre>
devi@31 1671 </pre>
devi@31 1672 </td>
devi@31 1673 </tr>
devi@31 1674 </table>
devi@57 1675 Обратите внимание на то, что код завершения команды может быть отличен от нуля
devi@57 1676 не только в тех случаях, когда команда была выполнена с ошибкой.
devi@57 1677 Многие команды используют код завершения, например, для того чтобы показать результаты проверки
devi@31 1678 <br/>
devi@49 1679 </p></li>
devi@49 1680 <li><p>
devi@49 1681 Команды, ход выполнения которых был прерван пользователем, выделяются цветом.
devi@31 1682 <table>
devi@31 1683 <tr class='command'>
devi@31 1684 <td class='script'>
devi@69 1685 <pre class='_interrupted_cline'>
devi@31 1686 \$ find / -name abc</pre>
devi@31 1687 <pre class='interrupted_output'>find: /home/devi-orig/.gnome2: Keine Berechtigung
devi@31 1688 find: /home/devi-orig/.gnome2_private: Keine Berechtigung
devi@31 1689 find: /home/devi-orig/.nautilus/metafiles: Keine Berechtigung
devi@31 1690 find: /home/devi-orig/.metacity: Keine Berechtigung
devi@31 1691 find: /home/devi-orig/.inkscape: Keine Berechtigung
devi@31 1692 ^C
devi@31 1693 </pre>
devi@31 1694 </td>
devi@31 1695 </tr>
devi@31 1696 </table>
devi@31 1697 <br/>
devi@49 1698 </p></li>
devi@49 1699 <li><p>
devi@49 1700 Команды, выполненные с привилегиями суперпользователя,
devi@49 1701 выделяются слева красной чертой.
devi@31 1702 <table>
devi@31 1703 <tr class='command'>
devi@31 1704 <td class='script'>
devi@31 1705 <pre class='_root_cline'>
devi@31 1706 # id</pre>
devi@31 1707 <pre class='_root_output'>
devi@31 1708 uid=0(root) gid=0(root) Gruppen=0(root)
devi@31 1709 </pre>
devi@31 1710 </td>
devi@31 1711 </tr>
devi@31 1712 </table>
devi@49 1713 <br/>
devi@49 1714 </p></li>
devi@49 1715 <li><p>
devi@49 1716 Изменения, внесённые в текстовый файл с помощью редактора,
devi@49 1717 запоминаются и показываются в журнале в формате ed.
devi@49 1718 Строки, начинающиеся символом "&lt;", удалены, а строки,
devi@49 1719 начинающиеся символом "&gt;" -- добавлены.
devi@31 1720 <table>
devi@31 1721 <tr class='command'>
devi@31 1722 <td class='script'>
devi@31 1723 <pre class='cline'>
devi@31 1724 \$ vi ~/.bashrc</pre>
devi@31 1725 <table><tr><td width='5'/><td class='diff'><pre>2a3,5
devi@49 1726 &gt; if [ -f /usr/local/etc/bash_completion ]; then
devi@31 1727 &gt; . /usr/local/etc/bash_completion
devi@49 1728 &gt; fi
devi@31 1729 </pre></td></tr></table></td>
devi@31 1730 </tr>
devi@31 1731 </table>
devi@49 1732 <br/>
devi@49 1733 </p></li>
devi@49 1734 <li><p>
devi@49 1735 Для того чтобы изменить файл в соответствии с показанными в диффшоте
devi@49 1736 изменениями, можно воспользоваться командой patch.
devi@49 1737 Нужно скопировать изменения, запустить программу patch, указав в
devi@49 1738 качестве её аргумента файл, к которому применяются изменения,
devi@49 1739 и всавить скопированный текст:
devi@48 1740 <table>
devi@48 1741 <tr class='command'>
devi@48 1742 <td class='script'>
devi@48 1743 <pre class='cline'>
devi@48 1744 \$ patch ~/.bashrc</pre>
devi@48 1745 </td>
devi@48 1746 </tr>
devi@48 1747 </table>
devi@49 1748 В данном случае изменения применяются к файлу ~/.bashrc
devi@49 1749 </p></li>
devi@49 1750 <li><p>
devi@49 1751 Для того чтобы получить краткую справочную информацию о команде,
devi@49 1752 нужно подвести к ней мышь. Во всплывающей подсказке появится краткое
devi@49 1753 описание команды.
devi@57 1754 </p>
devi@57 1755 <p>
devi@57 1756 Если справочная информация о команде есть,
devi@57 1757 команда выделяется голубым фоном, например: <span class="with_hint" title="главный текстовый редактор Unix">vi</span>.
devi@57 1758 Если справочная информация отсутствует,
devi@57 1759 команда выделяется розовым фоном, например: <span class="without_hint">notepad.exe</span>.
devi@57 1760 Справочная информация может отсутствовать в том случае,
devi@57 1761 если (1) команда введена неверно; (2) если распознавание команды LiLaLo выполнено неверно;
devi@57 1762 (3) если информация о команде неизвестна LiLaLo.
devi@57 1763 Последнее возможно для редких команд.
devi@57 1764 </p></li>
devi@57 1765 <li><p>
devi@57 1766 Большие, в особенности многострочные, всплывающие подсказки лучше
devi@57 1767 всего показываются браузерами KDE Konqueror, Apple Safari и Microsoft Internet Explorer.
devi@57 1768 В браузерах Mozilla и Firefox они отображаются не полностью,
devi@57 1769 а вместо перевода строки выводится специальный символ.
devi@49 1770 </p></li>
devi@49 1771 <li><p>
devi@49 1772 Время ввода команды, показанное в журнале, соответствует времени
devi@49 1773 <i>начала ввода командной строки</i>, которое равно тому моменту,
devi@49 1774 когда на терминале появилось приглашение интерпретатора
devi@49 1775 </p></li>
devi@49 1776 <li><p>
devi@49 1777 Имя терминала, на котором была введена команда, показано в специальном блоке.
devi@49 1778 Этот блок показывается только в том случае, если терминал
devi@49 1779 текущей команды отличается от терминала предыдущей.
devi@49 1780 </p></li>
devi@49 1781 <li><p>
devi@49 1782 Вывод не интересующих вас в настоящий момент элементов журнала,
devi@49 1783 таких как время, имя терминала и других, можно отключить.
devi@49 1784 Для этого нужно воспользоваться <a href='#visibility_form'>формой управления журналом</a>
devi@49 1785 вверху страницы.
devi@49 1786 </p></li>
devi@49 1787 <li><p>
devi@49 1788 Небольшие комментарии к командам можно вставлять прямо из командной строки.
devi@49 1789 Комментарий вводится прямо в командную строку, после символов #^ или #v.
devi@49 1790 Символы ^ и v показывают направление выбора команды, к которой относится комментарий:
devi@49 1791 ^ - к предыдущей, v - к следующей.
devi@49 1792 Например, если в командной строке было введено:
devi@31 1793 <pre class='cline'>
devi@31 1794 \$ whoami
devi@31 1795 </pre>
devi@31 1796 <pre class='output'>
devi@31 1797 user
devi@31 1798 </pre>
devi@31 1799 <pre class='cline'>
devi@31 1800 \$ #^ Интересно, кто я?
devi@31 1801 </pre>
devi@49 1802 в журнале это будет выглядеть так:
devi@49 1803
devi@31 1804 <pre class='cline'>
devi@31 1805 \$ whoami
devi@31 1806 </pre>
devi@31 1807 <pre class='output'>
devi@31 1808 user
devi@31 1809 </pre>
devi@31 1810 <table class='note'><tr><td width='100%' class='note_text'>
devi@31 1811 <tr> <td> Интересно, кто я?<br/> </td></tr></table>
devi@49 1812 </p></li>
devi@49 1813 <li><p>
devi@49 1814 Если комментарий содержит несколько строк,
devi@49 1815 его можно вставить в журнал следующим образом:
devi@31 1816 <pre class='cline'>
devi@31 1817 \$ whoami
devi@31 1818 </pre>
devi@31 1819 <pre class='output'>
devi@31 1820 user
devi@31 1821 </pre>
devi@31 1822 <pre class='cline'>
devi@31 1823 \$ cat > /dev/null #^ Интересно, кто я?
devi@31 1824 </pre>
devi@31 1825 <pre class='output'>
devi@31 1826 Программа whoami выводит имя пользователя, под которым
devi@31 1827 мы зарегистрировались в системе.
devi@31 1828 -
devi@31 1829 Она не может ответить на вопрос о нашем назначении
devi@31 1830 в этом мире.
devi@31 1831 </pre>
devi@49 1832 В журнале это будет выглядеть так:
devi@31 1833 <table>
devi@31 1834 <tr class='command'>
devi@31 1835 <td class='script'>
devi@31 1836 <pre class='cline'>
devi@31 1837 \$ whoami</pre>
devi@31 1838 <pre class='output'>user
devi@31 1839 </pre>
devi@31 1840 <table class='note'><tr><td class='note_title'>Интересно, кто я?</td></tr><tr><td width='100%' class='note_text'>
devi@31 1841 Программа whoami выводит имя пользователя, под которым<br/>
devi@31 1842 мы зарегистрировались в системе.<br/>
devi@31 1843 <br/>
devi@31 1844 Она не может ответить на вопрос о нашем назначении<br/>
devi@31 1845 в этом мире.<br/>
devi@31 1846 </td></tr></table>
devi@31 1847 </td>
devi@31 1848 </tr>
devi@31 1849 </table>
devi@49 1850 Для разделения нескольких абзацев между собой
devi@49 1851 используйте символ "-", один в строке.
devi@49 1852 <br/>
devi@31 1853 </p></li>
devi@49 1854 <li><p>
devi@49 1855 Комментарии, не относящиеся непосредственно ни к какой из команд,
devi@49 1856 добавляются точно таким же способом, только вместо симолов #^ или #v
devi@49 1857 нужно использовать символы #=
devi@49 1858 </p></li>
devi@87 1859
devi@87 1860 <p><li>
devi@87 1861 Содержимое файла может быть показано в журнале.
devi@87 1862 Для этого его нужно вывести с помощью программы cat.
devi@87 1863 Если вывод команды отметить симоволами #!,
devi@87 1864 содержимое файла будет показано в журнале
devi@87 1865 в специально отведённой для этого секции.
devi@87 1866 </li></p>
devi@87 1867
devi@87 1868 <p>
devi@87 1869 <li>
devi@87 1870 Для того чтобы вставить скриншот интересующего вас окна в журнал,
devi@87 1871 нужно воспользоваться командой l3shot.
devi@87 1872 После того как команда вызвана, нужно с помощью мыши выбрать окно, которое
devi@87 1873 должно быть в журнале.
devi@87 1874 </li>
devi@87 1875 </p>
devi@87 1876
devi@87 1877 <p>
devi@87 1878 <li>
devi@87 1879 Команды в журнале расположены в хронологическом порядке.
devi@87 1880 Если две команды давались одна за другой, но на разных терминалах,
devi@87 1881 в журнале они будут рядом, даже если они не имеют друг к другу никакого отношения.
devi@87 1882 <pre>
devi@87 1883 1
devi@87 1884 2
devi@87 1885 3
devi@87 1886 4
devi@87 1887 </pre>
devi@87 1888 Группы команд, выполненных на разных терминалах, разделяются специальной линией.
devi@87 1889 Под этой линией в правом углу показано имя терминала, на котором выполнялись команды.
devi@87 1890 Для того чтобы посмотреть команды только одного сенса,
devi@87 1891 нужно щёкнуть по этому названию.
devi@87 1892 </li>
devi@87 1893 </p>
devi@56 1894 </ol>
devi@23 1895 HELP
devi@23 1896
devi@23 1897 $Html_About = <<ABOUT;
devi@49 1898 <p>
devi@102 1899 <a href='http://xgu.ru/lilalo/'>LiLaLo</a> (L3) расшифровывается как Live Lab Log.<br/>
devi@49 1900 Программа разработана для повышения эффективности обучения Unix/Linux-системам.<br/>
igor@111 1901 (c) Игорь Чубин, 2004-2008<br/>
devi@49 1902 </p>
devi@23 1903 ABOUT
devi@23 1904 $Html_About.='$Id$ </p>';
devi@23 1905
devi@23 1906 $Html_JavaScript = <<JS;
devi@49 1907 function getElementsByClassName(Class_Name)
devi@49 1908 {
devi@49 1909 var Result=new Array();
devi@49 1910 var All_Elements=document.all || document.getElementsByTagName('*');
devi@49 1911 for (i=0; i<All_Elements.length; i++)
devi@49 1912 if (All_Elements[i].className==Class_Name)
devi@49 1913 Result.push(All_Elements[i]);
devi@49 1914 return Result;
devi@49 1915 }
devi@49 1916 function ShowHide (name)
devi@49 1917 {
devi@49 1918 elements=getElementsByClassName(name);
devi@49 1919 for(i=0; i<elements.length; i++)
devi@49 1920 if (elements[i].style.display == "none")
devi@49 1921 elements[i].style.display = "";
devi@49 1922 else
devi@49 1923 elements[i].style.display = "none";
devi@49 1924 //if (elements[i].style.visibility == "hidden")
devi@49 1925 // elements[i].style.visibility = "visible";
devi@49 1926 //else
devi@49 1927 // elements[i].style.visibility = "hidden";
devi@49 1928 }
devi@49 1929 function filter_by_output(text)
devi@49 1930 {
devi@49 1931
devi@49 1932 var jjj=0;
devi@49 1933
devi@49 1934 elements=getElementsByClassName('command');
devi@49 1935 for(i=0; i<elements.length; i++) {
devi@49 1936 subelems = elements[i].getElementsByTagName('pre');
devi@49 1937 for(j=0; j<subelems.length; j++) {
devi@49 1938 if (subelems[j].className = 'output') {
devi@49 1939 var str = new String(subelems[j].nodeValue);
devi@49 1940 if (jjj != 1) {
devi@49 1941 alert(str);
devi@49 1942 jjj=1;
devi@49 1943 }
devi@49 1944 if (str.indexOf(text) >0)
devi@49 1945 subelems[j].style.display = "none";
devi@49 1946 else
devi@49 1947 subelems[j].style.display = "";
devi@23 1948
devi@49 1949 }
devi@49 1950
devi@49 1951 }
devi@49 1952 }
devi@23 1953
devi@49 1954 }
devi@23 1955 JS
devi@23 1956
devi@89 1957 $SetCursorPosition_JS = <<JS;
devi@89 1958 function setCursorPosition(oInput,oStart,oEnd) {
devi@89 1959 oInput.focus();
devi@89 1960 if( oInput.setSelectionRange ) {
devi@89 1961 oInput.setSelectionRange(oStart,oEnd);
devi@89 1962 } else if( oInput.createTextRange ) {
devi@89 1963 var range = oInput.createTextRange();
devi@89 1964 range.collapse(true);
devi@89 1965 range.moveEnd('character',oEnd);
devi@89 1966 range.moveStart('character',oStart);
devi@89 1967 range.select();
devi@89 1968 }
devi@89 1969 }
devi@89 1970 JS
devi@89 1971
devi@23 1972 %Search_Machines = (
devi@49 1973 "google" => { "query" => "http://www.google.com/search?q=" ,
devi@49 1974 "icon" => "$Config{frontend_google_ico}" },
devi@49 1975 "freebsd" => { "query" => "http://www.freebsd.org/cgi/man.cgi?query=",
devi@49 1976 "icon" => "$Config{frontend_freebsd_ico}" },
devi@49 1977 "linux" => { "query" => "http://man.he.net/?topic=",
devi@49 1978 "icon" => "$Config{frontend_linux_ico}"},
devi@49 1979 "opennet" => { "query" => "http://www.opennet.ru/search.shtml?words=",
devi@49 1980 "icon" => "$Config{frontend_opennet_ico}"},
devi@49 1981 "local" => { "query" => "http://www.freebsd.org/cgi/man.cgi?query=",
devi@49 1982 "icon" => "$Config{frontend_local_ico}" },
devi@23 1983
devi@49 1984 );
devi@23 1985
devi@23 1986 %Elements_Visibility = (
devi@69 1987 "0 new_commands_table" => "новые команды",
devi@69 1988 "1 diff" => "редактор",
devi@69 1989 "2 time" => "время",
devi@69 1990 "3 ttychange" => "терминал",
devi@69 1991 "4 wrong_output wrong_cline wrong_root_output wrong_root_cline"
devi@69 1992 => "команды с ненулевым кодом завершения",
devi@69 1993 "5 mistyped_output mistyped_cline mistyped_root_output mistyped_root_cline"
devi@69 1994 => "неверно набранные команды",
devi@69 1995 "6 interrupted_output interrupted_cline interrupted_root_output interrupted_root_cline"
devi@49 1996 => "прерванные команды",
devi@69 1997 "7 tab_completion_output tab_completion_cline"
devi@49 1998 => "продолжение с помощью tab"
devi@23 1999 );
devi@23 2000
devi@23 2001 @Day_Name = qw/ Воскресенье Понедельник Вторник Среда Четверг Пятница Суббота /;
devi@23 2002 @Month_Name = qw/ Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь /;
devi@23 2003 @Of_Month_Name = qw/ Января Февраля Марта Апреля Мая Июня Июля Августа Сентября Октября Ноября Декабря /;
devi@23 2004 }
devi@23 2005
devi@56 2006
devi@56 2007
devi@56 2008
devi@56 2009 # Временно удалённый код
devi@56 2010 # Возможно, он не понадобится уже никогда
devi@56 2011
devi@56 2012
devi@56 2013 sub search_by
devi@56 2014 {
devi@56 2015 my $sm = shift;
devi@56 2016 my $topic = shift;
devi@56 2017 $topic =~ s/ /+/;
devi@56 2018
devi@56 2019 return "<a href='". $Search_Machines{$sm}->{"query"}."$topic'><img width='16' height='16' src='".
devi@56 2020 $Search_Machines{$sm}->{"icon"}."' border='0'/></a>";
devi@56 2021 }
devi@56 2022
igor@109 2023
igor@109 2024
igor@109 2025
igor@109 2026 ########################################################################################
igor@109 2027 #
igor@109 2028 # mywi
igor@109 2029 #
igor@109 2030 #
igor@109 2031 #
igor@109 2032 #
igor@109 2033 #
igor@109 2034 #
igor@109 2035 #
igor@109 2036
igor@109 2037
igor@109 2038
igor@109 2039 sub mywi_init
igor@109 2040 {
igor@114 2041 our $MyWiFile = "/home/igor/mywi/mywi.txt";
igor@114 2042 our $MyWiLog = "/home/igor/mywi/mywi.log";
igor@109 2043 our $section="";
igor@109 2044
igor@109 2045 our @MywiTXT; # Массив текстовых записей mywi
igor@109 2046 our %MywiHASH; # Хэш массивов записей
igor@109 2047 our %Query;
igor@109 2048
igor@109 2049 load_mywitxt($MyWiFile, \@MywiTXT, \%MywiHASH);
igor@109 2050 }
igor@109 2051
igor@109 2052 sub mywi_process_query($)
igor@109 2053 #
igor@109 2054 # Сделать подсказку по заданному запросу
igor@109 2055 # $_[0] - тема для подсказки
igor@109 2056 #
igor@109 2057 # Возвращает:
igor@109 2058 # строку-подсказку
igor@109 2059 #
igor@109 2060 {
igor@109 2061 my $query = shift;
igor@109 2062 parse_query($query, \%Query);
igor@109 2063 $result = search_in_txt(\%Query, \@MywiTXT, \%MywiHASH);
igor@109 2064
igor@109 2065 if (!$result) {
igor@109 2066 #add_to_log(\%Query, $MyWiLog);
igor@109 2067 return "$query nothing appropriate. Logged. ".join (";",%Query);
igor@109 2068 }
igor@109 2069
igor@109 2070 return $result;
igor@109 2071 }
igor@109 2072
igor@109 2073 ####################################################################################
igor@109 2074 # private section
igor@109 2075 ####################################################################################
igor@109 2076
igor@109 2077 sub load_mywitxt
igor@109 2078 #
igor@109 2079 # Загрузить файл с записями Mywi_TXT
igor@109 2080 # в массив
igor@109 2081 # $_[0] - указатель на массив для загрузки
igor@109 2082 # $_[1] - имя файла для загрузки
igor@109 2083 #
igor@109 2084 {
igor@109 2085 my $MyWiFile = $_[0];
igor@109 2086 my $MywiTXT = $_[1];
igor@109 2087 my $MywiHASH = $_[2];
igor@109 2088
igor@109 2089 open (MW, "$MyWiFile") or die "Can't open $MyWiFile for reading";
igor@109 2090 binmode MW, ":utf8";
igor@109 2091 @{$MywiTXT} = <MW>;
igor@109 2092 close (MWF);
igor@109 2093
igor@109 2094 for my $mywi_line (@{$MywiTXT}) {
igor@109 2095 my $topic = $mywi_line;
igor@109 2096 $topic =~ s@\s*\(.*\n@@;
igor@109 2097 push @{$$MywiHASH{"$topic"}}, $mywi_line;
igor@109 2098 # $MywiHASH{"$topic"} .= $mywi_line;
igor@109 2099 }
igor@109 2100 }
igor@109 2101
igor@109 2102 sub parse_query
igor@109 2103 #
igor@109 2104 # Строка запроса:
igor@109 2105 # [format:]topic[(section)]
igor@109 2106 # Элементы format и topic являются не обязательными
igor@109 2107 #
igor@109 2108 # $_[0] - строка запроса
igor@109 2109 # $_[1] - ссылка на хэш запроса
igor@109 2110 #
igor@109 2111 {
igor@109 2112 my $query_string = shift;
igor@109 2113 my $query_hash = shift;
igor@109 2114
igor@109 2115 %{$query_hash} = (
igor@109 2116 "format" => "txt",
igor@109 2117 "section" => "",
igor@109 2118 "topic" => "",
igor@109 2119 );
igor@109 2120
igor@109 2121 if ($query_string =~ s/^([^:]*)://) {
igor@109 2122 $query_hash->{"format"} = $1 || "txt";
igor@109 2123 }
igor@109 2124 if ($query_string =~ s/\(([^(]*)\)$//) {
igor@109 2125 $query_hash->{"section"} = $1 || "";
igor@109 2126 }
igor@109 2127 $query_hash->{"topic"} = $query_string;
igor@109 2128 }
igor@109 2129
igor@109 2130
igor@109 2131 sub search_in_txt
igor@109 2132 #
igor@109 2133 # Выполнить поиск в текстовой базе
igor@109 2134 # по известному запросу
igor@109 2135 # $_[0] -- ссылка на хэш запроса
igor@109 2136 # $_[1] -- ссылка на массив текстовых записей
igor@109 2137 # $_[2] -- ссылка на хэш массивов текстовых записей
igor@109 2138 # Результат:
igor@109 2139 # найденная текстовая запись в заданном формате
igor@109 2140 #
igor@109 2141 {
igor@109 2142 my %Query = %{$_[0]};
igor@109 2143 my %MywiHASH = %{$_[2]};
igor@109 2144
igor@109 2145 my $topic = $Query{"topic"};
igor@109 2146 my $section = $Query{"section"};
igor@109 2147 my $result = "";
igor@109 2148
igor@109 2149 return join("\n",@{$MywiHASH{"$topic"}})."\n";
igor@109 2150
igor@109 2151 for my $l (@{$$_[2]{$topic}}) {
igor@109 2152 # for my $l (@{$_[1]}) {
igor@109 2153 my $line = $l;
igor@109 2154 if (
igor@109 2155 ($section and $line =~ /^\s*\Q$topic\E\s*\($section*\)\s*-/ )
igor@109 2156 or (not $section and $line =~ /^\s*\Q$topic\E\s*(\([^)]*\)?)\s*-/) ) {
igor@109 2157 $line =~ s/^.* -//mg if ($Config{"short"});
igor@109 2158 $result .= "<para>$line</para>";
igor@109 2159 }
igor@109 2160 }
igor@109 2161 return $result;
igor@109 2162 }
igor@109 2163
igor@109 2164
igor@109 2165 sub add_to_log($$)
igor@109 2166 #
igor@109 2167 # Если в базе отсутствует информация по данной теме,
igor@109 2168 # сделать предположение доступным способом
igor@109 2169 # и добавить его в базу
igor@109 2170 # или просто сделать отметку о необходимости
igor@109 2171 # расширения базы
igor@109 2172 #
igor@109 2173 # Добавить запись в журнал
igor@109 2174 # $_[0] - запись (ссылка на хэш)
igor@109 2175 # $_[1] - имя файла-журнала
igor@109 2176 #
igor@109 2177 {
igor@109 2178 my $query = $_[0];
igor@109 2179 my $MyWiLog = $_[1];
igor@109 2180
igor@109 2181 open (MWF, ">>:utf8", $MyWiLog) or die "Can't open $MyWiLog for writing";
igor@109 2182 my $my_guess = mywi_guess($query);
igor@109 2183 print MWF "$my_guess\n";
igor@109 2184 close(MWF);
igor@109 2185 }
igor@109 2186
igor@109 2187 sub mywi_guess($)
igor@109 2188 # Сформировать исходную строку для журнала по заданному запросу
igor@109 2189 # Если секция принадлежит 0..9, в качестве основы для результирующего текста использовать whatis
igor@109 2190 # $_[0] - запись (ссылка на хэш)
igor@109 2191 #
igor@109 2192 # Возвращает:
igor@109 2193 # строку-предположение
igor@109 2194 {
igor@109 2195 my %query = %{$_[0]};
igor@109 2196
igor@109 2197 my $topic = $query{"topic"};
igor@109 2198 my $section = $query{"section"};
igor@109 2199
igor@109 2200 my $result = "$topic($section)";
igor@109 2201 if (!$section or $section =~ /^[1-9]$/)
igor@109 2202 {
igor@109 2203 # Запрос из категории 1-9
igor@109 2204 # Об этом может знать whatis
igor@109 2205 $result = `LANG=C whatis -- "$topic"`;
igor@109 2206 if ($result =~ /nothing appropriate/i) {
igor@109 2207 $result = $topic;
igor@109 2208 $result .= "($section)" if $section;
igor@109 2209 }
igor@109 2210 else {
igor@109 2211 1 while ($result =~ s/(\s+)-(\s+)/$1+$2/sg);
igor@109 2212 $result =~ s/\s+\(/(/;
igor@109 2213 chomp $result;
igor@109 2214 }
igor@109 2215 }
igor@109 2216 return $result;
igor@109 2217 }
igor@109 2218