Code covered by the BSD License  

Highlights from
Generate help files from m-files

image thumbnail
from Generate help files from m-files by Wolfgang Garn
Help files are generated from m-files.

wg_publish(m_function_file, destination_format, destination_directory)
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

Contact us at files@mathworks.com