# HG changeset patch # User devi # Date 1141125086 -7200 # Node ID c70be67ed3d4a87c6afe891785936efb33e0633d # Parent 3058ada85a582dd01dbaa305c5cf34f76bbc54fa Наведение порядка в коде. Обработка чуть лучше отделена от представления. + добавлено три совета в документацию diff -r 3058ada85a58 -r c70be67ed3d4 l3-frontend --- a/l3-frontend Sat Feb 25 08:31:35 2006 +0200 +++ b/l3-frontend Tue Feb 28 13:11:26 2006 +0200 @@ -24,7 +24,7 @@ # ^^^ our %Stat; -our %CommandsFDistribution; # Сколько раз в журнале встречается какая команда +our %frequency_of_command; # Сколько раз в журнале встречается какая команда our $table_number=1; my %mywi_cache_for; # Кэш для экономии обращений к mywi @@ -39,6 +39,8 @@ sub main; sub collapse_list($); +sub minutes_passed; + sub print_all; sub print_command_lines; sub print_files; @@ -177,7 +179,7 @@ # Commands for my $command (@commands) { $command =~ s/'//g; - $CommandsFDistribution{$command}++; + $frequency_of_command{$command}++; if (!$Commands_Description{$command}) { $mywi_cache_for{$command} ||= mywi_client ($command) || ""; my $mywi = join ("\n", grep(/\([18]|sh|script\)/, split(/\n/, $mywi_cache_for{$command}))); @@ -320,6 +322,45 @@ $$cl->{"class"}.="_root"; } +# my $hint; +# $hint = make_comment($$cl->{"cline"}); +# if ($hint) { +# $$cl->{hint} = $hint; +# } + $$cl->{hint}=""; + +# Выводим <head_lines> верхних строк +# и <tail_lines> нижних строк, +# если эти параметры существуют + my $output=""; + + if ($$cl->{"last_command"} eq "cat" && !$$cl->{"err"} && !($$cl->{"cline"} =~ /</)) { + my $filename = $$cl->{"cline"}; + $filename =~ s/.*\s+(\S+)\s*$/$1/; + $Files{$filename}->{"content"} = $$cl->{"output"}; + $Files{$filename}->{"source_command_id"} = $$cl->{"id"} + } + my @lines = split '\n', $$cl->{"output"}; + if (( + $Config{"head_lines"} + || $Config{"tail_lines"} + ) + && $#lines > $Config{"head_lines"} + $Config{"tail_lines"} ) { +# + for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) { + $output .= $lines[$i]."\n"; + } + $output .= $Config{"skip_text"}."\n"; + + my $start_line=$#lines-$Config{"tail_lines"}+1; + for (my $i=$start_line; $i<= $#lines; $i++) { + $output .= $lines[$i]."\n"; + } + } + else { + $output = $$cl->{"output"}; + } + $$cl->{short_output} = $output; #Обработка пометок # Если несколько пометок (notes) идут подряд, @@ -379,6 +420,13 @@ $$cl=0; } } + if ($$cl->{"class"} == "note") { + my $note_html = $$cl->{note}; + $note_html = join ("\n", map ("<p>$_</p>", split (/-\n/, $note))); + $note_html =~ s@(http:[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g; + $note_html =~ s@(www\.[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g; + $$cl->{"note_html"} = $note_html; + } } } @@ -420,8 +468,6 @@ } } - #$result = "Filter=".$Config{filter}."\n"; - $Stat{LastCommand} ||= 0; $Stat{TotalCommands} ||= 0; $Stat{ErrorCommands} ||= 0; @@ -451,11 +497,7 @@ # Если у нас недостаточно информации о том, подходит строка под фильтр или нет, # мы её выводим - #$result .= "before<br/>"; for my $filter_key (keys %filter) { - #$result .= "undefined local session id<br/>\n" if !defined($cl->{local_session_id}); - #$result .= "undefined filter key $filter_key <br/>\n" if !defined($Sessions{$cl->{local_session_id}}->{$filter_key}); - #$result .= $Sessions{$cl->{local_session_id}}->{$filter_key}." != ".$filter{$filter_key}; next COMMAND_LINE if defined($cl->{local_session_id}) && defined($Sessions{$cl->{local_session_id}}->{$filter_key}) @@ -470,10 +512,13 @@ $Stat{TotalTime} += $cl->{time} - $Stat{LastCommand} } my $seconds_since_last_command = $cl->{time} - $Stat{LastCommand}; + + if ($Stat{LastCommand} > $cl->{time}) { + $result .= "Время идёт вспять<br/>"; + }; $Stat{LastCommand} = $cl->{time}; $Stat{TotalCommands}++; - # Пропускаем строки, выходящие за границу "signature", # при условии, что границы указаны # Пропускаем неправильные/прерванные/другие команды @@ -490,14 +535,22 @@ || ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) || ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); + + + +# +## +## Начинается собственно вывод +## +# + +### Сначала обрабатываем границы разделов +### Если тип команды "note", это граница + if ($cl->{class} eq "note") { - my $note = $cl->{note}; - $note = join ("\n", map ("<p>$_</p>", split (/-\n/, $note))); - $note =~ s@(http:[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g; - $note =~ s@(www\.[a-zA-Z.0-9/?\_%-]*)@<a href='$1'>$1</a>@g; $this_day_result .= "<tr><td colspan='6'>" . "<h4 id='note$note_number'>".$cl->{note_title}."</h4>" if $cl->{note_title} - . "".$note."<p/><p/></td></tr>"; + . "".$cl->{note_html}."<p/><p/></td></tr>"; if ($cl->{note_title}) { push @{$toc[@toc]},"<a href='#note$note_number'>".$cl->{note_title}."</a>"; @@ -506,45 +559,6 @@ next; } - - my $output=""; -# Выводим <head_lines> верхних строк -# и <tail_lines> нижних строк, -# если эти параметры существуют - - if ($cl->{"last_command"} eq "cat" && !$cl->{"err"} && !($cl->{"cline"} =~ /</)) { - my $filename = $cl->{"cline"}; - $filename =~ s/.*\s+(\S+)\s*$/$1/; - $Files{$filename}->{"content"} = $cl->{"output"}; - $Files{$filename}->{"source_command_id"} = $cl->{"id"} - } - my @lines = split '\n', $cl->{"output"}; - if (( - $Config{"head_lines"} - || $Config{"tail_lines"} - ) - && $#lines > $Config{"head_lines"} + $Config{"tail_lines"} ) { - - for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) { - $output .= $lines[$i]."\n"; - } - $output .= $Config{"skip_text"}."\n"; - - my $start_line=$#lines-$Config{"tail_lines"}+1; - for ($i=$start_line; $i<= $#lines; $i++) { - $output .= $lines[$i]."\n"; - } - } - else { - $ output .= $cl->{"output"}; - } - -# -## -## Начинается собственно вывод -## -# - my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time}); # Добавляем спереди 0 для удобочитаемости @@ -555,47 +569,27 @@ $class=$cl->{"class"}; $Stat{ErrorCommands}++ if $class =~ /wrong/; $Stat{MistypedCommands}++ if $class =~ /mistype/; - - + # DAY CHANGE if ( $last_day ne $day) { if ($last_day) { # Вычисляем разность множеств. # Что-то вроде этого, если бы так можно было писать: -# @new_commands = keys %CommandsFDistribution - @known_commands; +# @new_commands = keys %frequency_of_command - @known_commands; $result .= "<h3 id='day$last_day'>".$Day_Name[$last_wday]."</h3>"; - - - for my $entry_class (sort keys %new_entries_of) { - my $new_commands_section = make_new_entries_table($entry_class=~/[0-9]+\s+(.*)/, \@known_commands); - - my $table_caption = "Таблица " - . $table_number++ - . ". " - . $Day_Name[$last_wday] - . ". Новые " - . $new_entries_of{$entry_class}; - if ($new_commands_section) { - $result .= "<table class='new_commands_table' width='700' cellspacing='0' cellpadding='0'>" - . "<tr class='new_commands_caption'>" - . "<td colspan='2' align='right'>$table_caption</td>" - . "</tr>" - . "<tr class='new_commands_header'>" - . "<td width=100>Команда</td><td width=600>Описание</td>" - . "</tr>" - . $new_commands_section - . "</table>" - } - + my $table_caption = "Таблица ".$table_number++.".".$Day_Name[$last_wday] + .". Новые ".$new_entries_of{$entry_class}; + my $new_commands_section = make_new_entries_table( + $table_caption, + $entry_class=~/[0-9]+\s+(.*)/, + \@known_commands); } - @known_commands = keys %CommandsFDistribution; - #$result .= "<table width='100%'>\n"; + @known_commands = keys %frequency_of_command; $result .= $this_day_result; - #$result .= "</table>"; } push @toc, "<a href='#day$day'>".$Day_Name[$wday]."</a>\n"; @@ -603,47 +597,11 @@ $last_wday=$wday; $this_day_result = q(); } - elsif ($seconds_since_last_command > 7200) { - my $hours_passed = int($seconds_since_last_command/3600); - my $passed_word = $hours_passed % 10 == 1 ? "прошла" - : "прошло"; - my $hours_word = $hours_passed % 10 == 1 ? "часа": - "часов"; - $this_day_result .= "<div class='much_time_passed'>" - . $passed_word." >".$hours_passed." ".$hours_word - . "</div>\n"; - } - elsif ($seconds_since_last_command > 600) { - my $minutes_passed = int($seconds_since_last_command/60); - - - my $passed_word = $minutes_passed % 100 > 10 - && $minutes_passed % 100 < 20 ? "прошло" - : $minutes_passed % 10 == 1 ? "прошла" - : "прошло"; - - my $minutes_word = $minutes_passed % 100 > 10 - && $minutes_passed % 100 < 20 ? "минут" : - $minutes_passed % 10 == 1 ? "минута": - $minutes_passed % 10 == 0 ? "минут" : - $minutes_passed % 10 > 4 ? "минут" : - "минуты"; - - if ($seconds_since_last_command < 1800) { - $this_day_result .= "<div class='time_passed'>" - . $passed_word." ".$minutes_passed." ".$minutes_word - . "</div>\n"; - } - else { - $this_day_result .= "<div class='much_time_passed'>" - . $passed_word." ".$minutes_passed." ".$minutes_word - . "</div>\n"; - } + else { + $this_day_result .= minutes_passed($seconds_since_last_command); } - #$this_day_result .= "<table cellspacing='0' cellpading='0' class='command' id='command:".$cl->{"id"}."' width='100%'><tr>\n"; $this_day_result .= "<div class='command' id='command:".$cl->{"id"}."' >\n"; - # CONSOLE CHANGE if ($cl->{"tty"} && $last_tty ne $cl->{"tty"} && 0) { @@ -657,44 +615,29 @@ # Session change if ( $last_session ne $cl->{"local_session_id"}) { my $tty = $cl->{"tty"}; - $this_day_result .= "<a href='?local_session_id=".$cl->{"local_session_id"}."'><div class='ttychange'>" + $this_day_result .= "<div class='ttychange'><a href='?local_session_id=".$cl->{"local_session_id"}."'>" . $Sessions{$cl->{"local_session_id"}}->{"tty"} - ."</div></a>"; + ."</a></div>"; $last_session=$cl->{"local_session_id"}; } # TIME - $this_day_result .= "<div class='time'>$hour:$min:$sec</div>" - if $Config{"show_time"} =~ /^y/i; - - #$this_day_result .= $Config{"show_time"} =~ /^y/i - # ? "<td width='100' valign='top' class='time' width='$Config{time_width}'>$hour:$min:$sec</td>" - # : "<td width='0'/>"; - -# CLASS -# if ($cl->{"err"}) { -# $this_day_result .= "<td width='6' valign='top'>" -# . "<table><tr><td width='6' height='6' class='err_box'>" -# . "E" -# . "</td></tr></table>" -# . "</td>"; -# } -# else { -# $this_day_result .= "<td width='10' valign='top'>" -# . " " -# . "</td>"; -# } + if ($Config{"show_time"} =~ /^y/i) { + $this_day_result .= "<div class='time'>$hour:$min:$sec</div>" + } # COMMAND - my $hint = make_comment($cl->{"cline"}); - my $cline; $prompt_hint = join (" ", map("$_=$cl->{$_}", grep (!/^(output|diff)$/, sort(keys(%{$cl}))))); $cline = "<span title='$prompt_hint'>".$cl->{"prompt"}."</span>".$cl->{"cline"}; $cline =~ s/\n//; - $cline = "<span title='$hint' class='with_hint'>$cline</span>" if $hint; - $cline = "<span class='without_hint'>$cline</span>" if !$hint; + if ($cl->{"hint"}) { + $cline = "<span title='$cl->{hint}' class='with_hint'>$cline</span>" ; + } + else { + $cline = "<span class='without_hint'>$cline</span>"; + } $this_day_result .= "<table cellpadding='0' cellspacing='0'><tr><td>\n<div class='cblock_$cl->{class}'>\n"; $this_day_result .= "<div class='cline'>\n" . $cline ; #cline @@ -710,8 +653,8 @@ $Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) || $Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}}) )) { - $this_day_result .= "<pre class='output'>\n" . $output . "</pre>\n"; - } + $this_day_result .= "<pre class='output'>\n" . $cl->{short_output} . "</pre>\n"; + } # DIFF $this_day_result .= "<pre class='diff'>".$cl->{"diff"}."</pre>" @@ -738,19 +681,6 @@ $this_day_result .= "</div>\n"; } -# COMMENT - if ( $Config{"show_comments"} =~ /^y/i) { - my $comment = make_comment($cl->{"cline"}); - if ($comment) { - $this_day_result .= - "<div class='note' width='100%'>" - . $comment - . "</div>\n" - ; - - } - } - # Вывод очередной команды окончен $this_day_result .= "</div>\n"; # cblock $this_day_result .= "</td></tr></table>\n" @@ -760,28 +690,14 @@ $result .= "<h3 id='day$last_day'>".$Day_Name[$last_wday]."</h3>"; for my $entry_class (keys %new_entries_of) { - my $new_commands_section = make_new_entries_table($entry_class=~/[0-9]+\s+(.*)/, \@known_commands); - my $table_caption = "Таблица " - . $table_number++ - . ". " - . $Day_Name[$last_wday] - . ". Новые " - . $new_entries_of{$entry_class}; - if ($new_commands_section) { - $result .= "<table class='new_commands_table' width='700' cellspacing='0' cellpadding='0'>" - . "<tr class='new_commands_caption'>" - . "<td colspan='2' align='right'>$table_caption</td>" - . "</tr>" - . "<tr class='new_commands_header'>" - . "<td width=100>Команда</td><td width=600>Описание</td>" - . "</tr>" - . $new_commands_section - . "</table>" - } - + my $table_caption = "Таблица ".$table_number++.".".$Day_Name[$last_wday] + . ". Новые ".$new_entries_of{$entry_class}; + my $new_commands_section = make_new_entries_table( + $table_caption, + $entry_class=~/[0-9]+\s+(.*)/, + \@known_commands); } - @known_commands = keys %CommandsFDistribution; - + @known_commands = keys %frequency_of_command; $result .= $this_day_result; } @@ -789,25 +705,36 @@ } +############# +# print_all +# +# Напечатать таблицу неизвестных команд +# +# In: $_[0] table_caption +# $_[1] entries_class +# @_[2..] known_commands +# Out: + sub make_new_entries_table { + my $table_caption; my $entries_class = shift; my @known_commands = @{$_[0]}; + my $result = ""; my %count; my @new_commands = (); - for my $c (keys %CommandsFDistribution, @known_commands) { + for my $c (keys %frequency_of_command, @known_commands) { $count{$c}++ } - for my $c (keys %CommandsFDistribution) { + for my $c (keys %frequency_of_command) { push @new_commands, $c if $count{$c} != 2; } - my $new_commands_section; if (@new_commands){ my $hint; - for my $c (reverse sort { $CommandsFDistribution{$a} <=> $CommandsFDistribution{$b} } @new_commands) { + for my $c (reverse sort { $frequency_of_command{$a} <=> $frequency_of_command{$b} } @new_commands) { $hint = make_comment($c); next unless $hint; my ($command, $hint) = $hint =~ m/(.*?) \s*- \s*(.*)/; @@ -815,9 +742,71 @@ $new_commands_section .= "<tr><td valign='top'>$command</td><td>$hint</td></tr>"; } } - return $new_commands_section; + if ($new_commands_section) { + $result .= "<table class='new_commands_table' width='700' cellspacing='0' cellpadding='0'>" + . "<tr class='new_commands_caption'>" + . "<td colspan='2' align='right'>$table_caption</td>" + . "</tr>" + . "<tr class='new_commands_header'>" + . "<td width=100>Команда</td><td width=600>Описание</td>" + . "</tr>" + . $new_commands_section + . "</table>" + } + return $result; } +############# +# print_all +# +# +# +# In: $_[0] seconds_since_last_command +# Out: "minutes passed" text + +sub minutes_passed +{ + my $seconds_since_last_command = shift; + my $result = ""; + if ($seconds_since_last_command > 7200) { + my $hours_passed = int($seconds_since_last_command/3600); + my $passed_word = $hours_passed % 10 == 1 ? "прошла" + : "прошло"; + my $hours_word = $hours_passed % 10 == 1 ? "часа": + "часов"; + $result .= "<div class='much_time_passed'>" + . $passed_word." >".$hours_passed." ".$hours_word + . "</div>\n"; + } + elsif ($seconds_since_last_command > 600) { + my $minutes_passed = int($seconds_since_last_command/60); + + + my $passed_word = $minutes_passed % 100 > 10 + && $minutes_passed % 100 < 20 ? "прошло" + : $minutes_passed % 10 == 1 ? "прошла" + : "прошло"; + + my $minutes_word = $minutes_passed % 100 > 10 + && $minutes_passed % 100 < 20 ? "минут" : + $minutes_passed % 10 == 1 ? "минута": + $minutes_passed % 10 == 0 ? "минут" : + $minutes_passed % 10 > 4 ? "минут" : + "минуты"; + + if ($seconds_since_last_command < 1800) { + $result .= "<div class='time_passed'>" + . $passed_word." ".$minutes_passed." ".$minutes_word + . "</div>\n"; + } + else { + $result .= "<div class='much_time_passed'>" + . $passed_word." ".$minutes_passed." ".$minutes_word + . "</div>\n"; + } + } + return $result; +} ############# # print_all @@ -1041,7 +1030,7 @@ # Некоторые значения пересчитываются! # Дальше их лучше уже не использовать!!! - my %CommandsFrequency = %CommandsFDistribution; + my %CommandsFrequency = %frequency_of_command; $Stat{TotalTime} ||= 0; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Stat{FirstCommand} || 0); @@ -1362,6 +1351,41 @@ добавляются точно таким же способом, только вместо симолов #^ или #v нужно использовать символы #= </p></li> + + <p><li> + Содержимое файла может быть показано в журнале. + Для этого его нужно вывести с помощью программы cat. + Если вывод команды отметить симоволами #!, + содержимое файла будет показано в журнале + в специально отведённой для этого секции. + </li></p> + + <p> + <li> + Для того чтобы вставить скриншот интересующего вас окна в журнал, + нужно воспользоваться командой l3shot. + После того как команда вызвана, нужно с помощью мыши выбрать окно, которое + должно быть в журнале. + </li> + </p> + + <p> + <li> + Команды в журнале расположены в хронологическом порядке. + Если две команды давались одна за другой, но на разных терминалах, + в журнале они будут рядом, даже если они не имеют друг к другу никакого отношения. +<pre> +1 + 2 +3 + 4 +</pre> + Группы команд, выполненных на разных терминалах, разделяются специальной линией. + Под этой линией в правом углу показано имя терминала, на котором выполнялись команды. + Для того чтобы посмотреть команды только одного сенса, + нужно щёкнуть по этому названию. + </li> + </p> </ol> HELP