35
36:- module(pldoc_index,
37 [ doc_for_dir/2, 38 dir_index//2, 39 object_summaries//3, 40 file_index_header//2, 41 doc_links//2, 42 doc_file_href/2, 43 places_menu//1, 44 source_directory/1 45 ]). 46:- use_module(doc_process). 47:- use_module(doc_html). 48:- use_module(doc_wiki). 49:- use_module(doc_search). 50:- use_module(doc_util). 51
52:- if(exists_source(library(doc_http))). 53:- use_module(library(http/http_dispatch)). 54:- use_module(library(doc_http), []). 55:- endif. 56
57:- use_module(library(http/html_write)). 58:- use_module(library(http/html_head)). 59:- use_module(library(readutil)). 60:- use_module(library(url)). 61:- use_module(library(option)). 62:- use_module(library(lists)). 63:- include(hooks). 64
67
68:- predicate_options(dir_index//2, 2,
69 [ directory(atom),
70 edit(boolean),
71 files(list),
72 members(list),
73 qualify(boolean),
74 title(atom),
75 if(oneof([true,loaded])),
76 recursive(boolean),
77 secref_style(oneof([number, title, number_title])),
78 pass_to(doc_links/4, 2)
79 ]). 80:- predicate_options(doc_links//2, 2,
81 [ files(list),
82 pass_to(pldoc_search:search_form/3, 1)
83 ]). 84:- predicate_options(file_index_header//2, 2,
85 [ directory(any),
86 files(list),
87 qualify(boolean),
88 secref_style(oneof([number, title, number_title])),
89 pass_to(pldoc_html:edit_button/4, 2),
90 pass_to(pldoc_html:source_button/4, 2)
91 ]). 92:- predicate_options(object_summaries//3, 3,
93 [ edit(boolean),
94 files(list),
95 module(atom),
96 public(list),
97 qualify(boolean),
98 secref_style(oneof([number, title, number_title]))
99 ]). 100:- predicate_options(doc_for_dir/2, 2, [pass_to(dir_index/4, 2)]). 101
108
109doc_for_dir(DirSpec, Options) :-
110 absolute_file_name(DirSpec,
111 [ file_type(directory),
112 access(read)
113 ],
114 Dir),
115 ( option(title(Title), Options)
116 -> true
117 ; file_base_name(Dir, Title)
118 ),
119 doc_write_page(
120 pldoc(dir_index),
121 title(Title),
122 \dir_index(Dir, Options),
123 Options).
124
125:- html_meta doc_write_page(+, html, html, +). 126
127doc_write_page(Style, Head, Body, Options) :-
128 option(files(_), Options),
129 !,
130 phrase(page(Style, Head, Body), HTML),
131 print_html(HTML).
132doc_write_page(Style, Head, Body, _) :-
133 reply_html_page(Style, Head, Body).
134
135
145
146dir_index(Dir, Options) -->
147 { dir_source_files(Dir, Files0, Options),
148 sort(Files0, Files),
149 maplist(ensure_doc_objects, Files),
150 directory_file_path(Dir, 'index.html', File),
151 b_setval(pldoc_file, File) 152 },
153 html([ \doc_resources(Options),
154 \doc_links(Dir, Options),
155 \dir_header(Dir, Options),
156 \subdir_links(Dir, Options),
157 h2(class([wiki,plfiles]), 'Prolog files'),
158 table(class(summary),
159 \file_indices(Files, [directory(Dir)|Options])),
160 \dir_footer(Dir, Options)
161 ]).
162
166
167dir_source_files(_, Files, Options) :-
168 option(members(Members), Options),
169 !,
170 findall(F, member(file(F,_Doc), Members), Files).
171dir_source_files(Dir, Files, Options) :-
172 directory_source_files(Dir, Files, Options).
173
177
178subdir_links(Dir, Options) -->
179 { option(members(Members), Options),
180 findall(SubDir, member(directory(SubDir, _, _, _), Members), SubDirs),
181 SubDirs \== []
182 },
183 html([ h2(class([wiki,subdirs]), 'Sub directories'),
184 table(class(subdirs),
185 \subdir_link_rows(SubDirs, Dir))
186 ]).
187subdir_links(_, _) --> [].
188
189subdir_link_rows([], _) --> [].
190subdir_link_rows([H|T], Dir) -->
191 subdir_link_row(H, Dir),
192 subdir_link_rows(T, Dir).
193
194subdir_link_row(Dir, From) -->
195 { directory_file_path(Dir, 'index.html', Index),
196 relative_file_name(Index, From, Link),
197 file_base_name(Dir, Base)
198 },
199 html(tr(td(a([class(subdir), href(Link)], ['[dir] ', Base])))).
200
207
(Dir, Options) -->
209 wiki_file(Dir, readme, Options),
210 !.
211dir_header(Dir, Options) -->
212 { ( option(title(Title), Options)
213 -> true
214 ; file_base_name(Dir, Title)
215 )
216 },
217 html(h1(class=dir, Title)).
218
226
(Dir, Options) -->
228 wiki_file(Dir, todo, Options),
229 !.
230dir_footer(_, _) -->
231 [].
232
236
237wiki_file(Dir, Type, Options) -->
238 { ( Opt =.. [Type,WikiFile],
239 option(Opt, Options)
240 -> true
241 ; directory_files(Dir, Files),
242 member(File, Files),
243 wiki_file_type(Type, Pattern),
244 downcase_atom(File, Pattern),
245 directory_file_path(Dir, File, WikiFile)
246 ),
247 access_file(WikiFile, read),
248 !,
249 read_file_to_codes(WikiFile, String, []),
250 wiki_codes_to_dom(String, [], DOM)
251 },
252 pldoc_html:html(DOM).
253
258
259wiki_file_type(readme, 'readme').
260wiki_file_type(readme, 'readme.md').
261wiki_file_type(readme, 'readme.txt').
262wiki_file_type(todo, 'todo').
263wiki_file_type(todo, 'todo.md').
264wiki_file_type(todo, 'todo.txt').
265
270
271file_indices([], _) -->
272 [].
273file_indices([H|T], Options) -->
274 file_index(H, Options),
275 file_indices(T, Options).
276
280
281file_index(File, Options) -->
282 { doc_summaries(File, Objs0),
283 module_info(File, ModuleOptions, Options),
284 doc_hide_private(Objs0, Objs1, ModuleOptions),
285 sort(Objs1, Objs)
286 },
287 html([ \file_index_header(File, Options)
288 | \object_summaries(Objs, File, ModuleOptions)
289 ]).
290
291doc_summaries(File, Objects) :-
292 xref_current_source(FileSpec),
293 xref_option(FileSpec, comments(collect)),
294 !,
295 Pos = File:0,
296 findall(doc(Obj,Pos,Summary),
297 xref_doc_summary(Obj, Pos, Summary), Objects).
298doc_summaries(File, Objects) :-
299 Pos = File:_Line,
300 findall(doc(Obj,Pos,Summary),
301 doc_comment(Obj, Pos, Summary, _), Objects).
302
303xref_doc_summary(M:Name/Arity, File:_, Summary) :-
304 xref_comment(File, Head, Summary, _Comment),
305 xref_module(File, Module),
306 strip_module(Module:Head, M, Plain),
307 functor(Plain, Name, Arity).
308
312
(File, Options) -->
314 prolog:doc_file_index_header(File, Options),
315 !.
316file_index_header(File, Options) -->
317 { ( option(directory(Dir), Options),
318 directory_file_path(Dir, Label, File)
319 -> true
320 ; file_base_name(File, Label)
321 ),
322 doc_file_href(File, HREF, Options)
323 },
324 html(tr(th([colspan(3), class(file)],
325 [ span(style('float:left'), a(href(HREF), Label)),
326 \file_module_title(File),
327 span(style('float:right'),
328 [ \source_button(File, Options),
329 \edit_button(File, Options)
330 ])
331 ]))).
332
333file_module_title(File) -->
334 { ( module_property(M, file(File))
335 ; xref_module(File, M)
336 ),
337 doc_comment(M:module(Title), _, _, _)
338 },
339 !,
340 html([&(nbsp), ' -- ', Title]).
341file_module_title(_) -->
342 [].
343
344
348
349doc_file_href(File, HREF, Options) :-
350 option(directory(Dir), Options),
351 atom_concat(Dir, Local0, File),
352 atom_concat(/, Local, Local0),
353 !,
354 ( option(files(Map), Options), 355 memberchk(file(File, DocFile), Map)
356 -> file_base_name(DocFile, HREF)
357 ; HREF = Local
358 ).
359doc_file_href(File, HREF, _) :-
360 doc_file_href(File, HREF).
361
362
363
371
372doc_file_href(File0, HREF) :-
373 insert_alias(File0, File),
374 ensure_slash_start(File, SlashFile),
375 http_location([path(SlashFile)], Escaped),
376 http_location_by_id(pldoc_doc, DocRoot),
377 atom_concat(DocRoot, Escaped, HREF).
378
379
384
385ensure_slash_start(File, File) :-
386 sub_atom(File, 0, _, _, /),
387 !.
388ensure_slash_start(File0, File) :-
389 atom_concat(/, File0, File).
390
391
395
396object_summaries(Objects, Section, Options) -->
397 { tag_pub_priv(Objects, Tagged, Options),
398 keysort(Tagged, Ordered)
399 },
400 obj_summaries(Ordered, Section, Options).
401
402obj_summaries([], _, _) -->
403 [].
404obj_summaries([_Tag-H|T], Section, Options) -->
405 object_summary(H, Section, Options),
406 obj_summaries(T, Section, Options).
407
408tag_pub_priv([], [], _).
409tag_pub_priv([H|T0], [Tag-H|T], Options) :-
410 ( private(H, Options)
411 -> Tag = z_private
412 ; Tag = a_public
413 ),
414 tag_pub_priv(T0, T, Options).
415
416
423
424object_summary(q(_Q,Obj), Section, Options) -->
425 { nonvar(Obj) },
426 !,
427 object_summary(Obj, Section, Options).
428object_summary(doc(Obj, _Pos, _Summary), wiki, Options) -->
429 !,
430 html(tr(class(wiki),
431 [ td(colspan(3), \object_ref(Obj, Options))
432 ])).
433object_summary(doc(Obj, _Pos, Summary), _Section, Options) -->
434 !,
435 ( { string_codes(Summary, Codes),
436 wiki_codes_to_dom(Codes, [], DOM0),
437 strip_leading_par(DOM0, DOM),
438 ( private(Obj, Options)
439 -> Class = private 440 ; Class = public 441 )
442 }
443 -> html(tr(class(Class),
444 [ td(\object_ref(Obj, Options)),
445 td(class(summary), DOM),
446 td([align(right)],
447 span(style('white-space: nowrap'),
448 [ \object_source_button(Obj, Options),
449 \object_edit_button(Obj, Options)
450 ]))
451 ]))
452 ; []
453 ).
454object_summary(Obj, Section, Options) -->
455 { prolog:doc_object_summary(Obj, _Cat, Section, Summary)
456 },
457 !,
458 object_summary(doc(Obj, _, Summary), Section, Options).
459object_summary(_, _, _) -->
460 [].
461
462
463 466
470
471doc_links(_Directory, Options) -->
472 { option(files(_), Options), !
473 }.
474doc_links(Directory, Options) -->
475 prolog:doc_links(Directory, Options),
476 !,
477 { option(html_resources(Resoures), Options, pldoc) },
478 html_requires(Resoures).
479doc_links(Directory, Options) -->
480 { ( Directory == ''
481 -> working_directory(Dir, Dir)
482 ; Dir = Directory
483 ),
484 option(html_resources(Resoures), Options, pldoc)
485 },
486 html([ \html_requires(Resoures),
487 div(class(navhdr),
488 [ div(class(jump),
489 div([ \places_menu(Dir),
490 \plversion
491 ])),
492 div(class(search), \search_form(Options)),
493 br(clear(right))
494 ])
495 ]).
496
497
501
502plversion -->
503 { current_prolog_flag(version_data, swi(Major, Minor, Patch, _))
504 },
505 !,
506 html(a([ class(prolog_version),
507 href('http://www.swi-prolog.org')
508 ],
509 [' SWI-Prolog ', Major, '.', Minor, '.', Patch])).
510
511plversion -->
512 { current_prolog_flag(version_data, yap(Major, Minor, Patch, _))
513 },
514 html(a([ class(prolog_version),
515 href('http://www.dcc.fc.up.pt/~vsc')
516 ],
517 [' YAP ', Major, '.', Minor, '.', Patch])).
518
519
523
(Dir) -->
525 prolog:doc_places_menu(Dir),
526 !.
527places_menu(Dir) -->
528 { findall(D, source_directory(D), List),
529 sort(List, Dirs)
530 },
531 html(form([ action(location_by_id(go_place))
532 ],
533 [ input([type(submit), value('Go')]),
534 select(name(place),
535 \packs_source_dirs(Dirs, Dir))
536 ])).
537
538packs_source_dirs(Dirs, Dir) -->
539 packs_link,
540 source_dirs(Dirs, Dir).
541
542source_dirs([], _) -->
543 [].
544source_dirs([H|T], WD) -->
545 { ( H == WD
546 -> Attrs = [selected]
547 ; Attrs = []
548 ),
549 format(string(IndexFile), '~w/index.html', [H]),
550 doc_file_href(IndexFile, HREF),
551 format(string(Call), 'document.location=\'~w\';', [HREF])
552 },
553 html(option([onClick(Call)|Attrs], H)),
554 source_dirs(T, WD).
555
556packs_link -->
557 { pack_property(_,_),
558 !,
559 http_link_to_id(pldoc_pack, [], HREF),
560 format(atom(Call), 'document.location=\'~w\';', [HREF])
561 },
562 html(option([ class(packs),
563 onClick(Call),
564 value(':packs:')
565 ],
566 'List extension packs')).
567packs_link -->
568 [].
569
575
576source_directory(Dir) :-
577 ( ground(Dir)
578 -> '$time_source_file'(File, _Time1, _System1),
579 file_directory_name(File, Dir), !
580 ; '$time_source_file'(File, _Time2, _System2),
581 file_directory_name(File, Dir)
582 )