texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

branch master updated: * tp/init/highlight_syntax.pm: null input file is


From: Patrice Dumas
Subject: branch master updated: * tp/init/highlight_syntax.pm: null input file is valid. Improve error handling, avoid unneeded file lexicals.
Date: Wed, 10 Aug 2022 07:07:32 -0400

This is an automated email from the git hooks/post-receive script.

pertusus pushed a commit to branch master
in repository texinfo.

The following commit(s) were added to refs/heads/master by this push:
     new 2b68951e2c * tp/init/highlight_syntax.pm: null input file is valid. 
Improve error handling, avoid unneeded file lexicals.
2b68951e2c is described below

commit 2b68951e2cc99f130bb4e93f819ff5bc77982fea
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Wed Aug 10 13:07:22 2022 +0200

    * tp/init/highlight_syntax.pm: null input file is valid.
    Improve error handling, avoid unneeded file lexicals.
---
 ChangeLog                                          |   5 +
 tp/init/highlight_syntax.pm                        | 283 ++++++++++++---------
 tp/tests/other/highlight_example.texi              |   4 +
 .../highlight_syntax_example/chapter.html          |   4 +
 4 files changed, 174 insertions(+), 122 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b7061f98bc..223cf21ae7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2022-08-10  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/init/highlight_syntax.pm: null input file is valid.
+       Improve error handling, avoid unneeded file lexicals.
+
 2022-08-10  Patrice Dumas  <pertusus@free.fr>
 
        * tp/init/chm.pm: null input file is valid.  Minor changes.
diff --git a/tp/init/highlight_syntax.pm b/tp/init/highlight_syntax.pm
index 6063a9527d..95ff8196a4 100644
--- a/tp/init/highlight_syntax.pm
+++ b/tp/init/highlight_syntax.pm
@@ -37,38 +37,8 @@ my %languages_extensions = (
 
 texinfo_add_valid_customization_option('HIGHLIGHT_SYNTAX_DEFAULT');
 
-texinfo_register_handler('structure', \&highlight_process);
-
-texinfo_register_command_formatting('example', 
\&highlight_preformatted_command);
-
-# normally this is done in preformatted type, but preformatted
-# types in example are ignored, register inline pending content
-# when opening an example block
-texinfo_register_command_opening('example', 
\&highlight_open_inline_container_type);
-
-sub highlight_open_inline_container_type($$$)
-{
-  my $self = shift;
-  my $cmdname = shift;
-  my $command = shift;
-
-  my $pending_formatted = $self->get_pending_formatted_inline_content();
-
-  if (defined($pending_formatted)) {
-    $self->associate_pending_formatted_inline_content($command, 
$pending_formatted);
-  }
-  return '';
-}
-
-
-# the end of the string was randomly generated once for all.
-my $range_separator = '_______________________________________ highlight 
texinfo _GT Haib0aik zei4YieH';
-
-my %languages = ();
-my %commands = ();
-my $highlight_out_dir;
-
-my %highlighted_languages_list;
+# reference on a hash
+my $highlighted_languages_list;
 
 # FIXME open shows an error message if the file is not found
 # which is a duplicate with the texinfo_register_init_loading_error
@@ -79,12 +49,13 @@ if (not(open(HIGHLIGHT_LANG_LIST, '-|', $cmd))) {
   texinfo_register_init_loading_error(
         sprintf(__('%s: %s'), $cmd, $!));
 } else {
+  $highlighted_languages_list = {};
   my $line;
   while (defined($line = <HIGHLIGHT_LANG_LIST>)) {
     chomp($line);
     if ($line =~ /^([A-Za-z0-9_\-]+) =/) {
        my $language = $1;
-       $highlighted_languages_list{$language} = 1;
+       $highlighted_languages_list->{$language} = 1;
     } else {
       texinfo_register_init_loading_warning(sprintf(__(
                         '%s: %s: cannot parse language line'), $cmd, $line))
@@ -93,6 +64,25 @@ if (not(open(HIGHLIGHT_LANG_LIST, '-|', $cmd))) {
   close(HIGHLIGHT_LANG_LIST);
 }
 
+if (defined($highlighted_languages_list)) {
+  if (scalar(keys(%$highlighted_languages_list)) > 0) {
+    texinfo_register_handler('structure', \&highlight_process);
+
+    texinfo_register_command_formatting('example', 
\&highlight_preformatted_command);
+
+    # normally this is done in preformatted type, but preformatted
+    # types in example are ignored in highlight_preformatted_command,
+    # so register a replacement.
+    # register inline pending content when opening an example block
+    texinfo_register_command_opening('example', 
\&highlight_open_inline_container_type);
+  } else {
+    # important if $cmd returns no output to have a message.  If there
+    # is some output, there will already be some line parse error messages.
+    texinfo_register_init_loading_warning(sprintf(__(
+      '%s: no highlighted language found'), $cmd));
+  }
+}
+
 sub _get_language($$$)
 {
   my $self = shift;
@@ -104,7 +94,8 @@ sub _get_language($$$)
 
   if ($cmdname eq 'example') {
     if ($command->{'args'} and scalar(@{$command->{'args'}}) > 0) {
-      $converted_language = 
Texinfo::Convert::NodeNameNormalization::convert($command->{'args'}->[0]);
+      $converted_language
+        = 
Texinfo::Convert::NodeNameNormalization::convert($command->{'args'}->[0]);
       if ($converted_language eq '') {
         $converted_language = undef;
       }
@@ -112,57 +103,68 @@ sub _get_language($$$)
   }
 
   if (not defined($converted_language) and defined($self)) {
-    my $default_highlight_language = 
$self->get_conf('HIGHLIGHT_SYNTAX_DEFAULT');
+    my $default_highlight_language
+      = $self->get_conf('HIGHLIGHT_SYNTAX_DEFAULT');
     if (defined($default_highlight_language)) {
       $converted_language = $default_highlight_language;
     }
   }
 
-  if (defined($converted_language) and 
defined($languages_name_mapping{$converted_language})) {
+  if (defined($converted_language)
+      and defined($languages_name_mapping{$converted_language})) {
     $language = $languages_name_mapping{$converted_language};
   } else {
     $language = $converted_language;
   }
 
-  if ($highlighted_languages_list{$language}) {
+  if ($highlighted_languages_list->{$language}) {
     return $language;
   } else {
     return undef;
   }
 }
 
+# the end of the string was randomly generated once for all.
+my $range_separator = '_______________________________________ highlight 
texinfo _GT Haib0aik zei4YieH';
+
+my %commands;
+
 sub highlight_process($$)
 {
   my $self = shift;
   my $document_root = shift;
 
-  return -1 if (defined($self->get_conf('OUTFILE'))
+  # initialization, important in case of multiple manuals processed
+  %commands = ();              # associates a command name and element to the 
resulting
+                               # highlighted text.
+                               # Also holds per language counters.
+
+  return 0 if (defined($self->get_conf('OUTFILE'))
         and $Texinfo::Common::null_device_file{$self->get_conf('OUTFILE')});
 
   my $document_name = $self->get_info('document_name');
   my $highlight_basename = "${document_name}_highlight";
 
-  $highlight_out_dir = $self->get_info('destination_directory');
+  my $highlight_out_dir = $self->get_info('destination_directory');
 
   my @highlighted_commands = ('example');
 
   my $collected_commands
     = Texinfo::Common::collect_commands_in_tree($document_root,
                                              \@highlighted_commands);
+
+  my %languages = ();
   foreach my $cmdname (@highlighted_commands) {
     if (scalar(@{$collected_commands->{$cmdname}}) > 0) {
       foreach my $element (@{$collected_commands->{$cmdname}}) {
         my $language = _get_language($self, $cmdname, $element);
         if (defined($language)) {
-          if (not exists($languages{$language})) {
-            $languages{$language} = {
-                     'counter' => 0,
-              };
-          }
+          $languages{$language} = {'counter' => 0}
+                 if (not exists($languages{$language}));
           $languages{$language}->{'counter'}++;
           my $counter = $languages{$language}->{'counter'};
           $languages{$language}->{'commands'}->[$counter-1] = [$element, 
$cmdname];
-          $commands{$cmdname}->{'input_counter'}++;
+          $commands{$cmdname}->{'input_languages_counters'}->{$language}++;
         }
       }
     }
@@ -280,8 +282,9 @@ sub highlight_process($$)
           $got_count++;
           my $element_command = 
$languages{$language}->{'commands'}->[$got_count-1];
           my $element = $element_command->[0];
-          my $command = $element_command->[1];
-          $commands{$command}->{'results'}->{$element} = $text;
+          my $cmdname = $element_command->[1];
+          $commands{$cmdname}->{'results'}->{$element} = $text;
+          $commands{$cmdname}->{'retrieved_languages_counters'}->{$language}++;
           $text = undef;
         }
         #print STDERR "$language $got_count $language_fragments_nr \n";
@@ -302,14 +305,18 @@ sub highlight_process($$)
     if (defined($text) and $text ne '') {
       my $element_command = 
$languages{$language}->{'commands'}->[$got_count-1];
       my $element = $element_command->[0];
-      my $command = $element_command->[1];
+      my $cmdname = $element_command->[1];
       $self->document_warn($self, sprintf(__(
                  "highlight_syntax.pm: %s: end of \@%s item %d not found"),
-                                  $language, $command, $got_count));
+                                  $language, $cmdname, $got_count));
     }
+    # note that this check is not the most detailed that could be done, a check
+    # by command could also be done.  Since for now there is only @example
+    # it is useless, and even if there were other commands, the failure is
+    # for a language, not a command, so it should not be needed either.
     if ($got_count != $languages{$language}->{'counter'}) {
       $self->document_warn($self, sprintf(__(
-         "highlight_syntax.pm: %s: processing produced %d items in HTML; 
expected %d, the number found in the document"),
+         "highlight_syntax.pm: %s: retrieved %d items in HTML; expected %d"),
                             $language, $got_count, $language_fragments_nr));
     }
     close (HIGHLIGHT_LANG_OUT);
@@ -317,6 +324,20 @@ sub highlight_process($$)
   return 0;
 }
 
+sub highlight_open_inline_container_type($$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $command = shift;
+
+  my $pending_formatted = $self->get_pending_formatted_inline_content();
+
+  if (defined($pending_formatted)) {
+    $self->associate_pending_formatted_inline_content($command, 
$pending_formatted);
+  }
+  return '';
+}
+
 sub highlight_preformatted_command($$$$$)
 {
   my $self = shift;
@@ -325,85 +346,103 @@ sub highlight_preformatted_command($$$$$)
   my $args = shift;
   my $content = shift;
 
-  my $language = _get_language($self, $cmdname, $command);
-  if (exists ($commands{$cmdname}->{'results'}->{$command})
-      and defined($commands{$cmdname}->{'results'}->{$command})) {
-    if (not defined($language)) {
-      $self->document_warn($self, sprintf(__(
-       "highlight_syntax.pm: output has HTML item for \@%s but no language 
%s"),
-                                  $cmdname, $command));
-    } else {
-
-      $commands{$cmdname}->{'output_counter'}++;
+  # if no commands were registered nor converted, do not
+  # warn if the language is known.  It means that there was
+  # no highlighting or some error.
+  if (exists ($commands{$cmdname})
+      and exists ($commands{$cmdname}->{'results'})) {
+    my $language = _get_language($self, $cmdname, $command);
+    if (exists ($commands{$cmdname}->{'results'}->{$command})
+        and defined($commands{$cmdname}->{'results'}->{$command})) {
+
+      if (not defined($language)) {
+        $self->document_warn($self, sprintf(__(
+         "highlight_syntax.pm: output has HTML item for \@%s but no language 
%s"),
+                                    $cmdname, $command));
+      } else {
+        $commands{$cmdname}->{'output_languages_counters'}->{$language}++;
 
-      if ($self->in_string()) {
-        return $content;
-      }
+        if ($self->in_string()) {
+          return $content;
+        }
 
-      # need to do all the formatting done for content inside
-      # of @example as it is discarded.  So need to do the preformatted
-      # type formatting, from _convert_preformatted_type() and 
_preformatted_class()
-      # since we are formatting @example itself, it is not in the preformatted
-      # context anymore, so we readd.
-      my @pre_classes = $self->preformatted_classes_stack();
-      # NOTE $pre_class_format is setup to match as 
$pre_class_commands{$cmdname}
-      # which is private
-      my $pre_class_format = $cmdname;
-      my $main_cmdname = $cmdname;
-      if (defined($Texinfo::Common::small_block_associated_command{$cmdname})) 
{
-        $pre_class_format
-          = $Texinfo::Common::small_block_associated_command{$cmdname};
-        $main_cmdname
-          = $Texinfo::Common::small_block_associated_command{$cmdname};
-      }
-      push @pre_classes, $pre_class_format;
-      my $pre_class;
-      foreach my $class (@pre_classes) {
-        # FIXME maybe add   or $pre_class eq 'menu'  to override
-        # 'menu' with 'menu-comment'?
-        $pre_class = $class unless ($pre_class
-                  and $Texinfo::Common::preformatted_code_commands{$pre_class}
-                  and !($Texinfo::Common::preformatted_code_commands{$class}
-                                 or $class eq 'menu'));
-      }
-      $pre_class = $pre_class.'-preformatted';
-
-      # FIXME not clear on that.  What to do with @example arguments?
-      my @classes;
-      if ($cmdname eq 'example') {
-        if ($command->{'args'}) {
-          for my $example_arg (@{$command->{'args'}}) {
-            # convert or remove all @-commands, using simple ascii and unicode
-            # characters
-            my $converted_arg
-               = 
Texinfo::Convert::NodeNameNormalization::convert($example_arg);
-            if ($converted_arg ne '') {
-              push @classes, $converted_arg;
+        # need to do all the formatting done for content inside
+        # of @example as it is discarded.  So need to do the preformatted
+        # type formatting, from _convert_preformatted_type() and 
_preformatted_class()
+        # since we are formatting @example itself, it is not in the 
preformatted
+        # context anymore, so we readd.
+        my @pre_classes = $self->preformatted_classes_stack();
+        # NOTE $pre_class_format is setup to match as 
$pre_class_commands{$cmdname}
+        # which is private
+        my $pre_class_format = $cmdname;
+        my $main_cmdname = $cmdname;
+        if 
(defined($Texinfo::Common::small_block_associated_command{$cmdname})) {
+          $pre_class_format
+            = $Texinfo::Common::small_block_associated_command{$cmdname};
+          $main_cmdname
+            = $Texinfo::Common::small_block_associated_command{$cmdname};
+        }
+        push @pre_classes, $pre_class_format;
+        my $pre_class;
+        foreach my $class (@pre_classes) {
+          # FIXME maybe add   or $pre_class eq 'menu'  to override
+          # 'menu' with 'menu-comment'?
+          $pre_class = $class unless ($pre_class
+                    and 
$Texinfo::Common::preformatted_code_commands{$pre_class}
+                    and !($Texinfo::Common::preformatted_code_commands{$class}
+                                   or $class eq 'menu'));
+        }
+        $pre_class = $pre_class.'-preformatted';
+
+        # FIXME not clear on that.  What to do with @example arguments?
+        my @classes;
+        if ($cmdname eq 'example') {
+          if ($command->{'args'}) {
+            for my $example_arg (@{$command->{'args'}}) {
+              # convert or remove all @-commands, using simple ascii and 
unicode
+              # characters
+              my $converted_arg
+                 = 
Texinfo::Convert::NodeNameNormalization::convert($example_arg);
+              if ($converted_arg ne '') {
+                push @classes, $converted_arg;
+              }
             }
           }
+        } elsif ($main_cmdname eq 'lisp') {
+          push @classes, $main_cmdname;
+          $main_cmdname = 'example';
         }
-      } elsif ($main_cmdname eq 'lisp') {
-        push @classes, $main_cmdname;
-        $main_cmdname = 'example';
+        unshift @classes, $main_cmdname;
+
+        my $result_content = $commands{$cmdname}->{'results'}->{$command};
+        # do it here, it is not done in preformatted.  It was correctly 
registered
+        # through highlight_open_inline_container_type.
+        $result_content = 
$self->get_associated_formatted_inline_content($command)
+                              . $result_content;
+        $result_content =~ s/^\n/\n\n/; # a newline immediately after a <pre> 
is ignored.
+        my $preformatted_result_content = $self->html_attribute_class('pre',
+                                          
[$pre_class]).">".$result_content."</pre>";
+        return $self->html_attribute_class('div', \@classes).">\n"
+               .$preformatted_result_content.'</div>'."\n";
+      }
+    # no error nor verbose message if there was no retrieved information
+    # for that language
+    } elsif (defined($language)
+             and 
$commands{$cmdname}->{'retrieved_languages_counters'}->{$language}) {
+      my $cmd_language_input_count
+         = $commands{$cmdname}->{'input_languages_counters'}->{$language};
+      my $cmd_language_retrieved_count
+         = $commands{$cmdname}->{'retrieved_languages_counters'}->{$language};
+      # message if the counters are equal, meaning language processed without 
failure.
+      # If they are not equal there should have been a message already
+      if ($cmd_language_input_count == $cmd_language_retrieved_count) {
+        $self->document_warn($self, sprintf(__(
+                "highlight_syntax.pm: output has no HTML item for \@%s %s %s"),
+                                    $cmdname, $language, $command));
+      } elsif ($self->get_conf('VERBOSE') or $self->get_conf('DEBUG')) {
+        warn "highlight_syntax.pm: output has no HTML item for \@$cmdname 
$language $command\n";
       }
-      unshift @classes, $main_cmdname;
-
-      my $result_content = $commands{$cmdname}->{'results'}->{$command};
-      # do it here, it is not done in preformatted.  It was correctly 
registered
-      # through highlight_open_inline_container_type.
-      $result_content = 
$self->get_associated_formatted_inline_content($command)
-                            . $result_content;
-      $result_content =~ s/^\n/\n\n/; # a newline immediately after a <pre> is 
ignored.
-      my $preformatted_result_content = $self->html_attribute_class('pre',
-                                        
[$pre_class]).">".$result_content."</pre>";
-      return $self->html_attribute_class('div', \@classes).">\n"
-             .$preformatted_result_content.'</div>'."\n";
     }
-  } elsif (defined($language)) {
-    $self->document_warn($self, sprintf(__(
-                       "highlight_syntax.pm: output has no HTML item for \@%s 
%s %s"),
-                                  $cmdname, $language, $command));
-    #print STDERR "$content\n";
   }
   return &{$self->default_command_conversion($cmdname)}($self, $cmdname,
                                                $command, $args, $content);
diff --git a/tp/tests/other/highlight_example.texi 
b/tp/tests/other/highlight_example.texi
index 4052e9a6ab..681a225407 100644
--- a/tp/tests/other/highlight_example.texi
+++ b/tp/tests/other/highlight_example.texi
@@ -34,4 +34,8 @@ sub do ($) @{
 @}
 @end example
 
+@example unknown
+unknown language
+@end example
+
 @bye
diff --git 
a/tp/tests/other/res_parser_html/highlight_syntax_example/chapter.html 
b/tp/tests/other/res_parser_html/highlight_syntax_example/chapter.html
index 0bc4d27915..7117d281a3 100644
--- a/tp/tests/other/res_parser_html/highlight_syntax_example/chapter.html
+++ b/tp/tests/other/res_parser_html/highlight_syntax_example/chapter.html
@@ -60,6 +60,10 @@ Previous: <a href="index.html" accesskey="p" 
rel="prev">top</a>, Up: <a href="in
 <span style="color:#FF0000">}</span>
 </pre></div>
 
+<div class="example user-unknown">
+<pre class="example-preformatted">unknown language
+</pre></div>
+
 </div>
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]