M2HTML - Documentation System for Matlab M-files in HTML M2HTML by itself generates an HTML documentation of Matlab M-files in the current directory. HTML files are also written in the current directory. M2HTML('PropertyName1',PropertyValue1,'PropertyName2',PropertyValue2,...) sets multiple option values. The list of option names and default values is: o verbose - Verbose mode [ {on} | off ] o mFiles - Cell array of strings or character array containing the list of M-files and/or directories of M-files for which an HTML documentation will be built [ '.' ] o htmlDir - Top level directory for generated HTML files [ '.' ] o recursive - Process subdirectories [ on | {off} ] o matlabSource - Include Matlab source code in the HTML documentation [ {on} | off ] o syntaxHighlighting - Syntax Highlighting [ {on} | off ] o useHorizontalTabs - Replace '\t' in source code by n white space characters [ 0 ... {4} ... n ] o globalHypertextLinks - [ on | {off} ] o toDo - Create a TODO file in each directory summarizing all the '% TODO %' lines found in code [ on | {off}] o indexFile - Basename of the HTML index file [ 'index' ] o fileExtension - Extension of generated HTML files [ '.html' ] o template - HTML template name to use [ 'blue' ] See also TEMPLATE.
This function calls:
This function is called by:
0001 function m2html(varargin) 0002 %M2HTML - Documentation System for Matlab M-files in HTML 0003 % M2HTML by itself generates an HTML documentation of Matlab M-files in the 0004 % current directory. HTML files are also written in the current directory. 0005 % M2HTML('PropertyName1',PropertyValue1,'PropertyName2',PropertyValue2,...) 0006 % sets multiple option values. The list of option names and default values is: 0007 % o verbose - Verbose mode [ {on} | off ] 0008 % o mFiles - Cell array of strings or character array containing the 0009 % list of M-files and/or directories of M-files for which an HTML 0010 % documentation will be built [ '.' ] 0011 % o htmlDir - Top level directory for generated HTML files [ '.' ] 0012 % o recursive - Process subdirectories [ on | {off} ] 0013 % o matlabSource - Include Matlab source code in the HTML documentation 0014 % [ {on} | off ] 0015 % o syntaxHighlighting - Syntax Highlighting [ {on} | off ] 0016 % o useHorizontalTabs - Replace '\t' in source code by n white space 0017 % characters [ 0 ... {4} ... n ] 0018 % o globalHypertextLinks - [ on | {off} ] 0019 % o toDo - Create a TODO file in each directory summarizing all the 0020 % '% TODO %' lines found in code [ on | {off}] 0021 % o indexFile - Basename of the HTML index file [ 'index' ] 0022 % o fileExtension - Extension of generated HTML files [ '.html' ] 0023 % o template - HTML template name to use [ 'blue' ] 0024 % 0025 % See also TEMPLATE. 0026 0027 % Copyright (C) 2003 Guillaume Flandin <Guillaume.Flandin@sophia.inria.fr> 0028 % INRIA Sophia Antipolis / CEA-SHFJ 0029 % $Revision: 1.0 $Date: 2003/29/04 17:33:43 $ 0030 0031 % This program is free software; you can redistribute it and/or 0032 % modify it under the terms of the GNU General Public License 0033 % as published by the Free Software Foundation; either version 2 0034 % of the License, or any later version. 0035 % 0036 % This program is distributed in the hope that it will be useful, 0037 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0038 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0039 % GNU General Public License for more details. 0040 % 0041 % You should have received a copy of the GNU General Public License 0042 % along with this program; if not, write to the Free Software 0043 % Foundation Inc, 59 Temple Pl. - Suite 330, Boston, MA 02111-1307, USA. 0044 0045 % Suggestions for improvement and fixes are always welcome, although no 0046 % guarantee is made whether and when they will be implemented. 0047 % Send requests to Guillaume.Flandin@sophia.inria.fr 0048 0049 % For tips on how to write Matlab code, see: 0050 % * MATLAB Programming Style Guidelines, by R. Johnson: 0051 % <http://www.datatool.com/prod02.htm> 0052 % * For tips on creating help for your m-files 'type help.m'. 0053 % * Matlab documentation on M-file Programming: 0054 % <http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/ch10_pr9.shtml> 0055 0056 % This function uses the Template class so that you can fully customize 0057 % the output. You can modify .tpl files in templates/blue/ or create new 0058 % templates in a new directory. 0059 % See the template class documentation for more details. 0060 0061 % Other Matlab to HTML converters available on the web: 0062 % 1/ mat2html.pl, J.C. Kantor, in Perl, 1995: 0063 % <http://fresh.t-systems-sfr.com/unix/src/www/mat2html> 0064 % 2/ htmltools, B. Alsberg, in Matlab, 1997: 0065 % <http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=175> 0066 % 3/ mtree2html2001, H. Pohlheim, in Perl, 1996, 2001: 0067 % <http://www.pohlheim.com/perl_main.html#matlabdocu> 0068 % 4/ MatlabToHTML, T. Kristjansson, binary, 2001: 0069 % <http://www.psi.utoronto.ca/~trausti/MatlabToHTML/MatlabToHTML.html> 0070 % 5/ mdoc, Peter Brinkmann, Matlab, 2003: 0071 % <http://www.math.uiuc.edu/~brinkman/software/mdoc/> 0072 % 6/ Ocamaweb, Miriad Technologies, Ocaml, 2002: 0073 % <http://ocamaweb.sourceforge.net/> 0074 % 7/ Matdoc, Moshe Kaminsky, Matlab, 2003: 0075 % <http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=3498> 0076 % 8/ Matlab itself, The Mathworks Inc, with HELPWIN and DOC 0077 0078 %------------------------------------------------------------------------------- 0079 %- Set up options 0080 %------------------------------------------------------------------------------- 0081 msgInvalidPair = 'Invalid parameter/value pair arguments.'; 0082 if mod(nargin,2) 0083 error(msgInvalidPair); 0084 end 0085 0086 options = struct('verbose', 1,... 0087 'mFiles', {{'.'}},... 0088 'htmlDir', '.',... 0089 'recursive', 0,... 0090 'matlabSource', 1,... 0091 'syntaxHighlighting', 1,... 0092 'useHorizontalTabs',4,... 0093 'globalHypertextLinks', 0,... 0094 'toDo', 0,... 0095 'indexFile','index',... 0096 'fileExtension', '.html',... 0097 'template','blue'); 0098 for i=1:2:nargin 0099 switch(lower(varargin{i})) 0100 case {'verbose', 'v'} 0101 if strcmpi(varargin{i+1},'on') 0102 options.verbose = 1; 0103 elseif strcmpi(varargin{i+1},'off') 0104 options.verbose = 0; 0105 else 0106 error(msgInvalidPair); 0107 end 0108 case {'mfiles', 'm'} 0109 if iscellstr(varargin{i+1}) 0110 options.mFiles = varargin{i+1}; 0111 elseif ischar(varargin{i+1}) 0112 options.mFiles = cellstr(varargin{i+1}); 0113 else 0114 error(msgInvalidPair); 0115 end 0116 case {'htmldir', 'html'} 0117 if ischar(varargin{i+1}) 0118 if isempty(varargin{i+1}), 0119 options.htmlDir = '.'; 0120 else 0121 options.htmlDir = varargin{i+1}; 0122 end 0123 if isempty(dir(options.htmlDir)) 0124 %- Create the top level HTML directory 0125 if options.verbose 0126 fprintf('Creating directory %s...\n',options.htmlDir); 0127 end 0128 if options.htmlDir(end) == filesep, 0129 options.htmlDir(end) = []; 0130 end 0131 [pathdir, namedir] = fileparts(options.htmlDir); 0132 if isempty(pathdir) 0133 [status, msg] = mkdir(namedir); 0134 else 0135 [status, msg] = mkdir(pathdir, namedir); 0136 end 0137 error(msg); 0138 end 0139 else 0140 error(msgInvalidPair); 0141 end 0142 case {'recursive', 'r'} 0143 if strcmpi(varargin{i+1},'on') 0144 options.recursive = 1; 0145 elseif strcmpi(varargin{i+1},'off') 0146 options.recursive = 0; 0147 else 0148 error(msgInvalidPair); 0149 end 0150 case {'matlabsource', 'source'} 0151 if strcmpi(varargin{i+1},'on') 0152 options.matlabSource = 1; 0153 elseif strcmpi(varargin{i+1},'off') 0154 options.matlabSource = 0; 0155 else 0156 error(msgInvalidPair); 0157 end 0158 case {'syntaxhighlighting', 'highlight'} 0159 if strcmpi(varargin{i+1},'on') 0160 options.syntaxHighlighting = 1; 0161 elseif strcmpi(varargin{i+1},'off') 0162 options.syntaxHighlighting = 0; 0163 else 0164 error(msgInvalidPair); 0165 end 0166 case {'usehorizontaltabs', 'tab', 'tabs'} 0167 if varargin{i+1} >= 0 0168 options.useHorizontalTabs = varargin{i+1}; 0169 else 0170 error(msgInvalidPair); 0171 end 0172 case {'globalhypertextlinks', 'glinks', 'global'} 0173 if strcmpi(varargin{i+1},'on') 0174 options.globalHypertextLinks = 1; 0175 elseif strcmpi(varargin{i+1},'off') 0176 options.globalHypertextLinks = 0; 0177 else 0178 error(msgInvalidPair); 0179 end 0180 case {'todo'} 0181 if strcmpi(varargin{i+1},'on') 0182 options.toDo = 1; 0183 elseif strcmpi(varargin{i+1},'off') 0184 options.toDO = 0; 0185 else 0186 error(msgInvalidPair); 0187 end 0188 case {'indexfile', 'index'} 0189 if ischar(varargin{i+1}) 0190 options.indexFile = varargin{i+1}; 0191 else 0192 error(msgInvalidPair); 0193 end 0194 case {'fileextension', 'ext'} 0195 if ischar(varargin{i+1}) & varargin{i+1}(1) == '.' 0196 options.fileExtension = varargin{i+1}; 0197 else 0198 error(msgInvalidPair); 0199 end 0200 case {'template', 'tpl'} 0201 if ischar(varargin{i+1}) 0202 options.template = varargin{i+1}; 0203 else 0204 error(msgInvalidPair); 0205 end 0206 otherwise 0207 error(msgInvalidPair); 0208 end 0209 end 0210 0211 %------------------------------------------------------------------------------- 0212 %- Define a few variables 0213 %------------------------------------------------------------------------------- 0214 %- Delimiters used in strtok: some of them may be useless (% " .), removed '.' 0215 strtok_delim = sprintf(' \t\n\r(){}[]<>+-*~!|\\@&/,:;="''%%'); 0216 0217 %------------------------------------------------------------------------------- 0218 %- Get template files location 0219 %------------------------------------------------------------------------------- 0220 s = fileparts(which(mfilename)); 0221 options.template = fullfile(s,'templates',options.template); 0222 0223 %------------------------------------------------------------------------------- 0224 %- Get list of M-files 0225 %------------------------------------------------------------------------------- 0226 mfiles = getmfiles(options.mFiles,{},options.recursive); 0227 if ~length(mfiles), fprintf('Nothing to be done.\n'); return; end 0228 if options.verbose, 0229 fprintf('Found %d M-files.\n',length(mfiles)); 0230 end 0231 mfiles = sort(mfiles); % sort list of M-files in dictionary order 0232 0233 %------------------------------------------------------------------------------- 0234 %- Get list of (unique) directories and (unique) names 0235 %------------------------------------------------------------------------------- 0236 mdirs = {}; 0237 names = {}; 0238 for i=1:length(mfiles) 0239 [mdirs{i}, names{i}] = fileparts(mfiles{i}); 0240 if isempty(mdirs{i}), mdirs{i} = '.'; end 0241 end 0242 0243 mdir = unique(mdirs); 0244 if options.verbose, 0245 fprintf('Found %d unique Matlab directories.\n',length(mdir)); 0246 end 0247 name = names; 0248 %name = unique(names); % output is sorted 0249 if options.verbose, 0250 fprintf('Found %d unique Matlab identifiers.\n',length(name)); 0251 end 0252 0253 %------------------------------------------------------------------------------- 0254 %- Get synopsis, H1 line, script/function, subroutines, cross-references 0255 %------------------------------------------------------------------------------- 0256 synopsis = cell(size(mfiles)); 0257 h1line = cell(size(mfiles)); 0258 subroutine = cell(size(mfiles)); 0259 hrefs = sparse(length(mfiles),length(mfiles)); 0260 todo = struct('mfile',[],'line',[],'comment',{{}}); 0261 for i=1:length(mfiles) 0262 %- Open for reading the M-file 0263 if options.verbose 0264 fprintf('Processing file %s...\n',mfiles{i}); 0265 end 0266 fid = openfile(mfiles{i},'r'); 0267 it = 0; % line number 0268 %- Initialize Synopsis and H1 Line 0269 synopsis{i} = ''; 0270 h1line{i} = ''; 0271 %- Initialize flag for synopsis cont ('...') 0272 flagsynopcont = 0; 0273 %- Look for synopsis and H1 line 0274 % Help is the first set of contiguous comment lines in an m-file 0275 % The H1 line is a short one-line description into the first help line 0276 while 1 0277 tline = fgetl(fid); 0278 if ~ischar(tline), break, end 0279 it = it + 1; 0280 tline = deblank(fliplr(deblank(fliplr(tline)))); 0281 %- Synopsis line 0282 if ~isempty(strmatch('function',tline)) 0283 synopsis{i} = tline; 0284 if ~isempty(strmatch('...',fliplr(tline))) 0285 flagsynopcont = 1; 0286 synopsis{i} = deblank(synopsis{i}(1:end-3)); 0287 end 0288 %- H1 Line 0289 elseif ~isempty(strmatch('%',tline)) 0290 % allow for the help lines to be before the synopsis 0291 if isempty(h1line{i}) 0292 h1line{i} = fliplr(deblank(tline(end:-1:2))); 0293 end 0294 if ~isempty(synopsis{i}), break, end 0295 %- Go through empty lines 0296 elseif isempty(tline) 0297 0298 %- Code found. Stop. 0299 else 0300 if flagsynopcont 0301 if isempty(strmatch('...',fliplr(tline))) 0302 synopsis{i} = [synopsis{i} tline]; 0303 flagsynopcont = 0; 0304 else 0305 synopsis{i} = [synopsis{i} deblank(tline(1:end-3))]; 0306 end 0307 else 0308 break; 0309 end 0310 end 0311 end 0312 %- Global Hypertext Links option 0313 % If false, hypertext links are done only among functions in the same 0314 % directory. 0315 if options.globalHypertextLinks 0316 hrefnames = names; 0317 else 0318 indhref = find(strcmp(mdirs{i},mdirs)); 0319 hrefnames = {names{indhref}}; 0320 end 0321 %- Compute cross-references and extract subroutines 0322 % hrefs(i,j) is 1 if mfiles{i} calls mfiles{j} and 0 otherwise 0323 while ischar(tline) 0324 % Remove blanks at both ends 0325 tline = deblank(fliplr(deblank(fliplr(tline)))); 0326 0327 % Split code into meaningful chunks 0328 splitc = splitcode(tline); 0329 for j=1:length(splitc) 0330 if isempty(splitc{j}) | ... 0331 splitc{j}(1) == '''' | ... 0332 ~isempty(strmatch('...',splitc{j})) 0333 % Forget about empty lines, char strings or conts 0334 elseif splitc{j}(1) == '%' 0335 % Cross-references are not taken into account in comments 0336 % Just look for potential TODO line 0337 if options.toDo 0338 if ~isempty(strmatch('% TODO %',splitc{j})) 0339 todo.mfile = [todo.mfile i]; 0340 todo.line = [todo.line it]; 0341 todo.comment{end+1} = splitc{j}(9:end); 0342 end 0343 end 0344 else 0345 % detect if this line is a declaration of a subroutine 0346 if ~isempty(strmatch('function',splitc{j})) 0347 subroutine{i}{end+1} = splitc{j}; 0348 else 0349 % get list of variables and functions 0350 symbol = {}; 0351 while 1 0352 [t,splitc{j}] = strtok(splitc{j},strtok_delim); 0353 if isempty(t), break, end; 0354 symbol{end+1} = t; 0355 end 0356 if options.globalHypertextLinks 0357 hrefs(i,:) = hrefs(i,:) + ismember(hrefnames,symbol); 0358 else 0359 hrefs(i,indhref) = hrefs(i,indhref) + ... 0360 ismember(hrefnames,symbol); 0361 end 0362 end 0363 end 0364 end 0365 tline = fgetl(fid); 0366 it = it + 1; 0367 end 0368 fclose(fid); 0369 end 0370 hrefs = hrefs > 0; 0371 0372 %------------------------------------------------------------------------------- 0373 %- Setup the HTML directories 0374 %------------------------------------------------------------------------------- 0375 for i=1:length(mdir) 0376 if ~(exist(fullfile(options.htmlDir,mdir{i})) == 7) 0377 ldir = splitpath(mdir{i}); 0378 for j=1:length(ldir) 0379 if ~(exist(fullfile(options.htmlDir,ldir{1:j})) == 7) 0380 %- Create the HTML directory 0381 if options.verbose 0382 fprintf('Creating directory %s...\n',... 0383 fullfile(options.htmlDir,ldir{1:j})); 0384 end 0385 if j == 1 0386 [status, msg] = mkdir(options.htmlDir,ldir{1}); 0387 else 0388 [status, msg] = mkdir(options.htmlDir,fullfile(ldir{1:j})); 0389 end 0390 error(msg); 0391 end 0392 end 0393 end 0394 end 0395 0396 %------------------------------------------------------------------------------- 0397 %- Write the master index file 0398 %------------------------------------------------------------------------------- 0399 tpl_master = 'master.tpl'; 0400 tpl_master_identifier_nbyline = 4; 0401 0402 %- Create the HTML template 0403 tpl = template(options.template,'remove'); 0404 tpl = set(tpl,'file','TPL_MASTER',tpl_master); 0405 tpl = set(tpl,'block','TPL_MASTER','rowdir','rowdirs'); 0406 tpl = set(tpl,'block','TPL_MASTER','idrow','idrows'); 0407 tpl = set(tpl,'block','idrow','idcolumn','idcolumns'); 0408 0409 %- Open for writing the HTML master index file 0410 curfile = fullfile(options.htmlDir,[options.indexFile options.fileExtension]); 0411 if options.verbose 0412 fprintf('Creating HTML file %s...\n',curfile); 0413 end 0414 fid = openfile(curfile,'w'); 0415 0416 %- Set some template variables 0417 tpl = set(tpl,'var','DATE',[datestr(now,13) ' ' datestr(now,1)]); 0418 tpl = set(tpl,'var','MASTERPATH', './'); 0419 tpl = set(tpl,'var','DIRS', sprintf('%s ',mdir{:})); 0420 0421 %- Print list of unique directories 0422 for i=1:length(mdir) 0423 tpl = set(tpl,'var','L_DIR',... 0424 fullurl(mdir{i},[options.indexFile options.fileExtension])); 0425 tpl = set(tpl,'var','DIR',mdir{i}); 0426 tpl = parse(tpl,'rowdirs','rowdir',1); 0427 end 0428 0429 %- Print full list of M-files 0430 for i=1:length(names) 0431 tpl = set(tpl,'var','L_IDNAME',... 0432 fullurl(mdirs{i},[names{i} options.fileExtension])); 0433 tpl = set(tpl,'var','IDNAME',names{i}); 0434 tpl = parse(tpl,'idcolumns','idcolumn',1); 0435 if mod(i,tpl_master_identifier_nbyline) == 0 0436 tpl = parse(tpl,'idrows','idrow',1); 0437 tpl = set(tpl,'var','idcolumns',''); 0438 elseif i == length(names) 0439 tpl = parse(tpl,'idrows','idrow',1); 0440 end 0441 end 0442 0443 %- Print the template in the HTML file 0444 tpl = parse(tpl,'OUT','TPL_MASTER'); 0445 fprintf(fid,'%s',get(tpl,'OUT')); 0446 fclose(fid); 0447 0448 %------------------------------------------------------------------------------- 0449 %- Copy template files (CSS, images, ...) 0450 %------------------------------------------------------------------------------- 0451 % Get list of files 0452 d = dir(options.template); 0453 d = {d(~[d.isdir]).name}; 0454 % Copy files 0455 for i=1:length(d) 0456 [p, n, ext] = fileparts(d{i}); 0457 if ~strcmp(ext,'.tpl') % do not copy .tpl files 0458 if ~(exist(fullfile(options.htmlDir,d{i}))) 0459 if options.verbose 0460 fprintf('Copying template file %s...\n',d{i}); 0461 end 0462 [status, errmsg] = copyfile(fullfile(options.template,d{i}),... 0463 options.htmlDir); 0464 error(errmsg); 0465 end 0466 end 0467 end 0468 0469 %------------------------------------------------------------------------------- 0470 %- Write an index for each HTML directory 0471 %------------------------------------------------------------------------------- 0472 tpl_mdir = 'mdir.tpl'; 0473 tpl_mdir_link = '<a href="%s">%s</a>'; 0474 0475 %- Create the HTML template 0476 tpl = template(options.template,'remove'); 0477 tpl = set(tpl,'file','TPL_MDIR',tpl_mdir); 0478 tpl = set(tpl,'block','TPL_MDIR','row-m','rows-m'); 0479 tpl = set(tpl,'block','TPL_MDIR','row-other','rows-other'); 0480 tpl = set(tpl,'block','TPL_MDIR','subdir','subdirs'); 0481 tpl = set(tpl,'block','TPL_MDIR','todolist','todolists'); 0482 tpl = set(tpl,'var','DATE',[datestr(now,13) ' ' datestr(now,1)]); 0483 0484 for i=1:length(mdir) 0485 %- Open for writing each HTML directory index file 0486 curfile = fullfile(options.htmlDir,mdir{i},... 0487 [options.indexFile options.fileExtension]); 0488 if options.verbose 0489 fprintf('Creating HTML file %s...\n',curfile); 0490 end 0491 fid = openfile(curfile,'w'); 0492 0493 %- Set template fields 0494 tpl = set(tpl,'var','INDEX', [options.indexFile options.fileExtension]); 0495 tpl = set(tpl,'var','MASTERPATH',backtomaster(mdir{i})); 0496 tpl = set(tpl,'var','MDIR', mdir{i}); 0497 0498 %- Display Matlab m-files and their H1 line 0499 tpl = set(tpl,'var','rows-m',''); 0500 for j=1:length(mdirs) 0501 if strcmp(mdirs{j},mdir{i}) 0502 tpl = set(tpl,'var','L_NAME', [names{j} options.fileExtension]); 0503 tpl = set(tpl,'var','NAME', names{j}); 0504 tpl = set(tpl,'var','H1LINE', h1line{j}); 0505 tpl = parse(tpl,'rows-m','row-m',1); 0506 end 0507 end 0508 0509 %- Display other Matlab-specific files (.mat,.mdl,.p) 0510 tpl = set(tpl,'var','rows-other',''); 0511 w = what(mdir{i}); 0512 w = w(1); 0513 for j=1:length(w.mat) 0514 tpl = set(tpl,'var','OTHERFILE',w.mat{j}); 0515 tpl = parse(tpl,'rows-other','row-other',1); 0516 end 0517 for j=1:length(w.mdl) 0518 tpl = set(tpl,'var','OTHERFILE',w.mdl{j}); 0519 tpl = parse(tpl,'rows-other','row-other',1); 0520 end 0521 for j=1:length(w.p) 0522 tpl = set(tpl,'var','OTHERFILE',w.p{j}); 0523 tpl = parse(tpl,'rows-other','row-other',1); 0524 end 0525 0526 %- Display subsequent directories and classes 0527 tpl = set(tpl,'var','subdirs',''); 0528 d = dir(mdir{i}); 0529 d = {d([d.isdir]).name}; 0530 d = {d{~ismember(d,{'.' '..'})}}; 0531 for j=1:length(d) 0532 if ismember(fullfile(mdir{i},d{j}),mdir) 0533 tpl = set(tpl,'var','SUBDIRECTORY',... 0534 sprintf(tpl_mdir_link,... 0535 fullurl(d{j},[options.indexFile options.fileExtension]),d{j})); 0536 else 0537 tpl = set(tpl,'var','SUBDIRECTORY',d{j}); 0538 end 0539 tpl = parse(tpl,'subdirs','subdir',1); 0540 end 0541 0542 %- Link to the TODO list if necessary 0543 tpl = set(tpl,'var','todolists',''); 0544 if options.toDo 0545 if ~isempty(intersect(find(strcmp(mdir{i},mdirs)),todo.mfile)) 0546 tpl = set(tpl,'var','LTODOLIST',['todo' options.fileExtension]); 0547 tpl = parse(tpl,'todolists','todolist',1); 0548 end 0549 end 0550 0551 %- Print the template in the HTML file 0552 tpl = parse(tpl,'OUT','TPL_MDIR'); 0553 fprintf(fid,'%s',get(tpl,'OUT')); 0554 fclose(fid); 0555 end 0556 0557 %------------------------------------------------------------------------------- 0558 %- Write a TODO list file for each HTML directory, if necessary 0559 %------------------------------------------------------------------------------- 0560 tpl_todo = 'todo.tpl'; 0561 0562 %- Create the HTML template 0563 tpl = template(options.template,'remove'); 0564 tpl = set(tpl,'file','TPL_TODO',tpl_todo); 0565 tpl = set(tpl,'block','TPL_TODO','filelist','filelists'); 0566 tpl = set(tpl,'block','filelist','row','rows'); 0567 tpl = set(tpl,'var','DATE',[datestr(now,13) ' ' datestr(now,1)]); 0568 0569 if options.toDo 0570 for i=1:length(mdir) 0571 mfilestodo = intersect(find(strcmp(mdir{i},mdirs)),todo.mfile); 0572 if ~isempty(mfilestodo) 0573 %- Open for writing each TODO list file 0574 curfile = fullfile(options.htmlDir,mdir{i},... 0575 ['todo' options.fileExtension]); 0576 if options.verbose 0577 fprintf('Creating HTML file %s...\n',curfile); 0578 end 0579 fid = openfile(curfile,'w'); 0580 0581 %- Set template fields 0582 tpl = set(tpl,'var','INDEX',[options.indexFile options.fileExtension]); 0583 tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i})); 0584 tpl = set(tpl,'var','MDIR', mdir{i}); 0585 0586 for k=1:length(mfilestodo) 0587 tpl = set(tpl,'var','MFILE',names{mfilestodo(k)}); 0588 tpl = set(tpl,'var','rows',''); 0589 nbtodo = find(todo.mfile == mfilestodo(k)); 0590 for l=1:length(nbtodo) 0591 tpl = set(tpl,'var','L_NBLINE',... 0592 [names{mfilestodo(k)} ... 0593 options.fileExtension ... 0594 '#l' num2str(todo.line(nbtodo(l)))]); 0595 tpl = set(tpl,'var','NBLINE',num2str(todo.line(nbtodo(l)))); 0596 tpl = set(tpl,'var','COMMENT',todo.comment{nbtodo(l)}); 0597 tpl = parse(tpl,'rows','row',1); 0598 end 0599 tpl = parse(tpl,'filelists','filelist',1); 0600 end 0601 0602 %- Print the template in the HTML file 0603 tpl = parse(tpl,'OUT','TPL_TODO'); 0604 fprintf(fid,'%s',get(tpl,'OUT')); 0605 fclose(fid); 0606 end 0607 end 0608 end 0609 0610 %------------------------------------------------------------------------------- 0611 %- Write an HTML file for each M-file 0612 %------------------------------------------------------------------------------- 0613 %- List of Matlab keywords (output from iskeyword) 0614 matlabKeywords = {'break', 'case', 'catch', 'continue', 'elseif', 'else', ... 0615 'end', 'for', 'function', 'global', 'if', 'otherwise', ... 0616 'persistent', 'return', 'switch', 'try', 'while'}; 0617 %'keyboard', 'pause', 'eps', 'NaN', 'Inf' 0618 0619 tpl_mfile = 'mfile.tpl'; 0620 0621 tpl_mfile_code = '<a href="%s" class="code" title="%s">%s</a>'; 0622 tpl_mfile_keyword = '<span class="keyword">%s</span>'; 0623 tpl_mfile_comment = '<span class="comment">%s</span>'; 0624 tpl_mfile_string = '<span class="string">%s</span>'; 0625 tpl_mfile_aname = '<a name="%s" href="#_subfunctions" class="code">%s</a>'; 0626 tpl_mfile_line = '%04d %s\n'; 0627 0628 %- Create the HTML template 0629 tpl = template(options.template,'remove'); 0630 tpl = set(tpl,'file','TPL_MFILE',tpl_mfile); 0631 tpl = set(tpl,'block','TPL_MFILE','script','scriptfile'); 0632 tpl = set(tpl,'block','TPL_MFILE','crossrefcall','crossrefcalls'); 0633 tpl = set(tpl,'block','TPL_MFILE','crossrefcalled','crossrefcalleds'); 0634 tpl = set(tpl,'block','TPL_MFILE','subfunction','subfunctions'); 0635 tpl = set(tpl,'block','TPL_MFILE','nosubfunction','nosubf'); 0636 tpl = set(tpl,'block','TPL_MFILE','source','thesource'); 0637 tpl = set(tpl,'var','DATE',[datestr(now,13) ' ' datestr(now,1)]); 0638 0639 for i=1:length(mdir) 0640 for j=1:length(mdirs) 0641 if strcmp(mdirs{j},mdir{i}) 0642 0643 curfile = fullfile(options.htmlDir,mdir{i},... 0644 [names{j} options.fileExtension]); 0645 0646 %- Open for writing the HTML file 0647 if options.verbose 0648 fprintf('Creating HTML file %s...\n',curfile); 0649 end 0650 fid = openfile(curfile,'w'); 0651 0652 %- Open for reading the M-file 0653 fid2 = openfile(mfiles{j},'r'); 0654 0655 %- Set some template fields 0656 tpl = set(tpl,'var','INDEX', [options.indexFile options.fileExtension]); 0657 tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i})); 0658 tpl = set(tpl,'var','MDIR', mdirs{j}); 0659 tpl = set(tpl,'var','NAME', names{j}); 0660 tpl = set(tpl,'var','H1LINE', h1line{j}); 0661 tpl = set(tpl,'var','scriptfile', ''); 0662 if isempty(synopsis{j}) 0663 tpl = set(tpl,'var','SYNOPSIS',get(tpl,'var','script')); 0664 else 0665 tpl = set(tpl,'var','SYNOPSIS', synopsis{j}); 0666 end 0667 0668 %- Set description template field 0669 descr = ''; 0670 flagsynopcont = 0; 0671 flag_seealso = 0; 0672 while 1 0673 tline = fgets(fid2); 0674 if ~ischar(tline), break, end 0675 tline = entity(fliplr(deblank(fliplr(tline)))); 0676 %- Synopsis line 0677 if ~isempty(strmatch('function',tline)) 0678 if ~isempty(strmatch('...',fliplr(deblank(tline)))) 0679 flagsynopcont = 1; 0680 end 0681 %- H1 line and description 0682 elseif ~isempty(strmatch('%',tline)) 0683 %- Hypertext links on the "See also" line 0684 ind = findstr(lower(tline),'see also'); 0685 if ~isempty(ind) | flag_seealso 0686 %- "See also" only in files in the same directory 0687 indsamedir = find(strcmp(mdirs{j},mdirs)); 0688 hrefnames = {names{indsamedir}}; 0689 r = deblank(tline); 0690 flag_seealso = 1; %(r(end) == ','); 0691 tline = ''; 0692 while 1 0693 [t,r,q] = strtok(r,sprintf(' \t\n\r.,;%%')); 0694 tline = [tline q]; 0695 if isempty(t), break, end; 0696 ii = strcmpi(hrefnames,t); 0697 if any(ii) 0698 jj = find(ii); 0699 tline = [tline sprintf(tpl_mfile_code,... 0700 [hrefnames{jj(1)} options.fileExtension],... 0701 synopsis{indsamedir(jj(1))},t)]; 0702 else 0703 tline = [tline t]; 0704 end 0705 end 0706 tline = sprintf('%s\n',tline); 0707 end 0708 descr = [descr tline(2:end)]; 0709 elseif isempty(tline) 0710 if ~isempty(descr), break, end; 0711 else 0712 if flagsynopcont 0713 if isempty(strmatch('...',fliplr(deblank(tline)))) 0714 flagsynopcont = 0; 0715 end 0716 else 0717 break; 0718 end 0719 end 0720 end 0721 tpl = set(tpl,'var','DESCRIPTION',... 0722 horztab(descr,options.useHorizontalTabs)); 0723 0724 %- Set cross-references template fields: 0725 ind = find(hrefs(j,:) == 1); 0726 tpl = set(tpl,'var','crossrefcalls',''); 0727 for k=1:length(ind) 0728 if strcmp(mdirs{j},mdirs{ind(k)}) 0729 tpl = set(tpl,'var','L_NAME_CALL', ... 0730 [names{ind(k)} options.fileExtension]); 0731 else 0732 tpl = set(tpl,'var','L_NAME_CALL', ... 0733 fullurl(backtomaster(mdirs{j}), ... 0734 mdirs{ind(k)}, ... 0735 [names{ind(k)} options.fileExtension])); 0736 end 0737 tpl = set(tpl,'var','NAME_CALL', names{ind(k)}); 0738 tpl = set(tpl,'var','H1LINE_CALL', h1line{ind(k)}); 0739 tpl = parse(tpl,'crossrefcalls','crossrefcall',1); 0740 end 0741 if isempty(ind), tpl = set(tpl,'var','crossrefcalls',''); end 0742 ind = find(hrefs(:,j) == 1); 0743 tpl = set(tpl,'var','crossrefcalleds',''); 0744 for k=1:length(ind) 0745 if strcmp(mdirs{j},mdirs{ind(k)}) 0746 tpl = set(tpl,'var','L_NAME_CALLED', ... 0747 [names{ind(k)} options.fileExtension]); 0748 else 0749 tpl = set(tpl,'var','L_NAME_CALLED', ... 0750 fullurl(backtomaster(mdirs{j}),... 0751 mdirs{ind(k)}, ... 0752 [names{ind(k)} options.fileExtension])); 0753 end 0754 tpl = set(tpl,'var','NAME_CALLED', names{ind(k)}); 0755 tpl = set(tpl,'var','H1LINE_CALLED', h1line{ind(k)}); 0756 tpl = parse(tpl,'crossrefcalleds','crossrefcalled',1); 0757 end 0758 if isempty(ind), tpl = set(tpl,'var','crossrefcalleds',''); end 0759 0760 %- Set subfunction template field 0761 tpl = set(tpl,'var','subfunctions',''); 0762 if isempty(subroutine{j}) 0763 tpl = set(tpl,'var','nosubf',get(tpl,'var','nosubfunction')); 0764 else 0765 tpl = set(tpl,'var','nosubf',''); 0766 for k=1:length(subroutine{j}) 0767 tpl = set(tpl,'var','L_SUB', ['#_sub' num2str(k)]); 0768 tpl = set(tpl,'var','SUB', subroutine{j}{k}); 0769 tpl = parse(tpl,'subfunctions','subfunction',1); 0770 end 0771 end 0772 0773 %- Display source code with cross-references 0774 if options.matlabSource 0775 fseek(fid2,0,-1); 0776 it = 1; 0777 matlabsource = ''; 0778 nbsubroutine = 1; 0779 %- Get href function names of this file 0780 indhrefnames = find(hrefs(j,:) == 1); 0781 hrefnames = {names{indhrefnames}}; 0782 %- Loop over lines 0783 while 1 0784 tline = fgetl(fid2); 0785 if ~ischar(tline), break, end 0786 myline = ''; 0787 splitc = splitcode(entity(tline)); 0788 for k=1:length(splitc) 0789 if isempty(splitc{k}) 0790 elseif ~isempty(strmatch('function',splitc{k})) 0791 %- Subfunctions definition 0792 myline = [myline ... 0793 sprintf(tpl_mfile_aname,... 0794 ['_sub' num2str(nbsubroutine-1)],splitc{k})]; 0795 nbsubroutine = nbsubroutine + 1; 0796 elseif splitc{k}(1) == '''' 0797 myline = [myline ... 0798 sprintf(tpl_mfile_string,splitc{k})]; 0799 elseif splitc{k}(1) == '%' 0800 myline = [myline ... 0801 sprintf(tpl_mfile_comment,deblank(splitc{k}))]; 0802 elseif ~isempty(strmatch('...',splitc{k})) 0803 myline = [myline sprintf(tpl_mfile_keyword,'...')]; 0804 if ~isempty(splitc{k}(4:end)) 0805 myline = [myline ... 0806 sprintf(tpl_mfile_comment,splitc{k}(4:end))]; 0807 end 0808 else 0809 %- Look for keywords 0810 r = splitc{k}; 0811 while 1 0812 [t,r,q] = strtok(r,strtok_delim); 0813 myline = [myline q]; 0814 if isempty(t), break, end; 0815 %- Highlight Matlab keywords & 0816 % cross-references on known functions 0817 if options.syntaxHighlighting & ... 0818 any(strcmp(matlabKeywords,t)) 0819 if strcmp('end',t) 0820 rr = fliplr(deblank(fliplr(r))); 0821 icomma = strmatch(',',rr); 0822 isemicolon = strmatch(';',rr); 0823 if ~(isempty(rr) | ~isempty([icomma isemicolon])) 0824 myline = [myline t]; 0825 else 0826 myline = [myline sprintf(tpl_mfile_keyword,t)]; 0827 end 0828 else 0829 myline = [myline sprintf(tpl_mfile_keyword,t)]; 0830 end 0831 elseif any(strcmp(hrefnames,t)) 0832 indt = indhrefnames(logical(strcmp(hrefnames,t))); 0833 flink = [t options.fileExtension]; 0834 ii = ismember({mdirs{indt}},mdirs{j}); 0835 if ~any(ii) 0836 % take the first one... 0837 flink = fullurl(backtomaster(mdirs{j}),... 0838 mdirs{indt(1)}, flink); 0839 else 0840 indt = indt(logical(ii)); 0841 end 0842 myline = [myline sprintf(tpl_mfile_code,... 0843 flink, synopsis{indt(1)}, t)]; 0844 else 0845 myline = [myline t]; 0846 end 0847 end 0848 end 0849 end 0850 matlabsource = [matlabsource sprintf(tpl_mfile_line,it,myline)]; 0851 it = it + 1; 0852 end 0853 tpl = set(tpl,'var','SOURCECODE',... 0854 horztab(matlabsource,options.useHorizontalTabs)); 0855 tpl = parse(tpl,'thesource','source'); 0856 else 0857 tpl = set(tpl,'var','thesource',''); 0858 end 0859 tpl = parse(tpl,'OUT','TPL_MFILE'); 0860 fprintf(fid,'%s',get(tpl,'OUT')); 0861 fclose(fid2); 0862 fclose(fid); 0863 end 0864 end 0865 end 0866 0867 %=============================================================================== 0868 function mfiles = getmfiles(mdirs,mfiles,recursive) 0869 for i=1:length(mdirs) 0870 if exist(mdirs{i}) == 2 % M-file 0871 mfiles{end+1} = mdirs{i}; 0872 elseif exist(mdirs{i}) == 7 % Directory 0873 w = what(mdirs{i}); 0874 w = w(1); %- Sometimes an array is returned... 0875 for j=1:length(w.m) 0876 mfiles{end+1} = fullfile(mdirs{i},w.m{j}); 0877 end 0878 if recursive 0879 d = dir(mdirs{i}); 0880 d = {d([d.isdir]).name}; 0881 d = {d{~ismember(d,{'.' '..'})}}; 0882 for j=1:length(d) 0883 mfiles = getmfiles(cellstr(fullfile(mdirs{i},d{j})),... 0884 mfiles,recursive); 0885 end 0886 end 0887 else 0888 fprintf('Warning: Unprocessed file %s.\n',mdirs{i}); 0889 end 0890 end 0891 0892 %=============================================================================== 0893 function fid = openfile(filename,permission) 0894 [fid, errmsg] = fopen(filename,permission); 0895 if ~isempty(errmsg) 0896 switch permission 0897 case 'r' 0898 error(sprintf('Cannot open %s in read mode.',filename)); 0899 case 'w' 0900 error(sprintf('Cannot open %s in write mode.',filename)); 0901 otherwise 0902 error(errmsg); 0903 end 0904 end 0905 0906 %=============================================================================== 0907 function s = backtomaster(mdir) 0908 ldir = splitpath(mdir); 0909 s = repmat('../',1,length(ldir)); 0910 0911 %=============================================================================== 0912 function ldir = splitpath(p) 0913 ldir = {}; 0914 p = deblank(p); 0915 while 1 0916 [t,p] = strtok(p,filesep); 0917 if isempty(t), break; end 0918 if ~strcmp(t,'.') 0919 ldir{end+1} = t; 0920 end 0921 end 0922 if isempty(ldir) 0923 ldir{1} = '.'; % should be removed 0924 end 0925 0926 %=============================================================================== 0927 function f = fullurl(varargin) 0928 %FULLURL Build full url from parts (using '/' and not filesep) 0929 0930 f = strrep(fullfile(varargin{:}),'\','/'); 0931 0932 %=============================================================================== 0933 function str = entity(str) 0934 %- See http://www.w3.org/TR/html4/charset.html#h-5.3.2 0935 str = strrep(str,'&','&'); 0936 str = strrep(str,'<','<'); 0937 str = strrep(str,'>','>'); 0938 str = strrep(str,'"','"'); 0939 0940 %=============================================================================== 0941 function str = horztab(str,n) 0942 %- For browsers, the horizontal tab character is the smallest non-zero 0943 %- number of spaces necessary to line characters up along tab stops that are 0944 %- every 8 characters: behaviour obtained when n = 0. 0945 if n > 0 0946 str = strrep(str,sprintf('\t'),blanks(n)); 0947 end