source: prextra/prhelp2html.m @ 23

Last change on this file since 23 was 15, checked in by bduin, 14 years ago

updated

File size: 19.5 KB
Line 
1%PRHELP2HTML Construct HTML file from help part of PRTools routine
2%
3%               S = PRHELP2HTML(COMMAND,RECREATE,SUBDIR)
4%
5% INPUT
6%   COMMAND    String with PRTools command, default: all prtools m-files
7%   RECREATE   0/1 flag indicating whether non-existing references
8%              in the SEE ALSO section should be created as well
9%   SUBDIR     String with desired sub-directory in which the HTML
10%              file should be stored
11%
12% OUTPUT
13%   S          HTML code written to file, empty in case of error
14%
15% DESCRIPTION
16% This command takes the help part of a PRTools command and creates a HTML
17% file in the desired sub-directory. In case it is not given, a
18% sub-directory is used with the same name as the (sub-)directory of
19% COMMAND.
20%
21% In creating HTML code the following formatting rules apply:
22% - NAME is used for the title and the first heading
23% - There are (slightly) different rules for standard sections of the
24%   PRTools help:
25%   INPUT, OUTPUT, DESCRIPTION, REFERENCES, EXAMPLES, SEE ALSO
26% - New sections are detected by their name in capitals starting at
27%   position 1 or 2 of the line.
28% - The first word of the first line is skipped (assuming it is identical
29%   to NAME).  The remaining part of the line is used as heading.
30% - The next block of lines is assumed to be ways to call the command and
31%   is printed as code (Courier size 3) on separate lines.
32% - The INPUT and OUTPUT sections are printed as two-column tables. The
33%   first column is printed as code.
34% - Multiple spaces in the source are used to define column separators.
35%   ACCIDENTAL MULTIPLE SPACES CAUSE ERRORS!!!!
36% - Blocks of lines in the following DESCRIPTION section are formatted as
37%   separate paragraphs.
38% - Lines starting with ' - ' will start a dotted list.
39% - Lines following an empty line and starting with multiple spaces are
40%   assumed to be code and printed as Courier_3.
41% - Lines containing sets of multiple spaces after the first words start a
42%   two-column table. Consecutive lines starting with multiple spaces are
43%   placed in the second column.
44% - Lines ending with a ':' force a break (<br>) in the paragraph.
45% - An attempt is made to detect code in text (using the Matlab convention
46%   of upper case characters only). This is printed as Courier 2.
47% - Literature references in the REFERENCE section generater a break if the
48%   line starts with a number.
49% - Code in the EXAMPLE section is printed as it is using Courier_2.
50% - Users are advised to neglect here the Matlab convention of capitals in
51%   order to facilitate direct copying and execution.
52% - References are created for command names in the EXAMPLE section that
53%   are preceded by 'See', e.g. 'See PREX_PLOTC'.
54% - References are created for all PRTools commands in the SEE ALSO
55%   section.
56
57
58
59
60function out = prhelp2html(name,recreate,subdir)
61
62if nargin < 3, subdir = []; end
63if nargin < 2 || isempty(recreate), recreate = 0; end
64if nargin < 1
65        run_all_files(mfilename);
66        s = prcontent2html('prtools');
67        if nargout > 0
68                out = s;
69        end
70        return;
71end
72
73file = which(name);
74if isempty(file)
75        disp(['  ----->  ' name ' not found']);
76        out = [];
77        return
78end
79%[pp,name] = fileparts(file);
80if isempty(subdir)
81        [xx,subdir] = fileparts(fileparts(file));
82end
83if isempty(strmatch(subdir,char('prtools','@dataset','@datafile','@mapping'),'exact'))
84%       disp([name ' Not PRTools'])
85        out = [];
86        return
87end
88
89disp(file)
90t = gethf(file); % help part
91
92t = strrep(t,char([10 13]),char(10));
93t = strrep(t,char([13 10]),char(10));
94t = strrep(t,char(13),char(10));
95t = strrep(t,char(9),char([32 32]));
96n = length(strfind(t,10));
97       
98s = ['<html>' content_manual '<head><title>' name '</title></head>' newline];
99
100s = [s '<body bgcolor="#ffffff"><p align="center"><font face="Courier" ' ...
101   'size=5><strong>' upper(name) '</strong></font></p>' newline];
102
103title = listn(t,1);
104[qq,title] = strtok(title); % get rid of first word, probably name
105s = [s '<h3>' title '</h3>' newline];
106s = [s '<p>' newline];
107liston = false;
108previous_empty = false;
109coding = false;
110cellopen = false;
111tabstate = false;
112
113if strfind(lower(title),'info')
114        state = 'text';
115else
116        state = 'start';
117end
118nextlinespace = htmlspace;
119for j=2:n                             % do for all lines
120        newlinespace = nextlinespace;
121        nextlinespace = htmlspace;
122        r = listn(t,j);
123        u = cleanstr(r);
124%     if strfind(r,'supplied')
125%        disp(r)
126%     end
127        [tok,posttok] = strtok(u);
128        single = isempty(strtok(posttok));
129        emptyline = isempty(tok);
130        if length(r) < 2,
131                startspace = false;
132                tabstartspace = false;
133        else
134                startspace = strcmp(r(1:2),'  ');
135                if length(r) < 4 || ~tabstate
136                        tabstartspace = false;
137                else
138                        tabstartspace = strcmp(r(1:4),'    ');
139                        colpos1 = find(r ~= ' ',1,'first');
140                end
141                if tabstartspace
142                        startspace = false;
143                end
144        end
145        uppertoken = isupper(tok);
146        upperline = isupper(u);
147        functioncall = ~isempty(strfind(lower(r),name));
148        input = strcmp(tok,'INPUT');
149        output = strcmp(tok,'OUTPUT');
150        listline = strcmp(tok,'-');
151        description = strcmp(tok,'DESCRIPTION');
152        example = strcmp(tok,'EXAMPLE') | strcmp(tok,'EXAMPLES');
153        reference = strcmp(tok,'REFERENCE') | strcmp(tok,'REFERENCES');
154        seealso = strcmpi(tok,'SEE') & strcmpi(strtok(posttok),'ALSO');
155        inputstate = strcmp(state,'input');
156        outputstate = strcmp(state,'output');
157        tabstate = strcmp(state,'tab');
158        startstate = strcmp(state,'start');
159        commandstate = strcmp(state,'command');
160        textstate = strcmp(state,'text');
161        examplestate = strcmp(state,'examp');
162        seealsostate = strcmp(state,'seealso');
163        refstate = strcmp(state,'reference');
164        iotabstate = inputstate | outputstate;
165  ntabs = regexp(strtrim(r),'   *','start');
166        tab = length(ntabs>1) | (length(ntabs)==1 && ntabs(1)>1);
167       
168        if seealso % get rid of also
169                [qq,posttok] = strtok(posttok);
170                single = isempty(strtok(posttok));
171        end
172               
173        if previous_empty && ~startspace && ~tabstartspace && ~tab && tabstate
174                if cellopen
175                        s = closecell(s);
176                        cellopen = false;
177                end
178                s = endtable(s);
179    s = [s '</p>' newline '<p>'];
180                state = oldstate;
181        end
182       
183        if emptyline                          % start new paragraph
184                if liston, s = [s '</ul>']; liston = false; end
185                if iotabstate
186      s = endtable(s);
187      state = 'text';
188    else
189                        s = [s '</p>' newline '<p>']; %#ok<AGROW>
190                end
191                if ~examplestate
192                        coding = false;
193                end
194               
195        elseif (startspace && ((functioncall && upperline) || commandstate)) || startstate
196                                                    % command
197                %n = findstr(u,'=');  % align =
198                %n = min(n,17);       % but dont exeggarate
199                n = find(r~=' ',1,'first');
200                s  = [s code(u,n,3) '<br>' newline];
201                state = 'command';
202               
203        elseif input && single                 % input
204                if commandstate || textstate         % start table
205                        s = [s '</p><p>' newline];        % new paragraph
206                        s = [s '<table cellspacing="0" cellpadding="3" width="100%"'...
207                                        ' align="center" border="0"']; % start table
208                        s = [s '<tr> <td width="100"><font size="4"><strong>Input</strong></font></td>'];
209                  state = 'input';
210                end
211        elseif output && single
212                if inputstate
213                        s = endtable(s); % end inputtable
214                end
215                if inputstate || commandstate || textstate  % start table
216                        s = [s '</p><p>'];                      % new paragraph
217                        s = [s '<table cellspacing="0" cellpadding="3" width="100%"'...
218                                        ' align="center" border="0"']; % start table
219                        s = [s '<tr> <td width="120"><font size="4"><strong>Output</strong></font></td>'];
220                end
221                state = 'output';
222        elseif iotabstate % input/output table
223               
224               
225    if uppertoken  % next input/output parameter
226      s = [s '<tr> <td width="120" valign="baseline">' makecode(tok,1) '</td>'];
227                        [f0,f1] = regexp(posttok,'^ *[:-] *');
228                        if ~isempty(f0)
229                                posttok = posttok(f1+1:end);
230                        end
231      s = [s '<td valign="baseline">' findmakecode(posttok)];
232    else % continuation of description
233      s = [s htmlspace findmakecode(u)];
234    end
235               
236        elseif (tab || tabstate) ...
237                        && ~examplestate && ~startspace && ~tabstartspace % arbitrary table
238                if ~tabstate     % start table
239                        if liston, s = [s '</ul>']; liston = false; end
240                s = [s '</p><p>'];                % new paragraph
241                        s = [s '<table cellspacing="0" cellpadding="3" width="100%"'...
242                                ' align="center" border="0"']; % start table
243                        oldstate = state;
244                        state = 'tab';
245                        tabstate = true;
246                        cellopen = false;
247                end
248                if cellopen
249                        s = closecell(s);
250                        cellopen = false;
251                end
252                % first cell
253                s = [s '<tr> <td width="120" valign="baseline">' makecode(tok,1) '</td>'];
254                % get rid of :
255                [f0,f1] = regexp(posttok,'^ *: *');
256                if ~isempty(f0)
257                        posttok = posttok(f1+1:end);
258                end
259                colpos0 = findstr(cleanstr(posttok),r); % store starting pos 2nd cell
260                % second cell
261                s = [s '<td valign="baseline">'];
262                [tok2,posttok2] = strtok(posttok);
263                if strcmp(tok2,'-') % possible start of list
264                        s = [s '<ul><li>' findmakecode(posttok2)];
265                        liston = true;
266                else
267                        s = [s  findmakecode(posttok)];
268                        liston = false;
269                end
270                cellopen = true;
271               
272        elseif startspace && tab && ~textstate
273                if liston, s = [s '</ul>']; liston = 0; end
274                s = [s htmlspace findmakecode(u)];
275        elseif description && single
276                s = endtable(s,tab);
277                s = [s '</p><h3> Description</h3><p>' newline];
278                state = 'text';
279        elseif reference && single
280                s = endtable(s,tab);
281                s = [s '</p><h3> Reference(s)</h3><p>' newline];
282                nref = 0;
283                state = 'reference';
284        elseif example && single
285                s = endtable(s,tab);
286                s = [s '</p><h3> Example(s)</h3><p>' newline];
287                state = 'examp';
288%       elseif seealso && single
289%               s = endtable(s,tab);
290%               s = [s '</p><h3> See also</h3><p>' newline];
291%               state = 'seealso';
292        elseif seealso
293                s = endtable(s,tab);
294                s = [s '</p><h3> See also</h3><p>' newline];
295                state = 'seealso';
296                if ~single
297                        s = [s commandrefs(posttok,recreate)];
298                end
299        else % undefined lines
300                if examplestate
301                        if length(u) > 3 && strcmpi(u(1:4),'see ')
302                                s = [s '</p>' commandrefs(u(5:end),recreate) '<p>'];
303                        else
304                                s = [s strrep(code(strrep(r,' ','#$!'),0,3),'#$!','&nbsp;') '<br>'];
305        %                       s = [s code(r) '<br>'];
306                        end
307                elseif refstate
308                        if abs(u(1)>=48) && abs(u(1)<=57) && nref > 0
309                                s = [s '<br>' u];
310                        else
311                                s = [s htmlspace u];
312                                nref = 1;
313                        end
314                elseif seealsostate
315                        if listline
316                                s = [s '<strong><font size="4">' findmakecode(u(3:end)) '</font></strong><br>'];
317                        else
318                                s = [s commandrefs(u,recreate)];               
319                        end
320                elseif tabstartspace && tabstate && (colpos1 > colpos0) ...
321                                && (previous_empty || coding) % start code in table
322                        s = [s  strrep(code(strrep(r(colpos0:end),' ','#$!'),0,3),'#$!','&nbsp;') '<br>'];
323                        coding = true;
324                elseif startspace && ~tabstate && ~liston ...
325                                && (previous_empty || coding) % code line
326                        s = [s strrep(code(strrep(r,' ','#$!'),2,3),'#$!','&nbsp;') '<br>'];
327                        nextlinespace = '';
328      coding = true;
329                elseif listline
330                        if ~liston
331                                s = [s '<ul>'];
332                                liston = true;
333                        end
334                        if u(end) == ':'
335                                s = [s '<li>' findmakecode(u(3:end-1)) '<br>'];
336                                nextlinespace = '';
337                        else
338                                s = [s '<li>' findmakecode(u(3:end))];
339                        end
340%               elseif tabstate && ~startspace && ~tabstartspace % end of table
341%                       s = endtable(s);
342%                       state = oldstate;
343%                       s = [s findmakecode(u)];
344                elseif tabstate % next line in table, store starting position
345                        colpos0 = colpos1;
346                        s = [s newlinespace findmakecode(cleanstr(u))];
347                else % just a line
348                        if u(end) == ':'
349                                s = [s newlinespace findmakecode(cleanstr(u(1:end-1))) '<br>'];
350                                nextlinespace = '';
351                        else
352                                s = [s newlinespace findmakecode(cleanstr(u))];
353                        end
354                %       s = [s newlinespace findmakecode(cleanstr(u))];
355                end
356        end
357       
358        if emptyline
359                previous_empty = true;
360        else
361                previous_empty = false;
362        end
363       
364end
365
366if cellopen
367        s = closecell(s);
368end
369if tabstate
370        s = endtable(s);
371end
372
373
374s = strrep(s,'<p>&nbsp;','<p>');
375s = strrep(s,' </font>&nbsp;',' </font>');
376s = strrep(s,['<p>' newline '&nbsp;'],'<p>');
377s = [s '</p>' content_manual '</body></html>'];
378[qq,name] = fileparts(name); % allows for names like dataset/show
379if exist(['./' subdir],'file') ~= 7
380        mkdir(subdir);
381end
382writf([fullfile(subdir,name) '.html'],s);
383disp([int2str(recreate) ' ' name ' html created'])
384if nargout > 0
385        out = s;
386end
387       
388return
389
390function i = isupper(s)
391% true if s doesnot change by upper
392i = strcmp(s,upper(s));
393return
394
395function out = code(s,n,fsize)
396        %convert s to Courier, add n spaces in front, fontsize fsize
397        if nargin < 3, fsize = 2; end
398        if nargin < 2, n = 0; end
399        out = ['<font face="Courier" size="' int2str(fsize) '">' htmlspace(n) s '</font>'];
400return
401
402function out = makecode(s,n,fsize)
403        %convert any consequetive set of uppers and make them Courier size fsize,
404        % add n spaces in front
405        if strmatch(s(end),char(',','.'))
406                send = s(end); s(end) = [];
407        elseif length(s) > 1 && ~isempty(strmatch(s(end-1:end),char(', ','. ')))
408                send = s(end-1:end); s(end-1:end) = [];
409        else
410                send = [];
411        end
412        if nargin < 3, fsize = 2; end
413        if nargin < 2, n = 0; end
414        out = [];
415        if isupper(s)
416                %out = code(lower(s),n);
417                out = code(s,n,fsize);
418        else
419                while ~isempty(s)
420                        [t,s] = strtok(s);
421                        if isupper(t)
422                                %t = code(lower(t));
423                                t = code(t,n,fsize);
424                        end
425                        out = [out ' ' t];
426                end
427        end
428        out = [out send];
429return
430       
431function s = cleanstr(s)
432        V = char([9 10 11 12 13 32]);
433        for n=1:length(s)
434                if all(V~=s(n))
435                        break;
436                end
437        end
438        s = s(n:end);
439        for n=length(s):-1:1
440                if all(V~=s(n))
441                        break
442                end
443        end
444        s = s(1:n);
445return
446
447function s = endtable(s,tab)
448if strcmp(s(end-7:end),char([60 47 112 62 10 60 112  62]))
449        s(end-7:end) = [];
450end
451if strcmp(s(end-6:end),char([60 47 112 62 60 112  62]))
452        s(end-7:end) = [];
453end
454if nargin < 2 || tab % don't do this for tab = 0
455        s = [s '</td></tr></table>' newline]; % end table
456end
457
458function s = commandrefs(r,recreate)
459        if nargin < 2, recreate = 0; end
460        s = [];
461        r_debug = r;
462        while ~isempty(r) && isempty(regexp(r,'^[ .,]*$', 'once' ))
463                [tok,r] = strtok(r,' .,');
464                tok = lower(tok);
465                htmlname = [tok '.html'];
466                file = which(tok);
467                pp = fileparts(file);
468                [qq,subdir] = fileparts(pp);
469                htmlname = fullfile(subdir,htmlname);
470                if exist(htmlname,'file') == 2
471                        s = [s '<a href="../' htmlname '">' tok '</a>, '];
472                elseif isempty(tok) || ~isempty(regexp(tok,'^ *', 'once' ))
473                        ;
474                elseif recreate
475                        tt = prhelp2html(tok); % don't iterate further!
476                        if ~isempty(tt)
477                                s = [s '<a href="../' htmlname '">' tok '</a>, '];
478                        else
479                                % disp([r_debug ' --> ' tok ])
480                                s = [s tok ', '];
481                        end
482                else
483                        s = [s tok ', '];
484                end
485        end
486        if ~isempty(s)
487%               s(end-1:end) = [];
488                s = code(s,0,3);
489        end
490        s = strrep(s,'\','/'); % avoid  \ in html addresses
491return
492
493function s = htmlspace(n)
494        if nargin < 1, n=1; end
495        if n > 0
496                s = repmat('&nbsp;',1,n);
497        else
498                s = [];
499        end
500return
501
502function s = findmakecode(r)
503% find pieces of code (capitals only) and convert them to lower Courier
504r = strrep(r,'. A ','. aA ');  % prevent conversion of A at the start of a sentence
505r = [' ' r ' ']; % ending space may be helpful
506r = strrep(r,'NaN',code('NaN'));
507
508[f0,f1] = regexp(r,'[ ,(\[]+[A-Z0123456789=<>(){},.''''*+\\/;:\[\]_ ]+[ .,-]');
509
510%[f0,f1,toks] = regexp(r,'[ ,(]+[A-Z0123456789=<>(){},*+\\/;:\[\]_ ]+[ .,-]');
511if ~isempty(f0)
512        if f0(1) > 1 % first part no code
513                s = r(1:f0(1)-1);
514        else
515                s = [];
516        end
517        for j=1:length(f0)  % all code parts
518                s = [s makecode(r(f0(j):f1(j)))];
519                if j < length(f0) % between code parts
520                        s = [s r(f1(j)+1:f0(j+1)-1)];
521                end
522        end
523        if f1(end) < length(r) % last part no code
524                s = [s r(f1(end)+1:end)];
525        end
526else
527        s = r;
528end
529
530if s(end) == ' ', s(end) = []; end % remove ending space
531s = strrep(s,'. aA ','. A ');  % convert prevention back
532
533function s = closecell(s)
534if strcmp(s(end-7:end),char([60 47 112 62 10 60 112  62]))
535        s(end-7:end) = [];
536elseif strcmp(s(end-6:end),char([60 47 112 62 60 112  62]))
537        s(end-7:end) = [];
538end
539s = [s '</td></tr>'];
540
541
542%LISTN List lines specified by their line number
543%
544% t = listn(r,n)
545% Get the lines in r given by the line numbers in n.
546function t = listn(r,n)
547k = [0,find(r==newline)];
548t = [];
549for j = n
550        if j < length(k)
551    t = [t,r(k(j)+1:k(j+1))];
552        end
553end
554return
555
556function run_all_files(command)
557
558dirs = {'ldc','dataset','datafile','mapping'};
559for n=1:length(dirs)
560        prtools_dir = fileparts(which(dirs{n}));
561        [qq,prtools_dirname] = fileparts(prtools_dir); % get rid of root
562        ff = dirnames(prtools_dir);
563        for j=1:length(ff)
564                [qq,name] = fileparts(ff{j});
565                if n==1
566                        feval(command,name); % prtools main commands
567                else
568                        feval(command,fullfile(prtools_dirname,name)); % subdir commands
569                end
570        end
571end
572
573function files = dirnames(direct)
574% get all m-files in dir
575
576allnames = dir(fullfile(direct,'*.m'));
577files = char(allnames(:).name);
578files(strmatch('Contents.m',files),:) = [];
579files(strmatch('Readme.m',files),:) = [];
580files = cellstr(files);
581
582
583function s = gethf(file)
584%GETHF Create heading file from m-file
585%
586%       s = gethf(file)
587%
588% The heading of the given m-file consisting of all starting % lines
589% is isolated and returned in s.
590%
591%       gethf(dir)
592%
593% All headings of the files in dir are merged into a file named headings.doc.
594% Default dir is cd.
595%
596% Use mergeprt for restoring
597if nargin == 0
598        gethf(cd);
599end
600if isdir(file)
601        files = dir(file);
602        docfile = ['headings.doc'];
603        m = size(files,1);
604        for i = 1:m
605                if (~files(i,:).isdir) & (files(i,:).name(end-1:end) == '.m')
606                        name = files(i,:).name;
607                        s = gethf(name);
608                        s = ['##1' name(1:end-2) newline s newline '##2' newline];
609                        %disp(s)
610                        appendf(docfile,s);
611                end
612        end
613else
614        %disp(file)
615        [s,ns] = readf(file);
616        p = grep(s,'%');
617        if isempty(p) % no comments found
618                s = [];
619                return
620        end
621        p = [p p(end)+10];  % trick
622        I = find(p - [0,p(1:length(p)-1)] ~= 1);
623        if p(1) == 1 & isempty(I), I = length(p) + 1; end
624%       if length(I) > 0 & I(1) > 1
625        if length(I) > 0
626                if I(1) == 1
627                        I(1) = [];
628                end
629                n = I(1) - 1;
630                s = listn(s,p(1):n+p(1)-1);
631                s = strrep(s,[newline '%'],newline);
632                %s = strrep(s,[newline ' '],newline);
633                %s = strrep(s,[newline newline],'&*&');
634                %s = strrep(s,[newline '        '],'*&* ');
635                %s = strrep(s,newline,' ');
636                %s = strrep(s,'&*&',[newline newline]);
637                %s = strrep(s,'*&*',newline);
638                s = s(2:end);
639        else
640                s = '';
641        end
642end
643
644function [r,n] = readf(file,newline)
645%READF Readfile
646%
647% [r,n] = readf(file,newline)
648% Reads file into string r. The number of lines
649% is returned in n.
650if nargin < 2, newline = 13; end
651fid = fopen(deblank(file),'r');
652if fid < 0
653   error(['Cann''t open ' file])
654end
655r = fscanf(fid,'%c');
656fclose(fid);
657n = length(find(r==newline));
658if r(length(r)) ~= newline, n = n + 1; end
659return
660
661
662
663function writf(file,r)
664%WRITF Write file
665%
666% writf(file,r)
667% Write file from string r
668fid = fopen(file,'w');
669if fid < 0
670   error(['Cannot open file ' file])
671end
672fprintf(fid,'%c',r);
673fclose(fid);
674return
675
676
677function [k,z] = grep(r,s)
678%GREP Get line specific lines
679%
680% [k,n] = grep(r,s)
681% Get the numbers of all lines in the set of lines r
682% that contain s.
683% n is the total number of lines.
684n = [0,find(r==newline)];
685m = findstr(r,s);
686[i,j] = sort([n,m]);;
687q = [0,j(1:length(j)-1)]-j;
688k = j(find(q>0))-1;
689z = length(n)-1; % # of lines
690return
691
692
693function t = content_manual
694t = ['<table border="0" cellspacing="0" cellpadding="3" width="100%" '...
695           'align="center"><tr><td><a href="../prtools.html">contents</a>' ...
696                 '</td><td><p align="right"><a '...
697     'href="http://prtools.org/manual" target="_top">manual</a></p></td>'...
698                 '</tr></table></p>'];
699return
700
Note: See TracBrowser for help on using the repository browser.