1% ===================================================================
    2% File 'logicmoo_util_strings.pl'
    3% Purpose: Common Logicmoo library Functions for Strings
    4% Maintainers: Douglas Miles/Annie Ogborn/Kino Coursey
    5% Contact: $Author: dmiles $@users.sourceforge.net ;
    6% Version: 'logicmoo_util_strings.pl' 1.0.0
    7% Revision:  $Revision: 1.7 $
    8% Revised At:   $Date: 2002/07/11 21:57:28 $
    9% ===================================================================
   10:-module(logicmoo_util_strings,[
   11         quoteAtomString/2,
   12         unquoteAtom/2,
   13         /*
   14         atom_to_number/2,
   15         */
   16         toUppercase/2,
   17         toLowercase/2,
   18         toPropercase/2,
   19         toCamelcase/2,
   20
   21         is_string/1,
   22         is_codelist/1,
   23         is_charlist/1,
   24
   25         stringToCodelist/2,
   26         trim/2,
   27         clean_codes/2,
   28         all_upper_atom/1,
   29         convert_to_string/2,
   30         atom_contains/2,
   31         atomsSameCI/2,
   32         isWhitespace/1
   33   ]).   34
   35:-ensure_loaded('../logicmoo/logicmoo_util_library.pl').   36:-use_module(library('logicmoo/logicmoo_util_library.pl')).   37:-ensure_loaded(library('logicmoo/logicmoo_util_bugger.pl')).   38
   39:- dynamic_transparent(camelSplitters/1).   40
   41:- multi_transparent(to_string_hook/3).   42
   43camelSplitters(V):-member(V,[' ','-','_',':','mt','doom','Mt','Doom']).
   44
   45%================================================================
   46% Atom / String functions
   47%================================================================
   48atomsSameCI(Name1,Name1):-!.
   49atomsSameCI(Name1,Name2):-atom(Name1),atom(Name2),downcase_atom(Name1,D1),downcase_atom(Name2,D2),!,D1=D2.
   50
   51clean_codes(X,Y):-trim(X,Y),!.  % actually cyc:trim/2
   52clean_codes(X,X).
   53
   54%clean_out_atom(X,Y):-atomSplit(X,C),delete(C,'',O),concat_atom_safe(C,' ',Y).
   55clean_out_atom(X,Y):-atom_codes(X,C),clean_codes(C,D),!,atom_codes(X,D),!,Y=X.
   56
   57%%atomSplit(A,B):-token_stream_of(A,AA),findall(B0,arg(1,AA,B),B).
   58
   59all_upper_atom(X):-toUppercase(X,N),!,N=X.
   60
   61atom_contains(F,C):- hotrace((atom(F),atom(C),sub_atom(F,_,_,_,C))).
   62
   63% convert any term to 'atom' string
   64convert_to_string(I,ISO):-
   65                term_to_string(I,IS),!,
   66		string_to_list(IS,LIST),!,
   67		list_replace(LIST,92,[92,92],LISTM),
   68		list_replace(LISTM,34,[92,34],LISTO),!,
   69		string_to_atom_safe(ISO,LISTO),!.
   70
   71list_replace(List,Char,Replace,NewList):-
   72	append(Left,[Char|Right],List),
   73	append(Left,Replace,NewLeft),
   74	list_replace(Right,Char,Replace,NewRight),
   75	append(NewLeft,NewRight,NewList),!.
   76list_replace(List,_Char,_Replace,List):-!.
   77
   78term_to_string(I,IS):- catch(string_to_atom(IS,I),_,fail),!.
   79term_to_string(I,IS):- term_to_atom(I,A),string_to_atom(IS,A),!.
   80
   81% ===========================================================
   82% CASE CHANGE
   83% ===========================================================
   84
   85noCaseChange(NC):-noCaseChange(NC,_),!.
   86noCaseChange([],[]):-!.
   87noCaseChange(VAR,VAR):-var(VAR),!.
   88noCaseChange(MiXed,MiXed):-atom(MiXed),atom_concat('#$',_,MiXed),!.
   89noCaseChange(c(VAR),c(VAR)):-!.
   90
   91toUppercase(MiXed,MiXed):-noCaseChange(MiXed),!.
   92toUppercase(V,V2):-string(V),!,atom_codes(V,VC),toUppercase(VC,CVC),string_to_atom(V2,CVC),!.
   93toUppercase(95,45):-!.
   94toUppercase(I,O):-integer(I),!,to_upper(I,O).
   95toUppercase([A|L],[AO|LO]):-
   96   toUppercase(A,AO),!,
   97   toUppercase(L,LO),!.
   98toUppercase(MiXed,CASED):-atom(MiXed),upcase_atom(MiXed,CASED),!.
   99toUppercase(MiXed,CASED):-atom(MiXed),!,
  100   atom_codes(MiXed,Codes),
  101   toUppercase(Codes,UCodes),
  102   atom_codes(CASED,UCodes),!.
  103toUppercase(MiXed,CASED):-compound(MiXed),MiXed=..MList,toUppercase(MList,UList),!,CASED=..UList.
  104toUppercase(A,A).
  105
  106toLowercase(MiXed,MiXed):-noCaseChange(MiXed),!.
  107toLowercase(V,V2):-string(V),!,atom_codes(V,VC),toLowercase(VC,CVC),string_to_atom(V2,CVC),!.
  108toLowercase(95,45):-!.
  109toLowercase(I,O):-integer(I),!,to_lower(I,O).
  110toLowercase([A|L],[AO|LO]):-
  111   toLowercase(A,AO),!,
  112   toLowercase(L,LO),!.
  113toLowercase(MiXed,CASED):-atom(MiXed),downcase_atom(MiXed,CASED),!.
  114toLowercase(MiXed,CASED):-atom(MiXed),!,
  115   atom_codes(MiXed,Codes),
  116   toLowercase(Codes,UCodes),
  117   atom_codes(CASED,UCodes),!.
  118toLowercase(MiXed,CASED):-compound(MiXed),MiXed=..MList,toLowercase(MList,UList),!,CASED=..UList.
  119toLowercase(A,A).
  120
  121toPropercase(VAR,VAR):-var(VAR),!.
  122toPropercase([],[]):-!.
  123toPropercase([CX|Y],[D3|YY]):-!,toPropercase(CX,D3),toPropercase(Y,YY).
  124toPropercase(D3,DD3):-atom(D3),camelSplitters(V),concat_atom([L,I|ST],V,D3),toPropercase([L,I|ST],LIST2),toPropercase(V,VV),concat_atom(LIST2,VV,DD3).
  125toPropercase(CX,Y):-atom(CX),name(CX,[S|SS]),char_type(S,to_lower(NA)),name(NA,[N]),name(Y,[N|SS]),!.
  126toPropercase(MiXed,UPPER):-compound(MiXed),MiXed=..MList,toPropercase(MList,UList),!,UPPER=..UList.
  127toPropercase(A,A).
  128
  129
  130toCamelcase(VAR,VAR):-var(VAR),!.
  131toCamelcase([],[]):-!.
  132toCamelcase([CX|Y],[D3|YY]):-!,toCamelcase(CX,D3),toCamelcase(Y,YY).
  133toCamelcase(D3,DD3):-atom(D3),camelSplitters(V),concat_atom([L,I|ST],V,D3),toCamelcase([L,I|ST],LIST2),toCamelcase(V,VV),concat_atom(LIST2,VV,DD3).
  134toCamelcase(CX,Y):-atom(CX),name(CX,[S|SS]),char_type(S,to_upper(NA)),name(NA,[N]),name(Y,[N|SS]),!.
  135toCamelcase(MiXed,UPPER):-compound(MiXed),MiXed=..MList,toCamelcase(MList,UList),!,UPPER=..UList.
  136toCamelcase(A,A).
  137
  138      
  139% ===========================================================
  140% Quote-Unquote
  141% ===========================================================
  142
  143quoteAtomString([34|T],Out):-name(Out,[34|T]),!.
  144quoteAtomString([H|T],Out):-!,append([34,H|T],[34],Quote),name(Out,Quote).
  145quoteAtomString(QU,QU):-concat_atom(['"'|_],QU),!.
  146quoteAtomString(UQ,QU):-concat_atom(['"',UQ,'"'],QU),!.
  147
  148unquoteAtom(Atom,New):-concat_atom(LIST,'"',Atom),concat_atom(LIST,'',New),!.
  149
  150% ===========================================================
  151% string/chars/codes
  152% ===========================================================
  153
  154is_charlist([X]):-atom(X),not(number(X)),atom_length(X,1).
  155is_charlist([X|T]):-atom(X),not(number(X)),atom_length(X,1),is_charlist(T),!.
  156
  157is_codelist([A]):-integer(A),!,A>8,A<129,!.
  158is_codelist([A|L]):-integer(A),!,A>8,A<129,is_codelist(L).
  159
  160is_string(X):-atom(X),!,atom_length(X,L),L>1,atom_concat('"',_,X),atom_concat(_,'"',X),!.
  161is_string(X):-var(X),!,fail.
  162is_string(string(_)):-!.
  163is_string("").
  164is_string(X):-string(X),!.
  165is_string(L):-is_charlist(L),!.
  166is_string(L):-is_codelist(L),!.
  167
  168
  169isWhitespace(32).
  170isWhitespace(N):-N<33;N>128.
  171
  172
  173% ===========================================================
  174% escapeString/Codes/Chars
  175% ===========================================================
  176
  177escapeString(R,RS):- (string(R);is_list(R)) ,string_to_atom(R,A),atom_codes(A,Codes),escapeCodes([34,92],92,Codes,RS),!.
  178
  179escapeCodes(_Escaped,_EscapeChar,[],[]):-!.
  180escapeCodes(Escaped,EscapeChar,[EscapeChar,Skip|Source],[EscapeChar,Skip|New]):-!,
  181   escapeCodes(Escaped,EscapeChar,Source,New),!.
  182escapeCodes(Escaped,EscapeChar,[Char|Source],[EscapeChar,Char|New]):-member(Char,Escaped),!,
  183   escapeCodes(Escaped,EscapeChar,Source,New),!.
  184escapeCodes(Escaped,EscapeChar,[Skipped|Source],[Skipped|New]):-
  185   escapeCodes(Escaped,EscapeChar,Source,New),!.
  186
  187
  188% ===========================================================
  189% [d|r]estringify/Codes/Chars
  190% ===========================================================
  191
  192destringify(X,X):-var(X);number(X),!.
  193destringify(X,S):-is_string(X),stringToCodelist(X,CL),name(S,CL),!.
  194destringify([],[]):-!.
  195destringify([H|T],[HH|TT]):-!,destringify(H,HH),destringify(T,TT),!.
  196destringify(X,P):-compound(X),X=..LIST,destringify(LIST,DL),P=..DL,!.
  197destringify(X,X):-not(atom(X)),!.
  198destringify(B,A):-atom_concat('#$',A,B),!.
  199destringify(B,B):-!.
  200
  201%stringToList(X,Y):-writeq(string_to_list(X,Y)),nl,fail.
  202stringToList(X,Y):-var(X),!,string_to_list(X,Y).
  203stringToList([],[]).
  204stringToList("",[]).
  205stringToList(X,Y):-atom(X),atom_codes(X,Codes),!,stringToList(Codes,Y),!.
  206stringToList(X,Y):-string(X),string_to_atom(X,M),!,stringToList(M,Y).
  207stringToList(X,Y):-string(X),!,string_to_list(X,Y).
  208stringToList(X,Y):-is_string(X),!,string_to_list(X,Y).
  209stringToList([X|XX],Y):-concat_atom([X|XX],' ',XXX),!,string_to_list(XXX,Y).
  210%prologPredToCyc(Predicate):-arity(PredicateHead)
  211
  212stringToCodelist(S,CL):-stringToCodelist2(S,SL),!,escapeString(SL,CS),!,stringToList(CL,CS),!.
  213
  214stringToCodelist2(string(S),Codes):-!,stringToCodelist2(S,Codes).
  215stringToCodelist2([],[]):-!.
  216stringToCodelist2([[]],[]):-!.
  217stringToCodelist2([''],[]):-!.
  218stringToCodelist2([X|T],[X|T]):-is_codelist([X|T]),!.
  219stringToCodelist2([X|T],Codes):-atom(X),is_charlist([X|T]),!,stringToList([X|T],Codes),!.
  220stringToCodelist2(String,Codes):-string(String),!,string_to_atom(String,Atom),atom_codes(Atom,Codes),!.
  221stringToCodelist2(Atom,Codes):-atom(Atom),atom_codes(Atom,Codes),!.
  222stringToCodelist2(A,Codes):- to_string_hook(A,_,L),atom_codes(L,Codes),!.
  223stringToCodelist2(Term,Codes):-sformat(Codes,'~q',[Term]),true.
  224
  225
  226%===================================================================
  227% Removes Leading and Trailing whitespaces and non ANSI charsets.
  228%====================================================================
  229:-assert(show_this_hide(trim,2)).  230:-current_prolog_flag(double_quotes,X),asserta(double_quotes(X)).  231:-set_prolog_flag(double_quotes,codes).  232
  233trim(S,Y):-flatten(S,S2),trim2(S2,Y).
  234
  235trim2(S,Y):-
  236      ground(S),%true,
  237      stringToList(S,X),
  238      ltrim(X,R),lists:reverse(R,Rvs), 
  239      addSpaceBeforeSym(Rvs,Rv),      
  240      ltrim(Rv,RY),lists:reverse(RY,Y),!.
  241     
  242addSpaceBeforeSym([H|T],[H,32|T]):-member(H,"?.!"),!.
  243addSpaceBeforeSym(H,H).
  244
  245:-retract(double_quotes(X)),set_prolog_flag(double_quotes,X).  246:-set_prolog_flag(double_quotes,string).  247
  248ltrim([],[]):-!.
  249ltrim([32,32,32,32,32,32,32|String],Out) :-trim(String,Out),!.
  250ltrim([32,32,32,32,32|String],Out) :-trim(String,Out),!.
  251ltrim([32,32,32|String],Out) :- trim(String,Out),!.
  252ltrim([32,32|String],Out) :- trim(String,Out),!.
  253ltrim([P|X],Y):- (isWhitespace(P);not(number(P));P<33;P>128),trim(X,Y),!.
  254ltrim(X,X)