function [mscript, html_code] = wg_publish(m_function_file, destination_format, destination_directory)
% WG_PUBLISH Publishes a m-function or script.
% Reads the comments within a m-function. It marks them up and extends them
% whenever necessary. It automatically creates the syntax and several
% headings. It also specified (%+) examples and even includes the
% graphics.
%
% Extra care was taken of LaTeX formulas.
%
% First the m-function is converted into a Matlab script. Then Matlab's
% pulish function is executed.
% In case the destination format is html, the 'see also' functions are
% enabled.
%
% This function is easy to adapt.
% Keywords for headings can be easily added, aswell as bold words. This
% should be done within the source code.
%
% If you need to generate help for an entire directory use |wg_publish_dir|.
% In case you have to create the help for a directory and all its
% subdirectories use |wg_publish_all|.
%
% Input:
% * (optional) m_function_file ... Matlab function file (path is not required)
% * (optional) destination_format ... 'doc','html' (default), 'latex', 'ppt', 'xml'
% * (optional) destination_directory ... folder where to place the published file
% (default: directory of the chosen m-file plus subdirectory named by the destination format).
%
% Output:
% * scripts and help files in the destination directory
% * mscript ... Matlab script containing the header of a m function (as
% cell array of strings)
% * html_code ... a cell array of strings containing the html code.
%
% Example
% Create help for any file
% |wg_publish( 'wg_publish.m' );|
%
% Generate a help file in the html subfolder for the specified file.
% |wg_publish( 'getAllDir.m' );|
%
% To create the file in latex format:
% |wg_publish( 'getAllDir.m','latex' );|
%
% To save the help file into the current folder just write:
% |wg_publish( 'getAllDir.m','html',pwd );|
%
%
% See also: publish, wg_publish_dir, wg_publish_all, create_index_html
%
%% Signature
% Author: W.Garn
% E-Mail: wgarn@yahoo.com
% Date: 2005/12/01 20:00:00
%
% Copyright 2005 W.Garn
%
% ToDo:
% * Improve the *see also* function to internal functions.
% It does not seem to work well with functions like sin, strfind.
% * No help for *Subfunctions* is generated.
% * Sometimes odd things occure with the formating.
%
if nargin<1
[file, path] = uigetfile('*.m','Select file to be published ...');
if ischar(file)
m_function_file = [path file];
wg_publish(m_function_file);
web([path 'html\' getFileName(file) '.html']);
end
%m_function_file = 'pgraph.m';
end
persistent recursion
if nargin<2
destination_format = 'html';
end
if nargin<3
dirFlag=0;
else
dirFlag=1;
if ~exist(destination_directory,'dir')
mkdir(destination_directory);
end
if ~ismember( destination_directory(length(destination_directory)),{'/','\'})
destination_directory = [destination_directory '/'];
end
end
if nargin>0
keyword = {'Syntax', 'Description','Arguments', 'Example',...
'Definition','See also:', 'To Do', 'ToDo'};
% Note: I think its a good idea to do the %% keyword highlighting already inside the m function.
bold_words = {'Input:','Output:'}; % including new line
bold_bullet_words = {'Author','Date:',...
'E-Mail','Email',...
'Copyright','Copyright(C)'};
% Notes: Date is critical
bw_ext = {'(s) :','(s):','(s)','s:',':','s'};% the bold words will automatically be extended by follwing extensions
% bold words are also bulleted
poptions.format = destination_format;
poptions.maxWidth = 300; % Image adjustments
poptions.maxHeight = 400;
poptions.figureSnapMethod = 'getframe'; %'print' does not work all the time
logFlag=0;fid_log=1;
if logFlag, fprintf(fid_log,'Logging has started.\n');end
try
if ~isempty(recursion) % was called before, hence terminate
disp('Recursive call attempted.');
if logFlag, fprintf(fid_log,'Recursive call attempted.\n');end
if logFlag, fprintf(fid_log,'In case you debugged. \nGo after "persistent recursion" line and execute "recursion=[]".\n');end
else
recursion='avoid it';
line_end = [char(13) char(10)]; %[char(10) char(13)]; % or '\n'
[code, absfile, file, directory] = file2str(m_function_file); % Read in source.
% Behind this directory the publish and html folder are created
% unless the directory was as input specified.
if ischar(absfile) % then not cancled
if dirFlag,
poptions.outputDir = destination_directory;
else
poptions.outputDir = [directory destination_format '/'];
end
m_function_file=file; % correct it in any case.
if logFlag, fprintf(fid_log,'Source file read.\n');end
%---------------------------------------------------
% function title and parameters (input, output)
I=findstr(code{1},'function');
if isempty(I)
html_code = '';
if logFlag, fprintf(fid_log,'Script identified.\n');end
publish(absfile,poptions); % just use the Matlab publish function
if logFlag, fprintf(fid_log,'Script published.\n');end
if strcmp(destination_format, 'html')
absfile = [poptions.outputDir getFileName(m_function_file) '.' destination_format];
web(absfile);
if logFlag, fprintf(fid_log,'Script as html displayed.\n');end
end
mscript = code;
if strcmp(destination_format, 'html')
html_code = file2str(absfile);
if strcmp( getFileName(absfile), 'contents')
end
else
html_code = [];
end
else % start working
if logFlag, fprintf(fid_log,'m-function identified.\n');end
syntax = code{1}(I(1)+9:length(code{1}));
% after function or before '=' up to '(' or space
%Output
I=findstr(syntax,'=');
if ~isempty(I)
output = syntax(1:I(1)-1);
str = strtrim( syntax(I(1)+1:length(syntax)));
else
output =[];
str = syntax;
end
%Input
I=findstr(str,'(');
if ~isempty(I)
J=findstr(str,')');
function_name = str(1:I(1)-1);
input = str(I(1)+1:J(1)-1);
else
function_name = str;
input =[];
end
if logFlag, fprintf(fid_log,'First line disassmbled.\n');end
%---------------------------------------------------
continued_comment = 1; k = 2; m=1; comment={};
while k<=length(code) && continued_comment
line = strtrim(code{k}); %Hence % is always the first character!
if isempty(line) % treat empty lines
comment{m} = '%';
else
if line(1)~='%' % no comments in line
continued_comment = 0;
else
%comment{m} = line; % Version 1 - as is
if length(line)>1 % Version 2 - trimmed
if line(2)==' '
comment{m} = ['% ' strtrim(line(3:length(line)))]; % a trimmed line
% elseif ~ismember( line(2), {'+','%'})
% comment{m} = ['% ' strtrim(line(3:length(line)))]; % a trimmed line
else
comment{m} = line;
end
else
comment{m} = '%';
end
end
end
m=m+1;
k=k+1;
end
if logFlag, fprintf(fid_log,'All comments read (%i lines).\n',length(comment));end
syntaxFound=0; descriptionFound=0;
if length(comment)>0
%----------------------------------------------------------
% Check for all the keywords and mark them up (even repeatedly)
kw_line = zeros(1,length(comment));
for ckeyword=1:length(keyword)
for k=1:length(comment)
I = strfind( lower(comment{k}), lower(keyword{ckeyword}) ); % that is anywhere
% first word after comment
I = strfind( lower(strtrim(comment{k}(2:length(comment{k})))), lower(keyword{ckeyword}) ); % that is anywhere
if ~isempty(I)
if I(1)==1 % first word after comment
comment{k} = ['%%' comment{k}(2:length(comment{k}))];
kw_line(k) = 1;
switch keyword{ckeyword}
case 'See also:'
comment{k} = strrep(comment{k},'See also:',['See also' line_end '%'] );
case 'Syntax'
syntaxFound=1;
case 'Description'
descriptionFound=1;
end
end
end
end
end
if logFlag, fprintf(fid_log,'Keywords were checked.\n');end
%----------------------------------------------------------
% Check for bold words.
bwords = [bold_words bold_bullet_words];
for cword=1:length(bwords)
for k=1:length(comment)
I = strfind( lower(comment{k}), lower(bwords{cword}) );
if ~isempty(I)
rest = comment{k}(I(1)+length(bwords{cword}) : length(comment{k}));
bw_ext_found = 0; h=0; fext=''; %look for extensions
while h<length(bw_ext) && ~bw_ext_found
h=h+1;
extI = strfind( lower(rest), lower(bw_ext{h}) );
if ~isempty(extI)
bw_ext_found=1; fext = bw_ext{h};
end
end
if sum(ismember(bwords{cword},bold_words))
% just bold
%comment{k} = strrep(comment{k},[bwords{cword} fext],['*' bwords{cword} fext '*']);
% bold and new line
comment{k} = strrep(comment{k},[bwords{cword} fext],['*' bwords{cword} fext '*' line_end '%%']);
else
comment{k} = strrep(comment{k},[bwords{cword} fext],['* *' bwords{cword} fext '*']);
end
end
end
end
if logFlag, fprintf(fid_log,'Bold words were checked.\n');end
end % there were comments
%----------------------------------------------------------
% Header: Function name; First line description; Syntax; Description
header{1} = ['%% ' function_name];
clu=0; % code lines used
if length(comment)>0 % there are comments
if ~kw_line(1) % then its no keyword and there is a first line description.
% force proper format
if length(comment{1})>1
if comment{1}(2)~=' ', % then include whitespace
header{2}=['% ' comment{1}(2:length(comment{1}))];
else
header{2}=comment{1};
end
else % no comment - not nice
header{2}=comment{1};
end
clu=1;
else % there is a keyword in the first line, where a description is supposed to be
header{2}=comment{1}; % just write the line anyway (but without special formatting)
end
else % no comments at all
header{2}='%';
end
if ~syntaxFound
header{3}=['%% Syntax' line_end '% ' syntax];
end
% Description
if length(comment)>1 % there are comments
if ~descriptionFound && ~kw_line(1) && ~kw_line(2) % then all lines until next keyword are the description.
m = length(header)+1;
header{m} = '%% Description';
k=2; m=m+1;go_on=1;
while k<=length(kw_line) && go_on
if ~kw_line(k),
header{m} = comment{k};
else go_on=0; end
k=k+1;m=m+1;
end
clu = k-2;
end
else
% there are no comments at all
end
if logFlag, fprintf(fid_log,'Header was built.\n');end
script1 = [header comment{1+clu:length(comment)}];
%Example parser
script2 = IncludeExamples(script1);
if logFlag, fprintf(fid_log,'Scan for examples has finished.\n');end
%empty line declarationes
for k=2:length(script2)-1
change = 1; change_before = 1;
if length(script2{k})==1
% check for equations in next line and the line
% before
I = strfind ( script2{k+1}, '$$');
if ~isempty(I) % change if no equation in next line
if strcmp( strtrim( script2{k+1}(2:I(1)+1) ), '$$')
change = 0;
end
end
I = strfind ( script2{k-1}, '$$');
if ~isempty(I) % change if no equation in next line
if strcmp( strtrim( script2{k-1}(2:I(1)+1) ), '$$')
change_before = 0;
end
end
if change && change_before
if script2{k}(1)=='%', script2{k}='%%'; end
end
end
end
% Image formating (only one image in a line)
[row, col] = master_strfind(script2, '<<', '>>');
if ~isempty(row)
for k=1:length(row)
str = script2{row(k)};
% first part individual handling
if col(k) == 3 % then it begins with "% <<"
%(which should be the case because of previous trimming)
str = ['%%' line_end str];
else
str = strrep(str,'<<',[line_end '%%' line_end '% <<']);
end
% last part individual handling
if isLastPart( '>>', str)
str = [ str line_end '%%'];
else
str = strrep(str,'>>',['>>' line_end '%%' line_end]);
end
script2{row(k)} = str;
end
end
script_head = 'script_';
str2file(script2, [script_head getFileName(m_function_file) '.m'], poptions.outputDir);
if logFlag, fprintf(fid_log,'Transformation into script accomplished.\n');end
% There is LaTeX formating, hence graphic size restriction
% is not possible, because of a Matlab bug.
if strcmp('latex',destination_format)
absfile = [poptions.outputDir script_head strrep(m_function_file,'.m','.tex')];
% There is still a bug (R14 SP2) in the publish file (actually the imread),
% which does not allow any image resizing.
poptions = rmfield(poptions,'maxWidth');
poptions = rmfield(poptions,'maxHeight');
else % neverthelss there can be latex formulas
% The publish function is very particular with Latex
% equations: [% new line]{[$$ equation]}[% new line]
% [row, col] = master_strfind(script2, '$$', '$$');
% eq_ids = CreateEquations( script2(row) );
%
% if ~isempty(row)
% poptions = rmfield(poptions,'maxWidth');
% poptions = rmfield(poptions,'maxHeight');
% end
absfile = [poptions.outputDir script_head getFileName(m_function_file) '.' destination_format];
end
publish ( [poptions.outputDir script_head getFileName(m_function_file) '.m'], poptions );
if logFlag, fprintf(fid_log,'Script got published.\n');end
absfile_final = strrep_first(absfile,script_head,'');
movefile( absfile, absfile_final); % rename
%-------------------------------------------------------------------
% Change html file - implement the see also links
html_code = '';
if strcmp(poptions.format,'html')
try % at least try (since the publish function could change any time.
str = file2str(absfile_final); % get it.
% Look for <h2> and 'See also'
I = find_strfind(lower(str), '<h2>see also');
if ~isempty(I)
for k=1:length(I) % even repeated see also
line = I(k) +1 ; % line after see also heading line
start = strfind(str{line},'<p>') +3;
ends = strfind(str{line},'</p>')-1; % hopefully in the same line
token = allstrtok( str{line}(start:ends),',.;');
links = '';
%abs_dd = destination_directory;
if isempty(allSlashes(m_function_file))
abs_file = which(m_function_file);
else
abs_file = m_function_file;
end
for k=1:length(token)-1 % just make as link
abs_ref_file = which([token{k} '.m']);
% make ref file relative
[rel_ref_file_path level] = absFile2relFile(abs_ref_file,abs_file);
if level~=0,
links = [links '<a href="' rel_ref_file_path token{k} '.html">' token{k} '</a>, '];
else
links = [links '<a href="' token{k} '.html">' token{k} '</a>, '];
end
end
if length(token)>0 % last token
links = [links '<a href="' token{length(token)} '.html">' token{length(token)} '</a>'];
end
links_line = [str{line}(1:start-1) links str{line}(ends+1:length(str{line}))]; %pretty long line
str{line} = links_line;
end
end
% Look for 'Copyright' and 'Pulished with'
str = master_strrep(str, '<p class="footer">Copyright', '<br>', '<p class="footer">Copyright (C) 2005 W.Garn');
str = master_strrep(str, 'Published with Matlab', '<br>', 'Published with wg_publish; V1.0');
% Change the absolute paths of image files
str = strrep(str, strrep(poptions.outputDir,'/','\'), '');
% Change LaTeX formulas, which were not recognized.
eq_name = getFileName(absfile);
[eq_ids, location] = CreateEquations( str, [eq_name '.m'], [getDirs(absfile) 'equations'] );
% Replace Tex equations by image references.
k=1;
while k<=length(eq_ids)
line = str{location(k,1)};
before = line(1:location(k,2)-1);
last_pos = location(k,3)+1;
%
html_eq = ['<img src="equations/' eq_ids{k} '" align="middle">'];
% build multiple equations in a line
new_line = [before html_eq];
if k<length(eq_ids),
if location(k+1,1)== location(k,1), go = 1;
else go=0; end
else go =0; end
while go
before = line( location(k,3)+1 : location(k+1,2)-1);
html_eq = ['<img src="equations/' eq_ids{k+1} '" align="middle">'];
last_pos = location(k+1,3)+1;
new_line = [new_line before html_eq];
k=k+1;
if k<length(eq_ids), % the break version seems to be really better
if location(k+1,1)== location(k,1), go = 1;
else go=0; end
else go =0; end
end
rest = line(last_pos:length(line));
str{location(k,1)} = [new_line rest];
k = k+1;
end
html_code = str;
str2file(str,absfile_final); % write back to html
if logFlag, fprintf(fid_log,'Changes in html file were executed.\n');end
catch
disp('Could not change the html file successfully.');
if logFlag, fprintf(fid_log,'Could not change the html file successfully.\n');end
end
web( absfile_final );
if logFlag, fprintf(fid_log,'Tried or displayed final html page.\n');end
end %of html
%-------------------------------------------------------------------
mscript = script2; % just the output
end % of not file cancle operation
end % of recursion avoidance
recursion=[]; % allow call
if logFlag, fprintf(fid_log,'Finished script and document publication.\n\n');end
end
if logFlag, fprintf(fid_log,'No syntax errors occured.\n');end
catch
disp('Sorry - something went wrong.');
disp('Turn on the logFlag. ');
disp('Please send me an email containing the source file and log trace. ');
disp('wgarn@yahoo.com');
recursion=[]; % allow call
if logFlag, fprintf(fid_log,'Syntax error occured. That should never happen.\n');end
end
end
%-------------------------------------------------------------------
function strings = master_strrep(strings, search_start_str, search_end_str, rep_str)
% Look for string beginning with 'search_start_str' ending with
% 'search_end_str', if both are found then replace by rep_str
% Input:
% * strings ... a cell array of strings
% * search_start_str ... first string to be found
% * search_end_str ... second string to be found
% * rep_str ... string which replaces {search_start_str, string in between
% and search_end_str}.
%
% Output:
% * strings ... modified strings
%
[I, pos] = find_strfind(lower(strings), lower(search_start_str));
if ~isempty(I) % exists
for k=1:length(I)
J = strfind(strings{I(k)} , search_end_str);
if ~isempty(J) % does exist.
p = find(J>pos(1)); % the one wright after the string
strings{I(k)} = [strings{I(k)}(1:pos(1)-1) rep_str strings{I(k)}(J(p):length(strings{I(k)}))];
end
end
end
%-------------------------------------------------------------------
function [row, col] = master_strfind(strings, search_start_str, search_end_str)
% Look for string beginning with 'search_start_str' ending with
% 'search_end_str', if both are found then replace by rep_str
% Input:
% * strings ... a cell array of strings
% * search_start_str ... first string to be found
% * search_end_str ... second string to be found
%
% Output:
% * row ... vector of which cell entry contains the search start and end string
% * col ... at which position the first search start string begins
% (corresponding vector)
%
row=[];col=[];
[I, pos] = find_strfind(lower(strings), lower(search_start_str));
if ~isempty(I) % exists
j=1;
for k=1:length(I)
J = strfind(strings{I(k)} , search_end_str);
if ~isempty(J) % does exist.
%p = find(J>pos(1)); % the one wright after the string
%strings{I(k)} = [strings{I(k)}(1:pos(1)-1) rep_str strings{I(k)}(J(p):length(strings{I(k)}))];
crow{j} = I(k);
ccol{j} = pos(k);
j=j+1;
end
end
if j>1, row = cell2mat(crow); col = cell2mat(ccol); end
end
%-------------------------------------------------------------------
function tokens = allstrtok(str, delimiter)
% Returns all tokens of a string
% Input:
% * str ... String
% * delimiter ... a delimiter, or a character array of delimiters.
%
% Output:
% * tokens ... a cell array of string tokens
%
if nargin<2
tokens ={};
rem = str; k=1;
while true
[str, rem] = strtok(rem);
if isempty(str), break; end
tokens{k} = strtrim(str);
k=k+1;
end
else
tokens ={};
rem = str; k=1;
while true
[str, rem] = strtok(rem, delimiter);
if isempty(str), break; end
tokens{k} = strtrim(str);
k=k+1;
end
end
%-------------------------------------------------------------------
function script2 = IncludeExamples(script1)
% Looks for line identifiers and makes life easier.
%
line_identifier = {'%+','% *'}; % perhaps this requires a change.
line_end = [char(13) char(10)]; %[char(10) char(13)]; % or '\n'
for nb=1:length(line_identifier)
k=1;
while k<=length(script1)
% I = strfind(script1{k}, line_identifier{nb});
% if ~isempty(I) % indeed there is a line identifier
% because line identifiers must start at the beginning of the line
% the version below is better (since strtrim was done previously)
if length(script1{k})>=length(line_identifier{nb})
if strcmp(script1{k}(1:length(line_identifier{nb})), line_identifier{nb}) % indeed there is a line identifier
switch line_identifier{nb}
case '%+'
script1{k}=script1{k}(1+length(line_identifier{nb}):length(script1{k}));
%just get rid of identifier that's it.
case '% *'
% insert an empty line before and skip consecutive
% lines.
script1{k}=['%%' line_end script1{k}];
k=k+1;
% find consecutive lines
if k<=length(script1)
together=~isempty(strfind(script1{k}, line_identifier{nb}));
else
together=0;
end
%if together, script2{k}=script1{k}; end
while together && k+1<length(script1)
k = k+1;
if k<=length(script1)
together=~isempty(strfind(script1{k}, line_identifier{nb}));
else
together=0;
end
if together, script1{k}=script1{k}; end
% else script2{k-1}=[script1{k-1} line_end '%%']; end
% it is better to end a bulleting always with an
% empty line.
end
end % of switch
else % no line identifier
%script2{k}=script1{k};
end % of if identifier
end
k=k+1;
end % of script loop
end % of identifier loop
script2=script1;
%-------------------------------------------------------------------
function [I pos]= find_strfind(strings, what)
% FIND_STRFIND finds the indizis of strings containing 'what'.
% Input:
% * strings ... cell array of strings.
% * what ... string search for
% Output:
% * I ... inidzis
% * pos ... first position of what string
%
IA = strfind(strings,what);
I=[]; pos = []; m=1;
for k=1:length(strings)
if ~isempty(IA{k})
I(m) = k;
pos(m) = IA{k}(1);
m=m+1;
end
end
%-------------------------------------------------------------------
function str2file(str, file, directory)
if nargin<3
fid = fopen( file,'w' );
else
if directory(length(directory))== '/' || directory(length(directory))== '\',
directory = directory(1:length(directory)-1);
end
if ~exist(directory,'dir'), mkdir(directory); end
fid = fopen( [directory '/' file],'w' );
end
line_end = [char(13) char(10)]; %[char(10) char(13)]; % or '\n'
for k=1:length(str)
%fprintf(fid, [str{k} line_end]);
%fprintf(1, [str{k} line_end]);
fwrite(fid,[str{k} line_end], 'uchar');
end
fclose(fid);
%-------------------------------------------------------------------
function [str, fullPath, file, directory]= file2str(file)
go = 1;
str=[];fullPath=[]; directory=[];
[fullPath, directory] = locateFile(file);
if isempty(fullPath)
%disp('Can not find file.');
[file, directory] = uigetfile('*.m','Please select file.');
if ~ischar(file), go=0; end
fullPath = [directory file];
end
if go
% Read file into cell array of strings
fid = fopen(fullPath);
k=1;
while 1
str{k} = fgetl(fid);
if ~ischar(str{k}), break, end
k=k+1;
end
fclose(fid);
if k>1, str(k)=[]; end % delete last entry.
end %of go
%-------------------------------------------------------------------
function [fullPathToFile, directory] = locateFile(file)
% LOCATEFILE Resolve a filename to an absolute location.
% LOCATEFILE(FILE) returns the absolute path to FILE. If FILE cannot be
% found, it returns an empty string.
% original:Matthew J. Simoneau, November 2003
% Modified by W.Garn, Nov. 2005
% Checking that the length is exactly one in the first two checks automatically
% excludes directories, since directory listings always include '.' and '..'.
if (length(dir(fullfile(pwd,file))) == 1)
% Relative path.
fullPathToFile = fullfile(pwd,file);
elseif (length(dir(file)) == 1)
% Absolute path.
fullPathToFile = file;
elseif ~isempty(which(file))
% An m-file on the path.
fullPathToFile = which(file);
else
fullPathToFile = '';
end
if isempty(fullPathToFile)
directory='';
else
s = max(allSlashes(fullPathToFile));
if isempty(s)
directory='';
else
directory = fullPathToFile(1:s);
end
end
%-------------------------------------------------------------------
function str = strrep_first(str,to_find,rep_with)
I = strfind(str,to_find);
if ~isempty(I)
str = [str(1:I(1)-1) rep_with str(I(1)+length(to_find):length(str))];
end
function pos = allSlashes(str)
Ib = strfind(str,'\');
Is = strfind(str,'/');
pos = union(Ib,Is);
function reply = isLastPart( x, in_str )
% isLastPart - is x last part in string then reply yes or no.
len = length(in_str);
xlen = length(x);
if xlen<=len
reply = strcmp( in_str(len-xlen+1:len), x );
else % the input might have been in the wrong order
reply = 0;
end
function s = hashEquation(a)
% HASHEQUATION Converts an arbitrary string into one suitable for a filename.
% HASHEQUATION(A) returns a string usitable for a filename.
% Copyright 1984-2002 The MathWorks, Inc.
% $Revision: 1.1.6.2 $ $Date: 2003/02/25 07:52:37 $
%
% Note: Backtraced to adapt output, slowly I get the feeling I should rewrite the
% publish function. W.Garn
if isempty(a)
d = 0;
else
d = sum(a+(1:length(a))+(1:length(a)).^2);
end
s = sprintf('eq%.0f',d);
function [eq_ids, location] = CreateEquations( lines_with_equations, file_name, directory )
% Creates the equations using the publish function.
% The lines containing equations are traced. And all equations are written
% into a script. It is important that the equation ends in the same line!
%
% Input:
% * lines_with_equations ... lines containing equations (cell array of
% strings)
% * file_name ... file name (can contain extension)
% * directory ... destination path
%
% Output:
% * Filenames of equations ... This files are assembled by
% [file_name]_eq[hashEquation("$$equation$$")]
%
% Extract all equations and format them
line_end = [char(13) char(10)]; %[char(10) char(13)]; % or '\n'
eq_ids=[]; location=[];
[equations,location] = findEquations( lines_with_equations);
for count=1:length(equations)
equations{count} = ['%' line_end '% ' equations{count} line_end '%'];
% equations{count} = ['%' line_end '% ' '$$' equations{count} '$$' line_end '%'];
end
% Write them into the file
if ~isempty(equations)
str2file(['%% Equations', equations], file_name, directory);
options.outputDir = directory;
if directory(length(directory))~='/' || directory(length(directory))~='\'
directory = [directory '/'];
end
publish([directory file_name], options);
I = strfind(file_name,'.');
if ~isempty(I)
file_name = file_name(1:max(I)-1);
end
% Create eq_ids
eq_ids = cell(length(equations),1);
for k=1:length(equations)
% manually stripe header (5 characters) and footer (3 characters)!
eq_ids{k} = [file_name '_' hashEquation( equations{k}(6 : length(equations{k})-3) ) '.png'];
end
end
function [equations, location] = findEquations( lines_with_equations)
% Creates the equations using the publish function.
% The lines containing equations are traced. And all equations are written
% into a script. It is important that the equation ends in the same line!
%
% Input:
% * lines_with_equations ... lines containing equations (cell array of
% strings)
%
% Output:
% * equations ... strings containing only the equations
% * location ... row and $$ start column and $$ end column.
%
% Extract all equations and format them
count = 1; equations=[]; eq_ids=[]; location=[];
for k=1:length(lines_with_equations)
% Analyse each line
str = lines_with_equations{k};
I = strfind(str,'$$');
if ~isempty(I) % there is a equation identifier
if length(I)>1 % and at least one equation ends in the line.
for nb=1:floor(length(I)/2) % number of equations in line
clocation{count} = [k, I(2*(nb-1)+1), I(2*nb)+1];
equations{count} = str(clocation{count}(2) : clocation{count}(3) );
count = count+1;
end
end
end
end
if ~isempty(equations)
location = cell2mat(clocation');
end