1/* Part of XPCE --- The SWI-Prolog GUI toolkit 2 3 Author: Jan Wielemaker and Anjo Anjewierden 4 E-mail: wielemak@science.uva.nl 5 WWW: http://www.swi-prolog.org/packages/xpce/ 6 Copyright (c) 2006-2022, University of Amsterdam 7 SWI-Prolog Solutions b.v. 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(pce_xref_gui, 37 [ gxref/0, 38 xref_file_imports/2, % +File, -Imports 39 xref_file_exports/2 % +File, -Exports 40 ]). 41:- use_module(pce). 42:- use_module(persistent_frame). 43:- use_module(tabbed_window). 44:- use_module(toolbar). 45:- use_module(pce_report). 46:- use_module(pce_util). 47:- use_module(pce_toc). 48:- use_module(pce_arm). 49:- use_module(pce_tagged_connection). 50:- use_module(dragdrop). 51:- use_module(pce_prolog_xref). 52:- use_module(print_graphics). 53:- use_module(tabular). 54:- use_module(library(lists)). 55:- use_module(library(autowin)). 56:- use_module(library(broadcast)). 57:- use_module(library(prolog_source)). 58:- require([ auto_call/1, 59 edit/1, 60 exists_file/1, 61 (\=)/2, 62 call_cleanup/2, 63 file_base_name/2, 64 file_directory_name/2, 65 portray_clause/2, 66 term_to_atom/2, 67 time_file/2, 68 absolute_file_name/3, 69 atomic_list_concat/3, 70 file_name_extension/3, 71 format_time/3, 72 maplist/3, 73 strip_module/3, 74 xref_called/4, 75 head_name_arity/3 76 ]). 77 78:- multifile 79 gxref_called/2. 80 81gxref_version('0.1.1'). 82 83:- dynamic 84 setting/2. 85 [ warn_autoload, 87 warn_not_called 88 ]) (. 89 90setting(warn_autoload, false). 91setting(warn_not_called, true). 92setting(hide_system_files, true). 93setting(hide_profile_files, true).
127gxref :- 128 in_pce_thread(xref_gui). 129 130xref_gui :- 131 send(new(XREF, xref_frame), open), 132 send(XREF, wait), 133 send(XREF, update). 134 135 xref_frame, persistent_frame, 137 "GUI for the Prolog cross-referencer"). ( 138 139initialise(F) :-> 140 send_super(F, initialise, 'Prolog XREF'), 141 new(FilterDialog, xref_filter_dialog), 142 send(new(BrowserTabs, tabbed_window), below, FilterDialog), 143 send(BrowserTabs, left, new(WSTabs, tabbed_window)), 144 send(BrowserTabs, name, browsers), 145 send(BrowserTabs, hor_shrink, 10), 146 send(BrowserTabs, hor_stretch, 10), 147 send(WSTabs, name, workspaces), 148 send_list([BrowserTabs, WSTabs], label_popup, F?tab_popup), 149 send(new(TD, tool_dialog(F)), above, BrowserTabs), 150 send(new(report_dialog), below, BrowserTabs), 151 send(F, append, BrowserTabs), 152 send_list(BrowserTabs, 153 [ append(new(xref_file_tree), files), 154 append(new(xref_predicate_browser), predicates) 155 ]), 156 send_list(WSTabs, 157 [ append(new(xref_depgraph), dependencies) 158 ]), 159 send(F, fill_toolbar, TD). 160 161tab_popup(_F, P:popup) :<- 162 "Popup for tab labels":: 163 new(P, popup), 164 send_list(P, append, 165 [ menu_item(close, message(@arg1, destroy)), 166 menu_item(detach, message(@arg1, untab)) 167 ]). 168 169fill_toolbar(F, TD:tool_dialog) :-> 170 send(TD, append, new(File, popup(file))), 171 send(TD, append, 172 new(Settings, popup(settings, 173 message(F, setting, @arg1, @arg2)))), 174 send(TD, append, new(View, popup(view))), 175 send(TD, append, new(Help, popup(help))), 176 send_list(File, append, 177 [ menu_item(exit, message(F, destroy)) 178 ]), 179 send_list(View, append, 180 [ menu_item(refresh, message(F, update)) 181 ]), 182 send_list(Help, append, 183 [ menu_item(about, message(F, about)) 184 ]), 185 send(Settings, show_current, @on), 186 send(Settings, multiple_selection, @on), 187 send(F, update_setting_menu). 188 189about(_F) :-> 190 gxref_version(Version), 191 send(@display, inform, 192 string('SWI-Prolog cross-referencer version %s\n\c 193 By Jan Wielemaker', Version)). 194 parts). ( 196 197workspace(F, Which:name, Create:[bool], Expose:bool, WS:window) :<- 198 "Find named workspace":: 199 get(F, member, workspaces, Tabs), 200 ( get(Tabs, member, Which, WS) 201 -> true 202 ; Create == @on 203 -> workspace_term(Which, New), 204 new(WS, New), 205 send(WS, name, Which), 206 send(Tabs, append, WS) 207 ), 208 ( Expose == @on 209 -> send(Tabs, on_top, WS?name) 210 ; true 211 ). 212 213workspace_term(file_info, prolog_file_info). 214workspace_term(header, xref_view). 215 216browser(F, Which:name, Browser:browser) :<- 217 "Find named browser":: 218 get(F, member, browsers, Tabs), 219 get(Tabs, member, Which, Browser). 220 221update(F) :-> 222 "Update all windows":: 223 send(F, xref_all), 224 get(F, member, browsers, Tabs), 225 send(Tabs?members, for_some, 226 message(@arg1, update)), 227 get(F, member, workspaces, WSs), 228 send(WSs?members, for_some, 229 message(@arg1, update)). 230 231xref_all(F) :-> 232 "Run X-referencer on all files":: 233 forall(( source_file(File), 234 exists_file(File) 235 ), 236 send(F, xref_file, File)). 237 238xref_file(F, File:name) :-> 239 "XREF a single file if not already done":: 240 ( xref_done(File, Time), 241 catch(time_file(File, Modified), _, fail), 242 Modified == Time 243 -> true 244 ; send(F, report, progress, 'XREF %s', File), 245 xref_source(File, [silent(true)]), 246 send(F, report, done) 247 ). 248 actions). ( 250 251 252file_info(F, File:name) :-> 253 "Show summary info on File":: 254 get(F, workspace, file_info, @on, @on, Window), 255 send(Window, file, File), 256 broadcast(xref_refresh_file(File)). 257 258file_header(F, File:name) :-> 259 "Create import/export header":: 260 get(F, workspace, header, @on, @on, View), 261 send(View, file_header, File). 262 settings). ( 264 265update_setting_menu(F) :-> 266 "Update the menu for the settings with the current values":: 267 get(F, member, tool_dialog, TD), 268 get(TD, member, menu_bar, MB), 269 get(MB, member, settings, Popup), 270 send(Popup, clear), 271 setting_menu(Entries), 272 ( member(Name, Entries), 273 setting(Name, Value), 274 send(Popup, append, new(MI, menu_item(Name))), 275 ( Value == true 276 -> send(MI, selected, @on) 277 ; true 278 ), 279 fail ; true 280 ). 281 282setting(F, S:name, PceVal:bool) :-> 283 "Update setting and redo analysis":: 284 pce_to_prolog_bool(PceVal, Val), 285 retractall(setting(S, _)), 286 assert(setting(S, Val)), 287 send(F, update). 288 289pce_to_prolog_bool(@on, true). 290pce_to_prolog_bool(@off, false). 291 xref_frame). ( 293 294 295 /******************************* 296 * WORKSPACE * 297 *******************************/ 298 xref_depgraph, picture, 300 "Workspace showing dependecies"). (arm). (print_graphics). ( 303 304initialise(W) :-> 305 send_super(W, initialise), 306 send(W, popup, new(P, popup)), 307 send_list(P, append, 308 [ menu_item(layout, message(W, layout)), 309 gap, 310 menu_item(view_whole_project, message(W, show_project)), 311 gap, 312 menu_item(clear, message(W, clear, destroy)), 313 gap, 314 menu_item(print, message(W, print)) 315 ]). 316 317update(P) :-> 318 "Initial screen":: 319 send(P, display, 320 new(T, text('Drag files or directories to dependency view\n\c 321 or use background menu to show the whole project')), 322 point(10,10)), 323 send(T, name, intro_text), 324 send(T, colour, grey50). 325 326remove_intro_text(P) :-> 327 "Remove the introductionary text":: 328 ( get(P, member, intro_text, Text) 329 -> send(Text, destroy) 330 ; true 331 ). 332 333show_project(P) :-> 334 get(P, sources, Sources), 335 send(P, clear, destroy), 336 forall(member(Src, Sources), 337 send(P, append, Src)), 338 send(P, update_links), 339 send(P, layout). 340 341sources(_, Sources:prolog) :<- 342 findall(S, dep_source(S), Sources).
348dep_source(Src) :- 349 source_file(Src), 350 ( setting(hide_system_files, true) 351 -> \+ library_file(Src) 352 ; true 353 ), 354 ( setting(hide_profile_files, true) 355 -> \+ profile_file(Src) 356 ; true 357 ). 358 359append(P, File:name, Create:[bool|{always}]) :-> 360 "Append File. If Create == always also if a system file":: 361 default(Create, @on, C), 362 get(P, node, File, C, _). 363 364node(G, File:name, Create:[bool|{always}], Pos:[point], 365 Gr:xref_file_graph_node) :<- 366 "Get the node representing File":: 367 ( get(G, member, File, Gr) 368 -> true 369 ; ( Create == @on 370 -> dep_source(File) 371 ; Create == always 372 ), 373 ( Pos == @default 374 -> get(G?visible, center, At) 375 ; At = Pos 376 ), 377 send(G, display, new(Gr, xref_file_graph_node(File)), At), 378 send(G, remove_intro_text) 379 ). 380 381update_links(G) :-> 382 "Add all export links":: 383 send(G?graphicals, for_all, 384 if(message(@arg1, instance_of, xref_file_graph_node), 385 message(@arg1, create_export_links))). 386 387layout(G, MoveOnly:[chain]) :-> 388 "Do graph layout":: 389 get(G?graphicals, find_all, 390 message(@arg1, instance_of, xref_file_graph_node), Nodes), 391 get(Nodes, find_all, not(@arg1?connections), UnConnected), 392 send(Nodes, subtract, UnConnected), 393 new(Pos, point(10,10)), 394 send(UnConnected, for_all, 395 and(message(@arg1, position, Pos), 396 message(Pos, offset, 0, 25))), 397 get(Nodes, head, First), 398 send(First, layout, 399 nominal := 100, 400 iterations := 1000, 401 network := Nodes, 402 move_only := MoveOnly). 403 404 dragdrop). ( 406 407drop(G, Obj:object, Pos:point) :-> 408 "Drop a file on the graph":: 409 ( send(Obj, instance_of, xref_file_text) 410 -> get(Obj, path, File), 411 ( get(G, node, File, Node) 412 -> send(Node, flash) 413 ; get(G, node, File, always, Pos, _Node), 414 send(G, update_links) 415 ) 416 ; send(Obj, instance_of, xref_directory_text) 417 -> get(Obj, files, Files), 418 layout_new(G, 419 ( send(Files, for_all, 420 message(G, append, @arg1, always)), 421 send(G, update_links) 422 )) 423 ). 424 425preview_drop(G, Obj:object*, Pos:point) :-> 426 "Show preview of drop":: 427 ( Obj == @nil 428 -> send(G, report, status, '') 429 ; send(Obj, instance_of, xref_file_text) 430 -> ( get(Obj, device, G) 431 -> send(Obj, move, Pos) 432 ; get(Obj, path, File), 433 get(Obj, string, Label), 434 ( get(G, node, File, _Node) 435 -> send(G, report, status, '%s: already in graph', Label) 436 ; send(G, report, status, 'Add %s to graph', Label) 437 ) 438 ) 439 ; send(Obj, instance_of, xref_directory_text) 440 -> get(Obj, path, Path), 441 send(G, report, status, 'Add files from directory %s', Path) 442 ). 443 xref_depgraph). ( 445 xref_file_graph_node, xref_file_text). ( 447 448:- send(@class, handle, handle(w/2, 0, link, north)). 449:- send(@class, handle, handle(w, h/2, link, west)). 450:- send(@class, handle, handle(w/2, h, link, south)). 451:- send(@class, handle, handle(0, h/2, link, east)). 452 453initialise(N, File:name) :-> 454 send_super(N, initialise, File), 455 send(N, font, bold), 456 send(N, background, grey80). 457 458create_export_links(N, Add:[bool]) :-> 459 "Create the export links to other files":: 460 get(N, path, Exporter), 461 forall(export_link(Exporter, Importer, Callables), 462 create_export_link(N, Add, Importer, Callables)). 463 464create_export_link(From, Add, Importer, Callables) :- 465 ( get(From?device, node, Importer, Add, INode) 466 -> send(From, link, INode, Callables) 467 ; true 468 ). 469 470create_import_links(N, Add:[bool]) :-> 471 "Create the import links from other files":: 472 get(N, path, Importer), 473 forall(export_link(Exporter, Importer, Callables), 474 create_import_link(N, Add, Exporter, Callables)). 475 476create_import_link(From, Add, Importer, Callables) :- 477 ( get(From?device, node, Importer, Add, INode) 478 -> send(INode, link, From, Callables) 479 ; true 480 ). 481 482link(N, INode:xref_file_graph_node, Callables:prolog) :-> 483 "Create export link to INode":: 484 ( get(N, connections, INode, CList), 485 get(CList, find, @arg1?from == N, C) 486 -> send(C, callables, Callables) 487 ; new(L, xref_export_connection(N, INode, Callables)), 488 send(L, hide) 489 ). 490 491:- pce_global(@xref_file_graph_node_recogniser, 492 make_xref_file_graph_node_recogniser). 493 494make_xref_file_graph_node_recogniser(G) :- 495 new(G, move_gesture(left, '')). 496 497event(N, Ev:event) :-> 498 "Add moving (overrule supreclass":: 499 ( send(@xref_file_graph_node_recogniser, event, Ev) 500 -> true 501 ; send_super(N, event, Ev) 502 ). 503 504popup(N, Popup:popup) :<- 505 get_super(N, popup, Popup), 506 send_list(Popup, append, 507 [ gap, 508 menu_item(show_exports, 509 message(@arg1, show_import_exports, export)), 510 menu_item(show_imports, 511 message(@arg1, show_import_exports, import)), 512 gap, 513 menu_item(hide, 514 message(@arg1, destroy)) 515 ]). 516 517show_import_exports(N, Which:{import,export}) :-> 518 "Show who I'm exporting to":: 519 get(N, device, G), 520 layout_new(G, 521 ( ( Which == export 522 -> send(N, create_export_links, @on) 523 ; send(N, create_import_links, @on) 524 ), 525 send(G, update_links) 526 )). 527 528layout_new(G, Goal) :- 529 get(G?graphicals, find_all, 530 message(@arg1, instance_of, xref_file_graph_node), Nodes0), 531 , 532 get(G?graphicals, find_all, 533 message(@arg1, instance_of, xref_file_graph_node), Nodes), 534 send(Nodes, subtract, Nodes0), 535 ( send(Nodes, empty) 536 -> send(G, report, status, 'No nodes added') 537 ; send(G, layout, Nodes), 538 get(Nodes, size, Size), 539 send(G, report, status, '%d nodes added', Size) 540 ). 541 xref_file_graph_node). ( 543 xref_export_connection, tagged_connection). ( 545 callables, prolog, get, "Callables in Import/export link"). ( 547 548initialise(C, From:xref_file_graph_node, To:xref_file_graph_node, 549 Callables:prolog) :-> 550 send_super(C, initialise, From, To), 551 send(C, arrows, second), 552 send(C, slot, callables, Callables), 553 length(Callables, N), 554 send(C, tag, xref_export_connection_tag(C, N)). 555 556callables(C, Callables:prolog) :-> 557 send(C, slot, callables, Callables). % TBD: update tag? 558 559called_by_popup(Conn, P:popup) :<- 560 "Create popup to show relating predicates":: 561 new(P, popup(called_by, message(Conn, edit_callable, @arg1))), 562 get(Conn, callables, Callables), 563 get(Conn?from, path, ExportFile), 564 get(Conn?to, path, ImportFile), 565 sort_callables(Callables, Sorted), 566 forall(member(C, Sorted), 567 append_io_callable(P, ImportFile, ExportFile, C)).
571append_io_callable(P, ImportFile, ExportFile, Callable) :- 572 callable_to_label(Callable, Label), 573 send(P, append, new(MI, menu_item(@nil, @default, Label))), 574 send(MI, popup, new(P2, popup)), 575 send(P2, append, 576 menu_item(prolog('<definition>'(Callable)), 577 @default, definition?label_name)), 578 send(P2, append, gap), 579 qualify_from_file(Callable, ExportFile, QCall), 580 findall(By, used_in(ImportFile, QCall, By), ByList0), 581 sort_callables(ByList0, ByList), 582 forall(member(C, ByList), 583 ( callable_to_label(C, CLabel), 584 send(P2, append, menu_item(prolog(C), @default, CLabel)))). 585 586edit_callable(C, Callable:prolog) :-> 587 "Edit definition or callers":: 588 ( Callable = '<definition>'(Def) 589 -> get(C?from, path, ExportFile), 590 edit_callable(Def, ExportFile) 591 ; get(C?to, path, ImportFile), 592 edit_callable(Callable, ImportFile) 593 ). 594 xref_export_connection). ( 596 597 xref_export_connection_tag, text, 599 "Text showing import/export count"). ( 600 connection, xref_export_connection, get, "Related connection"). ( 602 603initialise(Tag, C:xref_export_connection, N:int) :-> 604 send(Tag, slot, connection, C), 605 send_super(Tag, initialise, string('(%d)', N)), 606 send(Tag, colour, blue), 607 send(Tag, underline, @on). 608 @xref_export_connection_tag_recogniser, 610 new(popup_gesture(@receiver?connection?called_by_popup, left))). ( 611 612event(Tag, Ev:event) :-> 613 ( send_super(Tag, event, Ev) 614 -> true 615 ; send(@xref_export_connection_tag_recogniser, event, Ev) 616 ). 617 xref_export_connection_tag). (
627export_link(ExportFile, ImportingFile, Callables) :- 628 setof(Callable, 629 export_link_1(ExportFile, ImportingFile, Callable), 630 Callables0), 631 sort_callables(Callables0, Callables). 632 633 634export_link_1(ExportFile, ImportFile, Callable) :- % module export 635 nonvar(ExportFile), 636 xref_module(ExportFile, Module), 637 !, 638 ( xref_exported(ExportFile, Callable), 639 xref_defined(ImportFile, Callable, imported(ExportFile)), 640 xref_called(ImportFile, Callable) 641 ; defined(ExportFile, Callable), 642 single_qualify(Module:Callable, QCall), 643 xref_called(ImportFile, QCall) 644 ), 645 ImportFile \== ExportFile, 646 atom(ImportFile). 647export_link_1(ExportFile, ImportFile, Callable) :- % Non-module export 648 nonvar(ExportFile), 649 !, 650 defined(ExportFile, Callable), 651 xref_called(ImportFile, Callable), 652 atom(ImportFile), 653 ExportFile \== ImportFile. 654export_link_1(ExportFile, ImportFile, Callable) :- % module import 655 nonvar(ImportFile), 656 xref_module(ImportFile, Module), 657 !, 658 xref_called(ImportFile, Callable), 659 ( xref_defined(ImportFile, Callable, imported(ExportFile)) 660 ; single_qualify(Module:Callable, QCall), 661 QCall = M:G, 662 ( defined(ExportFile, G), 663 xref_module(ExportFile, M) 664 ; defined(ExportFile, QCall) 665 ) 666 ), 667 ImportFile \== ExportFile, 668 atom(ExportFile). 669export_link_1(ExportFile, ImportFile, Callable) :- % Non-module import 670 xref_called(ImportFile, Callable), 671 \+ ( xref_defined(ImportFile, Callable, How), 672 How \= imported(_) 673 ), 674 % see also undefined/2 675 ( xref_defined(ImportFile, Callable, imported(ExportFile)) 676 ; defined(ExportFile, Callable), 677 \+ xref_module(ExportFile, _) 678 ; Callable = _:_, 679 defined(ExportFile, Callable) 680 ; Callable = M:G, 681 defined(ExportFile, G), 682 xref_module(ExportFile, M) 683 ). 684 685 686 /******************************* 687 * FILTER * 688 *******************************/ 689 xref_filter_dialog, dialog, 691 "Show filter options"). ( 692 border, size, size(0,0)). ( 694 695initialise(D) :-> 696 send_super(D, initialise), 697 send(D, hor_stretch, 100), 698 send(D, hor_shrink, 100), 699 send(D, name, filter_dialog), 700 send(D, append, xref_file_filter_item(filter_on_filename)). 701 702resize(D) :-> 703 send(D, layout, D?visible?size). 704 xref_filter_dialog). ( 706 707 xref_file_filter_item, text_item, 709 "Filter files as you type"). ( 710 711typed(FFI, Id) :-> 712 "Activate filter":: 713 send_super(FFI, typed, Id), 714 get(FFI, displayed_value, Current), 715 get(FFI?frame, browser, files, Tree), 716 ( send(Current, equal, '') 717 -> send(Tree, filter_file_name, @nil) 718 ; ( text_to_regex(Current, Filter) 719 -> send(Tree, filter_file_name, Filter) 720 ; send(FFI, report, status, 'Incomplete expression') 721 ) 722 ).
729text_to_regex(Pattern, Regex) :- 730 send(@pce, last_error, @nil), 731 new(Regex, regex(Pattern)), 732 ignore(pce_catch_error(_, send(Regex, search, ''))), 733 get(@pce, last_error, @nil). 734 xref_file_filter_item). ( 736 737 738 739 /******************************* 740 * FILE TREE * 741 *******************************/ 742 xref_file_tree, toc_window, 744 "Show loaded files as a tree"). (arm). ( 746 747initialise(Tree) :-> 748 send_super(Tree, initialise), 749 send(Tree, clear), 750 listen(Tree, xref_refresh_file(File), 751 send(Tree, refresh_file, File)). 752 753unlink(Tree) :-> 754 unlisten(Tree), 755 send_super(Tree, unlink). 756 757refresh_file(Tree, File:name) :-> 758 "Update given file":: 759 ( get(Tree, node, File, Node) 760 -> send(Node, set_flags) 761 ; true 762 ). 763 764collapse_node(_, _:any) :-> 765 true. 766 767expand_node(_, _:any) :-> 768 true. 769 770update(FL) :-> 771 get(FL, expanded_ids, Chain), 772 send(FL, clear), 773 send(FL, report, progress, 'Building source tree ...'), 774 send(FL, append_all_sourcefiles), 775 send(FL, expand_ids, Chain), 776 send(@display, synchronise), 777 send(FL, report, progress, 'Flagging files ...'), 778 send(FL, set_flags), 779 send(FL, report, done). 780 781append_all_sourcefiles(FL) :-> 782 "Append all files loaded into Prolog":: 783 forall(source_file(File), 784 send(FL, append, File)), 785 send(FL, sort). 786 787clear(Tree) :-> 788 "Remove all nodes, recreate the toplevel":: 789 send_super(Tree, clear), 790 send(Tree, root, new(Root, toc_folder(project, project))), 791 forall(top_node(Name, Class), 792 ( New =.. [Class, Name, Name], 793 send(Tree, son, project, New))), 794 send(Root, for_all, message(@arg1, collapsed, @off)). 795 796append(Tree, File:name) :-> 797 "Add Prolog source file":: 798 send(Tree, append_node, new(prolog_file_node(File))). 799 800append_node(Tree, Node:toc_node) :-> 801 "Append a given node to the tree":: 802 get(Node, parent_id, ParentId), 803 ( get(Tree, node, ParentId, Parent) 804 -> true 805 ; send(Tree, append_node, 806 new(Parent, prolog_directory_node(ParentId))) 807 ), 808 send(Parent, son, Node). 809 810sort(Tree) :-> 811 forall(top_node(Name, _), 812 ( get(Tree, node, Name, Node), 813 send(Node, sort_sons, ?(@arg1, compare, @arg2)), 814 send(Node?sons, for_all, message(@arg1, sort)) 815 )). 816 817select_node(Tree, File:name) :-> 818 "User selected a node":: 819 ( exists_file(File) 820 -> send(Tree?frame, file_info, File) 821 ; true 822 ). 823 824set_flags(Tree) :-> 825 "Set alert-flags on all nodes":: 826 forall(top_node(Name, _), 827 ( get(Tree, node, Name, Node), 828 ( send(Node, instance_of, prolog_directory_node) 829 -> send(Node, set_flags) 830 ; send(Node?sons, for_all, message(@arg1, set_flags)) 831 ) 832 )). 833 834top_node('.', prolog_directory_node). 835top_node('alias', toc_folder). 836top_node('/', prolog_directory_node). 837 838 filter). ( 840 841filter_file_name(Tree, Regex:regex*) :-> 842 "Only show files that match Regex":: 843 ( Regex == @nil 844 -> send(Tree, filter_files, @nil) 845 ; send(Tree, filter_files, 846 message(Regex, search, @arg1?base_name)) 847 ). 848 849filter_files(Tree, Filter:code*) :-> 850 "Highlight files that match Filter":: 851 send(Tree, collapse_all), 852 send(Tree, selection, @nil), 853 ( Filter == @nil 854 -> send(Tree, expand_id, '.'), 855 send(Tree, expand_id, project) 856 ; new(Count, number(0)), 857 get(Tree?tree, root, Root), 858 send(Root, for_all, 859 if(and(message(@arg1, instance_of, prolog_file_node), 860 message(Filter, forward, @arg1)), 861 and(message(Tree, show_node_path, @arg1), 862 message(Count, plus, 1)))), 863 send(Tree, report, status, 'Filter on file name: %d hits', Count) 864 ), 865 send(Tree, scroll_to, point(0,0)). 866 867show_node_path(Tree, Node:node) :-> 868 "Select Node and make sure all parents are expanded":: 869 send(Node, selected, @on), 870 send(Tree, expand_parents, Node). 871 872expand_parents(Tree, Node:node) :-> 873 ( get(Node, collapsed, @nil) 874 -> true 875 ; send(Node, collapsed, @off) 876 ), 877 send(Node?parents, for_all, message(Tree, expand_parents, @arg1)). 878 879collapse_all(Tree) :-> 880 "Collapse all nodes":: 881 get(Tree?tree, root, Root), 882 send(Root, for_all, 883 if(@arg1?collapsed == @off, 884 message(@arg1, collapsed, @on))). 885 xref_file_tree). ( 887 888 prolog_directory_node, toc_folder, 890 "Represent a directory"). ( 891 flags, name*, get, "Warning status"). ( 893 894initialise(DN, Dir:name, Label:[name]) :-> 895 "Create a directory node":: 896 ( Label \== @default 897 -> Name = Label 898 ; file_alias_path(Name, Dir) 899 -> true 900 ; file_base_name(Dir, Name) 901 ), 902 send_super(DN, initialise, xref_directory_text(Dir, Name), Dir). 903 904parent_id(FN, ParentId:name) :<- 905 "Get id for the parent":: 906 get(FN, identifier, Path), 907 ( file_alias_path(_, Path) 908 -> ParentId = alias 909 ; file_directory_name(Path, ParentId) 910 ). 911 912sort(DN) :-> 913 "Sort my sons":: 914 send(DN, sort_sons, ?(@arg1, compare, @arg2)), 915 send(DN?sons, for_all, message(@arg1, sort)). 916 917compare(DN, Node:toc_node, Diff:{smaller,equal,larger}) :<- 918 "Compare for sorting children":: 919 ( send(Node, instance_of, prolog_file_node) 920 -> Diff = smaller 921 ; get(DN, label, L1), 922 get(Node, label, L2), 923 get(L1, compare, L2, Diff) 924 ). 925 926set_flags(DN) :-> 927 "Set alert images":: 928 send(DN?sons, for_all, message(@arg1, set_flags)), 929 ( get(DN?sons, find, @arg1?flags \== ok, _Node) 930 -> send(DN, collapsed_image, @xref_alert_closedir), 931 send(DN, expanded_image, @xref_alert_opendir), 932 send(DN, slot, flags, alert) 933 ; send(DN, collapsed_image, @xref_ok_closedir), 934 send(DN, expanded_image, @xref_ok_opendir), 935 send(DN, slot, flags, ok) 936 ), 937 send(@display, synchronise). 938 prolog_directory_node). ( 940 941 prolog_file_node, toc_file, 943 "Represent a file"). ( 944 flags, name*, get, "Warning status"). (base_name, name, get, "Base-name of file"). ( 947 948initialise(FN, File:name) :-> 949 "Create from a file":: 950 absolute_file_name(File, Path), 951 send_super(FN, initialise, new(T, xref_file_text(Path)), Path), 952 file_base_name(File, Base), 953 send(FN, slot, base_name, Base), 954 send(T, default_action, info). 955 956basename(FN, BaseName:name) :<- 957 "Get basename of the file for sorting":: 958 get(FN, identifier, File), 959 file_base_name(File, BaseName). 960 961parent_id(FN, ParentId:name) :<- 962 "Get id for the parent":: 963 get(FN, identifier, Path), 964 file_directory_name(Path, Dir), 965 ( file_alias_path('.', Dir) 966 -> ParentId = '.' 967 ; ParentId = Dir 968 ). 969 970sort(_) :-> 971 true. 972 973compare(FN, Node:toc_node, Diff:{smaller,equal,larger}) :<- 974 "Compare for sorting children":: 975 ( send(Node, instance_of, prolog_directory_node) 976 -> Diff = larger 977 ; get(FN, basename, L1), 978 get(Node, basename, L2), 979 get(L1, compare, L2, Diff) 980 ). 981 982set_flags(FN) :-> 983 "Set alert images":: 984 get(FN, identifier, File), 985 ( file_warnings(File, _) 986 -> send(FN, image, @xref_alert_file), 987 send(FN, slot, flags, alert) 988 ; send(FN, image, @xref_ok_file), 989 send(FN, slot, flags, ok) 990 ), 991 send(@display, synchronise). 992 993:- pce_global(@xref_ok_file, 994 make_xref_image([ image('16x16/doc.xpm'), 995 image('16x16/ok.xpm') 996 ])). 997:- pce_global(@xref_alert_file, 998 make_xref_image([ image('16x16/doc.xpm'), 999 image('16x16/alert.xpm') 1000 ])). 1001 1002:- pce_global(@xref_ok_opendir, 1003 make_xref_image([ image('16x16/opendir.xpm'), 1004 image('16x16/ok.xpm') 1005 ])). 1006:- pce_global(@xref_alert_opendir, 1007 make_xref_image([ image('16x16/opendir.xpm'), 1008 image('16x16/alert.xpm') 1009 ])). 1010 1011:- pce_global(@xref_ok_closedir, 1012 make_xref_image([ image('16x16/closedir.xpm'), 1013 image('16x16/ok.xpm') 1014 ])). 1015:- pce_global(@xref_alert_closedir, 1016 make_xref_image([ image('16x16/closedir.xpm'), 1017 image('16x16/alert.xpm') 1018 ])). 1019 1020make_xref_image([First|More], Image) :- 1021 new(Image, image(@nil, 0, 0, pixmap)), 1022 send(Image, copy, First), 1023 forall(member(I2, More), 1024 send(Image, draw_in, bitmap(I2))). 1025 prolog_file_node). ( 1027 1028 1029 1030 1031 /******************************* 1032 * FILE INFO * 1033 *******************************/ 1034 1035 prolog_file_info, window, 1037 "Show information on File"). (arm). ( 1039 tabular, tabular, get, "Displayed table"). (prolog_file, name*, get, "Displayed Prolog file"). ( 1042 1043initialise(W, File:[name]*) :-> 1044 send_super(W, initialise), 1045 send(W, pen, 0), 1046 send(W, scrollbars, vertical), 1047 send(W, display, new(T, tabular)), 1048 send(T, rules, all), 1049 send(T, cell_spacing, -1), 1050 send(W, slot, tabular, T), 1051 ( atom(File) 1052 -> send(W, prolog_file, File) 1053 ; true 1054 ). 1055 1056resize(W) :-> 1057 send_super(W, resize), 1058 get(W?visible, width, Width), 1059 send(W?tabular, table_width, Width-3). 1060 1061 1062file(V, File0:name*) :-> 1063 "Set vizualized file":: 1064 ( File0 == @nil 1065 -> File = File0 1066 ; absolute_file_name(File0, File) 1067 ), 1068 ( get(V, prolog_file, File) 1069 -> true 1070 ; send(V, slot, prolog_file, File), 1071 send(V, update) 1072 ). 1073 1074 1075clear(W) :-> 1076 send(W?tabular, clear). 1077 1078 1079update(V) :-> 1080 "Show information on the current file":: 1081 send(V, clear), 1082 send(V, scroll_to, point(0,0)), 1083 ( get(V, prolog_file, File), 1084 File \== @nil 1085 -> send(V?frame, xref_file, File), % Make sure data is up-to-date 1086 send(V, show_info) 1087 ; true 1088 ). 1089 1090 1091module(W, Module:name) :<- 1092 "Module associated with this file":: 1093 get(W, prolog_file, File), 1094 ( xref_module(File, Module) 1095 -> true 1096 ; Module = user % TBD: does not need to be true! 1097 ). 1098 info). ( 1100 1101show_info(W) :-> 1102 get(W, tabular, T), 1103 BG = (background := khaki1), 1104 get(W, prolog_file, File), 1105 new(FG, xref_file_text(File)), 1106 send(FG, font, huge), 1107 send(T, append, FG, halign := center, colspan := 2, BG), 1108 send(T, next_row), 1109 send(W, show_module), 1110 send(W, show_modified), 1111 send(W, show_undefined), 1112 send(W, show_not_called), 1113 send(W, show_exports), 1114 send(W, show_imports), 1115 true. 1116 1117show_module(W) :-> 1118 "Show basic module info":: 1119 get(W, prolog_file, File), 1120 get(W, tabular, T), 1121 ( xref_module(File, Module) 1122 -> send(T, append, 'Module:', bold, right), 1123 send(T, append, Module), 1124 send(T, next_row) 1125 ; true 1126 ). 1127 1128show_modified(W) :-> 1129 get(W, prolog_file, File), 1130 get(W, tabular, T), 1131 time_file(File, Stamp), 1132 format_time(string(Modified), '%+', Stamp), 1133 send(T, append, 'Modified:', bold, right), 1134 send(T, append, Modified), 1135 send(T, next_row). 1136 1137show_exports(W) :-> 1138 get(W, prolog_file, File), 1139 ( xref_module(File, Module), 1140 findall(E, xref_exported(File, E), Exports), 1141 Exports \== [] 1142 -> send(W, show_export_header, export, imported_by), 1143 sort_callables(Exports, Sorted), 1144 forall(member(Callable, Sorted), 1145 send(W, show_module_export, File, Module, Callable)) 1146 ; true 1147 ), 1148 ( findall(C-Fs, 1149 ( setof(F, export_link_1(File, F, C), Fs), 1150 \+ xref_exported(File, C)), 1151 Pairs0), 1152 Pairs0 \== [] 1153 -> send(W, show_export_header, defined, used_by), 1154 keysort(Pairs0, Pairs), % TBD 1155 forall(member(Callable-ImportFiles, Pairs), 1156 send(W, show_file_export, Callable, ImportFiles)) 1157 ; true 1158 ). 1159 1160show_export_header(W, Left:name, Right:name) :-> 1161 get(W, tabular, T), 1162 BG = (background := khaki1), 1163 send(T, append, Left?label_name, bold, center, BG), 1164 send(T, append, Right?label_name, bold, center, BG), 1165 send(T, next_row). 1166 1167show_module_export(W, File:name, Module:name, Callable:prolog) :-> 1168 get(W, prolog_file, File), 1169 get(W, tabular, T), 1170 send(T, append, xref_predicate_text(Module:Callable, @default, File)), 1171 findall(In, exported_to(File, Callable, In), InL), 1172 send(T, append, new(XL, xref_graphical_list)), 1173 ( InL == [] 1174 -> true 1175 ; sort_files(InL, Sorted), 1176 forall(member(F, Sorted), 1177 send(XL, append, xref_imported_by(F, Callable))) 1178 ), 1179 send(T, next_row). 1180 1181show_file_export(W, Callable:prolog, ImportFiles:prolog) :-> 1182 get(W, prolog_file, File), 1183 get(W, tabular, T), 1184 send(T, append, xref_predicate_text(Callable, @default, File)), 1185 send(T, append, new(XL, xref_graphical_list)), 1186 sort_files(ImportFiles, Sorted), 1187 qualify_from_file(Callable, File, QCall), 1188 forall(member(F, Sorted), 1189 send(XL, append, xref_imported_by(F, QCall))), 1190 send(T, next_row). 1191 1192qualify_from_file(Callable, _, Callable) :- 1193 Callable = _:_, 1194 !. 1195qualify_from_file(Callable, File, M:Callable) :- 1196 xref_module(File, M), 1197 !. 1198qualify_from_file(Callable, _, Callable).
TBD: Make sure the autoload library is loaded before we begin.
1208exported_to(ExportFile, Callable, ImportFile) :- 1209 xref_defined(ImportFile, Callable, imported(ExportFile)), 1210 atom(ImportFile). % avoid XPCE buffers. 1211exported_to(ExportFile, Callable, ImportFile) :- 1212 '$autoload':library_index(Callable, _, ExportFileNoExt), 1213 file_name_extension(ExportFileNoExt, _, ExportFile), 1214 xref_called(ImportFile, Callable), 1215 atom(ImportFile), 1216 \+ xref_defined(ImportFile, Callable, _). 1217 1218show_imports(W) :-> 1219 "Show predicates we import":: 1220 get(W, prolog_file, File), 1221 findall(E-Cs, 1222 setof(C, export_link_1(E, File, C), Cs), 1223 Pairs), 1224 ( Pairs \== [] 1225 -> sort(Pairs, Sorted), % TBD: use sort_files/2 1226 ( xref_module(File, _) 1227 -> send(W, show_export_header, from, imports) 1228 ; send(W, show_export_header, from, uses) 1229 ), 1230 forall(member(E-Cs, Sorted), 1231 send(W, show_import, E, Cs)) 1232 ; true 1233 ). 1234 1235show_import(W, File:name, Callables:prolog) :-> 1236 "Show imports from file":: 1237 get(W, tabular, T), 1238 send(T, append, xref_file_text(File)), 1239 send(T, append, new(XL, xref_graphical_list)), 1240 sort_callables(Callables, Sorted), 1241 forall(member(C, Sorted), 1242 send(XL, append, xref_predicate_text(C, @default, File))), 1243 send(T, next_row). 1244 1245 1246show_undefined(W) :-> 1247 "Add underfined predicates to table":: 1248 get(W, prolog_file, File), 1249 findall(Undef, undefined(File, Undef), UndefList), 1250 ( UndefList == [] 1251 -> true 1252 ; BG = (background := khaki1), 1253 get(W, tabular, T), 1254 ( setting(warn_autoload, true) 1255 -> Label = 'Undefined/autoload' 1256 ; Label = 'Undefined' 1257 ), 1258 send(T, append, Label, bold, center, BG), 1259 send(T, append, 'Called by', bold, center, BG), 1260 send(T, next_row), 1261 sort_callables(UndefList, Sorted), 1262 forall(member(Callable, Sorted), 1263 send(W, show_undef, Callable)) 1264 ). 1265 1266show_undef(W, Callable:prolog) :-> 1267 "Show undefined predicate":: 1268 get(W, prolog_file, File), 1269 get(W, module, Module), 1270 get(W, tabular, T), 1271 send(T, append, 1272 xref_predicate_text(Module:Callable, undefined, File)), 1273 send(T, append, new(L, xref_graphical_list)), 1274 findall(By, xref_called(File, Callable, By), By), 1275 sort_callables(By, Sorted), 1276 forall(member(P, Sorted), 1277 send(L, append, xref_predicate_text(Module:P, called_by, File))), 1278 send(T, next_row). 1279 1280 1281show_not_called(W) :-> 1282 "Show predicates that are not called":: 1283 get(W, prolog_file, File), 1284 findall(NotCalled, not_called(File, NotCalled), NotCalledList), 1285 ( NotCalledList == [] 1286 -> true 1287 ; BG = (background := khaki1), 1288 get(W, tabular, T), 1289 send(T, append, 'Not called', bold, center, colspan := 2, BG), 1290 send(T, next_row), 1291 sort_callables(NotCalledList, Sorted), 1292 forall(member(Callable, Sorted), 1293 send(W, show_not_called_pred, Callable)) 1294 ). 1295 1296show_not_called_pred(W, Callable:prolog) :-> 1297 "Show a not-called predicate":: 1298 get(W, prolog_file, File), 1299 get(W, module, Module), 1300 get(W, tabular, T), 1301 send(T, append, 1302 xref_predicate_text(Module:Callable, not_called, File), 1303 colspan := 2), 1304 send(T, next_row). 1305 prolog_file_info). ( 1307 1308 xref_predicate_text, text, 1310 "Text representing a predicate"). ( 1311 colour, colour, dark_green). ( 1313 callable, prolog, get, "Predicate indicator"). (classification, [name], get, "Classification of the predicate"). (file, name*, get, "File of predicate"). ( 1317 1318initialise(T, Callable0:prolog, 1319 Class:[{undefined,called_by,not_called}], 1320 File:[name]) :-> 1321 "Create from callable or predicate indicator":: 1322 single_qualify(Callable0, Callable), 1323 send(T, slot, callable, Callable), 1324 callable_to_label(Callable, File, Label), 1325 send_super(T, initialise, Label), 1326 ( File \== @default 1327 -> send(T, slot, file, File) 1328 ; true 1329 ), 1330 send(T, classification, Class).
1336single_qualify(_:Q0, Q) :- 1337 is_qualified(Q0), 1338 !, 1339 single_qualify(Q0, Q). 1340single_qualify(Q, Q). 1341 1342is_qualified(M:_) :- 1343 atom(M). 1344 1345pi(IT, PI:prolog) :<- 1346 "Get predicate as predicate indicator (Name/Arity)":: 1347 get(IT, callable, Callable), 1348 to_predicate_indicator(Callable, PI). 1349 1350classification(T, Class:[name]) :-> 1351 send(T, slot, classification, Class), 1352 ( Class == undefined 1353 -> get(T, callable, Callable), 1354 strip_module(Callable, _, Plain), 1355 ( autoload_predicate(Plain) 1356 -> send(T, colour, navy_blue), 1357 send(T, slot, classification, autoload) 1358 ; global_predicate(Plain) 1359 -> send(T, colour, navy_blue), 1360 send(T, slot, classification, global) 1361 ; send(T, colour, red) 1362 ) 1363 ; Class == not_called 1364 -> send(T, colour, red) 1365 ; true 1366 ). 1367 @xref_predicate_text_recogniser, 1369 new(handler_group(@arm_recogniser, 1370 click_gesture(left, '', single, 1371 message(@receiver, edit))))). ( 1372 1373event(T, Ev:event) :-> 1374 ( send_super(T, event, Ev) 1375 -> true 1376 ; send(@xref_predicate_text_recogniser, event, Ev) 1377 ). 1378 1379 1380arm(TF, Val:bool) :-> 1381 "Preview activiity":: 1382 ( Val == @on 1383 -> send(TF, underline, @on), 1384 ( get(TF, classification, Class), 1385 Class \== @default 1386 -> send(TF, report, status, 1387 '%s predicate %s', Class?capitalise, TF?string) 1388 ; send(TF, report, status, 1389 'Predicate %s', TF?string) 1390 ) 1391 ; send(TF, underline, @off), 1392 send(TF, report, status, '') 1393 ). 1394 1395edit(T) :-> 1396 get(T, file, File), 1397 get(T, callable, Callable), 1398 edit_callable(Callable, File). 1399 xref_predicate_text). ( 1401 1402 xref_file_text, text, 1404 "Represent a file-name"). ( 1405 path, name, get, "Filename represented"). (default_action, name := edit, both, "Default on click"). ( 1408 1409initialise(TF, File:name) :-> 1410 absolute_file_name(File, Path), 1411 file_name_on_path(Path, ShortId), 1412 short_file_name_to_atom(ShortId, Label), 1413 send_super(TF, initialise, Label), 1414 send(TF, name, Path), 1415 send(TF, slot, path, Path). 1416 1417:- pce_global(@xref_file_text_recogniser, 1418 make_xref_file_text_recogniser). 1419 1420make_xref_file_text_recogniser(G) :- 1421 new(C, click_gesture(left, '', single, 1422 message(@receiver, run_default_action))), 1423 new(P, popup_gesture(@arg1?popup)), 1424 new(D, drag_and_drop_gesture(left)), 1425 send(D, cursor, @default), 1426 new(G, handler_group(C, D, P, @arm_recogniser)). 1427 1428popup(_, Popup:popup) :<- 1429 new(Popup, popup), 1430 send_list(Popup, append, 1431 [ menu_item(edit, message(@arg1, edit)), 1432 menu_item(info, message(@arg1, info)), 1433 menu_item(header, message(@arg1, header)) 1434 ]). 1435 1436event(T, Ev:event) :-> 1437 ( send_super(T, event, Ev) 1438 -> true 1439 ; send(@xref_file_text_recogniser, event, Ev) 1440 ). 1441 1442arm(TF, Val:bool) :-> 1443 "Preview activity":: 1444 ( Val == @on 1445 -> send(TF, underline, @on), 1446 send(TF, report, status, 'File %s', TF?path) 1447 ; send(TF, underline, @off), 1448 send(TF, report, status, '') 1449 ). 1450 1451run_default_action(T) :-> 1452 get(T, default_action, Def), 1453 send(T, Def). 1454 1455edit(T) :-> 1456 get(T, path, Path), 1457 auto_call(edit(file(Path))). 1458 1459info(T) :-> 1460 get(T, path, Path), 1461 send(T?frame, file_info, Path). 1462 1463header(T) :-> 1464 get(T, path, Path), 1465 send(T?frame, file_header, Path). 1466 1467prolog_source(T, Src:string) :<- 1468 "Import declarations":: 1469 get(T, path, File), 1470 new(V, xref_view), 1471 send(V, file_header, File), 1472 get(V?text_buffer, contents, Src), 1473 send(V, destroy). 1474 xref_file_text). ( 1476 1477 xref_directory_text, text, 1479 "Represent a directory-name"). ( 1480 path, name, get, "Filename represented"). ( 1482 1483initialise(TF, Dir:name, Label:[name]) :-> 1484 absolute_file_name(Dir, Path), 1485 ( Label == @default 1486 -> file_base_name(Path, TheLabel) 1487 ; TheLabel = Label 1488 ), 1489 send_super(TF, initialise, TheLabel), 1490 send(TF, slot, path, Path). 1491 1492files(DT, Files:chain) :<- 1493 "List of files that belong to this directory":: 1494 new(Files, chain), 1495 get(DT, path, Path), 1496 ( source_file(File), 1497 sub_atom(File, 0, _, _, Path), 1498 send(Files, append, File), 1499 fail ; true 1500 ). 1501 1502:- pce_global(@xref_directory_text_recogniser, 1503 make_xref_directory_text_recogniser). 1504 1505make_xref_directory_text_recogniser(G) :- 1506 new(D, drag_and_drop_gesture(left)), 1507 send(D, cursor, @default), 1508 new(G, handler_group(D, @arm_recogniser)). 1509 1510event(T, Ev:event) :-> 1511 ( send_super(T, event, Ev) 1512 -> true 1513 ; send(@xref_directory_text_recogniser, event, Ev) 1514 ). 1515 1516arm(TF, Val:bool) :-> 1517 "Preview activiity":: 1518 ( Val == @on 1519 -> send(TF, underline, @on), 1520 send(TF, report, status, 'Directory %s', TF?path) 1521 ; send(TF, underline, @off), 1522 send(TF, report, status, '') 1523 ). 1524 xref_directory_text). ( 1526 1527 xref_imported_by, figure, 1529 "Indicate import of callable into file"). ( 1530 callable, prolog, get, "Callable term of imported predicate"). ( 1532 1533:- pce_global(@xref_horizontal_format, 1534 make_xref_horizontal_format). 1535 1536make_xref_horizontal_format(F) :- 1537 new(F, format(vertical, 1, @on)), 1538 send(F, row_sep, 3), 1539 send(F, column_sep, 0). 1540 1541initialise(IT, File:name, Imported:prolog) :-> 1542 send_super(IT, initialise), 1543 send(IT, format, @xref_horizontal_format), 1544 send(IT, display, new(F, xref_file_text(File))), 1545 send(F, name, file_text), 1546 send(IT, slot, callable, Imported), 1547 send(IT, show_called_by). 1548 1549path(IT, Path:name) :<- 1550 "Represented file":: 1551 get(IT, member, file_text, Text), 1552 get(Text, path, Path). 1553 1554show_called_by(IT) :-> 1555 "Add number indicating calls":: 1556 get(IT, called_by, List), 1557 length(List, N), 1558 send(IT, display, new(T, text(string('(%d)', N)))), 1559 send(T, name, called_count), 1560 ( N > 0 1561 -> send(T, underline, @on), 1562 send(T, colour, blue), 1563 send(T, recogniser, @xref_called_by_recogniser) 1564 ; send(T, colour, grey60) 1565 ). 1566 1567called_by(IT, ByList:prolog) :<- 1568 "Return list of callables satisfied by the import":: 1569 get(IT, path, Source), 1570 get(IT, callable, Callable), 1571 findall(By, used_in(Source, Callable, By), ByList).
1578used_in(Source, M:Callable, By) :- % we are the same module 1579 xref_module(Source, M), 1580 !, 1581 xref_called(Source, Callable, By). 1582used_in(Source, _:Callable, By) :- % we imported 1583 xref_defined(Source, Callable, imported(_)), 1584 !, 1585 xref_called(Source, Callable, By). 1586used_in(Source, Callable, By) :- 1587 xref_called(Source, Callable, By). 1588used_in(Source, Callable, '<export>') :- 1589 xref_exported(Source, Callable). 1590 event). ( 1592 @xref_called_by_recogniser, 1594 new(popup_gesture(@receiver?device?called_by_popup, left))). ( 1595 1596called_by_popup(IT, P:popup) :<- 1597 "Show called where import is called":: 1598 new(P, popup(called_by, message(IT, edit_called_by, @arg1))), 1599 get(IT, called_by, ByList), 1600 sort_callables(ByList, Sorted), 1601 forall(member(C, Sorted), 1602 ( callable_to_label(C, Label), 1603 send(P, append, menu_item(prolog(C), @default, Label)))). 1604 1605edit_called_by(IT, Called:prolog) :-> 1606 "Edit file on the predicate Called":: 1607 get(IT, path, Source), 1608 edit_callable(Called, Source). 1609 xref_imported_by). ( 1611 1612 xref_graphical_list, figure, 1614 "Show list of exports to files"). ( 1615 wrap, {extend,wrap,wrap_fixed_width,clip} := extend, get, 1617 "Wrapping mode"). ( 1618 1619initialise(XL) :-> 1620 send_super(XL, initialise), 1621 send(XL, margin, 500, wrap). 1622 1623append(XL, I:graphical) :-> 1624 ( send(XL?graphicals, empty) 1625 -> true 1626 ; send(XL, display, text(', ')) 1627 ), 1628 send(XL, display, I). 1629 layout). ( 1631 1632:- pce_global(@xref_graphical_list_format, 1633 make_xref_graphical_list_format). 1634 1635make_xref_graphical_list_format(F) :- 1636 new(F, format(horizontal, 500, @off)), 1637 send(F, column_sep, 0), 1638 send(F, row_sep, 0). 1639 1640margin(T, Width:int*, How:[{wrap,wrap_fixed_width,clip}]) :-> 1641 "Wrap items to indicated width":: 1642 ( Width == @nil 1643 -> send(T, slot, wrap, extend), 1644 send(T, format, @rdf_composite_format) 1645 ; send(T, slot, wrap, How), 1646 How == wrap 1647 -> FmtWidth is max(10, Width), 1648 new(F, format(horizontal, FmtWidth, @off)), 1649 send(F, column_sep, 0), 1650 send(F, row_sep, 0), 1651 send(T, format, F) 1652 ; throw(tbd) 1653 ). 1654 xref_graphical_list). ( 1656 1657 1658 1659 /******************************* 1660 * PREDICATES * 1661 *******************************/ 1662 xref_predicate_browser, browser, 1664 "Show loaded files"). ( 1665 1666initialise(PL) :-> 1667 send_super(PL, initialise), 1668 send(PL, popup, new(P, popup)), 1669 send_list(P, append, 1670 [ menu_item(edit, message(@arg1, edit)) 1671 ]). 1672 1673update(PL) :-> 1674 send(PL, clear), 1675 forall((defined(File, Callable), atom(File), \+ library_file(File)), 1676 send(PL, append, Callable, @default, File)), 1677 forall((xref_current_source(File), atom(File), \+library_file(File)), 1678 forall(undefined(File, Callable), 1679 send(PL, append, Callable, undefined, File))), 1680 send(PL, sort). 1681 1682append(PL, Callable:prolog, Class:[name], File:[name]) :-> 1683 send_super(PL, append, xref_predicate_dict_item(Callable, Class, File)). 1684 xref_predicate_browser). ( 1686 1687 xref_predicate_dict_item, dict_item, 1689 "Represent a Prolog predicate"). ( 1690 callable, prolog, get, "Callable term"). (file, name*, get, "Origin file"). ( 1693 1694initialise(PI, Callable0:prolog, _Class:[name], File:[name]) :-> 1695 "Create from callable, class and file":: 1696 single_qualify(Callable0, Callable), 1697 send(PI, slot, callable, Callable), 1698 callable_to_label(Callable, Label), 1699 send_super(PI, initialise, Label), 1700 ( File \== @default 1701 -> send(PI, slot, file, File) 1702 ; true 1703 ). 1704 1705edit(PI) :-> 1706 "Edit Associated prediate":: 1707 get(PI, file, File), 1708 get(PI, callable, Callable), 1709 edit_callable(Callable, File). 1710 xref_predicate_dict_item). ( 1712 1713 1714 /******************************* 1715 * UTIL CLASSES * 1716 *******************************/ 1717 xref_view, view, 1719 "View with additional facilities for formatting"). ( 1720 1721initialise(V) :-> 1722 send_super(V, initialise), 1723 send(V, font, fixed). 1724 1725update(_) :-> 1726 true. % or ->clear? ->destroy? 1727 1728file_header(View, File:name) :-> 1729 "Create import/export fileheader for File":: 1730 ( xref_module(File, _) 1731 -> Decls = Imports 1732 ; xref_file_exports(File, Export), 1733 Decls = [Export|Imports] 1734 ), 1735 xref_file_imports(File, Imports), 1736 send(View, clear), 1737 send(View, declarations, Decls), 1738 ( ( nonvar(Export) 1739 -> send(View, report, status, 1740 'Created module header for non-module file %s', File) 1741 ; send(View, report, status, 1742 'Created import header for module file %s', File) 1743 ) 1744 -> true 1745 ; true 1746 ). 1747 1748declarations(V, Decls:prolog) :-> 1749 pce_open(V, append, Out), 1750 call_cleanup(print_decls(Decls, Out), close(Out)). 1751 1752print_decls([], _) :- !. 1753print_decls([H|T], Out) :- 1754 !, 1755 print_decls(H, Out), 1756 print_decls(T, Out). 1757print_decls(Term, Out) :- 1758 portray_clause(Out, Term). 1759 xref_view). ( 1761 1762 1763 /******************************* 1764 * FILE-NAME LOGIC * 1765 *******************************/
1771short_file_name_to_atom(Atom, Atom) :- 1772 atomic(Atom), 1773 !. 1774short_file_name_to_atom(Term, Atom) :- 1775 term_to_atom(Term, Atom).
1783library_file(Path) :-
1784 current_prolog_flag(home, Home),
1785 sub_atom(Path, 0, _, _, Home).
1791profile_file(Path) :- 1792 file_name_on_path(Path, user_profile(File)), 1793 known_profile_file(File). 1794 1795known_profile_file('.swiplrc'). 1796known_profile_file('swipl.ini'). 1797known_profile_file('.pceemacsrc'). 1798known_profile_file(File) :- 1799 sub_atom(File, 0, _, _, 'lib/xpce/emacs').
1805sort_files(Files0, Sorted) :- 1806 sort(Files0, Files), % remove duplicates 1807 maplist(key_file, Files, Keyed), 1808 keysort(Keyed, KSorted), 1809 unkey(KSorted, Sorted). 1810 1811key_file(File, Key-File) :- 1812 file_name_on_path(File, Key). 1813 1814 1815 /******************************* 1816 * PREDICATES * 1817 *******************************/
1823available(File, Called, How) :- 1824 xref_defined(File, Called, How0), 1825 !, 1826 How = How0. 1827available(_, Called, How) :- 1828 built_in_predicate(Called), 1829 !, 1830 How = builtin. 1831available(_, Called, How) :- 1832 setting(warn_autoload, false), 1833 autoload_predicate(Called), 1834 !, 1835 How = autoload. 1836available(_, Called, How) :- 1837 setting(warn_autoload, false), 1838 global_predicate(Called), 1839 !, 1840 How = global. 1841available(_, Called, How) :- 1842 Called = _:_, 1843 defined(_, Called), 1844 !, 1845 How = module_qualified. 1846available(_, M:G, How) :- 1847 defined(ExportFile, G), 1848 xref_module(ExportFile, M), 1849 !, 1850 How = module_overruled. 1851available(_, Called, How) :- 1852 defined(ExportFile, Called), 1853 \+ xref_module(ExportFile, _), 1854 !, 1855 How == plain_file.
1862built_in_predicate(Goal) :-
1863 strip_module(Goal, _, Plain),
1864 xref_built_in(Plain).
1872autoload_predicate(Goal) :- 1873 '$autoload':library_index(Goal, _, _). 1874 1875 1876autoload_predicate(Goal, File) :- 1877 '$autoload':library_index(Goal, _, FileNoExt), 1878 file_name_extension(FileNoExt, pl, File).
1886global_predicate(Goal) :-
1887 predicate_property(user:Goal, _),
1888 !.
1894to_predicate_indicator(PI, PI) :- 1895 is_predicate_indicator(PI), 1896 !. 1897to_predicate_indicator(Callable, PI) :- 1898 callable(Callable), 1899 predicate_indicator(Callable, PI).
1905is_predicate_indicator(Name/Arity) :- 1906 atom(Name), 1907 integer(Arity). 1908is_predicate_indicator(Module:Name/Arity) :- 1909 atom(Module), 1910 atom(Name), 1911 integer(Arity).
1917predicate_indicator(Module:Goal, PI) :- 1918 atom(Module), 1919 !, 1920 predicate_indicator(Goal, PI0), 1921 ( hidden_module(Module) 1922 -> PI = PI0 1923 ; PI = Module:PI0 1924 ). 1925predicate_indicator(Goal, Name/Arity) :- 1926 callable(Goal), 1927 !, 1928 head_name_arity(Goal, Name, Arity). 1929predicate_indicator(Goal, Goal). 1930 (user):- !. 1932hidden_module(system) :- !. 1933hidden_module(M) :- 1934 sub_atom(M, 0, _, _, $).
1940sort_callables(Callables, Sorted) :- 1941 key_callables(Callables, Tagged), 1942 keysort(Tagged, KeySorted), 1943 unkey(KeySorted, SortedList), 1944 ord_list_to_set(SortedList, Sorted). 1945 1946key_callables([], []). 1947key_callables([H0|T0], [Key-H0|T]) :- 1948 key_callable(H0, Key), 1949 key_callables(T0, T). 1950 1951key_callable(Callable, k(Name, Arity, Module)) :- 1952 predicate_indicator(Callable, PI), 1953 ( PI = Name/Arity 1954 -> Module = user 1955 ; PI = Module:Name/Arity 1956 ). 1957 1958unkey([], []). 1959unkey([_-H|T0], [H|T]) :- 1960 unkey(T0, T).
1967ord_list_to_set([], []). 1968ord_list_to_set([H|T0], [H|T]) :- 1969 ord_remove_same(H, T0, T1), 1970 ord_list_to_set(T1, T). 1971 1972ord_remove_same(H, [H|T0], T) :- 1973 !, 1974 ord_remove_same(H, T0, T). 1975ord_remove_same(_, L, L).
1983callable_to_label(Callable, Label) :- 1984 callable_to_label(Callable, @nil, Label). 1985 1986callable_to_label(pce_principal:send_implementation(Id,_,_), _, Id) :- 1987 atom(Id), 1988 !. 1989callable_to_label(pce_principal:get_implementation(Id,_,_,_), _, Id) :- 1990 atom(Id), 1991 !. 1992callable_to_label('<export>', _, '<export>') :- !. 1993callable_to_label('<directive>'(Line), _, Label) :- 1994 !, 1995 atom_concat('<directive>@', Line, Label). 1996callable_to_label(_:'<directive>'(Line), _, Label) :- 1997 !, 1998 atom_concat('<directive>@', Line, Label). 1999callable_to_label(Callable, File, Label) :- 2000 to_predicate_indicator(Callable, PI0), 2001 ( PI0 = M:PI1 2002 -> ( atom(File), 2003 xref_module(File, M) 2004 -> PI = PI1 2005 ; PI = PI0 2006 ) 2007 ; PI = PI0 2008 ), 2009 term_to_atom(PI, Label).
2013edit_callable('<export>', File) :- 2014 !, 2015 edit(file(File)). 2016edit_callable(Callable, File) :- 2017 local_callable(Callable, File, Local), 2018 ( xref_defined(File, Local, How), 2019 xref_definition_line(How, Line) 2020 -> edit_location(Line, File, Location), 2021 edit(Location) 2022 ; autoload_predicate(Local) 2023 -> functor(Local, Name, Arity), 2024 edit(Name/Arity) 2025 ). 2026edit_callable(pce_principal:send_implementation(Id,_,_), _) :- 2027 atom(Id), 2028 atomic_list_concat([Class,Method], ->, Id), 2029 !, 2030 edit(send(Class, Method)). 2031edit_callable(pce_principal:get_implementation(Id,_,_,_), _) :- 2032 atom(Id), 2033 atomic_list_concat([Class,Method], <-, Id), 2034 !, 2035 edit(get(Class, Method)). 2036edit_callable('<directive>'(Line), File) :- 2037 File \== @nil, 2038 !, 2039 edit(file(File, line(Line))). 2040edit_callable(_:'<directive>'(Line), File) :- 2041 File \== @nil, 2042 !, 2043 edit(file(File, line(Line))). 2044edit_callable(Callable, _) :- 2045 to_predicate_indicator(Callable, PI), 2046 edit(PI). 2047 2048local_callable(M:Callable, File, Callable) :- 2049 xref_module(File, M), 2050 !. 2051local_callable(Callable, _, Callable). 2052 2053edit_location(File:Line, _MainFile, Location) => 2054 edit_location(Line, File, Location). 2055edit_location(Line, File, Location) => 2056 Location = file(File, line(Line)). 2057 2058 2059 2060 /******************************* 2061 * WARNINGS * 2062 *******************************/
2069file_warnings(File, Warnings) :- 2070 setof(W, file_warning(File, W), Warnings). 2071 2072file_warning(File, undefined) :- 2073 undefined(File, _) -> true. 2074file_warning(File, not_called) :- 2075 setting(warn_not_called, true), 2076 not_called(File, _) -> true.
2084not_called(File, NotCalled) :- % module version 2085 xref_module(File, Module), 2086 !, 2087 defined(File, NotCalled), 2088 \+ ( xref_called(File, NotCalled) 2089 ; xref_exported(File, NotCalled) 2090 ; xref_hook(NotCalled) 2091 ; xref_hook(Module:NotCalled) 2092 ; NotCalled = _:Goal, 2093 xref_hook(Goal) 2094 ; xref_called(_, Module:NotCalled) 2095 ; NotCalled = _:_, 2096 xref_called(_, NotCalled) 2097 ; NotCalled = M:G, 2098 xref_called(ModFile, G), 2099 xref_module(ModFile, M) 2100 ; generated_callable(Module:NotCalled) 2101 ). 2102not_called(File, NotCalled) :- % non-module version 2103 defined(File, NotCalled), 2104 \+ ( xref_called(ImportFile, NotCalled), 2105 \+ xref_module(ImportFile, _) 2106 ; NotCalled = _:_, 2107 xref_called(_, NotCalled) 2108 ; NotCalled = M:G, 2109 xref_called(ModFile, G), 2110 xref_module(ModFile, M) 2111 ; xref_called(AutoImportFile, NotCalled), 2112 \+ defined(AutoImportFile, NotCalled), 2113 global_predicate(NotCalled) 2114 ; xref_hook(NotCalled) 2115 ; xref_hook(user:NotCalled) 2116 ; generated_callable(user:NotCalled) 2117 ). 2118 2119generated_callable(M:Term) :- 2120 head_name_arity(Term, Name, Arity), 2121 prolog:generated_predicate(M:Name/Arity).
2129xref_called(Source, Callable) :- 2130 gxref_called(Source, Callable). 2131xref_called(Source, Callable) :- 2132 xref_called_cond(Source, Callable, _). 2133 2134xref_called_cond(Source, Callable, Cond) :- 2135 xref_called(Source, Callable, By, Cond), 2136 By \= Callable. % recursive calls
2142defined(File, Callable) :-
2143 xref_defined(File, Callable, How),
2144 atom(File),
2145 How \= imported(_),
2146 How \= (multifile).
2154undefined(File, Undef) :- 2155 xref_module(File, _), 2156 !, 2157 xref_called_cond(File, Undef, Cond), 2158 \+ ( available(File, Undef, How), 2159 How \== plain_file 2160 ), 2161 included_if_defined(Cond, Undef). 2162undefined(File, Undef) :- 2163 xref_called_cond(File, Undef, Cond), 2164 \+ available(File, Undef, _), 2165 included_if_defined(Cond, Undef).
2169included_if_defined(true, _) :- !. 2170included_if_defined(false, _) :- !, fail. 2171included_if_defined(fail, _) :- !, fail. 2172included_if_defined(current_predicate(Name/Arity), Callable) :- 2173 \+ functor(Callable, Name, Arity), 2174 !. 2175included_if_defined(\+ Cond, Callable) :- 2176 !, 2177 \+ included_if_defined(Cond, Callable). 2178included_if_defined((A,B), Callable) :- 2179 !, 2180 included_if_defined(A, Callable), 2181 included_if_defined(B, Callable). 2182included_if_defined((A;B), Callable) :- 2183 !, 2184 ( included_if_defined(A, Callable) 2185 ; included_if_defined(B, Callable) 2186 ). 2187 2188 2189 /******************************* 2190 * IMPORT/EXPORT HEADERS * 2191 *******************************/
We first resolve all imports to absolute files. Localizing is done afterwards. Imports is a list of
use_module(FileSpec, Callables)
2210xref_file_imports(FileSpec, Imports) :- 2211 canonical_filename(FileSpec, File), 2212 findall(Called, called_no_builtin(File, Called), Resolve0), 2213 resolve_old_imports(Resolve0, File, Resolve1, Imports0), 2214 find_new_imports(Resolve1, File, Imports1), 2215 disambiguate_imports(Imports1, File, Imports2), 2216 flatten([Imports0, Imports2], ImportList), 2217 keysort(ImportList, SortedByFile), 2218 merge_by_key(SortedByFile, ImportsByFile), 2219 maplist(make_import(File), ImportsByFile, Imports). 2220 2221canonical_filename(FileSpec, File) :- 2222 absolute_file_name(FileSpec, 2223 [ file_type(prolog), 2224 access(read), 2225 file_errors(fail) 2226 ], 2227 File). 2228 2229called_no_builtin(File, Callable) :- 2230 xref_called(File, Callable), 2231 \+ defined(File, Callable), 2232 \+ built_in_predicate(Callable). 2233 2234resolve_old_imports([], _, [], []). 2235resolve_old_imports([H|T0], File, UnRes, [From-H|T]) :- 2236 xref_defined(File, H, imported(From)), 2237 !, 2238 resolve_old_imports(T0, File, UnRes, T). 2239resolve_old_imports([H|T0], File, [H|UnRes], Imports) :- 2240 resolve_old_imports(T0, File, UnRes, Imports). 2241 2242find_new_imports([], _, []). 2243find_new_imports([H|T0], File, [FL-H|T]) :- 2244 findall(F, resolve(H, F), FL0), 2245 sort(FL0, FL), 2246 find_new_imports(T0, File, T). 2247 2248disambiguate_imports(Imports0, File, Imports) :- 2249 ambiguous_imports(Imports0, Ambig, UnAmbig, _Undef), 2250 ( Ambig == [] 2251 -> Imports = UnAmbig 2252 ; new(D, xref_disambiguate_import_dialog(File, Ambig)), 2253 get(D, confirm_centered, Result), 2254 ( Result == ok 2255 -> get(D, result, List), 2256 send(D, destroy), 2257 append(UnAmbig, List, Imports) 2258 ) 2259 ). 2260 2261ambiguous_imports([], [], [], []). 2262ambiguous_imports([[]-C|T0], Ambig, UnAmbig, [C|T]) :- 2263 !, 2264 ambiguous_imports(T0, Ambig, UnAmbig, T). 2265ambiguous_imports([[F]-C|T0], Ambig, [F-C|T], Undef) :- 2266 !, 2267 ambiguous_imports(T0, Ambig, T, Undef). 2268ambiguous_imports([A-C|T0], [A-C|T], UnAmbig, Undef) :- 2269 is_list(A), 2270 !, 2271 ambiguous_imports(T0, T, UnAmbig, Undef).
2278resolve(Callable, File) :- % Export from module files 2279 xref_exported(File, Callable), 2280 atom(File). 2281resolve(Callable, File) :- % Non-module files 2282 defined(File, Callable), 2283 atom(File), 2284 \+ xref_module(File, _). 2285resolve(Callable, File) :- % The Prolog autoload library 2286 autoload_predicate(Callable, File).
2293merge_by_key([], []). 2294merge_by_key([K-V|T0], [K-[V|Vs]|T]) :- 2295 same_key(K, T0, Vs, T1), 2296 merge_by_key(T1, T). 2297 2298same_key(K, [K-V|T0], [V|VT], T) :- 2299 !, 2300 same_key(K, T0, VT, T). 2301same_key(_, L, [], L).
2308make_import(RefFile, File-Imports, (:-use_module(ShortPath, PIs))) :- 2309 local_filename(File, RefFile, ShortPath), 2310 sort_callables(Imports, SortedImports), 2311 maplist(predicate_indicator, SortedImports, PIs). 2312 2313local_filename(File, RefFile, ShortPath) :- 2314 atom(RefFile), 2315 file_directory_name(File, Dir), 2316 file_directory_name(RefFile, Dir), % i.e. same dir 2317 !, 2318 file_base_name(File, Base), 2319 remove_extension(Base, ShortPath). 2320local_filename(File, _RefFile, ShortPath) :- 2321 file_name_on_path(File, ShortPath0), 2322 remove_extension(ShortPath0, ShortPath). 2323 2324 2325remove_extension(Term0, Term) :- 2326 Term0 =.. [Alias,ShortPath0], 2327 file_name_extension(ShortPath, pl, ShortPath0), 2328 !, 2329 Term =.. [Alias,ShortPath]. 2330remove_extension(ShortPath0, ShortPath) :- 2331 atom(ShortPath0), 2332 file_name_extension(ShortPath, pl, ShortPath0), 2333 !. 2334remove_extension(Path, Path). 2335 xref_disambiguate_import_dialog, auto_sized_dialog, 2337 "Prompt for alternative sources"). ( 2338 2339initialise(D, File:name, Ambig:prolog) :-> 2340 send_super(D, initialise, string('Disambiguate calls for %s', File)), 2341 forall(member(Files-Callable, Ambig), 2342 send(D, append_row, File, Callable, Files)), 2343 send(D, append, button(ok)), 2344 send(D, append, button(cancel)). 2345 2346append_row(D, File:name, Callable:prolog, Files:prolog) :-> 2347 send(D, append, xref_predicate_text(Callable, @default, File)), 2348 send(D, append, new(FM, menu(file, cycle)), right), 2349 send(FM, append, menu_item(@nil, @default, '-- Select --')), 2350 forall(member(Path, Files), 2351 ( file_name_on_path(Path, ShortId), 2352 short_file_name_to_atom(ShortId, Label), 2353 send(FM, append, menu_item(Path, @default, Label)) 2354 )). 2355 2356result(D, Disam:prolog) :<- 2357 "Get disambiguated files":: 2358 get_chain(D, graphicals, Grs), 2359 selected_files(Grs, Disam). 2360 2361selected_files([], []). 2362selected_files([PreText,Menu|T0], [File-Callable|T]) :- 2363 send(PreText, instance_of, xref_predicate_text), 2364 send(Menu, instance_of, menu), 2365 get(Menu, selection, File), 2366 atom(File), 2367 !, 2368 get(PreText, callable, Callable), 2369 selected_files(T0, T). 2370selected_files([_|T0], T) :- 2371 selected_files(T0, T). 2372 2373 2374ok(D) :-> 2375 send(D, return, ok). 2376 2377cancel(D) :-> 2378 send(D, destroy). 2379 xref_disambiguate_import_dialog). (
2387xref_file_exports(FileSpec, (:- module(Module, Exports))) :-
2388 canonical_filename(FileSpec, File),
2389 \+ xref_module(File, _),
2390 findall(C, export_link_1(File, _, C), Cs),
2391 sort_callables(Cs, Sorted),
2392 file_base_name(File, Base),
2393 file_name_extension(Module, _, Base),
2394 maplist(predicate_indicator, Sorted, Exports)
Cross-referencer front-end
XPCE based font-end of the Prolog cross-referencer. Tasks: