lilalo

annotate l3-frontend @ 100:2c00c61f2d7b

Коммичу изменения, но сам не знаю зачем.
Нужно l3-cgi переписать вообще с нуля.
Он мерзкий.

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