1:- module(elisp, [region/2, region_term/2, 2 mark_whole_buffer/2, 3 overwrite/2, overwrite/3, paragraph/2, 4 line_get/1, global_set_kbd/1, global_unset_kbd/1, dired_mark_swipl/0, 5 prolog_symbol_at_point/1, 6 book_bibitem/2, first_token_codes/2, 7 find_handle_call/4, 8 read_term_from_lisp/1, 9 read_mini_buffer/2, 10 send_off/1, 11 call_lisp/2, call_lisp/1, 12 call_lisp_wait/1, 13 call_lisp_value/2, 14 call_lisp_string/2, 15 lisp/1, lisp/2, lisp_to_list/2, 16 noreply/1, 17 get_string/2, set_string/2, 18 message/1, 19 insert_buffer/1, 20 insert/1, 21 set_mark_region/2, 22 neighbor_string/3, neighbor_string/5, 23 wait/1, wait/2, 24 read_codes/1, read_codes/2, 25 meta_handle/4, normal_keys/3 26 ]). 27 28:- use_module(pac(basic)). 29:- use_module(util(file)). 30:- use_module(pac(reduce)). 31:- use_module(util(polynomial)). 32:- use_module(util(tex)). 33:- use_module(util(obj)). 34:- use_module(util(misc)). 35 36% :- use_module(util('convert-dcg')). 37% :- use_module(util('sed(dcg_ts')). 38 39term_expansion --> pac:expand_pac. 40:- use_module(pac('expand-pac')). 41:- use_module(pac(op)). 42% :- use_module(util(xml)). 43 44% memo: be careful to use sed/3 (module prefix needed) [2014/05/23] 45% Prolog-Emacs Interface 46% get buffer region 47% :- use_module(pac('emacs-jockey')). 48 49% ?- qcompile(util('prolog-elisp')), module(elisp). 50:- nb_setval(command_history, [for_ascii(elisp:wrap($))]). 51:- nb_setval(edit_command, (=)). 52% :- use_module(library(edit)). 53 54% help//2 is det. 55% list all command names. 56help --> {shortcut_key(L)}, 57 peek(L), 58 insert('\n'), 59 smash. 60 61:- meta_predicate line( , , ). 62:- meta_predicate for_ascii( , , ).
66tex_cs_to_symbol --> sed(dcg_ts). % ts.
70tex_symbol_to_cs --> sed(dcg_st). % st. 71 72 73 /************************************ 74 * command history management * 75 ************************************/
80parse_commands --> split,
81 remove([]),
82 maplist(herbrand).
87parse_merge_history --> region,
88 parse_commands,
89 merge_history,
90 clear.
94merge_history(Cs):- nb_getval(command_history, L),
95 union(Cs, L, L0),
96 nb_setval(command_history, L0).
103merge_history(X, X):- merge_history(X).
109merge_history(F) --> region,
110 split,
111 remove([]),
112 maplist(phrase(F)),
113 merge_history.
118show_history(H) :- nb_getval(command_history, L),
119 insert('\n', L, L0),
120 smashq(L0, H).
125show_history(_, H) :- show_history(H).
129reset_history :- nb_setval(command_history, []).
133reset_history --> {reset_history}.
138set_history --> reset_history, parse_merge_history.
142show_command(X) :- nb_getval(edit_command, C),
143 smashq(C, X).
147show_command(_, X):- show_command(X).
151apply_command --> { nb_getval(edit_command, C) }, 152 phrase(C). 153 154% 155empty_history :- nb_getval(edit_command, []). 156 157% 158pop_history(X) :- nb_getval(edit_command, [X|R]), 159 nb_getval(edit_command, R). 160 161% 162push_history(X) :- nb_getval(edit_command, C), 163 nb_setval(edit_command, [X|C]). 164 165% 166save_line_number :- lisp('count-lines'(1, point()), I), 167 nb_setval(line_count, I). 168 169 170% ?- apropos(compound_non_zero_arity). 171% ?- compound_name_arguments(f(), N, A). 172%@ N = f, 173%@ A = []. 174% ?- compound_name_arguments(f, N, A). 175 176table_index(I) :- lisp('count-lines'(1, point()), J), 177 nb_getval(line_count, K), 178 I is J-K.
182comma_left(A, B, (A, B)).
186comma_right(A, B, (B, A)). 187 188 /******************************* 189 * region object manager * 190 *******************************/ 191 192% [2011/06/09] 193% Save a phrase / a phrase with environment at the region 194% to use it later.
198initial_region_obj :- nb_setval(state_obj, []).
202region_obj(X):- nb_getval(state_obj, S),
203 obj(X, S, S0),
204 nb_setval(state_obj, S0).
209get_phrase --> region,
210 herbrand(_),
211 call(pred([F, F0] :- let(F0, F))),
212 current(G),
213 { region_obj( put( [command(G)] ) ) },
214 clear.
219apply_phrase --> region,
220 { region_obj( get( [command(G)] ) ) },
221 phrase(G),
222 overwrite.
227bind_phrase --> region, 228 { region_obj( get( [command(G)] ) ) }, 229 current(X), 230 { bind_context(G, (X, []), (X0, _)) }, 231 peek(X0). 232 233 /**************** 234 * region * 235 ****************/
241region([], X) :- !, get_region(X). % [2014/10/12], [2020/01/11] 242region(A, A).
247get_region(R) :- lisp('send-region'()),
248 read_codes(R).
252get_region --> {get_region(R)}, peek(R).
256get_region(X, _, X) :- get_region(X). %
260region_term(X, Y) :- region(X, X0),
261 term_codes(Y, X0).
265get_buffer_region(X, Y) --> {get_buffer_region(X, Y, R)},
266 peek(R).
270get_buffer_region(X, Y, R) :-
271 lisp('send-region'(X, Y)),
272 read_codes(R).
276region_bound(_, X) :- region_bound(X).
region_bound(_, X)
.
280region_bound(X) :- call_lisp_string('region-bound'(), X0),
281 parse_lisp_form(X0, [X]).
286overwrite --> { kill_region }, smash_buffer. 287 288% 289overwrite([]) --> !, overwrite. 290overwrite(_) --> [].
294kill_region:- call_lisp_wait('kill-region'(mark(), point())).
298kill_region(Buf):- smash(Buf, QBuf),
299 call_lisp_wait(progn( 'set-buffer'(QBuf),
300 'kill-region'(mark(), point()))).
305insert_buffer([]):- !. 306insert_buffer(X):- smash(["$TEXT$ ", X, "\000\\n"]), 307 flush_output. 308% 309insert(X):- smash(X, Y), wait(insert(Y)).
312send_exp(L):- lisp(L).
316find_file(F) :- expand_file_search_path(F, F0),
317 lisp('find-file'(F0)).
321find_pred(X)--> {find_pred(X)}.
325find_pred(P/N):- functor(G, P, N), 326 source_file(G, F), 327 find_file(F). 328find_pred(P):- find_pred(P/0).
332eval_lisp_to_atom(F, S, A):- lisp_atom(["(", F, " ", S, ")"], A).
336eval_lisp_to_atom(F, X, Y, A):- 337 lisp_atom(["(", F, " ", X, " ", Y, ")"], A). 338 339% ?- atom_lisp_string(abc, X).
343atom_lisp_string(A, S):- atom_codes(A, C),
344 quote(C, S).
348read_file_name(P, F):- atom_lisp_string(P, P0),
349 eval_lisp_to_atom('read-file-name', P0, F).
353read_file_name(F):- read_file_name('file name: ', F).
358completing_read(Prompt, Atoms, R):- 359 atom_lisp_string(Prompt, P0), 360 maplist(atom_lisp_string, Atoms, As), 361 call_lisp_value('completing-read'(P0, #(As)), R). 362 363 364% ?- elisp:read_codes_from_minibuffer("Hi :", R). 365read_codes_from_minibuffer(Prompt, Codes):- 366 call_lisp_value('read-from-minibuffer'(Prompt), Codes). 367 368% ?- elisp:read_term_from_minibuffer("Hi :", Term). 369read_string_from_minibuffer(Prompt, String):- 370 read_codes_from_minibuffer(Prompt, Codes), 371 string_codes(String, Codes). 372 373% ?- elisp:read_term_from_minibuffer("Hi :", Term, [variable_names(V)]). 374read_term_from_minibuffer(Prompt, Term, Options):- 375 read_string_from_minibuffer(Prompt, String), 376 term_string(Term, String, Options). 377 378% ?- elisp:read_term_from_minibuffer("Hi :", Term). 379read_term_from_minibuffer(Prompt, Term):- 380 read_term_from_minibuffer(Prompt, Term, []).
384search_pred(Pred):- search_swipl(["^", Pred]).
388search_swipl(X):- smash(X, C),
389 dired_mark_swipl,
390 lisp('dired-do-search'(C)).
395dired_mark_swipl :- getenv(home, Home),
396 string_concat(Home,"/local/lib/pacpl7", PAC_dir),
397 dired_mark_regex(PAC_dir, ".*\\.pl$").
404dired_mark_regex(Dir, Regex) :- 405 lisp([progn, 'find-file'(Dir), 406 'dired-mark-files-regexp'(Regex)]). 407% True if J, Len, and X are unified so that X is a symbol of length Len, 408% of the category "prolog_symbol_continue", and at J of the current line, 409list_at_point(X):- line_get(Obj), 410 obj_get([line(Line), begin(B), point(P)], Obj, _), 411 string_codes(Y, Line), 412 I is P - B, 413 scan_string_at_point(Y, 0'[, 0'], I, S), 414 term_string(X, S).
sub_string(X, J, K, _, S)
,
J + length(B)
=< I =< K - length(E)
,
and that S has B as a prefix, and E as a suffix.422% ?- elisp:neighbor_string("abd", "a", "d", 1, S). 423% ?- elisp:neighbor_string("abd", "a", "bd", 1, S). 424 425neighbor_string(X, Open, Close, I, S):- neighbor_string(X, Open, Close, I, J, K), 426 N is K - J, 427 N >= 0, 428 sub_string(X, J, N, _, S). 429 430% ?- elisp:neighbor_string("abcd", "a", "d", 2, J, K). 431% ?- elisp:neighbor_string("abd", "a", "d", 2, J, K). 432% 433neighbor_string(X, Open, Close, I, J, K):- string_length(X, LX), 434 string_length(Open, LO), 435 string_length(Close, LC), 436 I0 is I - LO, 437 I0 >= 0, 438 neighbor_string_left(X, Open, LO, I0, J), 439 neighbor_string_right(X, Close, LC, I, K0, LX), 440 K is K0 + LC. 441 442% 443neighbor_string_left(X, S, N, I, I) :- sub_string(X, I, N, _, S), !. 444neighbor_string_left(X, S, N, I, K) :- I> 0, 445 I0 is I-1, 446 neighbor_string_left(X, S, N, I0, K). 447 448neighbor_string_right(X, S, N, I, I, _):- sub_string(X, I, N, _, S), !. 449neighbor_string_right(X, S, N, I, K, L):- I < L, 450 I0 is I + 1, 451 neighbor_string_right(X, S, N, I0, K, L). 452 453% 454neighbor_string(B, E, X) :- line_at_point(L, I), 455 neighbor_string(L, B, E, I, X).
462 /***************************** 463 * Control Emacs-buffer * 464 *****************************/
468stream_start :- wait('stream-start'()).
472wait(P, P) :- wait(P). 473 474% ?- elisp:message("hello"). 475message(M):- smash(M, M0), lisp(message(M0)).
479:- meta_predicate prolog( , , ). 480prolog(F) --> region, herbrand, phrase(F).
485line_exec :- line_get(I),
486 obj_get([line(Line)], I, _),
487 herbrand(_, Line, G),
488 !,
489 catch(G, _, fail).
493smash(F) --> prolog((F, smash)).
498herb(F) --> prolog((F, herbrand_opp)).
503solve(F) --> herbrand(_),
504 phrase(F),
505 herbrand_opp.
509line(F) --> line(F, "\n").
514line(A, Ins) --> split,
515 remove([]),
516 maplist(phrase(A)),
517 insert(Ins).
523paragraph(A) --> paragraph,
524 remove([]),
525 maplist(phrase(A)).
530lines --> split, remove([]).
line_get(G)
, scan(S)
, do(D)
, line_put(P)
],
the current line L = X + A + Y ('+' means codes concatenaton)
is rewritten to X + A0 + Y, by
applying G to get the line L,
applying S to L to get X, A, and Y, as above, and
applying D to A to get A0.
541line_edit(Ps):- obj_get([line_get(G), scan(S), do(D), line_put(P)], Ps),
542 call(G, I),
543 obj_get([line(L)], I),
544 call(S, X, A, Y, L, _),
545 % act(D, A, A0),
546 phrase(D, A, A0),
547 obj_put([left([X, A0]), right(Y)], I, I0),
548 call(P, I0).
554for_ascii(Act) --> { line_edit([line_get(line_get_forward),
555 scan(find_next_ascii_codes),
556 do(Act),
557 line_put(line_overwrite)
558 ])
559 }.
564open_at_point:- line_get(Obj),
565 obj_get([line(File)], Obj),
566 sh(open(File)).
570open_at_point --> {open_at_point}.
576line_at_point(X, I, P):- line_get(Obj),
577 obj_get([point(Q), line(Line), begin(P)], Obj),
578 string_codes(X, Line),
579 I is Q - P.
584line_at_point(X, I):- line_at_point(X, I, _). 585 586 /****************************** 587 * basic line operation * 588 ******************************/
point(P)
, begin(B)
, end(E)
, line(R)
], where
P is the current point, B the beginning point, E the end point
R the content of the line.
594line_get([point(P), begin(B), end(E), line(R)]):-
595 lisp(list('line-beginning-position'(),
596 'line-end-position'(),
597 point()),
598 [B,E,P]),
599 get_buffer_region(B, E, R).
point(P)
, begin(P)
, end(E)
, line(R)
], where
P is the current point, E the end point,
R the content of the line from P to E.
606line_get_forward([point(P), begin(P), end(E), line(R)]):-
607 lisp(list(point(), 'line-end-position'()), [P, E]),
608 get_buffer_region(P, E, R).
point(P)
, begin(B)
, end(P)
, line(R)
], where
P is the current point, B the beginning point,
R the content of the line from B to P.
614line_get_backward([point(P), begin(B), end(P), line(R)]):-
615 lisp(list(point(), 'line-beginning-position'()),
616 [P, B]),
617 get_buffer_region(B, P, R).
623line_overwrite(I):- obj_get([left(L), right(R)], I),
624 line_overwrite(I, L, R).
628line_overwrite(I, L) :- line_kill(I), smash_buffer(L).
633line_overwrite(I, L0, L1) :- line_kill(I),
634 smash_buffer(L0),
635 lisp(point(), P),
636 smash_buffer(L1),
637 lisp( 'goto-char'(P)).
642smash_buffer(X) :- smash(X, Y), elisp:insert_buffer(Y).
647smash_buffer(X, []) :- smash_buffer(X).
652line_kill(I) :- obj_get([begin(B), end(E)], I),
653 lisp('kill_region'(B, E)),
654 lisp('goto-char'(B)).
658line_kill --> {line_get(I), line_kill(I)}.
662line_wrap(L, R) --> {line_wrap(L, R)}.
666line_wrap(L, R):- line_get(I),
667 obj_get([line(Line)], I),
668 line_overwrite(I, [L, Line, R]).
673%?- sub_string("abc", X, Y, Z, U). 674% [2014/03/16] 675% ?- elisp:prolog_symbol_at_point(X). 676prolog_symbol_at_point(X):- line_at_point(Y, I), 677 symbol_at_index(Y, I, X).
682prolog_symbol_at_point(J, Len, X):- line_get(Obj),
683 obj_get([line(Line), begin(B), point(P)], Obj, _),
684 string_codes(Y, Line),
685 I is P - B,
686 symbol_at_index(Y, I, J, K, X, prolog_symbol_continue_chk),
687 Len is K - J.
691:- meta_predicate apply_symbol_at_point( ). 692apply_symbol_at_point(F):- prolog_symbol_at_point(J, Len, X), 693 call(F, X, Y), 694 number_string(J, J0), 695 number_string(Len, Len0), 696 with_output_to(string(Y0), writeq(Y)), 697 lisp('replace-in-line'(J0, Len0, Y0)).
701symbol_at_index(X, I, Y):- symbol_at_index(X, I, Y, prolog_symbol_continue_chk).
706symbol_at_index(X, I, Y, F):- symbol_at_index(X, I, _, _, Y, F).
713% ?- elisp:symbol_at_index("+abc-", 2, J, K, Y, prolog_symbol_continue_chk). 714:- meta_predicate symbol_at_index( , , , , , ). 715symbol_at_index(X, I, J, K, Y, F):- symbol_at_index(X, I, J, K, F), 716 L is K - J, 717 sub_string(X, J, L, _, Y). 718 719% ?- X=1.
725:- meta_predicate symbol_at_index( , , , , ). 726symbol_at_index(X, I, J, K, F):- 727 symbol_string_before(X, I, J, F), 728 symbol_string_after(X, I, K, F).
732prolog_symbol_continue_chk(C):- code_type(C, prolog_identifier_continue).
738:- meta_predicate symbol_string_after( , , , ). 739symbol_string_after(S, I, K, F):- succ(I, J), 740 string_code(J, S, C), 741 call(F, C), 742 !, 743 symbol_string_after(S, J, K, F). 744symbol_string_after(_, I, I, _).
750:- meta_predicate symbol_string_before( , , , ). 751symbol_string_before(S, I, K, F):- 752 string_code(I, S, C), 753 call(F, C), 754 !, 755 succ(J, I), 756 symbol_string_before(S, J, K, F). 757symbol_string_before(_, I, I, _). 758 759 /*********************************************** 760 * lisp list vs. prolog list * 761 ***********************************************/
768% ?- elisp:term_to_lisp_text(X, "(ab)"), elisp:term_to_lisp_text(X, Y). 769%@ X = [[ab]], 770term_to_lisp_text(X, Y):- nonvar(Y), !, 771 ( string(Y) 772 -> string_codes(Y, Y0) 773 ; Y0 = Y 774 ), 775 parse_lisp_form(Y0, X). 776term_to_lisp_text(X, Y):- once(term_to_lisp_string(X, Y)).
782parse_lisp_form(X, Y):- once(lisp_list(Y, X, [])).
789% ?- elisp:lisp_list(X, `()`, []). 790% ?- elisp:lisp_list(X, `(a)`, []). 791% ?- elisp:lisp_list(X, `a`, []). 792% ?- elisp:lisp_list(X, `a b c`, []). 793% ?- elisp:lisp_list(X, `"a" "b" "c"`, []). 794% ?- elisp:lisp_list(X, `"a" "b" c`, []). 795% ?- elisp:lisp_list(X, `(ab)`, []). 796% ?- elisp:lisp_list(X, `(a b)`, []). 797% ?- elisp:lisp_list(X, `(a(c)b"de")`, []). 798% ?- elisp:lisp_list(X, `(a(c)()b"de")`, []). 799% ?- elisp:lisp_list(X, `(a(c)()b"de""")`, []). 800% ?- elisp:lisp_list(X, `\\((a(c)()b"de""")`, []). 801% ?- elisp:lisp_list(X, `\\(a)\\`, []). 802 803lisp_list(X) --> skip_lisp_filler, lisp_list(X, []).
810lisp_list(X, Y) --> lisp_element(A), 811 {X=[A|X0]}, 812 skip_lisp_filler, 813 lisp_list(X0, Y). 814lisp_list(X, X) --> [].
821lisp_list_rest(X, X) --> ")". 822lisp_list_rest([A|X], Y) --> lisp_element(A), 823 skip_lisp_filler, 824 lisp_list_rest(X, Y).
830lisp_element(A) --> "(", !, skip_lisp_filler, 831 lisp_list_rest(A, []). 832lisp_element(A) --> lisp_string(A0), !, { herbrand(A0, A) }. 833lisp_element(A) --> non_string_atom(A0, []), { A0 \== [] }, !, 834 { herbrand(A0, A) }.
840skip_lisp_filler --> [A], { memberchk(A, `\s\t\r\n`) }, 841 skip_lisp_filler. 842skip_lisp_filler --> [].
847lisp_string([0'\"|X]) --> "\"", lisp_string_rest(X, []). % '
853% ?- elisp:lisp_string_rest(X, [], `abcd"`, Y). 854lisp_string_rest([0'\"|X], X) --> "\"". % ' 855lisp_string_rest([0'\\, X|Y], Z) --> "\\", [X], !, % ' 856 lisp_string_rest(Y, Z). 857lisp_string_rest([X|Y], Z) --> [X], lisp_string_rest(Y, Z).
862non_string_atom([X|Y], Z) -->[X], {\+ memberchk(X, `()\"\s\t\r\n`)}, 863 non_string_atom(Y, Z). 864non_string_atom(X, X) --> [].
868quit --> {lisp(print("PAC process has been quitted by user")),
869 lisp('stop-pac'())
870 }.
874% Ask emacs an edit command in codes, 875% If the codes form a prolog phrase H, 876% run H on (X, Y). 877% Otherwise, split the codes by spaces into a list H of atoms, 878% find an handle that H matches its argument, and 879% finally run the body of the handle as a phrase on (X, Y). 880 881edit_emacs_P --> {ask_command(Codes), 882 catch( herbrand(_, Codes, H), 883 _ , 884 split_codes_atoms(Codes, H) 885 ) 886 }, 887 run_command(H).
895run_command([X|Y]) --> !, ejockey:handle([X|Y]). 896run_command(-(X)) --> !, ejockey:handle([X]). 897run_command(X) --> phrase(X).
903split_codes_atoms(X, Y):- split(` `, X, S), 904 remove([], S, S0), 905 maplist(atom_codes, Y, S0). 906 907% 908skip_rest(X, X, []). 909 910% ?- elisp:leading_atoms(` aab bbb ccc & ddd eee`, A). 911% ?- elisp:leading_atoms([], X). 912 913leading_atoms(X, A):- tex:filler(X, Y), 914 once(leading_atoms(A, Y, [])). 915 916% ?- elisp:leading_atoms(X, [], R). 917% ?- elisp:leading_atoms(X, ` aab bbb ccc & ddd eee`, R). 918% ?- elisp:leading_atoms(X, `aab bbb ccc ddd eee`, R). 919% ?- elisp:handle_atom(X, `a`, R). 920 921leading_atoms(X) --> "&", skip_rest(X). 922 923leading_atoms([A|Y]) --> handle_atom(X), !, 924 { atom_codes(A, X) }, 925 tex:filler, 926 leading_atoms(Y). 927leading_atoms([]) --> at_end. 928 929at_end([], []). 930 931% ?- elisp:handle_atom(X, `abc def`, R). 932handle_atom(X) --> w("[a-z]", X, Y), wl("[a-zA-Z0-9]*", Y). 933handle_atom(X) --> w("[*/=?#.<>\\^\\-\\!]", X). 934 935% ?- elisp:make_splitter(`[ab]+`, S), call(S, `abcab`, R). 936make_splitter(Codes, S) :- string_codes(Regex, Codes), 937 let(S, phrase(wl(Regex))).
947edit_emacs_L(Ask, X, Y):- 948 call(Ask, Codes), 949 leading_atoms(Codes, Com), 950 once(find_handle_call(Com, Codes, X, Y)). 951 952% ?- edit_emacs_L('ask-handle'(), Codes). 953% ?- elisp:find_handle_call([split, a, b], _, X, Y).
962% ?- elisp:find_handle_call([f, c], `a`, Y), smash(Y). 963 964find_handle_call(Com, _Codes, X, Y):- is_list(Com), 965 member(Module, [ejockey, ejockey2]), 966 clause(Module:handle(H, X, Y), Body), 967 match_args(Com, H), 968 !, 969 once(Module:Body). 970% [2020/05/14] The following does not work. 971% Module:call(Body), !. 972% Module:onde(Body), !. 973find_handle_call(_, Codes, X, Y):- % for other type of handles 974 herbrand(_, Codes, C), 975 callable(C), 976 C =.. A, 977 append(A, [X, Y], B), 978 D =.. B, 979 ( clause(snippets:, Body) 980 -> G = snippets:Body 981 ; G = phrase(C, X, Y) 982 ), 983 once(G). % was "call(G), !."
If the tail Z of Y=[...|Z] is a variable the Z is unified with the corresponding tail U of X=[...|U].
997% ?- elisp:match_args([f, c], [frame, center]). 998% ?- elisp:match_args([sol, go, reg], [solve, goal|X]). 999% ?- elisp:match_args([mv, (.)], [mv, (.)]). 1000% ?- elisp:match_args([f, 'c/d'], [frame, File]). 1001% ?- elisp:match_args([f, b], [frame, File]). 1002% ?- elisp:match_args([f, b], [frame|File]). 1003 1004match_args([], []):-!. 1005match_args([A|B], [C|D]):- match_arg_one(A, C), !, 1006 match_args(B, D). 1007% 1008match_arg_one(A, B) :- var(B), A = B. 1009match_arg_one(A, B) :- atom(B), sub_atom(B, 0, _, _, A). 1010match_arg_one(A, B) :- number(B), number_atom(B, A). 1011match_arg_one(A, B) :- string(B), atom_string(A, B). 1012 1013% 1014normal_keys([], _, []). 1015normal_keys([X|Xs], Ys, [Y|Zs]):- select(Y, Ys, Y0s), 1016 match_arg_one(X, Y), 1017 !, 1018 normal_keys(Xs, Y0s, Zs). 1019 1020% ?- elisp:apropos_chk([a,b,c], axy). 1021apropos_chk([Y|_], X):- match_arg_one(Y, X), !. 1022apropos_chk([_|Ys], X):- apropos_chk(Ys, X).
1026ask_handle(Codes) :- call_lisp_value('ask-handle'(), Codes). 1027 1028% [2020/05/14] 1029% request from emacs as (prolog-query G). 1030% shortcut "s-l" (Command + L ) 1031userprolog_call(G, _, [G, " done.\n"]):- once(G). 1032 1033% ?- elisp:call_lisp_value(list("1","2","3"), R), elisp:lisp_to_list(R, List). 1034% ?- elisp:call_lisp_value(+(1,2,3), R). 1035% ?- elisp:call_lisp_value(list(1,2), R). % NOT work. 1036% ?- elisp:lisp_to_list(list(1,2), R). % OK. 1037% ?- elisp:call_lisp_string(list("1","2","3"), R).
1041ask_command(Codes) :- call_lisp_value('ask-command'(), Codes). 1042 1043% 1044qval(E, V):- call_lisp(E, string(S)), basic:smash(S, V). 1045% 1046elisp(E, V):- call_lisp(E, term(W)), string_codes(V, W). 1047 1048% ?- elisp:qval(cons(1, 2),V). 1049% ?- elisp:qval(cons(1, []),V). 1050% ?- elisp:qval(setq(w, 2),V). 1051% ?- elisp:qval(w, V). 1052% ?- elisp:qval(append(list(1,2,3), list(4, 5, 6)), V). 1053% ?- elisp:qval(setq(uu, #(hello)), V). 1054% ?- elisp:qval(setq(uu, "hello"), V). 1055% ?- elisp:qval(setq(uu, +(1,2,3)), V). 1056% ?- elisp:qval(setq(uu, #(+(1,2,3))), V). 1057% ?- elisp:qval(setq(uu, #(#(#(+(1,2,3))))), V). 1058% ?- elisp:qval(setq(uu, #(#(#(#(+(1,2,3)))))), V). 1059% ?- elisp:qval(uu, V).
1064lisp_to_list(M, L):- call_lisp(M, string(V)), 1065 term_to_lisp_text(L, V). 1066 1067% ?- elisp:lisp(+(1, 2, 3), Y). 1068% ?- elisp:lisp(sort(list(4, 8, 21, 17, 33, 7, 21, 7), #(>)), V). 1069% ?- elisp:lisp(sort(list(4, 8, 21, 17, 33, 7, 21, 7), #(<)), V). 1070lisp(X, Y) :- lisp_to_list(X, Y0), Y0 = [Y|_].
1076lisp_atom(X, Y) :- call_lisp(X, term(Z)), atom_codes(Y, Z).
1081no_reply_progn(E) :- wait(E).
1087unquote(X, Y):- append([[0'\"], Y0, [0'\"]], X), !, 1088 unbackquote(Y0, Y). 1089unquote(X, X).
1095unbackquote([], []). 1096unbackquote([0'\\, 0'\\|X], [0'\\|Y]):- !, unbackquote(X, Y). %' 1097unbackquote([0'\\, C|X], [0'\\, C|Y]):- !, unbackquote(X, Y). 1098unbackquote([C|X], [C|Y]):- unbackquote(X, Y).
1104list([]). 1105list([_|L]) :- list(L).
1111escapeoff --> eh:sed(elisp:escapeoff), flatten. 1112 1113escapeoff([X])--> "\\",[X]. 1114 1115 /******************** 1116 * read_codes * 1117 ********************/ 1118% ?- read_codes(X, `yz`). 1119% |:abcyz 1120read_codes(X, End):- get_code(C), C \== (-1), !, 1121 read_codes(C, End, End, [], X, []). 1122read_codes(_, _):- throw(unexpected_end_of_file(read_codes)). 1123% 1124read_codes(X):- read_codes(X, `\000\\n`). 1125% 1126read_codes(C, [C|R], End, Q, X, Y):- !, read_codes(R, End, [C|Q], X, Y). 1127read_codes(C, _, End, [], [C|X], Y):- !, read_codes(End, End, [], X, Y). 1128read_codes(C, _, End, Q, X, Y):- reverse(Q, Z, X), 1129 read_codes(C, End, End, [], Z, Y). 1130 1131% [2016/07/11] 1132% Knowing end-of-message by use of read_pending_codes/3. 1133% ?- elisp:lisp("\000\\n\n", R). 1134 1135read_codes([], End, Q, X, Y):- !, 1136 read_pending_codes(user_input, P, []), 1137 ( P==[] -> X = Y 1138 ; reverse(Q, Z, X), 1139 read_codes_suspended(P, End, Z, Y) 1140 ). 1141read_codes(R, End, Q, X, Y):- get_code(C), 1142 read_codes(C, R, End, Q, X, Y). 1143% 1144read_codes_suspended(S, End, X, Y):- 1145 ( append(A, End, S) -> append(A, Y, X) 1146 ; append(S, Z, X), 1147 read_pending_codes(user_input, P, []), 1148 read_codes_suspended(P, End, Z, Y) 1149 ). 1150 1151reverse([A|B], X, Y):- reverse(B, [A|X], Y). 1152reverse([], X, X). 1153 1154 /*************************************************** 1155 * call_lisp/read_mini_buffer * 1156 ***************************************************/
1161read_term_from_lisp(X) :-
1162 read_codes(Codes),
1163 term_codes(X, Codes).
term(V)
: V is unified with a return term codes
string(V)
: ask emacs-lisp to use 'prin1_to_string'
wait : ask emacs-lisp to send 'done' when done.
lisp : ask emacs-lisp not to reply.1172% ?- elisp:call_lisp([], string(V)). 1173call_lisp(X, Option):- 1174 ( noreply = Option 1175 -> term_to_lisp_string(X, X0), % just send without waiting. 1176 send_off(X0) 1177 ; wait = Option 1178 -> P = progn(X, 'send-done'()), 1179 term_to_lisp_string(P, X0), 1180 send_off(X0), 1181 read_codes(_) 1182 ; term(V) = Option -> % was value(V) 1183 term_to_lisp_string(respond(X, nil), X0), 1184 send_off(X0), 1185 read_codes(V) 1186 ; string(V) = Option -> 1187 term_to_lisp_string(respond(X, t), X0), 1188 send_off(X0), 1189 read_codes(V) 1190 ; throw(call_lisp(X, Option)) 1191 ). 1192% 1193send_off(X):- smash(["$SCRIPT$ ", X, "\000\\n"]), 1194 flush_output.
call_lisp(X, wait)
.
1198call_lisp(X):- call_lisp(X, wait).
call_lisp(X, noreply)
.1202lisp(X) :- call_lisp(X, noreply). 1203% 1204noreply(X) :- call_lisp(X, noreply).
call_lisp_wait(X)
.
1208wait(X) :- call_lisp_wait(X).
call_lisp(X, wait)
.
1212call_lisp_wait(X) :- call_lisp(X, wait).
call_lisp(X, term(Y))
.
1216call_lisp_value(X, Y) :- call_lisp(X, term(Y)).
string(Y)
]).1221call_lisp_string(X, Y) :- call_lisp(X, string(Y)). 1222 1223% ?- elisp:lisp(sort(list(4, 8, 21, 17, 33, 7, 21, 7), #(>)), V). 1224% ?- elisp:lisp(+(1, 2, 3), Y). 1225% ?- elisp:lisp(setq(uuu, +(1,2,3)), V). 1226% ?- elisp:lisp(progn(setq(uuu, +(1,2,3)), *(uuu, uuu)), V). 1227% ?- elisp:lisp(append(cons(#(x),#([a,b])), #([u,v])), R).
1232% ?- elisp:term_to_lisp_string(f(), X). 1233%@ X = "(f )" . 1234% ?- elisp:term_to_lisp_string(list(1,2,3), X). 1235%@ X = "(list 1 2 3 )" . 1236% ?- elisp:term_to_lisp_string(prog(a, b, c), X). 1237%@ X = "(prog a b c )" . 1238% ?- elisp:term_to_lisp_string(cond([a,b],[b,c]), X). 1239%@ X = "(cond (a b )(b c ))" . 1240% ?- elisp:term_to_lisp_string(defun(f, [a,b], +(a, b)), X). 1241%@ X = "(defun f (a b )(+ a b ))" . 1242 1243 1244term_to_lisp_string(X, Y):- term_to_tokens(X, Y0, []), 1245 tokens_to_string(Y0, Y).
1252% ?- elisp:term_to_tokens(f(a), R, []). 1253% ?- elisp:term_to_tokens(#(a), R, []). 1254% ?- elisp:term_to_tokens([f(a)], R, []). 1255% ?- elisp:term_to_tokens(f([a]), R, []). 1256% ?- elisp:term_to_tokens(f(123), R, []). 1257% ?- elisp:term_to_tokens(list(1,2,3), R, []). 1258% ?- elisp:term_to_tokens(#(#(1)), R, []). 1259% ?- elisp:term_to_tokens(#(list([1,2,3])), R, []). 1260% ?- elisp:term_to_tokens([a,b], R, []). 1261% ?- elisp:term_to_tokens([[a,b], [c,d]], R, []), tokens_to_string(R, R0). 1262 1263% # is reserved for quote. 1264term_to_tokens(X, ['('|Y], Z):- is_list(X), !, 1265 term_to_tokens_with_closing(X, Y, Z). 1266term_to_tokens(X, [X0|Y], Y):- atom(X), !, atom_string(X, X0). 1267term_to_tokens(X, [X0|Y], Y):- atomic(X), !, term_string(X, X0). 1268term_to_tokens(#(X), Y, Z) :- term_to_tokens([quote, X], Y, Z). 1269term_to_tokens(X, Y, Z) :- 1270 compound_name_arguments(X, F, Args), 1271 term_to_tokens([F|Args], Y, Z).
1278term_to_tokens_with_closing([], [')'|Y], Y). 1279term_to_tokens_with_closing([A|B], X, Y):- term_to_tokens(A, X, Z), 1280 term_to_tokens_with_closing(B, Z, Y).
tokens_to_string([a], X)
.
?- elisp:tokens_to_string(['(', '(', a, b, ')', ')'], X)
.1289tokens_to_string(X, Y):- 1290 tokens_to_string(X, Y0, []), 1291 atomics_to_string(Y0, Y). 1292% 1293tokens_to_string([], X, X). 1294tokens_to_string([T|R], X, Y):- tokens_to_string(T, X, Z), 1295 tokens_to_string(R, Z, Y). 1296tokens_to_string('(', ["("|X], X). 1297tokens_to_string(')', [")"|X], X). 1298tokens_to_string(A, [A, " "|X], X).
1303% ?- elisp:read_mini_buffer("hello", X). 1304 1305read_mini_buffer(Prompt, Str):- 1306 call_lisp('read-string'(Prompt), term(StrCodes)), 1307 string_codes(Str, StrCodes).
1311read_number(Max, X):- read_mini_buffer("number : ", S), 1312 number_string(X, S), 1313 between(1, Max, X). 1314 1315 /******************************** 1316 * set/get string globally * 1317 ********************************/
lisp(setq(X, Y))
.
?- elisp:setq(working_directory, "/Users/cantor/file.pdf")
.
1322setq(X, Y):-lisp(setq(X, Y)).
1327set_string(X, Y):- smash(Y, Y0), setq(X, Y0).
1331get_string(Atom, String):- 1332 call_lisp(Atom, string(V)), 1333 string_codes(V0, V), 1334 term_string(String, V0). 1335 1336line(X) :- elisp:call_lisp( 1337 'buffer-substring'( 'line-beginning-position'(), 1338 'line-end-position'()), 1339 term(X)).
1343mark_whole_buffer --> {lisp('mark-whole-buffer'())}.
1347set_mark_region :- lisp('mark-paragraph-region'()).
1351set_mark_region --> {set_mark_region}.
1356line_region(_, Line) :- line_get(Obj), obj_get([line(Line)], Obj).
1361% ?- elisp:cur_dir(D). 1362cur_dir(D) :- lisp_atom('default-directory', D).
1367% ?- elisp:cur_buf(X). 1368cur_buf(B) :- current_buffer_name(B).
1372current_buffer_name(X) :- current_buffer_name([], X).
1377% ?- elisp:current_buffer_name(_, Y). 1378current_buffer_name --> 1379 { call_lisp('buffer-name'('current-buffer'()), term(E)), 1380 atom_codes(A, E) 1381 }, 1382 peek(A).
1385default_directory(D) :- call_lisp_value('default-directory', D).
1391% ?- elisp:mark(X). 1392mark(X):- lisp(if(integerp(mark(t)), mark(), point()), X).
1396point(X) :- lisp(point(), X).
1400goto_char(P) :- lisp('goto-char'(P)).
1404goto_char(P) --> {goto_char(P)}.
1410goto_char(Key, String) :- sub_string(String, I, _, _, Key),
1411 mark(P),
1412 P0 is P + I,
1413 goto_char(P0).
1418goto_line(P) :- lisp( 'goto-line'(P)).
1423point_max(X):- lisp('point-max'(), X).
1428point_min(X):- lisp('point-min'(), X).
1433% ?- elisp:buffer_substring(20, 30, X). 1434buffer_substring(P, Q, S):- call_lisp('buffer-substring'(P, Q), term(S)).
1439% edit_command_set --> {edit_command_set}.
1447edit_command_set:- lisp(setq('edit-command-set', 1448 #(["set_dired", "dired", "prolog", "lisp", "prooftree"] ))). 1449 1450% ?- listing(quote).
1455edit --> { lisp_atom('read-string'("predicate[/N] : "), P), 1456 setof(X-Y, find_pred:locate(P, X, Y), Pairs), 1457 show_select_location(Pairs), 1458 length(Pairs, N), 1459 N > 0, 1460 ( N == 1 1461 -> J = 1 1462 ; call_lisp('ask-term'("number ? "), term(J0)), 1463 number_codes(J, J0) 1464 ), 1465 nth1(J, Pairs, _ - [file(F), line(G)]), 1466 atom_string(F, F0), 1467 lisp(progn('find-file'(F0), 'goto-line'(G))) 1468 }. 1469edit --> { lisp(message("No requested predicate found.")) }. 1470 1471% 1472show_select_location(Pairs) :- 1473 wait('switch-to-buffer'("*scratch*")), 1474 insert_buffer("** select number **\n"), 1475 length(Pairs, N), 1476 numlist(1, N, Ns), 1477 maplist(pred(([I, Spec - _, [I0, ".\t- ", Spec0, "\n"]]:- 1478 number_string(I, I0), 1479 term_string(Spec, Spec0))), 1480 Ns, Pairs, Specs), 1481 insert_buffer(Specs).
1486zip_minus([], [], []). 1487zip_minus([A|X], [B|Y], [A-B|R]):- zip_minus(X, Y, R).
1492% ?- elisp:visit_file_line("/Users/cantor/tmp/deldel.pl", 3). 1493visit_file_line(File, Line):- 1494 lisp(progn('find-file'(#(File)), 'goto-line'(Line))).
1499ask_number(P, X):- atomics_to_string(P, P0),
1500 lisp('ask-term'(P0), X).
1508ask_which([_], 1). 1509ask_which(Xs, J):- maplist([N-I, [N,-,I]], Xs, Ys), 1510 insert("\n\t", Ys, Zs), 1511 ask_number(["Select number:\n\t"|Zs], J). 1512 1513 /***************** 1514 * for tex * 1515 *****************/
1520wdf --> wrap_dollar_forwarding. 1521 1522% 1523wrap_dollar_forwarding --> for_ascii(X\[$, X, $]). 1524wrap_Red_forwarding --> for_ascii(X\['\\Red{', X, '}']). 1525wrap_Green_forwarding --> for_ascii(X\['\\Green{', X, '}']). 1526wrap_Blue_forwarding --> for_ascii(X\['\\Blue{', X, '}']). 1527wrap_with_single_quote --> region, 1528 line(X\['''', X, ''''], ',\n'), smash, overwrite.
1534% ?- elisp:find_next_ascii_codes(X, A, R, ` å® å® a b c `, Y). 1535find_next_ascii_codes(X, A, Y) --> skip_to_ascii_codes(X), 1536 ascii_codes(A), 1537 current(Y). 1538 1539%! ascii_codes(-X:codes, +Y:codes, -Z:codes) is det. 1540% True if 1541% X is unified with the maximum ascii codes prefix of Y, 1542% Z with the remainder of Y. 1543 1544% ?- elisp:ascii_codes(X, `ab cd `, R). 1545%@ X = [97, 98, 32, 99, 100], 1546%@ R = [32, 32] . 1547ascii_codes(X) --> wl(+(?(char(space)) + char(ascii\space)), X).
1554% ?- elisp:skip_to_ascii_codes(X, `abc`, Y). 1555 1556% ?- elisp:skip_to_ascii_codes(X, `åäº å½æ abc`, Y). 1557skip_to_ascii_codes(X) --> wl( *(char(\+ascii|space)) | char(space)^(>=(2)), X). 1558 1559$([],[]). % end_of_codes([], []). 1560 1561first_token_codes --> wl(*char(white)), w(*(.), X), wl(*char(white)), $, % end of codes peek(X).
1570% ?- elisp:global_set_kbd("ejockey:handle([eit])"). 1571global_set_kbd(A) :- global_set_kbd("C-c C-u", A).
1576global_set_kbd(Key, A) :-
1577 lisp('global-set-key'(kbd(Key),
1578 #(lambda(nil, interactive(), 'prolog-query'(A))))).
1583global_unset_kbd(K):- lisp('global-unset-key'(kbd(K))). 1584 1585 /****************************************** 1586 * Convert xml to quasi bibtex form * 1587 ******************************************/ 1588 1589% ?- scm(elisp). 1590% ?- abbreviation('ab cd', X). 1591 1592abbreviation(A, B):- string_code(I, A, 0'\s), !, % ' 1593 succ(J, I), 1594 sub_string(A, 0, J, _, B0), 1595 atom_string(B, B0). 1596abbreviation(A, A). 1597 1598% ?- make_key([published='2014', author='Obama'], Key). 1599 1600make_key(L, Key):- memberchk(published=Year, L), 1601 memberchk(author=Author, L), 1602 !, 1603 abbreviation(Author, Abbr), 1604 atom_concat(Abbr, Year, Key). 1605make_key(L, Key):- memberchk(published=Year, L), 1606 memberchk(publisher=Pub, L), 1607 !, 1608 abbreviation(Pub, Abbr), 1609 atom_concat(Abbr, Year, Key). 1610make_key(L, Key):- memberchk(published=Year, L), 1611 memberchk(publisher=Pub, L), 1612 !, 1613 abbreviation(Pub, Abbr), 1614 atom_concat(Abbr, Year, Key). 1615make_key(_, '??????'). 1616 1617% Use this predicate after exporting onto the Desktop directory. 1618% run unix command delicious-export [2016/12/16] 1619% ?- parse_xml_for_bibtex(Bib), maplist(writeln, Bib), length(Bib, Length). 1620% ?- parse_xml_for_bibtex(Bib), open('/Users/cantor/Desktop/test', write, X),maplist(writeqln(X), Bib), close(X). 1621 1622% Delicious Library 3; incremental export to bibtex 1623% revised Workflow: 1624% (0) => (1) =>(2) => (3) 1625% 1626% (0) initialize 1627% % touch ~/TeXLive/texmf-var/bibtex/bib/delicious-db.pl 1628% 1629% (1) run unix script [2016/12/16]: 1630% % delicious-export 1631% 1632% (2) run prolog query: 1633% ?- elisp:delicious_update. 1634%@ true . 1635 1636% 1637% (3) Open the output at the Desktop, and edit .bib files manually. 1638 1639% ?- elisp:delicious_bibtex_terms("~/TeXLive/texmf-var/bibtex/bib/deldelbooks1.pl"). 1640% ?- elisp:delicious_bibtex_terms("~/Desktop/test.pl", "~/Desktop/test.bib"). 1641 1642% ?- trace, elisp:delicious_update. 1643 1644delicious_update:- 1645 delicious_bibtex_terms("~/TeXLive/texmf-var/bibtex/bib/delicious-db.pl", 1646 "~/Desktop/new-delicious", ".bib"). 1647 1648delicious_bibtex_terms(DB, Bib_basic, Ext) :- parse_xml_for_bibtex(Bib), !, 1649 sort(Bib, Bib0), 1650 expand_file_name(DB, [DB0|_]), 1651 pshell(touch(DB0)), 1652 read_file_to_terms(DB0, Old_bib, []), 1653 subtract(Bib0, Old_bib, NewBooks), 1654 open(DB0, write, Y), 1655 maplist(writeq_book_term(Y), Bib0), 1656 close(Y), 1657 sort(NewBooks, NewBooks0), 1658 maplist(book_bibitem, NewBooks0, Bib1), 1659 atomics_to_string([Bib_basic, Ext],Bib_file), 1660 expand_file_name(Bib_file, [Out0|_]), 1661 string_length(Ext, N), 1662 sub_string(Out0, 0, _, N, Out_basic), 1663 ejockey:modify_file_name(Out_basic, 0, Ext, NewOut), 1664 open(NewOut, write, Z), 1665 maplist(writeln(Z), Bib1), 1666 close(Z). 1667 1668writeq_book_term(X, Book):- 1669 writeq(X, Book), 1670 write(X, ".\n"). 1671 1672% 1673delicious_bibtex(Out) :- parse_xml_for_bibtex(Bib), !, 1674 sort(Bib, Bib0), 1675 maplist(book_bibitem, Bib0, Bib1), 1676 expand_file_name(Out, [Out0|_]), 1677 open(Out0, write, X), 1678 maplist(writeln(X), Bib1), 1679 close(X). 1680 1681writeqln(S, X):- writeq(S, X), write(S, '.\n'). 1682 1683% parse_xml_for_bibtex(Bib):- 1684% expand_file_name("~/Desktop/Delicious Library/Library Media Data.xml", [File]), 1685% parse_xml_for_bibtex(File, Dom), 1686% maplist(pred(([book(L), book([key=Key|L])]:- make_key(L, Key))), 1687% Dom, Bib). 1688 1689% % ?- parse_xml_for_bibtex("/path/to/xml-file", Dom). 1690% parse_xml_for_bibtex(File, Books):- 1691% Keys = [ 1692% published, 1693% publisher, 1694% title, 1695% upc, 1696% author], 1697% parse_xml_to_books(File, Books, Keys). 1698% % 1699% parse_xml_to_books(File, Books, Keys):- 1700% load_xml(File, Dom, [encoding('utf-8')]), 1701% flatten_element_list(Dom, Books, [], Keys). 1702 1703% 1704flatten_element_list([A|B], X, Y, Keys):- 1705 once(flatten_element(A, X, X0, Keys)), 1706 flatten_element_list(B, X0, Y, Keys). 1707flatten_element_list([], X, X, _). 1708 1709% 1710flatten_element(element(library, _, L), X, Y, Keys):- 1711 flatten_element_list(L, X, Y, Keys). 1712flatten_element(element(items, _, L), X, Y, Keys):- 1713 flatten_element_list(L, X, Y, Keys). 1714flatten_element(element(book, L, _), [book(L0)|X], X, Keys):- 1715 projection(L, Keys, L0). 1716flatten_element(_, X, X, _). 1717 1718% 1719projection([], _, []). 1720projection([Eq|L], Keys, [Eq0|L0]):- modify_value(Eq, Eq0), !, 1721 projection(L, Keys, L0). 1722projection([Eq|L], Keys, [Eq|L0]):- Eq = (K = _), memberchk(K, Keys), !, 1723 projection(L, Keys, L0). 1724projection([_|L], Keys, L0):- projection(L, Keys, L0). 1725 1726% 1727modify_value(published = V, published = V0):- 1728 sub_atom(V, 0, 4, _, V0). 1729modify_value(K = 'ï¼', K = void). 1730modify_value('aspect=ï¼', aspect = undefined). 1731 1732% Target sample. 1733% @book{Noro-2003, 1734% author = {éå æ£è¡ and 横山 åå¼}, 1735% publisher = {æ±äº¬å¤§å¦åºçä¼}, 1736% pages = {288}, 1737% title = {ã°ã¬ããã¼åºåºã®è¨ç®åºç¤ç¯ï¼è¨ç®ä»£æ°å ¥é}, 1738% keywords = {ç§å¦ã»ãã¯ããã¸ã¼}, 1739% ISBN = {4130614045}, 1740% language = {æ¥æ¬èª (Published)}, 1741% price = {ï¿¥ 4,536}, 1742% year = {2003} 1743% } 1744 1745book_bibitem(book(L), BB):- 1746 select(key=Keyval, L, L0), 1747 maplist(pred( [published=V, [year, " = ", "{", V, "}"]] 1748 & [K=V, [K, " = ", "{", V, "}"]]), L0, Items), insert(",\n", Items, Items0), smash(["@book{", Keyval, ",\n", Items0, "\n}\n"], BB).
Execute G almost in the same way as
for phrase(G, X, Y)
when P = [X,Y],
or call(G)
when P=[].
For each atomic pharse P of G
meta_handle(B, M, Sp, [])
is executed when call(Sp, M, P, B)
is true.
This predicate is convenient to test
handles, which may have handle calls in the body, and see their outputs on emacs buffer window.
1772% helpers. 1773 1774id([X,X]). 1775id([]). 1776 1777transitive([], [], []). 1778transitive([X, Y], [X, Z], [Z, Y]). 1779 1780:- meta_predicate meta_handle( , , , ). 1781 1782% 1783meta_handle(X,Y,Z,U):- meta_handle_plain(X,Y,Z,U). 1784 1785% 1786meta_handle_plain((A,B), M, Sp, P):- transitive(P, Q, R), 1787 meta_handle_plain(A, M, Sp, Q), 1788 meta_handle_plain(B, M, Sp, R). 1789meta_handle_plain(M:A, _, Sp, P):- meta_handle_plain(A, M, Sp, P). 1790meta_handle_plain(A;B, M, Sp, P):- 1791 (meta_handle_plain(A, M, Sp, P) 1792 ; meta_handle_plain(B, M, Sp, P)). 1793meta_handle_plain(A->B, M, Sp, P):- transitive(P, Q, R), 1794 meta_handle_plain(A, M, Sp, Q), !, 1795 meta_handle_plain(B, M, Sp, R). 1796meta_handle_plain((A->B; C), M, Sp, P):- transitive(P, Q, R), 1797 (meta_handle_plain(A, M, Sp, Q), !, meta_handle_plain(B, M, Sp, R) 1798 ; meta_handle_plain(C, M, Sp, P)). 1799meta_handle_plain(nopac({A}), M, _, P):- id(P), 1800 ( M==[], !, call(A) 1801 ; call(M:A) ). 1802meta_handle_plain(A, M, Sp, P) :- Sp\==[], Sp\= _:[], 1803 call(Sp, A, M, P, G), 1804 !, 1805 meta_handle_plain(G, M, Sp, []). 1806meta_handle_plain(A, [], _, P):- apply(A, P). 1807meta_handle_plain(A, M, _, P):- apply(M:A, P). 1808 1809:- initial_region_obj.