1######################################################################## 2## 3## Copyright (C) 2009-2021 The Octave Project Developers 4## 5## See the file COPYRIGHT.md in the top-level directory of this 6## distribution or <https://octave.org/copyright/>. 7## 8## This file is part of Octave. 9## 10## Octave is free software: you can redistribute it and/or modify it 11## under the terms of the GNU General Public License as published by 12## the Free Software Foundation, either version 3 of the License, or 13## (at your option) any later version. 14## 15## Octave is distributed in the hope that it will be useful, but 16## WITHOUT ANY WARRANTY; without even the implied warranty of 17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18## GNU General Public License for more details. 19## 20## You should have received a copy of the GNU General Public License 21## along with Octave; see the file COPYING. If not, see 22## <https://www.gnu.org/licenses/>. 23## 24######################################################################## 25 26## -*- texinfo -*- 27## @deftypefn {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type}) 28## @deftypefnx {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type}, @var{fsee_also}) 29## Undocumented internal function. 30## @end deftypefn 31 32## Run @code{makeinfo} on a given text. 33## 34## The string @var{text} is run through the @code{__makeinfo__} program 35## to generate output in various formats. This string must contain valid 36## Texinfo formatted text. 37## 38## The @var{output_type} selects the format of the output. This can be either 39## @t{"html"}, @t{"texinfo"}, or @t{"plain text"}. By default this is 40## @t{"plain text"}. If @var{output_type} is @t{"texinfo"}, the @t{@@seealso} 41## macro is expanded, but otherwise the text is unaltered. 42## 43## If the optional argument @var{see_also} is present, it is used to expand the 44## Octave specific @t{@@seealso} macro. This argument must be a function 45## handle, that accepts a cell array of strings as input argument (each 46## elements of the array corresponds to the arguments to the @t{@@seealso} 47## macro), and return the expanded string. If this argument is not given, the 48## @t{@@seealso} macro will be expanded to the text 49## 50## @example 51## See also: arg1, arg2, ... 52## @end example 53## 54## @noindent 55## for @t{"plain text"} output, and 56## 57## @example 58## See also: @@ref@{arg1@}, @@ref@{arg2@}, ... 59## @end example 60## 61## @noindent 62## otherwise. 63## 64## The optional output argument @var{status} contains the exit status of the 65## @code{makeinfo} program as returned by @code{system}. 66 67function [retval, status] = __makeinfo__ (text, output_type = "plain text", fsee_also) 68 69 ## Check input 70 if (nargin < 1 || nargin > 3) 71 print_usage (); 72 endif 73 74 if (! ischar (text)) 75 error ("__makeinfo__: first input argument must be a string"); 76 endif 77 78 if (! ischar (output_type)) 79 error ("__makeinfo__: second input argument must be a string"); 80 endif 81 82 ## NOTE: The 3rd argument is used by Octave Forge function 83 ## generate_package_html, not by core Octave. This functionality 84 ## can only be removed when that function has been updated. 85 if (nargin < 3) 86 if (strcmpi (output_type, "plain text")) 87 fsee_also = @(T) ["\nSee also:", sprintf(" %s,", T{:})(1:end-1), "\n"]; 88 else 89 fsee_also = @(T) ["\nSee also:", sprintf(" @ref{%s},", T{:})(1:end-1), "\n"]; 90 endif 91 endif 92 93 if (! is_function_handle (fsee_also)) 94 error ("__makeinfo__: third input argument must be a function handle"); 95 endif 96 97 ## Formatting in m-files has an extra space at the beginning of every line. 98 ## Remove these unwanted spaces if present. First text char is "\n" delim. 99 if (text(2) == " ") 100 text = strrep (text, "\n ", "\n"); 101 endif 102 ## Texinfo crashes if @end tex does not appear first on the line. 103 text = regexprep (text, '^ +@end tex', '@end tex', 'lineanchors'); 104 text = regexprep (text, '@seealso', '@xseealso'); 105 106 ## We don't want *ref macros to clutter plain text output with "Note ..." 107 if (strcmp (output_type, "plain text")) 108 text = regexprep (text, '@ref{(?:[^}]*?),?(?:XREF)?([^,}]+)}', '$1'); 109 text = regexprep (text, '@xref{(?:[^}]*?),?(?:XREF)?([^,}]+)}', 'See $1'); 110 text = regexprep (text, '@pxref{(?:[^}]*?),?(?:XREF)?([^,}]+)}', 'see $1'); 111 endif 112 113 file = texi_macros_file (); 114 fid = fopen (file, "r"); 115 if (fid < 0) 116 error ("unable to open %s for reading", file); 117 else 118 macros_text = fread (fid, Inf, "*char")'; 119 text = [macros_text text]; 120 endif 121 fclose (fid); 122 123 if (strcmpi (output_type, "texinfo")) 124 status = 0; 125 retval = text; 126 return; 127 endif 128 129 ## Create the final TeXinfo input string 130 text = sprintf ("\\input texinfo\n\n%s\n\n@bye\n", text); 131 132 unwind_protect 133 ## Write Texinfo to tmp file 134 template = "octave-help-XXXXXX"; 135 [fid, name] = mkstemp (fullfile (tempdir, template), true); 136 if (fid < 0) 137 error ("__makeinfo__: could not create temporary file"); 138 endif 139 fprintf (fid, "%s", text); 140 fclose (fid); 141 142 ## Take action depending on output type 143 switch (lower (output_type)) 144 case "plain text" 145 cmd = sprintf ('%s --no-headers --no-warn --no-validate --plaintext --output=- "%s"', 146 makeinfo_program (), name); 147 case "html" 148 cmd = sprintf ('%s --no-headers --html --no-warn --no-validate --output=- "%s"', 149 makeinfo_program (), name); 150 otherwise 151 error ("__makeinfo__: unsupported output type: '%s'", output_type); 152 endswitch 153 154 ## Call makeinfo 155 [status, retval] = system (cmd); 156 157 ## On error, retry with force to ensure user gets *something* 158 if (status) 159 cmd = regexprep (cmd, '--output=', '--force --output=', 'once'); 160 [status_force, retval] = system (cmd); 161 ## original return value usually more useful 162 if (status_force) 163 status = status_force; 164 end 165 end 166 167 ## Clean up extra newlines generated by makeinfo 168 if (strcmpi (output_type, "plain text")) 169 if (numel (retval) > 2 && retval(end-1:end) == "\n\n") 170 retval = retval(1:end-2); 171 endif 172 endif 173 174 ## Clean up start of @deftypefn expansion which includes extra ':' 175 retval = regexprep (retval, '^ -- : +', ' -- ', "lineanchors"); 176 177 unwind_protect_cleanup 178 if (exist (name, "file")) 179 delete (name); 180 endif 181 end_unwind_protect 182 183endfunction 184 185 186## No test needed for internal helper function. 187%!assert (1) 188