The HIGHLIGHT_SYNTAX is great and is suitable for most of the cases.
However, since it works with a predefined set of supported programs it
limits the user's options and requires the text2any to grow as new
syntax highlighters emerge and may be sensible for highlighters *CLI*
changes.

This change introduces a new *tex2any* variable that allows users to
specify a highlighter program/script that receives the language as first
argument and the code to be highlighted into the *stdin* and prints the
result in the *stdout*.

Even that the source highlighting is experimental, this change does not
deprecate the previous work, keeping backwards compatibility with the
cost of the highlighter program variable to be called
*HIGHLIGHT_SYNTAX_CMD*.

Rationale
=========

I'm writing a manual that highlights a language that is not actually
supported by *source-highlight*. Even if I was able to create a language
definition for the *source-highlight*, I could not easily use the
definition I wrote, since I'm not able to customize how the
*source-highlight* is invoked and providing the *--lang-def* is not an
option at this point.

The only way I could find to highlight my examples was to set the
*source-highlight* data directory over the *SOURCE_HIGHLIGHT_DATADIR*
environment variable and distribute the entire *source-highlight* data
directory within my manual, which was not ideal.

Signed-off-by: Carlos Maniero <[email protected]>
---
 doc/texinfo.texi                              |  45 ++-
 tp/Texinfo/Options.pm                         |   1 +
 tp/Texinfo/XS/main/options_data.h             |   3 +-
 tp/Texinfo/XS/main/options_defaults.c         |   2 +
 tp/Texinfo/XS/main/options_init_free.c        | 337 +++++++++---------
 tp/Texinfo/options_data.txt                   |   2 +
 tp/ext/highlight_syntax_cmd.pm                | 154 ++++++++
 tp/tests/Makefile.onetst                      |   2 +
 tp/tests/other/custom_highlighter.pl          |  37 ++
 tp/tests/other/highlight_cmd_example.texi     |  36 ++
 tp/tests/other/list-of-tests                  |   4 +
 .../other_highlight_syntax_cmd_example.sh     |  25 ++
 tp/texi2any.pl                                |   6 +
 13 files changed, 478 insertions(+), 176 deletions(-)
 create mode 100644 tp/ext/highlight_syntax_cmd.pm
 create mode 100755 tp/tests/other/custom_highlighter.pl
 create mode 100644 tp/tests/other/highlight_cmd_example.texi
 create mode 100755 tp/tests/test_scripts/other_highlight_syntax_cmd_example.sh

diff --git a/doc/texinfo.texi b/doc/texinfo.texi
index bed6320d84..33910ae9ab 100644
--- a/doc/texinfo.texi
+++ b/doc/texinfo.texi
@@ -17483,17 +17483,13 @@ customization set by the user.
 Source highlighting is experimental, feedback is welcomed.
 @end quotation
 @end cartouche
+Support for source code syntax highlighting is available in @command{texi2any}
+for the HTML output, with the help of external software. This feature is turned
+on by setting @code{HIGHLIGHT_SYNTAX} or @code{HIGHLIGHT_SYNTAX_CMD}.  Source
+code highlighting is set up for @code{@@example} blocks.
 
+@subsection Supported syntax highlighting programs
 @vindex HIGHLIGHT_SYNTAX
-@vindex HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE
-Support for source code syntax highlighting is available in
-@command{texi2any} for the HTML output, with the help of external software.
-This feature is turned on by setting @code{HIGHLIGHT_SYNTAX}.  Source code
-highlighting is set up for @code{@@example} blocks.  The language
-specified for syntax highlighting is the first argument on the 
@code{@@example} line
-(@pxref{@code{@@example}}), or @code{HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE} if set
-and there is no first argument.
-
 The @code{HIGHLIGHT_SYNTAX} value determines the command used for highlighting:
 @table @code
 @item highlight
@@ -17505,6 +17501,31 @@ Use @command{pygmentize} from 
@url{https://pygments.org/};
 Use @command{source-highlight} (@pxref{,,,source-highlight, GNU 
Source-highlight}).
 @end table
 
+@vindex HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE
+@subsection Defining the @code{@@example} code language
+The language specified for syntax highlighting is the first argument on the
+@code{@@example} line (@pxref{@code{@@example}}), or
+@code{HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE} if set and there is no first argument.
+
+@vindex HIGHLIGHT_SYNTAX_CMD
+@subsection Using a custom software for highlighting
+If the predefined supported softwares are not suitable for you, you can use the
+@code{HIGHLIGHT_SYNTAX_CMD}. Just like @code{HIGHLIGHT_SYNTAX}, it enables code
+syntax highlighting, but it uses a provided external software instead of the
+predefined programs to produce the highlighted html output.
+
+The given software must receive the language as the first argument and the code
+to be highlighted into the @code{stdin}. The result should be returned at the
+@code{stdout}.
+
+Usage example:
+@example
+@command{texi2any} --html my_manual.texi -c HIGHLIGHT_SYNTAX_CMD 
./my_highlighter.pl
+@end example
+
+If the @code{@@example} does not have a language, the block will not be sent to
+the highlighter software unless the @code{HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE} is
+set.
 
 @node HTML Xref
 @nodedescription Standard algorithm for interoperability.
@@ -19032,6 +19053,12 @@ for @code{source-highlight} (@pxref{Syntax 
Highlighting}).
 The default language used for syntax highlighting when there is no
 language information.
 
+@item HIGHLIGHT_SYNTAX_CMD
+Just like @code{HIGHLIGHT_SYNTAX}, if set, @code{@@example} blocks with
+language information as first argument are highlighted in the HTML output.  The
+value is the external program that will be executed to perform the syntax
+highlighting. (@pxref{Syntax Highlighting}).
+
 @item HTML_MATH
 Method to use to render @code{@@math} (@pxref{HTML Customization for Math}).
 This can be unset, set to
diff --git a/tp/Texinfo/Options.pm b/tp/Texinfo/Options.pm
index 2543dda37d..135ed6379b 100644
--- a/tp/Texinfo/Options.pm
+++ b/tp/Texinfo/Options.pm
@@ -79,6 +79,7 @@ our %converter_customization_options = (
   'FOOTNOTE_SEPARATE_HEADER_LEVEL'   => undef,
   'HEADER_IN_TABLE'                  => undef,
   'HIGHLIGHT_SYNTAX'                 => undef,
+  'HIGHLIGHT_SYNTAX_CMD'             => undef,
   'HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE' => undef,
   'HTML_MATH'                        => undef,
   'HTML_ROOT_ELEMENT_ATTRIBUTES'     => undef,
diff --git a/tp/Texinfo/XS/main/options_data.h 
b/tp/Texinfo/XS/main/options_data.h
index a9fd1a63ea..b3abff2d37 100644
--- a/tp/Texinfo/XS/main/options_data.h
+++ b/tp/Texinfo/XS/main/options_data.h
@@ -14,7 +14,7 @@
 #undef PACKAGE_URL
 #undef PACKAGE_VERSION
 
-#define TXI_OPTIONS_NR 228
+#define TXI_OPTIONS_NR 229
 
 typedef struct OPTIONS {
     size_t BIT_user_function_number;
@@ -96,6 +96,7 @@ typedef struct OPTIONS {
     OPTION FOOTNOTE_END_HEADER_LEVEL;
     OPTION FOOTNOTE_SEPARATE_HEADER_LEVEL;
     OPTION HEADER_IN_TABLE;
+    OPTION HIGHLIGHT_SYNTAX_CMD;
     OPTION HIGHLIGHT_SYNTAX;
     OPTION HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE;
     OPTION HTML_MATH;
diff --git a/tp/Texinfo/XS/main/options_defaults.c 
b/tp/Texinfo/XS/main/options_defaults.c
index 5b496ded22..39a74fdbee 100644
--- a/tp/Texinfo/XS/main/options_defaults.c
+++ b/tp/Texinfo/XS/main/options_defaults.c
@@ -137,6 +137,7 @@ set_converter_customization_options_defaults (OPTIONS 
*options)
   option_set_conf (&options->FOOTNOTE_END_HEADER_LEVEL, -1, 0);
   option_set_conf (&options->FOOTNOTE_SEPARATE_HEADER_LEVEL, -1, 0);
   option_set_conf (&options->HEADER_IN_TABLE, -1, 0);
+  option_set_conf (&options->HIGHLIGHT_SYNTAX_CMD, -2, 0);
   option_set_conf (&options->HIGHLIGHT_SYNTAX, -2, 0);
   option_set_conf (&options->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE, -2, 0);
   option_set_conf (&options->HTML_MATH, -2, 0);
@@ -282,6 +283,7 @@ add_converter_customization_options_defaults (OPTIONS_LIST 
*options_list)
   add_option_value (options_list, "FOOTNOTE_END_HEADER_LEVEL", -1, 0);
   add_option_value (options_list, "FOOTNOTE_SEPARATE_HEADER_LEVEL", -1, 0);
   add_option_value (options_list, "HEADER_IN_TABLE", -1, 0);
+  add_option_value (options_list, "HIGHLIGHT_SYNTAX_CMD", -2, 0);
   add_option_value (options_list, "HIGHLIGHT_SYNTAX", -2, 0);
   add_option_value (options_list, "HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE", -2, 0);
   add_option_value (options_list, "HTML_MATH", -2, 0);
diff --git a/tp/Texinfo/XS/main/options_init_free.c 
b/tp/Texinfo/XS/main/options_init_free.c
index 7ccbc11561..7bed8195b4 100644
--- a/tp/Texinfo/XS/main/options_init_free.c
+++ b/tp/Texinfo/XS/main/options_init_free.c
@@ -93,6 +93,7 @@ initialize_options (OPTIONS *options)
   initialize_option (&options->FOOTNOTE_END_HEADER_LEVEL, GOT_integer, 
"FOOTNOTE_END_HEADER_LEVEL");
   initialize_option (&options->FOOTNOTE_SEPARATE_HEADER_LEVEL, GOT_integer, 
"FOOTNOTE_SEPARATE_HEADER_LEVEL");
   initialize_option (&options->HEADER_IN_TABLE, GOT_integer, 
"HEADER_IN_TABLE");
+  initialize_option (&options->HIGHLIGHT_SYNTAX_CMD, GOT_char, 
"HIGHLIGHT_SYNTAX_CMD");
   initialize_option (&options->HIGHLIGHT_SYNTAX, GOT_char, "HIGHLIGHT_SYNTAX");
   initialize_option (&options->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE, GOT_char, 
"HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE");
   initialize_option (&options->HTML_MATH, GOT_char, "HTML_MATH");
@@ -350,6 +351,7 @@ free_options (OPTIONS *options)
   free_option (&options->FOOTNOTE_END_HEADER_LEVEL);
   free_option (&options->FOOTNOTE_SEPARATE_HEADER_LEVEL);
   free_option (&options->HEADER_IN_TABLE);
+  free_option (&options->HIGHLIGHT_SYNTAX_CMD);
   free_option (&options->HIGHLIGHT_SYNTAX);
   free_option (&options->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE);
   free_option (&options->HTML_MATH);
@@ -608,6 +610,7 @@ clear_options (OPTIONS *options)
   clear_option (&options->FOOTNOTE_END_HEADER_LEVEL);
   clear_option (&options->FOOTNOTE_SEPARATE_HEADER_LEVEL);
   clear_option (&options->HEADER_IN_TABLE);
+  clear_option (&options->HIGHLIGHT_SYNTAX_CMD);
   clear_option (&options->HIGHLIGHT_SYNTAX);
   clear_option (&options->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE);
   clear_option (&options->HTML_MATH);
@@ -866,6 +869,7 @@ copy_options (OPTIONS *destination, const OPTIONS *source)
   copy_option (&destination->FOOTNOTE_END_HEADER_LEVEL, 
&source->FOOTNOTE_END_HEADER_LEVEL);
   copy_option (&destination->FOOTNOTE_SEPARATE_HEADER_LEVEL, 
&source->FOOTNOTE_SEPARATE_HEADER_LEVEL);
   copy_option (&destination->HEADER_IN_TABLE, &source->HEADER_IN_TABLE);
+  copy_option (&destination->HIGHLIGHT_SYNTAX_CMD, 
&source->HIGHLIGHT_SYNTAX_CMD);
   copy_option (&destination->HIGHLIGHT_SYNTAX, &source->HIGHLIGHT_SYNTAX);
   copy_option (&destination->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE, 
&source->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE);
   copy_option (&destination->HTML_MATH, &source->HTML_MATH);
@@ -1107,172 +1111,173 @@ setup_sortable_options (OPTION **to_sort, OPTIONS 
*options)
   to_sort[59] = &options->HEADERS;   /* converter_cmdline */
   to_sort[60] = &options->HEADER_IN_TABLE;   /* converter_customization */
   to_sort[61] = &options->HIGHLIGHT_SYNTAX;   /* converter_customization */
-  to_sort[62] = &options->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE;   /* 
converter_customization */
-  to_sort[63] = &options->HTMLXREF_FILE;   /* converter_customization */
-  to_sort[64] = &options->HTMLXREF_MODE;   /* converter_customization */
-  to_sort[65] = &options->HTML_MATH;   /* converter_customization */
-  to_sort[66] = &options->HTML_ROOT_ELEMENT_ATTRIBUTES;   /* 
converter_customization */
-  to_sort[67] = &options->ICONS;   /* converter_customization */
-  to_sort[68] = &options->IGNORE_REF_TO_TOP_NODE_UP;   /* 
converter_customization */
-  to_sort[69] = &options->IMAGE_LINK_PREFIX;   /* converter_customization */
-  to_sort[70] = &options->INCLUDE_DIRECTORIES;   /* array_cmdline */
-  to_sort[71] = &options->INDENTED_BLOCK_COMMANDS_IN_TABLE;   /* 
converter_customization */
-  to_sort[72] = &options->INDEX_ENTRY_COLON;   /* converter_customization */
-  to_sort[73] = &options->INDEX_SPECIAL_CHARS_WARNING;   /* 
converter_customization */
-  to_sort[74] = &options->INFO_JS_DIR;   /* converter_customization */
-  to_sort[75] = &options->INFO_SPECIAL_CHARS_QUOTE;   /* 
converter_customization */
-  to_sort[76] = &options->INFO_SPECIAL_CHARS_WARNING;   /* 
converter_customization */
-  to_sort[77] = &options->INLINE_CSS_STYLE;   /* converter_customization */
-  to_sort[78] = &options->INPUT_FILE_NAME_ENCODING;   /* 
converter_customization */
-  to_sort[79] = &options->INTERNAL_LINKS;   /* program_cmdline */
-  to_sort[80] = &options->JS_WEBLABELS;   /* converter_customization */
-  to_sort[81] = &options->JS_WEBLABELS_FILE;   /* converter_customization */
-  to_sort[82] = &options->L2H_CLEAN;   /* converter_customization */
-  to_sort[83] = &options->L2H_FILE;   /* converter_customization */
-  to_sort[84] = &options->L2H_HTML_VERSION;   /* converter_customization */
-  to_sort[85] = &options->L2H_L2H;   /* converter_customization */
-  to_sort[86] = &options->L2H_SKIP;   /* converter_customization */
-  to_sort[87] = &options->L2H_TMP;   /* converter_customization */
-  to_sort[88] = &options->LATEX_FLOATS_FILE_EXTENSION;   /* 
converter_customization */
-  to_sort[89] = &options->LINKS_BUTTONS;   /* converter_other */
-  to_sort[90] = &options->LOCALE_ENCODING;   /* converter_customization */
-  to_sort[91] = &options->MACRO_EXPAND;   /* program_cmdline */
-  to_sort[92] = &options->MATHJAX_CONFIGURATION;   /* converter_customization 
*/
-  to_sort[93] = &options->MATHJAX_SCRIPT;   /* converter_customization */
-  to_sort[94] = &options->MATHJAX_SOURCE;   /* converter_customization */
-  to_sort[95] = &options->MAX_HEADER_LEVEL;   /* converter_customization */
-  to_sort[96] = &options->MENU_ENTRY_COLON;   /* converter_customization */
-  to_sort[97] = &options->MENU_SYMBOL;   /* converter_customization */
-  to_sort[98] = &options->MESSAGE_ENCODING;   /* converter_customization */
-  to_sort[99] = &options->MISC_BUTTONS;   /* converter_other */
-  to_sort[100] = &options->MONOLITHIC;   /* converter_customization */
-  to_sort[101] = &options->NODE_FILES;   /* converter_cmdline */
-  to_sort[102] = &options->NODE_FOOTER_BUTTONS;   /* converter_other */
-  to_sort[103] = &options->NODE_NAME_IN_INDEX;   /* converter_customization */
-  to_sort[104] = &options->NODE_NAME_IN_MENU;   /* converter_customization */
-  to_sort[105] = &options->NO_CSS;   /* converter_customization */
-  to_sort[106] = &options->NO_CUSTOM_HTML_ATTRIBUTE;   /* 
converter_customization */
-  to_sort[107] = &options->NO_NUMBER_FOOTNOTE_SYMBOL;   /* 
converter_customization */
-  to_sort[108] = &options->NO_TOP_NODE_OUTPUT;   /* converter_customization */
-  to_sort[109] = &options->NO_WARN;   /* program_cmdline */
-  to_sort[110] = &options->NUMBER_FOOTNOTES;   /* converter_cmdline */
-  to_sort[111] = &options->NUMBER_SECTIONS;   /* converter_cmdline */
-  to_sort[112] = &options->OPEN_DOUBLE_QUOTE_SYMBOL;   /* 
converter_customization */
-  to_sort[113] = &options->OPEN_QUOTE_SYMBOL;   /* converter_customization */
-  to_sort[114] = &options->OUTFILE;   /* converter_cmdline */
-  to_sort[115] = &options->OUTPUT_CHARACTERS;   /* converter_customization */
-  to_sort[116] = &options->OUTPUT_ENCODING_NAME;   /* converter_customization 
*/
-  to_sort[117] = &options->OUTPUT_FILE_NAME_ENCODING;   /* 
converter_customization */
-  to_sort[118] = &options->OUTPUT_PERL_ENCODING;   /* converter_customization 
*/
-  to_sort[119] = &options->PACKAGE;   /* converter_customization */
-  to_sort[120] = &options->PACKAGE_AND_VERSION;   /* converter_customization */
-  to_sort[121] = &options->PACKAGE_NAME;   /* converter_customization */
-  to_sort[122] = &options->PACKAGE_URL;   /* converter_customization */
-  to_sort[123] = &options->PACKAGE_VERSION;   /* converter_customization */
-  to_sort[124] = &options->PASSIVE_ICONS;   /* converter_other */
-  to_sort[125] = &options->PREFIX;   /* converter_customization */
-  to_sort[126] = &options->PRE_BODY_CLOSE;   /* converter_customization */
-  to_sort[127] = &options->PROGRAM;   /* converter_customization */
-  to_sort[128] = &options->PROGRAM_NAME_IN_ABOUT;   /* converter_customization 
*/
-  to_sort[129] = &options->PROGRAM_NAME_IN_FOOTER;   /* 
converter_customization */
-  to_sort[130] = &options->SECTION_BUTTONS;   /* converter_other */
-  to_sort[131] = &options->SECTION_FOOTER_BUTTONS;   /* converter_other */
-  to_sort[132] = &options->SECTION_NAME_IN_TITLE;   /* converter_customization 
*/
-  to_sort[133] = &options->SHORT_TOC_LINK_TO_TOC;   /* converter_customization 
*/
-  to_sort[134] = &options->SHOW_BUILTIN_CSS_RULES;   /* program_customization 
*/
-  to_sort[135] = &options->SHOW_TITLE;   /* converter_customization */
-  to_sort[136] = &options->SORT_ELEMENT_COUNT;   /* program_customization */
-  to_sort[137] = &options->SORT_ELEMENT_COUNT_WORDS;   /* 
program_customization */
-  to_sort[138] = &options->SPLIT;   /* converter_cmdline */
-  to_sort[139] = &options->SPLIT_SIZE;   /* converter_cmdline */
-  to_sort[140] = &options->SUBDIR;   /* converter_cmdline */
-  to_sort[141] = &options->T4H_LATEX_CONVERSION;   /* converter_customization 
*/
-  to_sort[142] = &options->T4H_MATH_CONVERSION;   /* converter_customization */
-  to_sort[143] = &options->T4H_TEX_CONVERSION;   /* converter_customization */
-  to_sort[144] = &options->TEST;   /* converter_customization */
-  to_sort[145] = &options->TEXI2DVI;   /* program_customization */
-  to_sort[146] = &options->TEXI2HTML;   /* converter_customization */
-  to_sort[147] = &options->TEXINFO_DTD_VERSION;   /* converter_customization */
-  to_sort[148] = &options->TEXINFO_LANGUAGE_DIRECTORIES;   /* array_cmdline */
-  to_sort[149] = &options->TEXINFO_OUTPUT_FORMAT;   /* converter_customization 
*/
-  to_sort[150] = &options->TEXTCONTENT_COMMENT;   /* converter_customization */
-  to_sort[151] = &options->TOC_LINKS;   /* converter_customization */
-  to_sort[152] = &options->TOP_BUTTONS;   /* converter_other */
-  to_sort[153] = &options->TOP_FILE;   /* converter_customization */
-  to_sort[154] = &options->TOP_FOOTER_BUTTONS;   /* converter_other */
-  to_sort[155] = &options->TOP_NODE_FILE_TARGET;   /* converter_customization 
*/
-  to_sort[156] = &options->TOP_NODE_UP;   /* converter_customization */
-  to_sort[157] = &options->TOP_NODE_UP_URL;   /* converter_customization */
-  to_sort[158] = &options->TRACE_INCLUDES;   /* program_cmdline */
-  to_sort[159] = &options->TRANSLITERATE_FILE_NAMES;   /* converter_cmdline */
-  to_sort[160] = &options->TREE_TRANSFORMATIONS;   /* program_customization */
-  to_sort[161] = &options->TXI_MARKUP_NO_SECTION_EXTENT;   /* 
converter_customization */
-  to_sort[162] = &options->USE_ACCESSKEY;   /* converter_customization */
-  to_sort[163] = &options->USE_ISO;   /* converter_customization */
-  to_sort[164] = &options->USE_LINKS;   /* converter_customization */
-  to_sort[165] = &options->USE_NEXT_HEADING_FOR_LONE_NODE;   /* 
converter_customization */
-  to_sort[166] = &options->USE_NODES;   /* converter_customization */
-  to_sort[167] = &options->USE_NODE_DIRECTIONS;   /* converter_customization */
-  to_sort[168] = &options->USE_NUMERIC_ENTITY;   /* converter_customization */
-  to_sort[169] = &options->USE_REL_REV;   /* converter_customization */
-  to_sort[170] = &options->USE_SETFILENAME_EXTENSION;   /* 
converter_customization */
-  to_sort[171] = &options->USE_TITLEPAGE_FOR_TITLE;   /* 
converter_customization */
-  to_sort[172] = &options->USE_UNICODE_COLLATION;   /* converter_customization 
*/
-  to_sort[173] = &options->USE_UNIDECODE;   /* converter_customization */
-  to_sort[174] = &options->USE_XML_SYNTAX;   /* converter_customization */
-  to_sort[175] = &options->VERBOSE;   /* converter_cmdline */
-  to_sort[176] = &options->VERTICAL_HEAD_NAVIGATION;   /* 
converter_customization */
-  to_sort[177] = &options->WORDS_IN_PAGE;   /* converter_customization */
-  to_sort[178] = &options->XREF_USE_FLOAT_LABEL;   /* converter_customization 
*/
-  to_sort[179] = &options->XREF_USE_NODE_NAME_ARG;   /* 
converter_customization */
-  to_sort[180] = &options->XS_EXTERNAL_CONVERSION;   /* 
converter_customization */
-  to_sort[181] = &options->XS_EXTERNAL_FORMATTING;   /* 
converter_customization */
-  to_sort[182] = &options->XS_STRXFRM_COLLATION_LOCALE;   /* 
converter_customization */
-  to_sort[183] = &options->_INLINE_STYLE_WIDTH;   /* converter_customization */
-  to_sort[184] = &options->afivepaper;   /* unique_at_command */
-  to_sort[185] = &options->afourlatex;   /* unique_at_command */
-  to_sort[186] = &options->afourpaper;   /* unique_at_command */
-  to_sort[187] = &options->afourwide;   /* unique_at_command */
-  to_sort[188] = &options->allowcodebreaks;   /* multiple_at_command */
-  to_sort[189] = &options->bsixpaper;   /* unique_at_command */
-  to_sort[190] = &options->clickstyle;   /* multiple_at_command */
-  to_sort[191] = &options->codequotebacktick;   /* multiple_at_command */
-  to_sort[192] = &options->codequoteundirected;   /* multiple_at_command */
-  to_sort[193] = &options->contents;   /* multiple_at_command */
-  to_sort[194] = &options->deftypefnnewline;   /* multiple_at_command */
-  to_sort[195] = &options->documentdescription;   /* unique_at_command */
-  to_sort[196] = &options->documentencoding;   /* multiple_at_command */
-  to_sort[197] = &options->documentlanguage;   /* multiple_at_command */
-  to_sort[198] = &options->evenfooting;   /* multiple_at_command */
-  to_sort[199] = &options->evenfootingmarks;   /* unique_at_command */
-  to_sort[200] = &options->evenheading;   /* multiple_at_command */
-  to_sort[201] = &options->evenheadingmarks;   /* unique_at_command */
-  to_sort[202] = &options->everyfooting;   /* multiple_at_command */
-  to_sort[203] = &options->everyfootingmarks;   /* unique_at_command */
-  to_sort[204] = &options->everyheading;   /* multiple_at_command */
-  to_sort[205] = &options->everyheadingmarks;   /* unique_at_command */
-  to_sort[206] = &options->exampleindent;   /* multiple_at_command */
-  to_sort[207] = &options->firstparagraphindent;   /* multiple_at_command */
-  to_sort[208] = &options->fonttextsize;   /* unique_at_command */
-  to_sort[209] = &options->footnotestyle;   /* unique_at_command */
-  to_sort[210] = &options->frenchspacing;   /* multiple_at_command */
-  to_sort[211] = &options->headings;   /* multiple_at_command */
-  to_sort[212] = &options->kbdinputstyle;   /* multiple_at_command */
-  to_sort[213] = &options->microtype;   /* multiple_at_command */
-  to_sort[214] = &options->novalidate;   /* unique_at_command */
-  to_sort[215] = &options->oddfooting;   /* multiple_at_command */
-  to_sort[216] = &options->oddfootingmarks;   /* unique_at_command */
-  to_sort[217] = &options->oddheading;   /* multiple_at_command */
-  to_sort[218] = &options->oddheadingmarks;   /* unique_at_command */
-  to_sort[219] = &options->pagesizes;   /* unique_at_command */
-  to_sort[220] = &options->paragraphindent;   /* multiple_at_command */
-  to_sort[221] = &options->setchapternewpage;   /* unique_at_command */
-  to_sort[222] = &options->setfilename;   /* unique_at_command */
-  to_sort[223] = &options->shortcontents;   /* multiple_at_command */
-  to_sort[224] = &options->smallbook;   /* unique_at_command */
-  to_sort[225] = &options->summarycontents;   /* multiple_at_command */
-  to_sort[226] = &options->urefbreakstyle;   /* multiple_at_command */
-  to_sort[227] = &options->xrefautomaticsectiontitle;   /* multiple_at_command 
*/
+  to_sort[62] = &options->HIGHLIGHT_SYNTAX_CMD;   /* converter_customization */
+  to_sort[63] = &options->HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE;   /* 
converter_customization */
+  to_sort[64] = &options->HTMLXREF_FILE;   /* converter_customization */
+  to_sort[65] = &options->HTMLXREF_MODE;   /* converter_customization */
+  to_sort[66] = &options->HTML_MATH;   /* converter_customization */
+  to_sort[67] = &options->HTML_ROOT_ELEMENT_ATTRIBUTES;   /* 
converter_customization */
+  to_sort[68] = &options->ICONS;   /* converter_customization */
+  to_sort[69] = &options->IGNORE_REF_TO_TOP_NODE_UP;   /* 
converter_customization */
+  to_sort[70] = &options->IMAGE_LINK_PREFIX;   /* converter_customization */
+  to_sort[71] = &options->INCLUDE_DIRECTORIES;   /* array_cmdline */
+  to_sort[72] = &options->INDENTED_BLOCK_COMMANDS_IN_TABLE;   /* 
converter_customization */
+  to_sort[73] = &options->INDEX_ENTRY_COLON;   /* converter_customization */
+  to_sort[74] = &options->INDEX_SPECIAL_CHARS_WARNING;   /* 
converter_customization */
+  to_sort[75] = &options->INFO_JS_DIR;   /* converter_customization */
+  to_sort[76] = &options->INFO_SPECIAL_CHARS_QUOTE;   /* 
converter_customization */
+  to_sort[77] = &options->INFO_SPECIAL_CHARS_WARNING;   /* 
converter_customization */
+  to_sort[78] = &options->INLINE_CSS_STYLE;   /* converter_customization */
+  to_sort[79] = &options->INPUT_FILE_NAME_ENCODING;   /* 
converter_customization */
+  to_sort[80] = &options->INTERNAL_LINKS;   /* program_cmdline */
+  to_sort[81] = &options->JS_WEBLABELS;   /* converter_customization */
+  to_sort[82] = &options->JS_WEBLABELS_FILE;   /* converter_customization */
+  to_sort[83] = &options->L2H_CLEAN;   /* converter_customization */
+  to_sort[84] = &options->L2H_FILE;   /* converter_customization */
+  to_sort[85] = &options->L2H_HTML_VERSION;   /* converter_customization */
+  to_sort[86] = &options->L2H_L2H;   /* converter_customization */
+  to_sort[87] = &options->L2H_SKIP;   /* converter_customization */
+  to_sort[88] = &options->L2H_TMP;   /* converter_customization */
+  to_sort[89] = &options->LATEX_FLOATS_FILE_EXTENSION;   /* 
converter_customization */
+  to_sort[90] = &options->LINKS_BUTTONS;   /* converter_other */
+  to_sort[91] = &options->LOCALE_ENCODING;   /* converter_customization */
+  to_sort[92] = &options->MACRO_EXPAND;   /* program_cmdline */
+  to_sort[93] = &options->MATHJAX_CONFIGURATION;   /* converter_customization 
*/
+  to_sort[94] = &options->MATHJAX_SCRIPT;   /* converter_customization */
+  to_sort[95] = &options->MATHJAX_SOURCE;   /* converter_customization */
+  to_sort[96] = &options->MAX_HEADER_LEVEL;   /* converter_customization */
+  to_sort[97] = &options->MENU_ENTRY_COLON;   /* converter_customization */
+  to_sort[98] = &options->MENU_SYMBOL;   /* converter_customization */
+  to_sort[99] = &options->MESSAGE_ENCODING;   /* converter_customization */
+  to_sort[100] = &options->MISC_BUTTONS;   /* converter_other */
+  to_sort[101] = &options->MONOLITHIC;   /* converter_customization */
+  to_sort[102] = &options->NODE_FILES;   /* converter_cmdline */
+  to_sort[103] = &options->NODE_FOOTER_BUTTONS;   /* converter_other */
+  to_sort[104] = &options->NODE_NAME_IN_INDEX;   /* converter_customization */
+  to_sort[105] = &options->NODE_NAME_IN_MENU;   /* converter_customization */
+  to_sort[106] = &options->NO_CSS;   /* converter_customization */
+  to_sort[107] = &options->NO_CUSTOM_HTML_ATTRIBUTE;   /* 
converter_customization */
+  to_sort[108] = &options->NO_NUMBER_FOOTNOTE_SYMBOL;   /* 
converter_customization */
+  to_sort[109] = &options->NO_TOP_NODE_OUTPUT;   /* converter_customization */
+  to_sort[110] = &options->NO_WARN;   /* program_cmdline */
+  to_sort[111] = &options->NUMBER_FOOTNOTES;   /* converter_cmdline */
+  to_sort[112] = &options->NUMBER_SECTIONS;   /* converter_cmdline */
+  to_sort[113] = &options->OPEN_DOUBLE_QUOTE_SYMBOL;   /* 
converter_customization */
+  to_sort[114] = &options->OPEN_QUOTE_SYMBOL;   /* converter_customization */
+  to_sort[115] = &options->OUTFILE;   /* converter_cmdline */
+  to_sort[116] = &options->OUTPUT_CHARACTERS;   /* converter_customization */
+  to_sort[117] = &options->OUTPUT_ENCODING_NAME;   /* converter_customization 
*/
+  to_sort[118] = &options->OUTPUT_FILE_NAME_ENCODING;   /* 
converter_customization */
+  to_sort[119] = &options->OUTPUT_PERL_ENCODING;   /* converter_customization 
*/
+  to_sort[120] = &options->PACKAGE;   /* converter_customization */
+  to_sort[121] = &options->PACKAGE_AND_VERSION;   /* converter_customization */
+  to_sort[122] = &options->PACKAGE_NAME;   /* converter_customization */
+  to_sort[123] = &options->PACKAGE_URL;   /* converter_customization */
+  to_sort[124] = &options->PACKAGE_VERSION;   /* converter_customization */
+  to_sort[125] = &options->PASSIVE_ICONS;   /* converter_other */
+  to_sort[126] = &options->PREFIX;   /* converter_customization */
+  to_sort[127] = &options->PRE_BODY_CLOSE;   /* converter_customization */
+  to_sort[128] = &options->PROGRAM;   /* converter_customization */
+  to_sort[129] = &options->PROGRAM_NAME_IN_ABOUT;   /* converter_customization 
*/
+  to_sort[130] = &options->PROGRAM_NAME_IN_FOOTER;   /* 
converter_customization */
+  to_sort[131] = &options->SECTION_BUTTONS;   /* converter_other */
+  to_sort[132] = &options->SECTION_FOOTER_BUTTONS;   /* converter_other */
+  to_sort[133] = &options->SECTION_NAME_IN_TITLE;   /* converter_customization 
*/
+  to_sort[134] = &options->SHORT_TOC_LINK_TO_TOC;   /* converter_customization 
*/
+  to_sort[135] = &options->SHOW_BUILTIN_CSS_RULES;   /* program_customization 
*/
+  to_sort[136] = &options->SHOW_TITLE;   /* converter_customization */
+  to_sort[137] = &options->SORT_ELEMENT_COUNT;   /* program_customization */
+  to_sort[138] = &options->SORT_ELEMENT_COUNT_WORDS;   /* 
program_customization */
+  to_sort[139] = &options->SPLIT;   /* converter_cmdline */
+  to_sort[140] = &options->SPLIT_SIZE;   /* converter_cmdline */
+  to_sort[141] = &options->SUBDIR;   /* converter_cmdline */
+  to_sort[142] = &options->T4H_LATEX_CONVERSION;   /* converter_customization 
*/
+  to_sort[143] = &options->T4H_MATH_CONVERSION;   /* converter_customization */
+  to_sort[144] = &options->T4H_TEX_CONVERSION;   /* converter_customization */
+  to_sort[145] = &options->TEST;   /* converter_customization */
+  to_sort[146] = &options->TEXI2DVI;   /* program_customization */
+  to_sort[147] = &options->TEXI2HTML;   /* converter_customization */
+  to_sort[148] = &options->TEXINFO_DTD_VERSION;   /* converter_customization */
+  to_sort[149] = &options->TEXINFO_LANGUAGE_DIRECTORIES;   /* array_cmdline */
+  to_sort[150] = &options->TEXINFO_OUTPUT_FORMAT;   /* converter_customization 
*/
+  to_sort[151] = &options->TEXTCONTENT_COMMENT;   /* converter_customization */
+  to_sort[152] = &options->TOC_LINKS;   /* converter_customization */
+  to_sort[153] = &options->TOP_BUTTONS;   /* converter_other */
+  to_sort[154] = &options->TOP_FILE;   /* converter_customization */
+  to_sort[155] = &options->TOP_FOOTER_BUTTONS;   /* converter_other */
+  to_sort[156] = &options->TOP_NODE_FILE_TARGET;   /* converter_customization 
*/
+  to_sort[157] = &options->TOP_NODE_UP;   /* converter_customization */
+  to_sort[158] = &options->TOP_NODE_UP_URL;   /* converter_customization */
+  to_sort[159] = &options->TRACE_INCLUDES;   /* program_cmdline */
+  to_sort[160] = &options->TRANSLITERATE_FILE_NAMES;   /* converter_cmdline */
+  to_sort[161] = &options->TREE_TRANSFORMATIONS;   /* program_customization */
+  to_sort[162] = &options->TXI_MARKUP_NO_SECTION_EXTENT;   /* 
converter_customization */
+  to_sort[163] = &options->USE_ACCESSKEY;   /* converter_customization */
+  to_sort[164] = &options->USE_ISO;   /* converter_customization */
+  to_sort[165] = &options->USE_LINKS;   /* converter_customization */
+  to_sort[166] = &options->USE_NEXT_HEADING_FOR_LONE_NODE;   /* 
converter_customization */
+  to_sort[167] = &options->USE_NODES;   /* converter_customization */
+  to_sort[168] = &options->USE_NODE_DIRECTIONS;   /* converter_customization */
+  to_sort[169] = &options->USE_NUMERIC_ENTITY;   /* converter_customization */
+  to_sort[170] = &options->USE_REL_REV;   /* converter_customization */
+  to_sort[171] = &options->USE_SETFILENAME_EXTENSION;   /* 
converter_customization */
+  to_sort[172] = &options->USE_TITLEPAGE_FOR_TITLE;   /* 
converter_customization */
+  to_sort[173] = &options->USE_UNICODE_COLLATION;   /* converter_customization 
*/
+  to_sort[174] = &options->USE_UNIDECODE;   /* converter_customization */
+  to_sort[175] = &options->USE_XML_SYNTAX;   /* converter_customization */
+  to_sort[176] = &options->VERBOSE;   /* converter_cmdline */
+  to_sort[177] = &options->VERTICAL_HEAD_NAVIGATION;   /* 
converter_customization */
+  to_sort[178] = &options->WORDS_IN_PAGE;   /* converter_customization */
+  to_sort[179] = &options->XREF_USE_FLOAT_LABEL;   /* converter_customization 
*/
+  to_sort[180] = &options->XREF_USE_NODE_NAME_ARG;   /* 
converter_customization */
+  to_sort[181] = &options->XS_EXTERNAL_CONVERSION;   /* 
converter_customization */
+  to_sort[182] = &options->XS_EXTERNAL_FORMATTING;   /* 
converter_customization */
+  to_sort[183] = &options->XS_STRXFRM_COLLATION_LOCALE;   /* 
converter_customization */
+  to_sort[184] = &options->_INLINE_STYLE_WIDTH;   /* converter_customization */
+  to_sort[185] = &options->afivepaper;   /* unique_at_command */
+  to_sort[186] = &options->afourlatex;   /* unique_at_command */
+  to_sort[187] = &options->afourpaper;   /* unique_at_command */
+  to_sort[188] = &options->afourwide;   /* unique_at_command */
+  to_sort[189] = &options->allowcodebreaks;   /* multiple_at_command */
+  to_sort[190] = &options->bsixpaper;   /* unique_at_command */
+  to_sort[191] = &options->clickstyle;   /* multiple_at_command */
+  to_sort[192] = &options->codequotebacktick;   /* multiple_at_command */
+  to_sort[193] = &options->codequoteundirected;   /* multiple_at_command */
+  to_sort[194] = &options->contents;   /* multiple_at_command */
+  to_sort[195] = &options->deftypefnnewline;   /* multiple_at_command */
+  to_sort[196] = &options->documentdescription;   /* unique_at_command */
+  to_sort[197] = &options->documentencoding;   /* multiple_at_command */
+  to_sort[198] = &options->documentlanguage;   /* multiple_at_command */
+  to_sort[199] = &options->evenfooting;   /* multiple_at_command */
+  to_sort[200] = &options->evenfootingmarks;   /* unique_at_command */
+  to_sort[201] = &options->evenheading;   /* multiple_at_command */
+  to_sort[202] = &options->evenheadingmarks;   /* unique_at_command */
+  to_sort[203] = &options->everyfooting;   /* multiple_at_command */
+  to_sort[204] = &options->everyfootingmarks;   /* unique_at_command */
+  to_sort[205] = &options->everyheading;   /* multiple_at_command */
+  to_sort[206] = &options->everyheadingmarks;   /* unique_at_command */
+  to_sort[207] = &options->exampleindent;   /* multiple_at_command */
+  to_sort[208] = &options->firstparagraphindent;   /* multiple_at_command */
+  to_sort[209] = &options->fonttextsize;   /* unique_at_command */
+  to_sort[210] = &options->footnotestyle;   /* unique_at_command */
+  to_sort[211] = &options->frenchspacing;   /* multiple_at_command */
+  to_sort[212] = &options->headings;   /* multiple_at_command */
+  to_sort[213] = &options->kbdinputstyle;   /* multiple_at_command */
+  to_sort[214] = &options->microtype;   /* multiple_at_command */
+  to_sort[215] = &options->novalidate;   /* unique_at_command */
+  to_sort[216] = &options->oddfooting;   /* multiple_at_command */
+  to_sort[217] = &options->oddfootingmarks;   /* unique_at_command */
+  to_sort[218] = &options->oddheading;   /* multiple_at_command */
+  to_sort[219] = &options->oddheadingmarks;   /* unique_at_command */
+  to_sort[220] = &options->pagesizes;   /* unique_at_command */
+  to_sort[221] = &options->paragraphindent;   /* multiple_at_command */
+  to_sort[222] = &options->setchapternewpage;   /* unique_at_command */
+  to_sort[223] = &options->setfilename;   /* unique_at_command */
+  to_sort[224] = &options->shortcontents;   /* multiple_at_command */
+  to_sort[225] = &options->smallbook;   /* unique_at_command */
+  to_sort[226] = &options->summarycontents;   /* multiple_at_command */
+  to_sort[227] = &options->urefbreakstyle;   /* multiple_at_command */
+  to_sort[228] = &options->xrefautomaticsectiontitle;   /* multiple_at_command 
*/
 }
 
 
diff --git a/tp/Texinfo/options_data.txt b/tp/Texinfo/options_data.txt
index 217bc0a8bc..20715f459b 100644
--- a/tp/Texinfo/options_data.txt
+++ b/tp/Texinfo/options_data.txt
@@ -241,6 +241,8 @@ FOOTNOTE_END_HEADER_LEVEL          converter_customization 
undef   integer
 FOOTNOTE_SEPARATE_HEADER_LEVEL     converter_customization undef   integer
 HEADER_IN_TABLE                    converter_customization undef   integer
 # for ext/highlight_syntax.pm
+HIGHLIGHT_SYNTAX_CMD               converter_customization undef   char
+# for ext/highlight_syntax.pm
 HIGHLIGHT_SYNTAX                   converter_customization undef   char
 # for ext/highlight_syntax.pm
 HIGHLIGHT_SYNTAX_DEFAULT_LANGUAGE  converter_customization undef   char
diff --git a/tp/ext/highlight_syntax_cmd.pm b/tp/ext/highlight_syntax_cmd.pm
new file mode 100644
index 0000000000..fcdd1105af
--- /dev/null
+++ b/tp/ext/highlight_syntax_cmd.pm
@@ -0,0 +1,154 @@
+# highlight_syntax_cmd.pm: interface for syntax highlighting
+#
+#    Copyright (C) 2021-2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License,
+# or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Originally written by Carlos Maniero.
+
+use 5.006;
+use strict;
+
+use IPC::Open3;
+use Symbol;
+
+texinfo_register_handler('structure', \&highlight_cmd_process);
+texinfo_register_command_formatting('example', 
\&highlight_cmd_preformatted_command);
+
+my @highlight_result;
+
+sub highlight_cmd_process ($$)
+{
+  my $self = shift;
+  my $document = shift;
+
+  my $document_root = $document->tree();
+
+  my $program_cmd = $self->get_conf('HIGHLIGHT_SYNTAX_CMD');
+
+  my $collected_commands
+    = Texinfo::Common::collect_commands_in_tree($document_root, ['example']);
+
+  foreach my $element (@{$collected_commands->{'example'}}) {
+    my $language
+      = Texinfo::Convert::NodeNameNormalization::convert_to_normalized(
+                                                  $element->{'args'}->[0]);
+
+    if (!$language) {
+      push @highlight_result, undef;
+      next;
+    }
+
+    my $text = _convert_element($self, $element);
+
+    my $cmd = $program_cmd.' '.$language;
+
+    my ($wtr, $rdr, $err);
+    $err = gensym();
+
+    my $pid = IPC::Open3::open3($wtr, $rdr, $err, $cmd);
+    if (!$pid) {
+      $self->converter_document_error(sprintf(__('%s: %s'), $cmd, $!));
+      return 1;
+    }
+
+    binmode($wtr, ':utf8');
+    binmode($rdr, ':utf8');
+    binmode($err, ':utf8');
+
+    print $wtr $text;
+    if (!close($wtr)) {
+      $self->converter_document_error(
+        sprintf(__('%s: error closing input: %s'), $cmd, $!));
+      close ($rdr);
+      close ($err);
+      return 1;
+    }
+
+    my @outlines = <$rdr>;
+    my @errlines = <$err>;
+    my $status = 0;
+    if (!close($rdr)) {
+      $self->converter_document_error(
+        sprintf(__('%s: error closing output: %s'), $cmd, $!));
+      $status = 1;
+    }
+    if (!close($err)) {
+      $self->converter_document_error(
+        sprintf(__('%s: error closing errors: %s'), $cmd, $!));
+      $status = 1;
+    }
+    waitpid($pid, 0);
+    if (@errlines) {
+      $status = 1;
+      $self->converter_document_error(sprintf(__('%s: errors: %s'),
+                                           $cmd, shift @errlines));
+      foreach my $error_line (@errlines) {
+        $self->converter_document_error(sprintf(__('  %s'), $error_line), 1);
+      }
+    }
+
+    return 1 if ($status);
+
+    push @highlight_result, join('', @outlines)
+  }
+  return 0;
+}
+
+sub _convert_element($$)
+{
+  my $self = shift;
+  my $element = shift;
+
+  my $text = Texinfo::Convert::Text::convert_to_text($element,
+                                $self->{'convert_text_options'});
+  return $text;
+}
+
+sub highlight_cmd_preformatted_command($$$$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $command = shift;
+  my $args = shift;
+  my $content = shift;
+  my $result = shift @highlight_result;
+
+  if (!defined($result)) {
+    # Use the default conversion if there is no highlight to this command
+    return &{$self->default_command_conversion($cmdname)}($self, $cmdname,
+                                                 $command, $args, $content);
+  }
+
+  # extract the language from the @example command
+  # The language is always the first element.
+  my $language
+     = 
Texinfo::Convert::NodeNameNormalization::convert_to_normalized(@{$command->{'args'}}[0]);
+
+  my $div_classes = ["example", "user-" . $language];
+  my @pre_classes = qw(example-preformatted);
+
+  # In case the command produces the pre tag, extract its classes and removes
+  # the pre tag.
+  if ($result =~ m/<pre.*class=(?:([A-z]*?)(?: 
.*>|>)|(?:"(.*?)")|(?:'(.*?)'))/gi) {
+    push @pre_classes, $1 || $2 || $3;
+  }
+
+  $result =~ s/<pre.*?>//gi;
+  $result =~ s/<\/pre.*?>//gi;
+
+  return $self->html_attribute_class('div', $div_classes).">\n"
+    .$self->html_attribute_class('pre', \@pre_classes).">\n"
+      .$result."</pre>\n</div>";
+}
diff --git a/tp/tests/Makefile.onetst b/tp/tests/Makefile.onetst
index 4841a4a973..c7b385f235 100644
--- a/tp/tests/Makefile.onetst
+++ b/tp/tests/Makefile.onetst
@@ -145,6 +145,8 @@ type_other_one_test_files_generated_list =  \
     test_scripts/other_highlight_syntax_example_highlight.sh \
     test_scripts/other_highlight_syntax_example_default_language.sh \
     test_scripts/other_highlight_syntax_example_latin9.sh \
+    test_scripts/other_highlight_syntax_cmd_example.sh \
+    test_scripts/other_highlight_syntax_cmd_example.sh \
     test_scripts/other_index_collation_test_plaintext.sh \
     test_scripts/other_index_collation_test_collation_language.sh \
     test_scripts/other_index_collation_test_collation_locale_en.sh \
diff --git a/tp/tests/other/custom_highlighter.pl 
b/tp/tests/other/custom_highlighter.pl
new file mode 100755
index 0000000000..2b84c628c3
--- /dev/null
+++ b/tp/tests/other/custom_highlighter.pl
@@ -0,0 +1,37 @@
+#! /usr/bin/env perl
+
+# custom_highlighter: a dummy implementation for a highligther
+#
+# Copyright 2010-2024 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License,
+# or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Original author: Carlos Maniero <[email protected]>
+
+use 5.006;
+
+use strict;
+
+my $lang = $ARGV[0];
+
+print "<pre class=\"highlight-$lang\">\n";
+foreach my $line (<STDIN>) {
+  chomp($line);
+  if ($line) {
+    print "<div>$line</div>\n";
+  } else {
+    print "\n";
+  }
+}
+print "</pre>";
diff --git a/tp/tests/other/highlight_cmd_example.texi 
b/tp/tests/other/highlight_cmd_example.texi
new file mode 100644
index 0000000000..e9efb8ec6a
--- /dev/null
+++ b/tp/tests/other/highlight_cmd_example.texi
@@ -0,0 +1,36 @@
+\input texinfo @c -*-texinfo-*-
+
+@node Top
+@top top
+
+@node chapter
+@chapter châp
+
+Texinfo
+@example texinfo
+@code{texinfo}
+@@code@{protécted@}
+@end example
+
+C
+@example c
+int main() @{
+    return 0;
+@}
+@end example
+
+No argument
+@example
+texinfo_set_from_init_file('NO_CSS', 1);
+@end example
+
+perl
+@example perl
+my $list = ['ça', 'bôù', 'é', '@'e @ogonek{a} @euro{} @equiv{}'];
+sub do ($) @{
+  my $arg = shift;
+  return $arg + 4;
+@}
+@end example
+
+@bye
diff --git a/tp/tests/other/list-of-tests b/tp/tests/other/list-of-tests
index 963befe46b..13effe9ee5 100644
--- a/tp/tests/other/list-of-tests
+++ b/tp/tests/other/list-of-tests
@@ -8,6 +8,10 @@ highlight_syntax_example_default_language 
highlight_example.texi --html -c HIGHL
 
 highlight_syntax_example_latin9 highlight_example.texi --html 
--init=highlight_syntax.pm -c 'OUTPUT_ENCODING_NAME=ISO-8859-15'
 
+# syntax highlighting command in examples
+
+highlight_syntax_cmd_example highlight_cmd_example.texi --html -c 
HIGHLIGHT_SYNTAX_CMD="source-highlight --src-lang"
+highlight_syntax_cmd_example highlight_cmd_example.texi --html -c 
HIGHLIGHT_SYNTAX_CMD="./other/custom_highlighter.pl"
 
 # collation
 
diff --git a/tp/tests/test_scripts/other_highlight_syntax_cmd_example.sh 
b/tp/tests/test_scripts/other_highlight_syntax_cmd_example.sh
new file mode 100755
index 0000000000..758e98b5ea
--- /dev/null
+++ b/tp/tests/test_scripts/other_highlight_syntax_cmd_example.sh
@@ -0,0 +1,25 @@
+#! /bin/sh
+# This file generated by maintain/regenerate_cmd_tests.sh
+
+if test z"$srcdir" = "z"; then
+  srcdir=.
+fi
+
+one_test_logs_dir=test_log
+
+
+
+if test "z$OTHER_TESTS" != z"yes"; then
+  echo "Skipping other tests that are not easily reproducible"
+  exit 77
+fi
+
+dir=other
+name='highlight_syntax_cmd_example'
+mkdir -p $dir
+
+"$srcdir"/run_parser_all.sh -dir $dir $name
+exit_status=$?
+cat $dir/$one_test_logs_dir/$name.log
+exit $exit_status
+
diff --git a/tp/texi2any.pl b/tp/texi2any.pl
index a5bc9a74d6..84e7e879ea 100755
--- a/tp/texi2any.pl
+++ b/tp/texi2any.pl
@@ -1366,6 +1366,12 @@ if ($cmdline_options->{'HIGHLIGHT_SYNTAX'}) {
                                  $internal_extension_dirs);
 }
 
+my $highlight_syntax_cmd_file = 'highlight_syntax_cmd.pm';
+if ($cmdline_options->{'HIGHLIGHT_SYNTAX_CMD'}) {
+  locate_and_load_extension_file($highlight_syntax_cmd_file,
+                                 $internal_extension_dirs);
+}
+
 # For tests, set some strings to values not changing with releases
 my %test_conf = (
     'PACKAGE_VERSION' => '',

base-commit: f7294c1143f8e93fdd53670ddd1a7b09293d2926
-- 
2.46.1


Reply via email to