// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) 2008-2009 - T. Pettersen
// Copyright (C) 2010 - DIGITEO - Allan CORNET
// Copyright (C) 2011 - DIGITEO - Michael Baudin
//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution. The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
//==============================================================================
function [helptxt,demotxt]=help_from_sci(funname,helpdir,demodir)
// Generate help files and demo files from the head comments section of a .sci source file.
//
// Calling Sequence
// help_from_sci() // generate an empty function template
// helptxt = help_from_sci() // generate an empty function template
// help_from_sci(funname,helpdir) // generate helpdir/funname.xml from funname.sci.
// help_from_sci(dirname,helpdir) // process dirname/*.sci and create helpdir/*.xml help files.
// help_from_sci(dirname,helpdir,demodir) // as above but also creating demodir/*.dem.sce demo files.
// [helptxt,demotxt]=help_from_sci(funname) // return funname.xml and funname.dem.sce code as two text matrixes.
// Parameters
// funname: the name of a single .sci source file to be processed.
// dirname: directory name where all .sci files will be processed.
// helpdir: optional path where the .xml help file will be created.
// demodir: optional path where .dem.sce demo files will be created based on code from the Examples section.
// helptxt: returns the XML help code if helpdir is empty, or the path to the .xml file.
// demotxt: returns the demo code if demodir is empty, or the path to the .dem.sce file.
//
// Description
// The help_from_sci function generates .xml help files based on the head comments section
// of .sci source files. Optionally .dem.sce demo files can be generated based on
// code from the Examples section in the head comments section of .sci files.
//
// In order for help_from_sci to format the .xml file properly the
// head comments section should comply with some simple formatting rules.
//
// The first comment line following the function definition should contain a short description
// of the function.
//
// The remaining comments are formatted according to the following (optional) headlines:
// "Calling Sequence", "Parameters", "Description", "Examples", "See also", "Used functions",
// "Authors" and "Bibliography".
//
// The following guidelines should be used when writing the source code comments:
//
// Calling Sequence - one example pr. line.
// Parameters - separate parameter name and
// description by a ":". Keep the description of each parameter on the same line.
// Description - formatting of the text can be done
// using XML commands. Compare the output of head_comments("help_from_sci") with help("help_from_sci")
// to get some hints.
// Adding an empty comment line in the Description section is interpreted as the
// start of a new paragraph.
// See also - list one function name pr line.
// Authors - write one author on each line following
// the Authors headline. Use ";" to separate the authors name
// from any add additional information.
// Bibliography - write one reference pr line
// following the References headline.
//
//
// Examples
// help_from_sci() // Open an empty source code template in the scinotes editor.
// // Save this template as test_fun.sci in the current directory before running
// // the next example commands.
//
// help_from_sci("test_fun") // return the xml skeleton as a text string
//
// help_from_sci("test_fun",".") // create the xml help file in the current directory.
//
// // create both a xml help file and a demo file in the current directory.
// help_from_sci("test_fun",".",".")
//
// // From a toolbox root directory a typical calling sequence would be:
// // help_from_sci("macros","help\en_US","demos")
// // This command would process all .sci files in the macros directory
// // and use the head comments section to update all .xml help files in the
// // help\en_US directory an rebuild the .dem.sce files in the demos\ directory.
//
// See also
// help
// help_skeleton
// head_comments
//
// Authors
// Copyright (C) 2008-2009 - T. Pettersen
// Copyright (C) 2010 - DIGITEO - Allan CORNET
// Copyright (C) 2011 - DIGITEO - Michael Baudin
if argn(2) == 0 then
helptxt = [..
"function [z] = function_template(x,y)"
"// Short description on the first line following the function header."
"//"
"// Calling Sequence"
"// [z] = template_function(x,y) // calling examples, one pr. line"
"//"
"// Parameters"
"// x: the x parameter // single line description of each parameter."
"// y: the y parameter // parameter name and description must be "
"// z: the z parameter // separated by "":""."
"//"
"// Description"
"// Here is a description of the function."
"// Add an empty comment line to format the text into separate paragraphs."
"//"
"// XML format commands may also be used directly in the text, "
"// as in the following examples."
"//"
"// This is an example of a itemized list:"
"// "
"// An itemized list is shown here"
"// "
"// The help text for help_from_sci was generated from the head comments section of help_from_sci.sci"
"// Compare the output from head_comments(""help_from_sci"") and help(""help_from_sci"")"
"// to see more examples on how to write the head comments section."
"//"
"// This is an example of the programlisting tag:"
"// z = test_fun(x, y)"
"//"
"// This is an example of a latex equation:"
"// "
"// \begin{eqnarray}"
"// m = |M| \beta^{1-p},"
"// \end{eqnarray}"
"// "
"//"
"// Examples"
"// [z] = test_fun(1, 2) // examples of use"
"//"
"// // An empty comment line in the Examples section will add a halt() statement"
"// // in the demo file test_fun.dem.sce generated by help_from_sci."
"//"
"// See also"
"// help_from_sci"
"// help_skeleton"
"//"
"// Authors"
"// Author name ; should be listed one pr line. Use "";"" to separate names from additional information "
"//"
"// Bibliography"
"// Literature references one pr. line"
""
"// start of coding after on empty line to mark the end of the head_comments section"
"z = sin(x).*cos(x + y);"
"endfunction"
];
mputl(helptxt, TMPDIR + filesep() + "function_template.sci");
if (isdef("editor") | (funptr("editor") <> 0)) then
editor(TMPDIR + filesep() + "function_template.sci");
end
[helptxt, demotxt] = help_from_sci("TMPDIR/function_template");
return;
end
if argn(2) < 3 then demodir = []; end
if argn(2) < 2 then helpdir = []; end
if ~isempty(demodir) & ~isdir(demodir) then
error(sprintf(gettext("%s: Wrong value for input argument #%d: A valid existing directory is expected.\n"), "help_from_sci", 3));
end
if isdir(funname) then
printf(gettext("%s: Reading from directory %s\n"), "help_from_sci", funname);
files = findfiles(funname, "*.sci"); // read *.sci files.
for i = 1:size(files, "r")
[tmp, out] = fileparts(files(i));
if isempty(helpdir) then
help_from_sci(funname + filesep() + files(i), ".", demodir);
printf(gettext("%s: Processing of file: %s to %s\n"), "help_from_sci", funname + "/" + out, out);
else
help_from_sci(funname + filesep() + files(i), helpdir, demodir);
printf(gettext("%s: Processing of file: %s to %s\n"), "help_from_sci", funname + "/" + out, helpdir + "/" + out);
end
if ~isempty(demodir) then
printf(gettext("%s: Processing of file: %s\n"), "help_from_sci" , demodir + "/" + out + ".dem.sce");
else
printf("\n");
end
end
printf(gettext("%s: processed %i files.\n"), "help_from_sci", i);
helptxt = "";
return;
end
out = tokens(pathconvert(funname), filesep());
out = out($);
out = tokens(out,".");
out = out(1); // remove .sci (...wont work for fil.name.sci)
demotxt = ["mode(1)"
"//"
"// Demo of "+out+".sci"
"//"
""];
verno = ver();
verno = verno(1,2);
helptxt = [
""
""
""
""
""
""
];
if isempty(strindex(funname, ".sci")) then funname = funname + ".sci"; end;
if isempty(fileinfo(funname)) then
error(sprintf(gettext("%s: The file %s does not exist.\n"),"help_from_sci",funname));
end;
f = mopen(funname, "rt");
if isempty(f) then
error(sprintf(gettext("%s: Cannot open file %s.\n"), "help_from_sci", funname + ".sci"));
end
line = " ";
doc = [];
while isempty(strindex(line, "function ")) & ~meof(f), line = mgetl(f, 1); end
line = mgetl(f,1);
line = replaceTabBySpace(line);
short_descr = stripblanks(strsubst(line, "//", ""), %T);
helptxt = [helptxt;
" "
" "+out+""
" "+short_descr+""
" "
];
cmds = ["CALLING SEQUENCE", "PARAMETERS", "DESCRIPTION", "EXAMPLES", "SEE ALSO", ..
"AUTHORS", "BIBLIOGRAPHY", "USED FUNCTIONS"];
doing = "search";
i = strindex(line, "//");
line = mgetl(f, 1);
line = replaceTabBySpace(line);
// Continue until empty line or end of file or a scilab command line (Bug#5487)
while (~isempty(stripblanks(line)) & ~meof(f)) & ~isempty(regexp(stripblanks(line),"/^\/\/*/"))
if stripblanks(line) == "//" then
if doing == "Description" then
in = "new_descr_param";
else
in = "";
end
else
in = strsplit(line, i(1) + 1);
in = stripblanks(in(2));
code = in; // store original line for the demos.
if (doing ~= "Examples") then // Replacing characters like <, > or & should not be done in the Examples
in = strsubst(in, "&", "&"); // remove elements that make xml crash.
in = strsubst(in, "< ", "< ");
if strindex(in ,"<") then
if ~helpfromsci_isxmlstr(in) then
in = strsubst(in, "<", "<");
end;
end
in = strsubst(in, " >", " >");
if strindex(in, ">") then
if ~helpfromsci_isxmlstr(in) then
in = strsubst(in, ">", ">");
end;
end
end
end
IN = convstr(in, "u");
if find(cmds == IN) then
[add_txt, doing] = change_activity(doing, in);
helptxt = [helptxt; add_txt];
else
if doing == "Calling Sequence" then
helptxt = [helptxt;" " + in];
elseif doing == "Parameters" then
i = strindex(in, ":");
if ~isempty(i) then
if length(in) > i(1) then
in = strsplit(in,i(1));
par_name = in(1);
par_descr = in(2);
else
par_name = in;
par_descr = " ";
end
helptxt = [helptxt; " " + par_name + ""];
helptxt = [helptxt;" " + par_descr + ""];
end
elseif doing == "Description" & in == "new_descr_param" then
helptxt = [helptxt;" ";" "];
elseif doing == "Description" then
helptxt = [helptxt; in];
elseif doing == "Examples" & convstr(in, "u") ~= "EXAMPLES" then
if isempty(stripblanks(in)) then
demotxt = [demotxt; "halt() // Press return to continue"; " "];
else
demotxt = [demotxt; code];
end
helptxt = [helptxt; in];
elseif doing == "See also" & convstr(in, "u") ~= "SEE ALSO" & ~isempty(stripblanks(in)) then
str = stripblanks(in);
i = strindex(str, " ");
if i <> [] then
str = stripblanks(strsplit(str, i(1)));
else
str = [str str];
end
helptxt = [helptxt; " " + str(2) + ""];
elseif doing == "Authors" & convstr(in, "u") ~= "AUTHORS" & ~isempty(stripblanks(in)) then
[name, ref] = chop(in, ";");
if isempty(ref) then
helptxt = [helptxt; " " + name + ""];
else
helptxt = [helptxt; " " + name + "" + ref + ""];
end
elseif doing == "Bibliography" & convstr(in, "u") ~= "BIBLIOGRAPHY" & ~isempty(stripblanks(in)) then
helptxt = [helptxt;" " + in + ""];
elseif doing == "Used functions" & convstr(in, "u") ~= "USED FUNCTIONS" & ~isempty(stripblanks(in)) then
helptxt = [helptxt;" " + in + ""];
end
end
line = mgetl(f,1);
line = replaceTabBySpace(line);
i = strindex(line, "//");
end
helptxt = [helptxt; change_activity(doing, "FINISHED")];
mclose(f);
if ~isempty(helpdir) then
fnme = pathconvert(helpdir, %t, %f) + out + ".xml";
answ = 1;
if isfile(fnme) then // file exists...
answ = messagebox(fnme + " exists!", "Warning - help_from_sci", "warning", ["Create anyway" "Skip file"], "modal");
end
if answ == 1 then
mputl(helptxt, fnme);
helptxt = fnme;
else
printf(gettext("%s: File skipped %s."), "help_from_sci", out + ".xml");
helptxt = "";
end
end
demotxt = [demotxt; "//========= E N D === O F === D E M O =========//"];
if ~isempty(demodir) then
fnme = demodir + filesep() + out + ".dem.sce";
answ = 1;
if isfile(fnme) then
answ = messagebox(fnme + " exists!", "Warning - help_from_sci", "warning", ["Create anyway" "Skip file"], "modal");
end
if answ == 1 then
mputl(demotxt, fnme);
demotxt = fnme;
else
printf(gettext("%s: File skipped %s."), "help_from_sci", out + ".demo.sce");
demotxt = "";
end
end
endfunction
//==============================================================================
function tf = helpfromsci_isxmlstr(str)
// Returns %t if the current string is a xml line
if ( ~isempty(regexp(str, "/\<*[a-z]\>/")) ) then
tf=%t
elseif ( ~isempty(regexp(str, "/\<(.*)\/\>/")) ) then
tf=%t
else
tf=%f
end
endfunction
//==============================================================================
function [head, tail] = chop(str, tok)
i = regexp(str, "/" + tok + "/", "o");
if isempty(i) then
head = str;
tail = [];
else
head = part(str, 1:i - 1);
tail = part(str, i + 1:length(str));
end
endfunction
//==============================================================================
function strOut = replaceTabBySpace(strIn)
strOut = strsubst(strIn, ascii(9), part(" ",1:4));
endfunction
//==============================================================================
function [txt, doing] = change_activity(currently_doing, start_doing)
doing = start_doing;
select convstr(currently_doing,"u")
case "CALLING SEQUENCE" then
txt = [" "; ""];
case "PARAMETERS" then
txt = [" "; ""];
case "DESCRIPTION" then
txt = [""; ""];
case "EXAMPLES" then
txt = [" ]]>"; ""];
case "SEE ALSO" then
txt = [" "; ""];
case "AUTHORS" then
txt = [" "; ""];
case "BIBLIOGRAPHY" then
txt = [""];
case "USED FUNCTIONS" then
txt = [""];
else
txt = "";
end
select convstr(start_doing, "u"),
case "CALLING SEQUENCE"
txt = [txt; ""; ""; " Calling Sequence"; " "];
case "PARAMETERS"
txt = [txt; ""; ""; " Parameters"; " "];
case "DESCRIPTION"
txt = [txt; ""; ""; " Description"; " "];
case "EXAMPLES"
txt = [txt; ""; ""; " Examples"; " "; " See also"; " "];
case "AUTHORS"
txt = [txt; ""; ""; " Authors"; " "];
case "BIBLIOGRAPHY"
txt = [txt; ""; ""; " Bibliography"];
case "USED FUNCTIONS"
txt = [txt; ""; ""; " Used functions"];
case "FINISHED"
txt = [txt; ""];
end
endfunction
//==============================================================================