1:- module(misc, [
    2	 compile_pred_word/4
    3  ,  random_choice/2
    4  ,  collect_subterm/3
    5  ,  collect_subterm/4
    6  ,  completing_optional_args/3
    7  ,  cs/2
    8  ,  desugaring/2
    9  ,  dir_minus/3
   10  ,  dir_plus/3
   11  ,  directory_files/3
   12  ,  directory_remove_ymhms/1
   13  ,  drop3zw/2
   14  ,  find_exportables_from_calls/2
   15  ,  ignore/2
   16  ,  insert/3
   17  ,  insert_pause/2
   18  ,  kanji/3
   19  ,  list/2
   20  ,  map_directory_files/2
   21  ,  matrix_paths/2
   22  ,  parse_time/3
   23  ,  parse_utf8/2
   24  ,  predicate_arity/2
   25  ,  predicate_arity_for_export/2
   26  ,  rename_directory_suffix/3
   27  ,  set/2
   28  ,  split_by_filler/3
   29  ,  string/2
   30  ,  shell_string/2, shell_string/3, qshell_string/2
   31  ,  texadjust/2
   32  ,  texuncomment/2
   33  ,  token_and_split/3
   34  ,  try2problem/2
   35  ,  expand_sgn_brace/2			]).   36
   37:- use_module(pac(basic)).   38:- use_module(util(file)).   39:- use_module(util('meta2')).   40:- use_module(util(math)).   41:- use_module(pac('expand-word')).   42
   43term_expansion --> pac:expand_pac.
   44:- use_module(pac(op)).   45%
   46:- use_module(pac('expand-pac')).   47
   48		/***********************************
   49		* Compile clause / DCG with regex  *
   50		***********************************/
   51
   52new_names([V|Vs], [A=V|Eqs], N, Prefix, As):-
   53	new_name(N, As, A, Prefix, K),
   54	new_names(Vs, Eqs, K, Prefix, As).
   55new_names([], [], _, _, _).
   56
   57%
   58new_name(N, As, B, Prx, K):- atom_concat(Prx, N, B),
   59						\+ memberchk(B, As),
   60						!,
   61						succ(N, K).
   62new_name(N, As, A, Prx, K):- succ(N, N1),
   63						new_name(N1, As, A, Prx, K).
   64
   65% ?- ejockey:subtractq([X,Y,X,Y,X,Y], [X], R).
   66subtractq([], _, []).
   67subtractq([A|As], B,  C):- memq(A, B), !,
   68	subtractq(As, B, C).
   69subtractq([A|As], B, [A|C]):- subtractq(As, B, C).
   70
   71%
   72expand_clause_slim(X, Y):-
   73	expand_clause(X, [], Y0),
   74	maplist(pred([X:-true, X] & [C, C]),  Y0, Y).
   75%
   76compile_pred_word(X-->X0, Eqs, H0, R0):-!,
   77		maplist(pred([A=P, A, P]), Eqs, As, Vs),
   78		expand_clause_slim(X-->X0, [H|R]),
   79		term_variables(H, HVs),
   80		subtractq(HVs, Vs, SVs),
   81		new_names(SVs, Eqs0, 1, 'A', As),
   82		append(Eqs0, Eqs, Eqs1),
   83		term_string(H, H0, [variable_names(Eqs1),
   84							quoted(true)]),
   85		maplist(pred(([U, [V,".\n"]] :-
   86								numbervars(U, 0, _),
   87								term_string(U, V, [ numbervars(true),
   88													quoted(true)]))),
   89				R, R0).
   90compile_pred_word(X, Eqs, H0, R0):-
   91		expand_clause_slim(X, [H|R]),
   92		term_string(H, H0, [variable_names(Eqs),
   93							quoted(true)]),
   94		maplist(pred(([U, [V,".\n"]] :-
   95								numbervars(U, 0, _),
   96								term_string(U, V, [ numbervars(true),
   97													quoted(true)]))),
   98				R, R0).
   99
  100
  101			/********************
  102			*     shell string  *
  103			********************/
 shell_string(+X:term, -Y:string) is det
Expand a shell command term X into a string that can be passed to shell/1.
  109% ?- shell_string(open("1"), X).
  110% ?- shell_string(open(1), X).
  111% ?- shell_string(open(abc), X).
  112% ?- shell_string(open(-l, -m, abc), X).
  113% ?- shell_string(open(-f(a)), X).
  114% ?- shell_string(open(-f(a)), X).
  115
  116% ?- shell_string(a, Y).
  117% ?- shell_string([[a]], Y).
  118% ?- shell_string([[a],[b]], Y).
  119% ?- shell_string([[a]+[b]], Y).
  120% ?- shell_string(f(-a + b), Y).
  121% ?- shell_string(f(-a + b, -c + d), Y).
  122% ?- shell_string(f(-1 + b, -c + d, e), Y).
  123% ?- shell_string(f(-1,  b, -c + d, e), Y).
  124% ?- shell_string(f(a + b + c + d + e), Y).
  125% ?- shell_string(f(a); g(b), Y).
  126% ?- shell_string(f(1); g(1), Y).
  127% ?- shell_string({f(a); g(b)}, Y).
  128
  129shell_infix(L / R, L, /, R).
  130shell_infix(L ; R, L, ;, R).
  131shell_infix('|'(L,R), L, '|', R).
  132shell_infix(L > R, L, >, R).
  133shell_infix(L >> R, L, >>, R).
  134shell_infix(L << R, L, <<, R).
  135shell_infix(&(L, R), L, &, R).
  136shell_infix(&&(L, R), L, &&, R).
  137%
  138qshell_string(X, Y):- shell_string(X, " > /dev/null 2>&1", Y).
  139%
  140shell_string(X, Y):- shell_string(X, "", Y).
  141%
  142shell_string([], Z, Z):-!.
  143shell_string([X], Y, Z):-!, shell_string(X, Y, Z).
  144shell_string([X,Y|Z], U, V):-!, shell_string([Y|Z], U, W),
  145	string_concat(" ", W, W0),
  146	shell_string(X, W0, V).
  147shell_string(A+B, X, Y):-!, shell_string(B, X, X0),
  148	shell_string(A, X0, Y).
  149shell_string(-A, X, Y):-!, shell_string("-" + A, X, Y).
  150shell_string(--(A), X, Y):-!, shell_string("--" + A, X, Y).
  151shell_string(A, X, Y):- shell_infix(A, L, F, R), !,
  152	shell_string(R, X, X0),
  153	string_concat(F, X0, X1),
  154	shell_string(L, X1, Y).
  155shell_string({A}, X, Y):-!, shell_string("( " + A + " )", X, Y).
  156shell_string(shell(A), X, Y):-!, shell_string({A}, X, Y).
  157shell_string(A, X, Y):- compound(A), !,
  158	A =.. B,
  159	shell_string(B, X, Y).
  160shell_string(A, X, Y):- atomic(A), string_concat(A, X, Y).
  161
  162
  163		/**********************************
  164		*     compleging optional args    *
  165		**********************************/
  166
  167% ?- completing_optional_args([a(hello)], [], R).
  168% ?- completing_optional_args([a(X):hello], [], R).
  169% ?- completing_optional_args([a(X): !(X=hello)], [], R).
  170% ?- completing_optional_args([a(X):hello], [], R).
  171% ?- completing_optional_args([a(X):hello], [a(world)], R).
 completing_optional_args(+X, +Y, -Z) is det
option Z is unified with Y completed with default option X.
  176completing_optional_args(X, Y, Z):-
  177	completing_optional_args(X, Y, Z, []).
  178
  179% ?- zdd_array:completing_optional_args([a(X)], [a(Y)], R, S).
  180% ?- zdd_array:completing_optional_args([a(world)], [a(hello)], R, S).
  181% ?- zdd_array:completing_optional_args([a(X):b], [a(Y)], R, S).
  182% ?- zdd_array:completing_optional_args([a(X):10], [a(Y)], R, S).
  183
  184completing_optional_args([], R, R, []):-!.
  185completing_optional_args([A|As], Bs, [B|R], R0):- (A = A0:_ ; A0= A), !,
  186	functor(A0, F, 1),
  187	functor(B, F, 1),
  188	( select(B, Bs, Cs); Cs = Bs ), !,
  189	unify_one(A, B),
  190	completing_optional_args(As, Cs,  R,  R0).
  191
  192% For preventing expansion brace {..} by open_dict as pac macro.
  193% ( not used )
  194:- set_prolog_flag(open_dict, false).  195unify_default({G}, _):-!, once(G).
  196unify_default(X, X).
  197:- set_prolog_flag(open_dict, true).  198
  199%
  200unify_one(A:Val, B):- !, functor(A, F, 1),
  201	functor(B, F, 1),
  202	arg(1, A, U),
  203	arg(1, B, V),
  204	(	var(V)	->	U = Val,	% unify_default(Val, U),
  205					V = U
  206	;	var(U)	->  U = V
  207	;	true
  208	).
  209unify_one(A, A):-!.
  210unify_one(_, _).
  211
  212			/************************
  213			*       Set kind        *
  214			************************/
 set(+X:term, -Y:list) is det
Evaluate a set expression X into a list Y.
  219% ?- set([a,b]-[1,2], R).
  220% ?- set(singleton(pow([1,2])), X), length(X, L).
  221
  222set(emptyset,[]):-! .
  223set(X,X):-listp(X),! .
  224set(singleton(A),[B]):-!,set(A,B) .
  225set(A+B,A1):-!,(set(A,A2),set(B,A3)),union(A2,A3,A1) .
  226set(plus(A,B),A1):-!,set(A+B,A1) .
  227set(cup(A),A1):-!,(set(A,A2),set(append(A2),A3)),sort(A3,A1) .
  228set(cap(A),A1):-!,set(A,A2),math:bigcap(A2,A1) .
  229set(++(A,B),A1):-!,(set(A,A2),set(B,A3)),math:direct_sum(A2,A3,A1) .
  230set(A*B,A1):-!,(set(A,A2),set(B,A3)),math:product(A2,A3,A1) .
  231set(A-B,A1):-!,(set(A,A2),set(B,A3)),
  232	pac_meta:pac_product(misc:set_aux,A2,A3,A1) .
  233set(\(A,B),A1):-!,(set(A,A2),set(B,A3)),subtract(A2,A3,A1) .
  234set(#(A,B),A1):-!,(set(A,A2),set(B,A3)),scramble_cons(A2,A3,A1) .
  235set(&(A,B),A1):-!,(set(A,A2),set(B,A3)),math:intersection(A2,A3,A1) .
  236set(pow(A),A1):-!,set(A,A2), math:powerset(A2,A1) .
  237set(zip(A,B),A1):-!,(set(A,A2),set(B,A3)),zip(A2,A3,A1) .
  238set(sort(A),A1):-!,set(A,A2),sort(A2,A1) .
  239set((A->B),A1):-!,(set(A,A2),set(B,A3)),math:mapset(A2,A3,A1) .
  240set(..(I,J),A1):-(I0 is I,J0 is J),!,numlist(I0,J0,A1) .
  241set(in(X,Y),A1):-!,(set(X,A2),set(Y,A3)),truth(memberchk,A2,A3,A1) .
  242set(X=Y,A1):-!,(set(X,A2),set(Y,A3)),truth(==,A2,A3,A1) .
  243set(X=<Y,A1):-!,(set(X,A2),set(Y,A3)),truth(subset,A2,A3,A1) .
  244set(X>=Y,A1):-!,set(Y=<X,A1) .
  245set(X<Y,A1):-!,(set(X,A2),set(Y,A3)),truth(math:proper_subset,A2,A3,A1) .
  246set(X>Y,A1):-set(Y<X,A1) .
  247
  248%
  249set_aux(A,B,A-B).
 insert(+M:term, +X:list, -Y:list) is det
Insert M beteen every successive elements of X, and unify Y with the result.
  255% ?- misc:insert(a, [1,2,3], R).
  256insert(M, [A|P], [A|Q]):- foldl(pred(M, [B, [M, B| U], U]), P, Q, []).
  257insert(_, [], []).
  258
  259%
  260truth(X, true) :- call(X), !.
  261truth(_, false).
  262
  263truth(X, Y, true) :- call(X, Y), !.
  264truth(_, _, false).
  265
  266truth(X, Y, Z, true) :- call(X, Y, Z), !.
  267truth(_, _, _, false).
 desugaring(+X:term, -Y:term) is det
Eliminate infix '-' and '/', and prefix '+', '-', and ufify Y with the result.
  273% ?- desugaring( -(a-b-c), Y).
  274
  275desugaring(X-Y,A1+ -1*A2):-!,desugaring(X,A1),desugaring(Y,A2).
  276desugaring(+X,A1):-!,desugaring(X,A1).
  277desugaring(-X,-1*A1):-!,desugaring(X,A1).
  278desugaring(X/Y,A1 rdiv A2):-!,desugaring(X,A1),desugaring(Y,A2).
  279desugaring(X,X).
  280
  281insert_pause(cs(item),[cs(pause),cs(item)]):-! .
  282insert_pause(X,A1):-(listp(X),maplist(insert_pause,X,Y)),!,insert_pause(Y,A1) .
  283insert_pause(X,A1):-(X=..[F|As],maplist(insert_pause,As,Bs),Z=..[F|Bs]),!,
  284		insert_pause(Z,A1).
  285
  286texadjust([cs(item)|X],A1):-texadjust(X,Y),!,texadjust([10,cs(item)|Y],A1) .
  287
  288cs(cs(N),[N]):-!.
  289cs(A,A1):-listp(A),!,maplist(cs,A,A1) .
  290cs(A,A1):-A=..[_A2|As], maplist(cs,As,A1) .
  291
  292texuncomment(comment(_A1),[]).
  293
  294try2problem(env(try,Body),A1):-try2problem(Body,A2),try2problem(env(problem,A2),A1).
  295
  296drop3zw(ddol(E),[cs(noindent),cs(skip),"3zw",env(coronamath,[dol([cs(displaystyle)," ",E])])]).
  297
  298
  299
  300% product(A, B, C):-
  301% 	foldr( pred(B, [X,P,Q] :-
  302% 		foldr(pred(X, [Y,U,[X-Y|U]]), B, P, Q)), A, [], C).
  303
  304% product_cons(A, B, C):-
  305% 	foldr( pred(B, [X,P,Q] :- foldr(pred(X, [Y,U,[[X|Y]|U]]), B, P, Q)), A, [], C).
  306
  307% ?- product_cons([1,2],[[a,b],[c,d,e]], X).
  308%@ X = [[1,a,b],[1,c,d,e],[2,a,b],[2,c,d,e]] .
  309
  310% product3(A, B, C, D):-
  311% 	foldr( pred([B,C], [X,P,Q] :-
  312% 		foldr(pred([X,C], [Y,U, V]:-
  313% 			 foldr(pred([X,Y], [Z, M, [X-Y-Z|M]]), C, U, V)),
  314% 				B, P, Q)), A, [], D).
  315
  316% product4(A, B, C, D, E):-
  317% 	foldr( pred([B,C,D],
  318% 		    [X, P, Q] :-
  319% 		foldr(pred([X,C,D],
  320% 			   [Y, U, V]:-
  321% 			 foldr(pred([X,Y,D],
  322% 				    [Z, M, N]:-
  323% 			      foldr(pred([X,Y,Z],
  324% 					 [W, R,[X-Y-Z-W|R]]), D, M, N)),
  325% 			       C, U, V)),
  326% 		      B, P, Q)),
  327% 	        A, [], E).
  328
  329matrix_paths([], [[]]).
  330matrix_paths([X|Y], Z):- matrix_paths(Y,  PY),
  331	foldr(pred(PY, [J, P, Q]:-
  332	     foldr(pred(J, [K, N, [[J|K]|N]]), PY, P, Q)),
  333	      X, [], Z).
  334
  335
  336% ?- time(repeat(10^8, choices_by_fold([[1,2],[a,b,c],[3,4]], R))).
  337%@ % 7,900,000,001 inferences, 394.599 CPU in 394.833 seconds (100% CPU, 20020346 Lips)
  338%@ true.
  339
  340% ?- time(repeat(10^8, choices([[1,2],[a,b,c],[3,4]], R))).
  341%@ % 4,300,000,001 inferences, 138.387 CPU in 138.479 seconds (100% CPU, 31072358 Lips)
  342%@ true.
by [compile, pac, region] of emacs-jockey.pl
choices_by_fold(X, Y):- reverse(X, X0), foldl(pred([A,B,C] :- foldr( pred(B, [L,P,Q] :- foldr(pred(L, [M,U,[[L|M]|U]]), B, P, Q)), A, [], C)), X0, [[]], Y).
  357% ?- length(L, 10), maplist(misc:random_choice([[a,b],[c,d,e]]), L), maplist(writeln, L).
  358
  359random_choice([L|R], [A|Q]):- length(L, N), I is random(N),
  360			      nth0(I, L, A),
  361			      random_choice(R, Q).
  362random_choice([], []).
 list(+X:term, -Y:list) is det
Expand a list term X into a list Y.
  368% ?- list([1,2]\[1,2,3,4], R).
  369% ?- list([a,b]^2, R).
  370% ?- list(^^([a,b], 2), R).
  371% ?- list([a,b]^2+[c,d]^3+[e,f]^4, R), length(R, L).
  372% ?- list([a,b]^0+[c,d]^1+[e,f]^2, R), length(R, L).
  373% ?- list([a,b]^^3, R), length(R, L).
  374
  375list(A+B,A1):-!, list(A,A2),
  376	list(B,A3),
  377	append(A2,A3,A1).
  378list(\(A,B),Z):-!, list(A,X),list(B,Y), append(X,Z,Y) .
  379list(A/B,Z):-!, list(A,X),list(B,Y), append(Z,Y,X) .
  380list(E^L,A1):-N is L,!,list(E,A2),times(N,A2,A1) .
  381list(^^(E,L),C):-N is L,!,list(E,A),math:nlist(A,N,C) .
  382list(X,X):-listp(X),! .
  383list(+A,A1):-!,list(A,A2), append(A2,A1) .
  384list(flat(A),A1):-list(A,A2),flatten(A2,A1) .
 string(+X:term, -Y:string) is det
Expand a string term X into a string Y.
  389% ?- string("ab"+"cd"+"ef", X).
  390% ?- string("abcd"/"cd", X).
  391% ?- string("ab"\"abcd", X).
  392% ?- string(("ab"\"abcd")^3, X).
  393% ?- string(("ab"\"abcd")^3, X).
  394% ?- val(string((+) @ (list@ (+(["ab", "cd"], ["ef", "gf"])))), Y).
  395% ?- string(reverse("abcd"), X).
  396% ?- string(reverse(reverse("uvw") + reverse("ab" + "12")), X).
  397
  398string(A+B,A1):-!, string(A,A2),
  399	string(B,A3),
  400	string_concat(A2,A3,A1).
  401string(\(A,B),Z):-!, string(A,X),
  402	string(B,Y),
  403	string_concat(X,Z,Y).
  404string(A/B,Z):-!, string(A,X),
  405	string(B,Y),
  406	string_concat(Z,Y,X).
  407string(E^L,A1):-N is L,!,string(E,A2),
  408	string_times(N,A2,A1) .
  409string(reverse(X),B):-!, string(X,A1),
  410	string_codes(A1,A2),
  411	reverse(A2,A),
  412	string_codes(B,A).
  413string(+A,A1):-!, string(A,A2),
  414	list(A2,A3),
  415	string_list_concat(A3,A1).
  416string(X,X):-(string(X);atom(X)),!.
  417
  418
  419% split by variable length filler.
  420split_by_filler(X) --> filler, token_and_split(X).
  421%
  422token_and_split([]) --> current([]).
  423token_and_split([A|X]) --> wl("[^\s\t\r\n]+", A, []),  split_by_filler(X).
  424
  425%
  426filler -->	filler(_, _).
  427%
  428filler(X, Y) --> wl("[\s\t\n\r]*", X, Y).
  429%
  430delimiter_plus --> wl(+("[\t\r\n]" | "\s\s+"), _, _).
  431%
  432delimiter_plus(X, Y) --> wl(+("[\t\r\n]" | "\s\s+"), X, Y).
  433
  434
  435		/************************************
  436		*     new splitter. [2024/05/24]    *
  437		************************************/
X, Y as Difference-list is unified with a list of words splitted by filler \t, \n, \r, and spaces \s\s+. This splitter does not include empty word in the output.
 split_plus(?X) is det
Equivalent to split_plus(?X, []).
  447% ?- split_plus(Ws, `   `, []).
  448% ?- split_plus(Ws, ` a + a  `, []), maplist(string_codes, X, Ws).
  449% ?- split_plus(Ws, `\t\n a + a\n\t  `, []), maplist(string_codes, X, Ws).
  450
  451split_plus(X) --> split_plus(X, []).
  452%
  453split_plus(X, Y) --> filler, !, words(X, Y).
  454%
  455words(X, X) --> current([]), !.
  456words([[C|W]|Xs], Y) --> [C], word_tail(W), words(Xs, Y).
  457%
  458word_tail([]) --> filler, current([]), !.
  459word_tail([]) --> delimiter_plus, !.
  460word_tail([C|W]) --> [C], word_tail(W).
  461
  462% ?- Codes = ` a + b  c  `,
  463%	 Fregex = "[\s\t\n\r]*",
  464%	 Dregex = +("[\t\r\n]" | "\s\s+"),
  465%	 pred_split(Fregex, Dregex, Splitted, Codes, []),
  466%	 maplist(string_codes, Strings, Splitted).
  467
  468pred_split(Filler, Delimiter, X) -->
  469	{	pac_word:let_wl(F, Filler),
  470		pac_word:let_wl(D, Delimiter)
  471	},
  472	pred_split(F, D, X, []).
  473%
  474pred_split(F, D, X, Y) --> call(F), !, words(F, D, X, Y).
  475%
  476words(_, _, X, X) --> current([]), !.
  477words(F, D, [[C|W]|Xs], Y) --> [C], word_tail(F, D, W), words(F, D, Xs, Y).
  478%
  479word_tail(F, _, []) --> call(F), current([]), !.
  480word_tail(_, D, []) --> call(D), !.
  481word_tail(F, D, [C|W]) --> [C], word_tail(F, D, W).
  482
  483% ?- time((	Codes = ` a + b  c `,
  484%		Fregex = "[\s\t\n\r]*",
  485%		Dregex = +("[\t\r\n]" | "\s\s+"),
  486%		pac_word:let_wl(F, Fregex),
  487%		pac_word:let_wl(D, Dregex),
  488%	let(Split, mrec([F, D],
  489%		[ Pred_split  = ( [X, Y, A, B]:-call(F, A, C), !,
  490%					call(Words, X, Y, C, B)),
  491%		  Words = (
  492%					( [X, X, [], []]:-! )
  493%				&	([[[C|W]|Xs], Y, [C|A], B]:-
  494%						call(Word_tail, W, A, A0),
  495%						call(Words, Xs, Y, A0, B))),
  496%		 Word_tail = (
  497%					([[], A, B]:-call(F, A, B), current([], B, B))
  498%				&	([[], A, B]:- call(D, A, B), !)
  499%				&	([[C|W], [C|A], B]:- call(Word_tail, W, A, B)))])),
  500%	 call(Split, Splitted, [], Codes, []))),
  501%	 maplist(string_codes, Strings, Splitted).
  502%@ % 8,758 inferences, 0.001 CPU in 0.001 seconds (98% CPU, 6950794 Lips)
  503%@ Codes = [32, 97, 32, 43, 32, 98, 32, 32, 99|...],
  504%@ Fregex = "[ \t\n\r]*",
  505%@ Dregex = + ("[\t\r\n]"| "  +"),
  506%@ F = user:'nt#558',
  507%@ D = user:'nt#562',
  508%@ Split = misc:'pac#574'([user:'nt#558', user:'nt#562']),
  509%@ Pred_split = 'pac#574'([user:'nt#558', user:'nt#562']),
  510%@ Words = 'pac#575'([user:'nt#558', user:'nt#562']),
  511%@ Word_tail = 'pac#576'([user:'nt#558', user:'nt#562']),
  512%@ Splitted = [[97, 32, 43, 32, 98], [99]],
  513%@ Strings = ["a + b", "c"] .
  514
  515% ?- filler(`   abc`, X).
  516% ?- string_chars("ab", L), split_by_filler(X, L, Y).
  517% ?- string_chars("    ", L), split_by_filler(X, L, Y).
  518% ?- string_chars(" ab  c\n \t   ", L), split_by_filler(X, L, Y).
  519% ?- string_chars(" ab  c\nd\t ef   ", L), split_by_filler(X, L, Y).
  520
  521% Apply set operation on directories as a set of files.
  522:- meta_predicate directory_files(2,?,?).  523directory_files(E, Ds, L):-
  524	maplist(pred([D, D0]:-expand_file_name(D, [D0])), Ds, Es),
  525	maplist(directory_files, Es, Ls),
  526	call(E, Ls, L).
  527
  528:- meta_predicate map_directory_files(1, ?).  529map_directory_files(F, D):- directory_files(D, Fs),
  530	working_directory(D0, D),
  531	maplist(ignore(F), Fs),
  532	working_directory(_, D0).
  533
  534ignore(F, X):- ignore(call(F, X)).
  535
  536% ?- directory_remove_ymhms('/Volumes/sparrow/raw-scan-master').
  537% ?- directory_remove_ymhms('/Volumes/shark/searchable-master').
  538directory_remove_ymhms(D):- expand_file_name(D, [D0]),
  539	map_directory_files(pred(([X]:-
  540					atom_codes(X, X0),
  541					parse_time_me(".pdf", X0, Y0),
  542					atom_codes(Y,Y0),
  543					rename_file(X, Y) )),
  544					D0).
  545
  546% :- listing(parse_time).
  547% ?-  misc:parse_time(`pdf`, `2007年12月21日21時35分18秒.pdf`, P), atom_codes(Y, P).
  548
  549parse_time(Ext) -->
  550	w(*(char(digit)), Year),	"å¹´",
  551	w(*(char(digit)), Month),	"月",
  552	w(*(char(digit)), Day),		"日",
  553	w(*(char(digit)), Hour),	"時",
  554	w(*(char(digit)), Minute),	"分",
  555	w(*(char(digit)), Second),	"秒",
  556	".",
  557	w(*(.), Ext),
  558	current([]),
  559	{ append([Year, Month, Day, Hour, Minute, Second, `.`,  Ext], Y) },
  560	peek(Y).
  561
  562% ?- dir_minus('~/Desktop', '~/Desktop', Z).
  563% ?- dir_minus('~', '~/Desktop', Z).
  564% ?- dir_minus('~', '~', Z).
  565dir_minus(X,Y,Z):- directory_files(fun([[A,B]]-> (set::(A\B))), [X, Y], Z).
  566dir_plus(X,Y,Z):- directory_files(fun([[A,B]]-> (set::(A+B))), [X, Y], Z).
  567
  568%
  569rename_directory_suffix(Suffix0, Suffix, Dir):-
  570	expand_file_name(Dir, [Dir0]),
  571	map_directory_files(
  572 	 pred([Suffix0,Suffix], [X]:- (	atom_concat(X0, Suffix0, X),
  573					atom_concat(X0, Suffix, Y),
  574					rename_file(X, Y)
  575				)),
  576	Dir0).
  577
  578:- meta_predicate collect_subterm(1,?,?).  579
  580collect_subterm(F, X, Y):- collect_subterm(X, Y0, [], F), sort(Y0, Y).
  581
  582%
  583collect_subterm(X, [X|V], V, F):- call(F, X), !.
  584collect_subterm(X, V, W, F):- compound(X), !,
  585	X=..[_|As],
  586	foldr(	pred(F, [A, P, Q] :- collect_subterm(A, P, Q, F), As, V, W)).
  587collect_subterm(_, V, V, _).
  588
  589% :- dynamic calls/2.
  590% % from swi library.
  591% assert_call_graph :-
  592%         retractall(calls(_, _)),
  593%         prolog_walk_code([ trace_reference(_),
  594%                            on_trace(assert_edge),
  595%                            source(false)
  596%                          ]),
  597%         predicate_property(calls(_,_), number_of_clauses(N)),
  598%         format('Got ~D edges~n', [N]).
  599
  600% assert_edge(Callee, Caller, _Where) :-
  601%         calls(Caller, Callee), !.
  602% assert_edge(Callee, Caller, _Where) :-
  603%         assertz(calls(Caller, Callee)).
  604
  605%
  606predicate_arity(F, L):-
  607	setof(P/N,
  608		A^X^(	predicate_property(A:X, file(F)),
  609			functor(X, P, N)
  610		  ),
  611	      L),
  612	insert(", ", L, L0),
  613	smash(["[", L0, "]"]).
  614
  615%
  616predicate_arity_for_export(F,  L):-
  617	writeln('start ...'),
  618	assert_call_graph,
  619	writeln('call graph done'),
  620	find_exportables_from_calls(F, L).
  621
  622% ?- qcompile(zdd(zdd)), module(zdd).
  623
  624
  625% ?- find_exportables_from_calls('/Users/cantor/local/lib/pacpl7/engine.pl', Expo), insert(",\n", Expo, E), maplist(write, E).
  626
  627find_exportables_from_calls(Loc,  Exp):-
  628	predicate_arity(Loc,  L0),
  629	setof(F/N, P^X^(
  630			member(F/N, L0),
  631			functor(P, F, N),
  632			once(calls(X,  user:P)),
  633			\+ predicate_property(X, file(Loc))
  634		       ),
  635	      Exp),
  636	insert(",\n", Exp, E),
  637	maplist(write, E).
  638
  639
  640% ?- calls(X, user:assocq(_,_,_)), predicate_property(X, file(A)).
  641% ?- misc:residue(([a,b,c,d,e]-[a,b]-[c]), R).
  642
  643residue(X-Y,V):-!, residue(X,A),
  644	residue(Y,U),
  645	append(U,V,A).
  646residue(X,X).
  647
  648% ?-  parse_utf8(`My name is 向井 国昭.`, R), smash(R).
  649parse_utf8 --> sed(kanji(A), =(A)),
  650	maplist(pred(([X, Y] :- listp(X), string_codes(Y, X))
  651	       &
  652	       ([X, Y] :- char_code(Y, X)))).
  653
  654kanji(A)  --> w(char(utf8b), A, B), wl(*char(utf8c), B).
  655
  656% ?- misc:cgi_bin_name_edit.
  657%@ true.
  658
  659% For test.
  660% cgi_bin_name_edit :- cgi_bin_name_edit(
  661%      		"/Users/cantor/Desktop/http_request.js",
  662% 		"/Users/cantor/Desktop/http_request1.js").
  663% for test.
  664% cgi_bin_name_edit :- cgi_bin_name_edit(
  665% 	 	"/Users/cantor/local/cgi-bin/http_request.js",
  666% 		"/Users/cantor/Desktop/http_request.js").
  667
  668% cgi_bin_name_edit(In_js_name, Out_js_name) :-  getenv(cgi_bin, U),
  669% 	atomics_to_string([U, /], V),
  670% 	term_string(V, V0),
  671% 	atomics_to_string([V0, ";"], V1),
  672% 	string_codes(V1, V2),
  673% 	setup_call_cleanup(
  674% 	 (	open(In_js_name, read, In),
  675% 		open(Out_js_name, write, Out) ),
  676% 		repeat_line(V2, In, Out),
  677% 	(	close(In),
  678% 		close(Out))).
  679
  680% cgi_bin_name_edit(V, A, B):-
  681% 	head_sed(sed([V],
  682% 		 (wl("[\s\t]*var[\s\t]+CGIBIN[\s\t]*=[\s\t]*", X), wl(".*")),
  683% 		 (X + V)), A, B).
  684%
  685repeat_line(V, In, Out):- read_line_to_codes(In, A),
  686	A \== end_of_file,
  687	cgi_bin_name_edit(V, A, B),
  688	maplist(put_code(Out), B),
  689	put_code(Out, 0'\n),			%%%% '
  690	!,
  691	repeat_line(V, In, Out).
  692repeat_line(_,_,_).
  693
  694
  695% ?- expand_sgn_brace(sgn([a,b]), X).
  696% ?- expand_sgn_brace((sgn([a,b]), sgn([c,d])), X).
  697expand_sgn_brace(sgn([A,A0|B]),(A1;A2)):-!,
  698	expand_sgn_brace(sgn([A]),A1),
  699	expand_sgn_brace(sgn([A0|B]),A2).
  700expand_sgn_brace(sgn([A]),A1):-!,expand_sgn_brace(A,A1).
  701expand_sgn_brace((A,B),(A1,A2)):-!,expand_sgn_brace(A,A1),
  702	expand_sgn_brace(B,A2).
  703expand_sgn_brace((A;B),(A1;A2)):-!,expand_sgn_brace(A,A1),
  704	expand_sgn_brace(B,A2).
  705expand_sgn_brace(\+A,\+A1):-!,expand_sgn_brace(A,A1).
  706expand_sgn_brace(A/N,A0/N):-!,expand_sgn_brace(A,A0).
  707expand_sgn_brace(X,A1):-is_list(X),!,
  708	maplist(expand_sgn_brace,X,A1).
  709expand_sgn_brace(X,X).
  710
  711% Samples defining functions on a sort of expressions.
  712
  713% ?- listing(list_plus).
  714% ?- misc:list_plus([a,b,c]+[d,e,f]+[g,h,i], R).
  715
  716list_concat(X+Y,A1):-list_concat(X,A2),
  717	list_cocnat(Y,A3),
  718	append(A2,A3,A1) .
  719list_concat(X,X).
  720
  721
  722% ?- listing(my_add).
  723% ?- misc:my_add(1+2+3+4+5, R).
  724my_add(X+Y,A1):- my_add(X,A2),
  725	my_add(Y,A3),
  726	plus(A2,A3,A1).
  727my_add(X,X).
  728
  729% ?- misc:string_rev(rev("abc"), R).
  730%@ R = "cba" .
  731% ?- write_canonical([rev/1-misc:string_reverse]).
  732%@ [:(-(/(rev,1),misc),string_reverse)]
  733
  734% list_plus		:= [(+)/2-append].
  735% list_rev		:= [rev/1-reverse].
  736% list_plus_rev	:= (list_plus + list_rev).
  737% list_plus_only	:= (list_plus_rev \ list_rev).
  738
  739% % string sort.
  740% % ?- misc:string_plus_rev(rev(rev("abc")+rev("def")), R).
  741% %@ R = "defabc" .
  742
  743% string_plus		:= [(+)/2- string_concat].
  744% string_rev		:= [rev/1- (misc:pred(([X, Y]:-
  745% 								string_codes(X, X0),
  746% 								reverse(X0, Y0),
  747% 								string_codes(Y, Y0))))].
  748% string_plus_rev	:= (string_plus + string_rev).
  749% string_plus_rev_meet := (string_plus * string_rev).
  750% string_plus_only	:= (string_plus_rev \ string_rev).
  751
  752% empty_sgn := [].
  753
  754% Example uses of @
  755% uuu(A,B) --> A@B.
  756% vvv(A,B) --> #(A)@B.
  757% www(A, B) --> fun([X,Y,Z]->(X@Y@Z))@A@B.
  758%?- misc:www(append, [a,b], [c,d], R).
  759%@ R = [a, b, c, d].
  760% ?- call(fun([F,X]-> F@X), append([a,b]), [c,d], R).
  761%@ R = [a, b, c, d].
  762
  763% DISCOURSE by @brebs
  764
  765% ?- split_list_at_nth1(N, [a,b,c], [X|T], End).
  766% ?- split_list_at_nth1(N, [a,b,c], St, [a,b,c|T]).
  767% ?- trace, split_list_at_nth1(N, [a,b], Start, End).
  768split_list_at_nth1(Nth1, Long, Start, End) :-
  769    (   nonvar(Nth1) -> must_be(nonneg, Nth1), Once = true
  770    ;   is_list(Long), once(is_list(Start) ; is_list(End)) -> Once = true
  771    ;   is_list(End), is_list(Start) -> Once = true
  772    ;   Once = false
  773    ),
  774    split_list_at_nth1_(Long, 0, Nth1, Once, Start, End).
  775
  776split_list_at_nth1_(L, N, N, Once, [], L) :-
  777    (Once == true -> ! ; true).
  778split_list_at_nth1_([H|T], N, Nth1, Once, [H|Upto], End) :-
  779    N1 is N + 1,
  780    split_list_at_nth1_(T, N1, Nth1, Once, Upto, End)