1/* Part of LogicMOO Base Logicmoo Path Setups
    2% ===================================================================
    3% File '$FILENAME.pl'
    4% Purpose: An Implementation in SWI-Prolog of certain debugging tools
    5% Maintainer: Douglas Miles
    6% Contact: $Author: dmiles $@users.sourceforge.net ;
    7% Version: '$FILENAME.pl' 1.0.0
    8% Revision: $Revision: 1.1 $
    9% Revised At:  $Date: 2002/07/11 21:57:28 $
   10% Licience: LGPL
   11% ===================================================================
   12*/
   13% File: /opt/PrologMUD/pack/logicmoo_base/prolog/logicmoo/util/logicmoo_util_filesystem.pl
   14:- module(logicmoo_util_filesystem,
   15          [ 
   16            add_library_search_path/2,
   17            add_file_search_path/2,
   18            add_to_search_path/2,
   19            add_to_search_path/3,
   20            add_to_search_path_first/2,
   21            add_to_search_path_last/2,
   22            atom_concat_safe0/3,
   23            atom_ensure_endswtih/3,
   24            canonical_pathname/2,
   25            load_with_asserter/4,
   26            clip_dir_sep/2,
   27            concat_paths/2,
   28            concat_paths/3,
   29            current_dirs/1,
   30            current_dirs0/1,
   31            %maybe_add_import_module/3,
   32            current_filedir/1,
   33            current_filesource/1,
   34            enumerate_files/2,
   35            enumerate_files0/2,
   36            enumerate_files00/2,
   37            enumerate_files01/2,
   38            enumerate_files1/2,
   39            enumerate_files2/2,
   40            enumerate_m_files/3,
   41            exists_directory_safe/1,
   42            exists_dirf/1,
   43            exists_file_or_dir/1,
   44            exists_file_safe/1,
   45            expand_file_name_safe/2,
   46            expand_wfm/2,
   47            filematch/2,
   48            filematch3/3,
   49            filematch_ext/3,
   50            global_pathname/2,
   51            if_startup_script/0,
   52            in_include_file/0,
   53            if_startup_script/1,
   54            in_search_path/2,
   55            is_directory/1,
   56            join_path/3,
   57            join_path_if_needed/3,
   58            local_directory_search_combined/1,
   59            local_directory_search_combined2/1,
   60            locally_to_dir/2,
   61            my_absolute_file_name/2,
   62            %maybe_delete_import_module/2,
   63            normalize_path/2,
   64            os_to_prolog_filename/2,
   65            prolog_file_dir/1,
   66            prolog_file_dir/2,
   67            relative_pathname/2,
   68            remove_search_path/2,
   69            resolve_dir/2,
   70            time_file_safe/2,
   71            to_filename/2,
   72            upcase_atom_safe/2,
   73            with_filematch/1,
   74            with_filematches/1,
   75            contains_wildcard/1
   76
   77
   78            
   79          ]).   80
   81
   82:- multifile
   83        local_directory_search/1.   84:- meta_predicate
   85        add_to_search_path(2, ?, ?),
   86        enumerate_files(:, -),
   87        filematch(:, -),
   88        filematch_ext(+, :, -),
   89        if_startup_script(0),
   90        with_filematch(0).   91:- module_transparent
   92        add_library_search_path/2,
   93        add_file_search_path/2,
   94        add_to_search_path/2,
   95        add_to_search_path_first/2,
   96        add_to_search_path_last/2,
   97        atom_concat_safe0/3,
   98        atom_ensure_endswtih/3,
   99        canonical_pathname/2,
  100        clip_dir_sep/2,
  101        concat_paths/2,
  102        concat_paths/3,
  103        current_dirs/1,
  104        current_dirs0/1,
  105        current_filedir/1,
  106        current_filesource/1,
  107        enumerate_files0/2,
  108        enumerate_files00/2,
  109        enumerate_files01/2,
  110        enumerate_files1/2,
  111        enumerate_files2/2,
  112        enumerate_m_files/3,
  113        exists_directory_safe/1,
  114        exists_dirf/1,
  115        exists_file_or_dir/1,
  116        exists_file_safe/1,
  117        expand_file_name_safe/2,
  118        expand_wfm/2,
  119        filematch3/3,
  120        global_pathname/2,
  121        if_startup_script/0,
  122        in_search_path/2,
  123        is_directory/1,
  124        join_path/3,
  125        join_path_if_needed/3,
  126        local_directory_search/1,
  127        local_directory_search_combined/1,
  128        local_directory_search_combined2/1,
  129        locally_to_dir/2,
  130        my_absolute_file_name/2,
  131        normalize_path/2,
  132        os_to_prolog_filename/2,
  133        prolog_file_dir/1,
  134        prolog_file_dir/2,
  135        relative_pathname/2,
  136        remove_search_path/2,
  137        time_file_safe/2,
  138        to_filename/2,
  139        upcase_atom_safe/2,
  140        %maybe_add_import_module/3,
  141        with_filematches/1.  142:- dynamic
  143        local_directory_search/1.  144
  145:- set_module(class(library)).  146% % % OFF :- system:use_module(library(dialect)).
  147
  148:- use_module(library(occurs)).  149:- use_module(library(gensym)).  150:- use_module(library(when)).  151
  152:- use_module(library(occurs)).  153:- use_module(library(gensym)).  154:- use_module(library(when)).  155
  156
  157:- use_module(library(backcomp)).  158:- use_module(library(codesio)).  159:- use_module(library(charsio)).  160:- use_module(library(debug)).  161:- use_module(library(check)).  162
  163
  164:- use_module(library(edinburgh)).  165:- use_module(library(debug)).  166:- use_module(library(prolog_stack)).  167:- use_module(library(make)).  168
  169
  170% :- use_module(library(gui_tracer)).
  171:- use_module(library(system)).  172:- use_module(library(socket)).  173:- use_module(library(readutil)).  174:- abolish(system:time/1).  175:- use_module(library(statistics)).  176:- use_module(library(ssl)).  177:- use_module(library(prolog_codewalk)).  178:- use_module(library(prolog_source)).  179:- use_module(library(date)).  180%:- use_module(library(editline)).
  181:- use_module(library(listing)).  182
  183:- ensure_loaded(library(logicmoo/no_repeats)).  184
  185:- if(exists_source(library(filesex))).  186%:- set_prolog_flag(generate_debug_info, true).=
  187:- '@'( ensure_loaded(library(filesex)), 'user').  188
  189:-endif.  190
  191
  192assert_at_line_count(M,Pos,File,Cl):-
  193  stream_position_data(line_count,Pos,Line),
  194  '$compile_aux_clauses'([M:Cl], '$source_location'(File, Line)).
  195
  196assert_at_line_count_p1(Pred1,Cl,_Vs,_):- call(Pred1,Cl).
  197assert_at_line_count_p2(Pred2,Cl, Vs,_):- call(Pred2,Cl,Vs).
  198
  199:- meta_predicate(load_with_asserter(+,+,1,+)).  200load_with_asserter(File0,File,Asserter,Options):-    
  201   once(absolute_file_name(File0, File, [access(read)]);
  202        absolute_file_name(File0, File, [access(read),file_type(prolog)])),
  203   open(File, read, In),
  204   set_stream(In, encoding(iso_latin_1)),
  205   repeat,
  206   read_clause(In, Cl, Options),
  207   % DMiles: i am putting them in backwards (cuz, the hypens- confuse me if they pop out first in the debugger)
  208   call(Asserter,Cl),
  209   Cl==end_of_file, !,
  210   close(In).
  211   
  212
  213
  214% '/root/lib/swipl/pack/mpi'
  215% pack_property(Pack, directory(PackDir)),atom_concat(PackDir,'/*',writeln(WC),expand_file_name(WC,O),O\=[],length(O,L).
  216
  217% file_tree(Dir,Files):-
 resolve_dir(?Dir, ?Dir) is semidet
Resolve Dir.
  225resolve_dir(Dir,Dir):- is_absolute_file_name(Dir),!,exists_directory(Dir),!.
  226resolve_dir(Path,Dir):- 
  227  (prolog_load_context(directory,SDir);
  228   (prolog_load_context(file,File),file_directory_name(File,SDir));
  229   (prolog_load_context(source,File),file_directory_name(File,SDir));
  230   (catch((current_source_file(F),to_filename(F,File),atom(File)),_,fail),file_directory_name(File,SDir));
  231    working_directory(SDir,SDir)),exists_directory(SDir),
  232    catch(absolute_file_name(Path,Dir,[relative_to(SDir),access(read),file_errors(fail),file_type(directory)]),_,fail),
  233    exists_directory(Dir).
 add_file_search_path(+Alias, +WildCard) is det
Create an alias when it is missing
:- add_file_search_path(all_utils, '../*/util/').
  244add_file_search_path(Name,Path):-  must(resolve_dir(Path,Dir)),
  245   is_absolute_file_name(Dir), (( \+ user:file_search_path(Name,Dir)) ->asserta(user:file_search_path(Name,Dir));true).
 add_library_search_path(+Dir, +Patterns:list(atom)) is det
Create an autoload index INDEX.pl for Dir by scanning all files that match any of the file-patterns in Patterns. Typically, this appears as a directive in MKINDEX.pl. For example:
:- add_library_search_path('../*/util/',[ 'logicmoo_util_*.pl']).
  258add_library_search_path(Path,Masks):- 
  259   forall(resolve_dir(Path,Dir), 
  260      (make_library_index(Dir, Masks), 
  261        (user:library_directory(Dir) -> true ; (asserta(user:library_directory(Dir)), 
  262          (access_file(Dir,write)->reload_library_index;true))))).
  263
  264
  265:- meta_predicate(with_filematch(0)).  266
  267%= 	 	 
 with_filematch(:GoalG) is semidet
Using Filematch.
  273with_filematch(G):- expand_wfm(G,GG),!,GG.
  274
  275%= 	 	 
 with_filematches(?G) is semidet
Using Filematches.
  281with_filematches(G):- forall(expand_wfm(G,GG),GG).
  282
  283
  284%= 	 	 
 expand_wfm(?G, ?GG) is semidet
Expand Wfm.
  290expand_wfm(G,GG):- once((sub_term(Sub, G),compound(Sub),Sub=wfm(F))),
  291   (filematch(F,M),subst(G,wfm(F),M,GG),y_must(with_filematch(G), (G\=@=GG))).
  292
  293
  294:- export(current_filesource/1).  295:- export(current_filedir/1).  296
  297%= 	 	 
 current_filedir(?D) is semidet
Current Filedir.
  303current_filedir(D):- no_repeats(D,(current_filesource(F),file_directory_name(F,D))).
  304
  305%= 	 	 
 current_filesource(?F) is semidet
Current Filesource.
  311current_filesource(F):-source_location(F,_).
  312current_filesource(F):-seeing(X),is_stream(X),stream_property(X,file_name(F)).
  313current_filesource(F):-stream_property(_,file_name(F)).
  314
  315:- export(filematch/2).  316:- meta_predicate(filematch(:,-)).  317
  318%= 	 	 
 filematch(?Spec, -Result) is semidet
Filematch.
  324filematch(Spec,Result):-  enumerate_files(Spec,Result).
  325
  326
  327:- thread_local(t_l:file_ext/1).  328:- meta_predicate(filematch_ext(+,:,-)).  329:- export(filematch_ext/3).  330
  331%= 	 	 
 filematch_ext(+Ext, ?FileIn, -File) is semidet
Filematch Ext.
  337filematch_ext(Ext,FileIn,File):-
  338  locally_tl(file_ext(Ext),findall(File,filematch(FileIn,File),List)),
  339   when_ends_with(Ext,List,File).
  340
  341when_ends_with(_Ext,[],_File):- !,fail.
  342when_ends_with(Ext,List,File):- ((member(File,List),only_if_ends_with(Ext,File)))*->true;member(File,List).
  343
  344only_if_ends_with(Ext,File):- atom(Ext),!,Ext\==[],atom_concat(_,Ext,File).
  345only_if_ends_with([Ext|L],File):- only_if_ends_with(Ext,File)->true;only_if_ends_with(L,File).
  346
  347%= 	 	 
  348:- meta_predicate(enumerate_files(:,-)).  349:- export(enumerate_files/2).
 enumerate_files(?CALL1, -Result) is semidet
Enumerate Files.
  355enumerate_files(Spec0,Result):- strip_module(Spec0,_,Spec),
  356   call((atom(Spec),(exists_file_safe(Spec);exists_directory(Spec)),prolog_to_os_filename(Result,Spec))),
  357   absolute_file_name(Spec,Result),exists_file_or_dir(Result),!.
  358enumerate_files(Spec,Result):-absolute_file_name(Spec,Result),exists_file_or_dir(Result),!.
  359enumerate_files(M:Spec,Result):-
  360   call((no_repeats_old([Result],((enumerate_m_files(M,Spec,NResult),once((normalize_path(NResult,Result)->exists_file_or_dir(Result)))))))).
  361
  362
  363%= 	 	 
 enumerate_m_files(?M, ?Mask, ?File1) is semidet
Enumerate Module Files.
  369:- export(enumerate_m_files/3).  370enumerate_m_files(user, Mask,File1):-!,enumerate_files0(Mask,File1).
  371enumerate_m_files(M, Mask,File1):- enumerate_files0(Mask,File1)*->true;enumerate_m_files_mscoped(M, Mask,File1).
  372
  373
  374%= 	 	 
 enumerate_m_files_mscoped(?M, ?Mask, ?File1) is semidet
Enumerate Module Files Mscoped.
  380enumerate_m_files_mscoped(M, Mask,File1):- 
  381  findall(t_l:search_first_dir(Dir),
  382   (((M\=user,user:file_search_path(M,SP),expand_file_search_path(SP,Dir));
  383     ((module_property(M, file(File)),directory_file_path(Dir,_,File)))),
  384   exists_directory(Dir)),List),
  385  list_to_set(List,Set),
  386  locally(Set,enumerate_files0(Mask,File1)).
  387
  388:- export(enumerate_files0/2).  389
  390%= 	 	 
 enumerate_files0(?Mask, ?File1) is semidet
Enumerate Files Primary Helper.
  396enumerate_files0(Mask,File1):- absolute_file_name(Mask,X,[expand(true),file_errors(fail),solutions(all)]),expand_file_name(X,Y),Y\==[],member(File1,Y).
  397enumerate_files0(Mask,File1):- one_must(filematch3('./',Mask,File1),(current_filedir(D),filematch3(D,Mask,File1))).
  398enumerate_files0(Spec,Result):- enumerate_files00(Spec,Result).
  399enumerate_files0(Spec,Result):- to_filename(Spec,Result).
  400enumerate_files0(Mask,File1):-  (current_dirs(D),filematch3(D,Mask,File1)).
  401
  402enumerate_files01(_Mask,_File1):-fail.
  403
  404
  405%= 	 	 
 enumerate_files00(?Spec, ?Result) is semidet
Enumerate Files Primary Helper Primary Helper.
  411enumerate_files00(Spec,Result):- expand_file_name_safe(Spec,ResultList),ResultList\=[],!,member(NResult,ResultList),enumerate_files2(NResult,Result).
  412enumerate_files00(Spec,Result):- enumerate_files1(Spec,M),enumerate_files2(M,Result).
  413
  414
  415:- export(filematch3/3).  416
  417%= 	 	 
 filematch3(?RelativeTo, ?Mask, ?File1) is semidet
Filematch3.
  423filematch3(RelativeTo,Mask,File1):-
  424   findall(Ext,t_l:file_ext(Ext),EXTs),flatten([EXTs,'','pl.in'],Flat),
  425   absolute_file_name(Mask,File1Matched,[extensions(Flat),
  426   expand(true),file_errors(fail),solutions(all),relative_to(RelativeTo),access(read)]),expand_file_name_safe(File1Matched,File1S),member(File1,File1S).
  427filematch3(RelativeTo,Mask,File1):-absolute_file_name(Mask,File1Matched,[file_type(directory),
  428   expand(true),file_errors(fail),solutions(all),relative_to(RelativeTo),access(read)]),expand_file_name_safe(File1Matched,File1S),member(File1,File1S).
  429
  430:- export(enumerate_files2/2).  431
  432%= 	 	 
 enumerate_files2(?Spec, ?Result) is semidet
Enumerate Files Extended Helper.
  438enumerate_files2(Spec,Result):-sub_atom(Spec,_,1,_,'*') -> enumerate_files1(Spec,Result);Spec=Result.
  439
  440:- export(enumerate_files1/2).  441
  442must_filematch(string(A),string(A)):-!.
  443must_filematch(A,B):- filematch_smart(A,B) *-> true ; throw(must_filematch(A,B)).
  444
  445filematch_smart(Match,Each):- filematch(Match,Each)*-> true; filematch_smart_1(Match,Each) *-> true; filematch_smart_2(Match,Each).
  446%filematch_smart_2(Match,Each):- atom(Match),absolute_file_name(Match,Dir0),expand_file_name(Dir0,DirS),DirS\==[],!,member(Each,DirS).
  447filematch_smart_1(Match,Each):- absolute_file_name(Match,Dir0,
  448 [file_errors(fail),expand(true),solutions(all)]),
  449  expand_file_name_wc(Dir0,DirS),
  450  member(Each,DirS).
  451filematch_smart_2(Match,Each):- atom(Match),!, \+ is_absolute_file_name(Match),!, filematch_smart_2(pddl(Match),Each).
  452
  453
  454must_filematch_list(Match,List):- findall(File, must_filematch(Match,File), List).
  455
  456
  457%= 	 	 
 enumerate_files1(:TermAtom, ?Result) is semidet
Enumerate Files Secondary Helper.
  463enumerate_files1(Atom,Result):- atomic(Atom),\+(is_absolute_file_name(Atom)),atomic_list_concat(List,'/',Atom),!,concat_paths(List,Result).
  464enumerate_files1(Spec,Result):- exists_file_or_dir(Spec),!,Result=Spec.
  465enumerate_files1(P/C,Result):- !,concat_paths(P,C,Result).
  466enumerate_files1(Spec,Result):- expand_file_name_safe(Spec,ResultList),member(Result,ResultList).
  467enumerate_files1(Spec,Result):- user:file_search_path(Spec,Result).
  468enumerate_files1(Spec,Result):- expand_file_search_path(Spec,Result).
  469enumerate_files1(Spec,Result):- absolute_file_name(Spec,Result).
  470enumerate_files1(Atom,Result):- atomic(Atom),once((member(Sep,['/**/','/**','**']),atomic_list_concat([B,A|R],Sep,Atom))),concat_paths([B,'**',A|R],Result).
  471
  472:- export(expand_file_name_safe/2).  473
  474%= 	 	 
 expand_file_name_safe(?I, ?O) is semidet
Expand File Name Safely Paying Attention To Corner Cases.
  481expand_file_name_safe(I,O):-var(I),trace_or_throw(instanciation_error(expand_file_name_safe(I,O))),!.
  482expand_file_name_safe(I,O):- atom(I),expand_file_name_wc(I,O),O\==[],!.
  483expand_file_name_safe(I,O):- \+ compound(I), catch(expand_file_name(I,O),_,fail),O\==[I],O\=[],!.
  484expand_file_name_safe(I,[O]):- catch(expand_file_search_path(I,O),_,fail),O\==[I],!.
  485expand_file_name_safe(I,L):- 
  486  findall(O,
  487    (absolute_file_name(I,O,[expand(true),solutions(all)]);
  488     absolute_file_name(I,O,[expand(true),solutions(all),file_type(directory)])),
  489    L),!.
  490
  491
  492expand_file_name_wc(I,O):- atom(I),atomic_list_concat(List,'/',I),nav_each(List,O).
  493
  494nav_each([''|Seg],O):- !,nav_each('/',Seg,O).
  495nav_each([Path|Seg],O):- nav_each('.',[Path|Seg],O).
  496
  497nav_each([],_,O):-!, O = [].
  498nav_each([L|List],Seg,S):- !, is_list(List),
  499  nav_each(L,Seg,O1), nav_each(List,Seg,O2), append(O1,O2,O), list_to_set(O,S).
  500nav_each(Path,Seg,O):- notrace(catch(expand_file_name(Path,S),_,fail)), [Path]\==S,!, nav_each(S,Seg,O).
  501nav_each(Path, _, O):- \+ exists_dirf(Path),!, O = [].
  502nav_each(Path,[],[O]):- !, absolute_file_name(Path,O),!.
  503nav_each(Path,['.'],O):- nav_each(Path,[''],O),!. 
  504nav_each(Path,[''],O):- !, (exists_directory(Path) -> nav_each(Path,[],O) ; O = []).
  505nav_each(Path,[A|Seg],O):-  directory_file_path(Path,A,Try),!,nav_each(Try,Seg,O).
  506:- export(exists_file_or_dir/1).  507
  508
  509%= 	 	 
 exists_file_or_dir(?X) is semidet
Exists File Or Dir.
  515exists_file_or_dir(X):- nonvar(X),( X=(_:F)->exists_file_or_dir(F); (atomic(X),once((catch(exists_file_safe(X),E,(fmt(E:X),fail));is_directory(X))))).
  516:- export(is_directory/1).  517
  518%= 	 	 
 is_directory(?X) is semidet
If Is A Directory.
  524is_directory(X):-exists_directory(X).
  525
  526:- export(concat_paths/3).  527
  528%= 	 	 
 concat_paths(?ParentIn, ?Child, ?Result) is semidet
Concat Paths.
  534concat_paths(A,'',A).
  535concat_paths(A,'/',A):- atom_concat(_,'/',A),!.
  536concat_paths(A,'/',A):- !.
  537concat_paths(ParentIn,'**',Result):-!, member(Child,['./','./*/','./*/*/','./*/*/*/','./*/*/*/*/','./*/*/*/*/*/']),
  538   concat_paths(ParentIn,Child,Result).
  539concat_paths(ParentIn,Child,Result):- 
  540   filematch(ParentIn,Parent),
  541   once((is_directory(Parent) -> directory_file_path(Parent,Child,Joined) ; atom_concat(Parent,Child,Joined))),!,
  542   filematch(Joined,Result).
  543
  544:- export(concat_paths/2).  545
  546%= 	 	 
 concat_paths(:TermJoined, ?Result) is semidet
Concat Paths.
  552concat_paths([Joined],Result):- !,filematch(Joined,Result).
  553concat_paths([ParentIn,Child|MORE],Result):- concat_paths(ParentIn,Child,ResultM),concat_paths([ResultM|MORE],Result).
  554
  555
  556:- thread_local(t_l:search_first_dir/1).  557
  558
  559%= 	 	 
 current_dirs(?DO) is semidet
Current Dirs.
  565current_dirs(DO):- no_repeats(DO,(current_dirs0(D),(atom_concat(DO,'/',D)->true;DO=D))).
  566
  567%= 	 	 
 current_dirs0(?D) is semidet
Current Dirs Primary Helper.
  573current_dirs0(D):- t_l:search_first_dir(D).
  574current_dirs0(D):- prolog_load_context(directory,D).
  575current_dirs0(D):- working_directory(D,D).
  576current_dirs0(D):- quintus:current_stream(_,read,Y), stream_property(Y,file_name(FN)), file_directory_name(FN,D).
  577current_dirs0(D):- stream_property(_,file_name(FN)), file_directory_name(FN,D).
  578
  579%current_dirs0(D):- expand_file_name('*/',X),member(E,X),absolute_file_name(E,D),exists_directory(D).
  580%current_dirs0(D):- expand_file_name('*/*/',X),member(E,X),absolute_file_name(E,D),exists_directory(D).
  581%current_dirs0(D):- expand_file_name('*/*/*/',X),member(E,X),absolute_file_name(E,D),exists_directory(D).
  582current_dirs0(D):- source_file_property(FN, modified(_)), file_directory_name(FN,D).
  583current_dirs0('.').
  584
  585:- export(to_filename/2).  586:- thread_local(t_l:default_extension/1).  587
  588%= 	 	 
 to_filename(?FileName, ?AFN) is semidet
Converted To Filename.
  594to_filename( FileName, AFN ) :- atomic(FileName),exists_file_safe(FileName),!,AFN=FileName.
  595to_filename( FileName, AFN ) :-
  596 ((((t_l:default_extension( Ext ));Ext='.tlp';Ext='';Ext='.pl'), 
  597     current_dirs(D),
  598     member(TF,[false,true]),
  599        absolute_file_name(FileName,AFN,[solutions(all),expand(TF),access(read),relative_to(D),file_errors(fail),extensions(['',Ext,'.pl','.tlp','.clp','.P'])]),
  600        exists_file_safe(AFN))),!.
  601
  602
  603:- export((add_to_search_path/2,add_to_search_path_first/2,prolog_file_dir/2,if_startup_script/1,if_startup_script/0)).  604
  605:- export(prolog_file_dir/1).  606
  607%= 	 	 
 prolog_file_dir(?Here) is semidet
Prolog File Dir.
  613prolog_file_dir(Here):- prolog_load_context(file, HereF),file_directory_name(HereF,Here).
  614prolog_file_dir(Here):- working_directory(Here,Here).
  615:- export(prolog_file_dir/2).  616
  617%= 	 	 
 prolog_file_dir(?Rel, ?ABSF) is semidet
Prolog File Dir.
  623prolog_file_dir(Rel,ABSF):-prolog_file_dir(Here),absolute_file_name(Rel,ABSF,[relative_to(Here),file_type(directory),expand(true)]),!.
  624prolog_file_dir(Rel,ABSF):-prolog_file_dir(Here),absolute_file_name(Rel,ABSF,[relative_to(Here),expand(true)]),!.
 in_include_file is semidet
In Include File.
  631in_include_file:- prolog_load_context(file,F),!, \+ prolog_load_context(source,F).
  632
  633%= 	 	 
 remove_search_path(?Alias, ?Abs) is semidet
Remove Search Path.
  639remove_search_path(Alias, Abs) :- ignore((clause(user:file_search_path(Alias, AbsW0),true,Ref),
  640                                          absolute_file_name(AbsW0,AbsW),same_file(Abs,AbsW),erase(Ref),fail)).
  641
  642%= 	 	 
 add_to_search_path_first(?Alias, ?Abs) is semidet
Add Converted To Search Path First.
  648add_to_search_path_first(Alias, Abs) :- remove_search_path(Alias, Abs), asserta(user:file_search_path(Alias, Abs)).
  649
  650%= 	 	 
 add_to_search_path_last(?Alias, ?Abs) is semidet
Add Converted To Search Path Last.
  656add_to_search_path_last(Alias, Abs) :- remove_search_path(Alias, Abs), assertz(user:file_search_path(Alias, Abs)).
  657
  658%= 	 	 
 in_search_path(?Alias, ?Abs) is semidet
In Search Path.
  664in_search_path(Alias, Abs) :- user:file_search_path(Alias,Was0),absolute_file_name(Was0,Was),same_file(Abs,Was).
  665
  666
  667
  668%= 	 	 
 add_to_search_path(?Alias, ?Abs) is semidet
Add Converted To Search Path.
  674add_to_search_path(Alias, Abs):- add_to_search_path(add_to_search_path_last, Alias, Abs).
  675:- meta_predicate add_to_search_path(2,?,?).  676
  677%= 	 	 
 add_to_search_path(:PRED2How, ?Alias, ?Abs) is semidet
Add Converted To Search Path.
  683add_to_search_path(How, Alias, AbsIn) :- strip_module(AbsIn,_,Abs),!,
  684  ( (atom(Abs),is_absolute_file_name(Abs)) -> call(How,Alias,Abs)     
  685   ; (prolog_file_dir(Abs,ABSF),call(How,Alias,ABSF))).
  686
  687:- add_to_search_path(logicmoo, './../').  688
  689
  690% Was this our startup file?
  691
  692%= 	 	 
 if_startup_script is semidet
If Startup Script.
  698if_startup_script:- prolog_load_context(source, HereF),current_prolog_flag(associated_file,HereF),!.
  699if_startup_script:- prolog_load_context(source, HereF),file_base_name(HereF,HereFB),
  700   current_prolog_flag(os_argv,List),!,member(Arg,List),file_base_name(Arg,ArgFB),atom_concat(ArgFB,_,HereFB),!.
  701
  702:- meta_predicate(if_startup_script(0)).  703
  704%= 	 	 
 if_startup_script(:Goal) is semidet
If Startup Script.
  710if_startup_script(Call):-if_startup_script->Call;dmsg(\+ if_startup_script(Call)).
  711
  712:- export(normalize_path/2).  713
  714%= 	 	 
 normalize_path(?Where, ?WhereF3) is semidet
Normalize Path.
  720normalize_path(Where,WhereF3):-absolute_file_name(Where,WhereF),prolog_to_os_filename(WhereF,WhereF1),prolog_to_os_filename(WhereF2,WhereF1),!,clip_dir_sep(WhereF2,WhereF3).
  721normalize_path(Where,WhereF2):-clip_dir_sep(Where,WhereF2).
  722
  723
  724%= 	 	 
 clip_dir_sep(?Where, ?WhereF2) is semidet
Clip Dir Sep.
  730clip_dir_sep('/','/'):-!.
  731clip_dir_sep(Where,WhereF2):-atom_concat(WhereF2,'/',Where),!.
  732clip_dir_sep(Where,Where):-!.
  733
  734
  735
  736%= 	 	 
 my_absolute_file_name(?F, ?A) is semidet
My Absolute File Name.
  742my_absolute_file_name(F,A):-notrace(catch(expand_file_name(F,[A]),_,fail)),F\=A,!.
  743my_absolute_file_name(F,A):-notrace(catch(absolute_file_name(F,A,[access(read),file_errors(fail),file_type(directory)]),_,fail)),!.
  744my_absolute_file_name(F,A):-notrace(catch(absolute_file_name(F,A,[access(read),file_errors(fail),file_ext('')]),_,fail)),!.
  745my_absolute_file_name(F,A):-notrace(catch(absolute_file_name(F,A),_,fail)),!.
  746
  747% register search path hook
  748
  749
  750
  751%= 	 	 
 join_path_if_needed(?A, ?B, ?C) is semidet
Join Path If Needed.
  757join_path_if_needed(_,B,C):- atom(B), exists_directory(B)->B=C,!.
  758join_path_if_needed(A,B,C):- compound(B),!, my_absolute_file_name(B,BB),atom(BB),!,join_path_if_needed(A,BB,C).
  759join_path_if_needed(A,B,C):- compound(A),!, my_absolute_file_name(A,AA),atom(AA),!,join_path_if_needed(AA,B,C).
  760join_path_if_needed(A,B,C):- compound(C),!, my_absolute_file_name(C,CC),atom(CC),!,join_path_if_needed(A,B,CC).
  761join_path_if_needed(A,B,C):- directory_file_path(A,B,C).
  762
  763
  764%= 	 	 
 locally_to_dir(?Locally, ?Dir) is semidet
Locally Converted To Dir.
  770locally_to_dir(Locally,Dir):- clause(user:file_search_path(logicmoo,RunDir),true),
  771 join_path_if_needed(RunDir,Locally,Directory),
  772 my_absolute_file_name(Directory,Dir),exists_directory(Dir),!.
  773locally_to_dir(Directory,Dir):-  my_absolute_file_name(Directory,Dir),exists_directory(Dir),!.
  774
  775
  776
  777:- dynamic(local_directory_search/1).  778
  779
  780user:file_search_path(library,ATLIB):-  getenv('PATH_INDIGOLOG',AT),atom_concat(AT,'/lib',ATLIB).
  781user:file_search_path(indigolog,AT):-  getenv('PATH_INDIGOLOG',AT).
  782user:file_search_path(logicmoo,Dir):-  local_directory_search(Locally), locally_to_dir(Locally,Dir).
  783user:file_search_path(Atom,Dir):- atom(Atom),upcase_atom(Atom,ATOM),atom_concat('PATH_',ATOM,Var), getenv(Var,AT), atom_string(Dir,AT).
  784
  785
  786
  787%= 	 	 
 local_directory_search_combined(?X) is semidet
Local Directory Search Combined.
  793local_directory_search_combined(X):-local_directory_search(X).
  794local_directory_search_combined(X):-local_directory_search_combined2(X).
  795% for now dont do the concat 3 version
  796local_directory_search_combined(PL):-local_directory_search_combined2(A),local_directory_search(B),join_path(A,B,PL),exists_directory_safe(PL).
  797
  798%= 	 	 
 local_directory_search_combined2(?PL) is semidet
Local Directory Search Combined Extended Helper.
  804local_directory_search_combined2(PL):-local_directory_search(A),local_directory_search(B),join_path(A,B,PL),exists_directory_safe(PL).
  805:- multifile(local_directory_search/1).  806:- dynamic(local_directory_search/1).  807% Add the locations that the MUD source files will be picked up by the system
  808local_directory_search('../..').
  809%local_directory_search('~logicmoo-mud/cynd/startrek'). % home vtDirection CynD world
  810% local_directory_search('.').
  811local_directory_search('..'). 
  812%local_directory_search('../runtime'). 
  813%local_directory_search('../src_game'). % for user overrides and uploads
  814%local_directory_search('../src_assets').  % for non uploadables (downloadables)
  815%local_directory_search('../src_modules'). % for big modules
  816%local_directory_search('../src_webui').  % for web UI modules
  817
  818%= 	 	 
 local_directory_search(?VALUE1) is semidet
Local Directory Search.
  824local_directory_search('../src'). % shared_library preds
  825local_directory_search('../src_lib').
  826local_directory_search('../src_mud').  % for vetted src of the MUD
  827%local_directory_search('../externals/XperiMental/src_incoming').  % areeba underlay
  828
  829
  830
  831
  832
  833%= 	 	 
 exists_dirf(?X) is semidet
Exists Dirf.
  839exists_dirf(X):-atomic(X),(exists_file_safe(X);exists_directory(X)).
  840
  841%= 	 	 
  842
  843exists_file_safe(File):- 
  844  catch((((nonvar(File),(File=(_:F)->exists_file_safe(F);(atomic(File),exists_file(File)))))),_,fail).
  845
  846
  847%= 	 	 
 exists_file_safe(?File) is semidet
Exists File Safely Paying Attention To Corner Cases.
  854%= 	 	 
 exists_directory_safe(?File) is semidet
Exists Directory Safely Paying Attention To Corner Cases.
  860exists_directory_safe(File):- must(atomic(File)),exists_directory(File).
  861/*
  862concat_atom_safe(List,Sep,[Atom]):-atom(Atom),!,concat_atom(List,Sep,Atom),!.
  863concat_atom_safe(List,Sep,Atom):-atom(Atom),!,concat_atom(ListM,Sep,Atom),!,List = ListM.
  864concat_atom_safe(List,Sep,Atom):- concat_atom(List,Sep,Atom),!.
  865*/
  866
  867%= 	 	 
 upcase_atom_safe(?A, ?B) is semidet
Upcase Atom Safely Paying Attention To Corner Cases.
  873upcase_atom_safe(A,B):-atom(A),upcase_atom(A,B),!.
  874
  875%= 	 	 
 time_file_safe(?F, ?INNER_XML) is semidet
Time File Safely Paying Attention To Corner Cases.
  881time_file_safe(_:F,INNER_XML):-atom(F),!,exists_file_safe(F),time_file(F,INNER_XML).
  882time_file_safe(F,INNER_XML):-exists_file_safe(F),!,time_file(F,INNER_XML).
  883
  884
  885
  886
  887% =================================================================================
  888% Utils
  889% =================================================================================
  890
  891
  892%= 	 	 
 global_pathname(?B, ?A) is semidet
Global Pathname.
  898global_pathname(B,A):- atom(B), absolute_file_name(B,A),!.
  899global_pathname(B,A):-relative_pathname(B,A).
  900
  901
  902%= 	 	 
 relative_pathname(?Path, ?Relative) is semidet
Relative Pathname.
  908relative_pathname(Path,Relative):-absolute_file_name(Path,[relative_to('./')],Absolute),member(Rel,['./','../','../../']),absolute_file_name(Rel,Clip),
  909  canonical_pathname(Absolute,AbsoluteA),
  910  canonical_pathname(Clip,ClipA),
  911  atom_concat_safe0(ClipA,RelativeA,AbsoluteA),!,atom_concat_safe0(Rel,RelativeA,Relative),!.
  912relative_pathname(Path,Relative):-canonical_pathname(Path,Relative),!.
  913
  914atom_concat_safe0(L,R,A):- ((atom(A),(atom(L);atom(R))) ; ((atom(L),atom(R)))), !, atom_concat(L,R,A),!.
  915
  916
  917%= 	 	 
 canonical_pathname(?Absolute, ?AbsoluteB) is semidet
Canonical Pathname.
  923canonical_pathname(Absolute,AbsoluteB):-prolog_to_os_filename(AbsoluteA,Absolute),expand_file_name_safe(AbsoluteA,[AbsoluteB]),!.
  924
  925
  926
  927% ===============================================================================================
  928% join_path(CurrentDir,Filename,Name)
  929% ===============================================================================================
  930
  931
  932
  933
  934%= 	 	 
 join_path(?CurrentDir, ?Filename, ?Name) is semidet
Join Path.
  940join_path(CurrentDir,Filename,Name):-
  941     atom_ensure_endswtih(CurrentDir,'/',Out),atom_ensure_endswtih('./',Right,Filename),
  942     atom_concat(Out,Right,Name),!.
  943
  944:- multifile current_directory_search/1.  945:- module_transparent current_directory_search/1.  946
  947
  948%= 	 	 
 atom_ensure_endswtih(?A, ?E, ?A) is semidet
Atom Ensure Endswtih.
  954atom_ensure_endswtih(A,E,A):-atom(E),atom_concat(_Left,E,A),!.
  955atom_ensure_endswtih(A,E,O):-atom(A),atom(E),atom_concat(A,E,O),!.
  956atom_ensure_endswtih(A,E,O):-atom(A),atom(O),atom_concat(A,E,O),!.
  957atom_ensure_endswtih(A,O,O):-atom(A),atom(O),!.
  958
  959
  960%= 	 	 
 os_to_prolog_filename(?OS, ?PL) is semidet
Outputs Converted To Prolog Filename.
  966os_to_prolog_filename(OS,_PL):-sanity(atom(OS)),fail.
  967os_to_prolog_filename(_OS,PL):-sanity(var(PL)),fail.
  968os_to_prolog_filename(OS,PL):-exists_file_safe(OS),!,PL=OS.
  969os_to_prolog_filename(OS,PL):-exists_directory_safe(OS),!,PL=OS.
  970os_to_prolog_filename(OS,PL):-current_directory_search(CurrentDir),join_path(CurrentDir,OS,PL),exists_file_safe(PL),!.
  971os_to_prolog_filename(OS,PL):-current_directory_search(CurrentDir),join_path(CurrentDir,OS,PL),exists_directory_safe(PL),!.
  972
  973os_to_prolog_filename(OS,PL):-atom(OS),atomic_list_concat([X,Y|Z],'\\',OS),atomic_list_concat([X,Y|Z],'/',OPS),!,os_to_prolog_filename(OPS,PL).
  974os_to_prolog_filename(OS,PL):-atom_concat_safe0(BeforeSlash,'/',OS),os_to_prolog_filename(BeforeSlash,PL).
  975os_to_prolog_filename(OS,PL):-absolute_file_name(OS,OSP),OS \== OSP,!,os_to_prolog_filename(OSP,PL).
  976
  977
  978dedupe_files(SL0,SL):- maplist(relative_file_name,SL0,SL1), list_to_set(SL1,SL2),maplist(absolute_file_name_or_dir,SL2,SLO),!,
  979  list_to_set(SLO,SL),!.
  980
  981  relative_file_name(A,S):-  prolog_canonical_source(A,L), file_name_on_path(L,S), atom(S), \+ name(S,[]), (exists_file_safe(S);exists_directory(S)),!.
  982  relative_file_name(A,A).          
  983
  984exists_all_filenames(S0, SL, Options):- 
  985  findall(N, (relative_from(D), 
  986     absolute_file_name_or_dir(S0, N, 
  987        [relative_to(D), file_errors(fail), access(read), solutions(all)|Options])), SL0),
  988  dedupe_files(SL0,SL),!.
  989
  990
  991absolute_file_name_or_dir(S0,N):-absolute_file_name_or_dir(S0,N,[file_errors(fail), access(read), solutions(all)]).
  992absolute_file_name_or_dir(S0,N,Options):- 
  993  absolute_file_name(S0,N,Options)*-> true
  994  ;(\+ member(file_ext(_),Options),
  995    \+ member(file_type(_),Options),!,
  996      (absolute_file_name(S0,N,[file_type(directory)|Options]) *-> true
  997     ; absolute_file_name(S0,N,[file_type(txt)|Options]))).
  998
  999absolute_file_name_or_dir(S0,N,Options):- absolute_file_name(S0,N,Options).
 1000
 1001:- export(resolve_local_files/2). 1002resolve_local_files(S0,SL):- is_list(S0), !, maplist(resolve_local_files,S0,SS), append(SS,SF),dedupe_files(SF,SL).
 1003resolve_local_files(S0,SL):- atom(S0), exists_file_safe(S0), !, SL = [S0].
 1004resolve_local_files(S0,SS):- atom(S0),atom_concat(AA,'M.e',S0),atom_concat(AA,'.e',SL),resolve_local_files(SL,SS),!.
 1005resolve_local_files(S0,SS):- atom(S0),atom_concat('answers/Mueller2004c/',AA,S0),atom_concat("ecnet/",AA,SL),resolve_local_files(SL,SS),!.
 1006%resolve_local_files(S0,SS):- atom(S0),atom_concat("answers/",AA,S0),atom_concat("examples/",AA,SL),resolve_local_files(SL,SS),!.
 1007resolve_local_files(S0,SS):- findall(S1,resolve_local_files_1(S0,S1),SL),flatten(SL,SF),dedupe_files(SF,SS),SS\==[], !.
 1008% expand_file_search_path
 1009%resolve_local_files(S0,SS):- atom(S0), findall(S1,resolve_local_files_1(ec(S0),S1),SL),flatten(SL,SF),dedupe_files(SF,SS),!.
 1010   
 1011resolve_local_files_1(S0,SL):- atom(S0), expand_file_name(S0,SL), SL = [E|_], exists_file_safe(E), !.
 1012resolve_local_files_1(S0,SL):- exists_all_filenames(S0,SL, [expand(false)]), SL \= [].
 1013resolve_local_files_1(S0,SL):- exists_all_filenames(S0,SL, [expand(true)]), SL \= [].
 1014resolve_local_files_1(S0,SL):- expand_file_search_path(S0,S1),S0\==S1,resolve_local_files(S1,SL).
 1015resolve_local_files_1(S0,SS):- atom(S0), file_base_name(S0,S1), S0\==S1, resolve_local_files(S1,SS).
 1016%resolve_local_files_1(S0,SL):- atom(S0), resolve_local_files(ec(S0),SL).
 1017
 1018relative_from(D):- working_directory(D,D),exists_directory(D).
 1019relative_from(F):- stream_property(_,file_name(F)),nonvar(F).
 1020
 1021/*
 1022resolve_file(S0,SS):- atom(S0), exists_file_safe(S0), !, SS=S0. 
 1023resolve_file(S0,SS):- absolute_file_name(S0, SS, [expand(true), file_errors(fail), access(read)]), !.
 1024resolve_file(S0,SS):- relative_from(F), absolute_file_name(S0, SS, [relative_to(F),file_errors(fail),access(read)]), !.
 1025resolve_file(S0,SS):- atom(S0), file_base_name(S0,S1), S0\==S1, resolve_file(S1,SS).
 1026*/
 1027
 1028:- export(needs_resolve_local_files/2). 1029needs_resolve_local_files(F, L):- \+ is_stream(F), \+ is_filename(F),
 1030  resolve_local_files(F, L), !,  L \= [], L \= [F].
 1031
 1032:- export(is_filename/1). 1033is_filename(F):- atom(F), \+ is_stream(F),
 1034  (exists_file_safe(F);is_absolute_file_name(F)).
 1035
 1036%chop_e(InputNameE,InputName):- atom_concat(InputName,'.e',InputNameE),!.
 1037%chop_e(InputName,InputName).
 1038
 1039
 1040
 1041contains_wildcard(Spec):- sformat(S,'~q',[Spec]),
 1042   (sub_string(S, _, _, _, '*');sub_string(S, _, _, _, '?')),!.
 1043
 1044:- fixup_exports.