cedit.red 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. module cedit; % REDUCE input string editor.
  2. % Author: Anthony C. Hearn;
  3. create!-package('(cedit),'(util));
  4. fluid '(!*mode rprifn!* rterfn!*);
  5. global '(!$eol!$
  6. !*blanknotok!*
  7. !*eagain
  8. !*full
  9. crbuf!*
  10. crbuf1!*
  11. crbuflis!*
  12. esc!*
  13. inputbuflis!*
  14. statcounter);
  15. %esc!* := intern ascii 125; %this is system dependent and defines
  16. %a terminator for strings.
  17. symbolic procedure rplacw(u,v);
  18. if atom u or atom v then errach list('rplacw,u,v)
  19. else rplacd(rplaca(u,car v),cdr v);
  20. symbolic procedure cedit n;
  21. begin scalar x,ochan;
  22. if null terminalp() then rederr "Edit must be from a terminal";
  23. ochan := wrs nil;
  24. if n eq 'fn then x := reversip crbuf!*
  25. else if null n
  26. then if null crbuflis!*
  27. then <<statcounter := statcounter-1;
  28. rederr "No previous entry">>
  29. else x := cdar crbuflis!*
  30. else if (x := assoc(car n,crbuflis!*))
  31. then x := cedit0(cdr x,car n)
  32. else <<statcounter := statcounter-1;
  33. rederr list("Entry",car n,"not found")>>;
  34. crbuf!* := nil;
  35. x := for each j in x collect j; %to make a copy.
  36. terpri();
  37. editp x;
  38. terpri();
  39. x := cedit1 x;
  40. wrs ochan;
  41. if x eq 'failed then nil else crbuf1!* := x
  42. end;
  43. symbolic procedure cedit0(u,n);
  44. % Returns input string augmented by appropriate mode.
  45. begin scalar x;
  46. if not(x := assoc(n,inputbuflis!*)) or ((x := cadr x) eq !*mode)
  47. then return u
  48. else return append(explode x,append(cdr explode '! ,u))
  49. end;
  50. symbolic procedure cedit1 u;
  51. begin scalar x,y,z;
  52. z := setpchar '!>;
  53. if not !*eagain
  54. then <<prin2t "For help, type ?"; !*eagain := t>>;
  55. while u and (car u eq !$eol!$) do u := cdr u;
  56. u := append(u,list '! ); %to avoid 'last char' problem.
  57. if !*full then editp u;
  58. top:
  59. x := u; %current pointer position.
  60. a:
  61. y := readch(); %current command.
  62. if y eq '!P or y eq '!p then editp x
  63. else if y eq '!I or y eq '!i then editi x
  64. else if y eq '!C or y eq '!c then editc x
  65. else if y eq '!D or y eq '!d then editd x
  66. else if y eq '!F or y eq '!f then x := editf(x,nil)
  67. else if y eq '!E or y eq '!e
  68. then <<terpri(); editp1 u; setpchar z; return u>>
  69. else if y eq '!Q or y eq '!q then <<setpchar z; return 'failed>>
  70. else if y eq '!? then edith()
  71. else if y eq '!B or y eq '!b then go to top
  72. else if y eq '!K or y eq '!k then editf(x,t)
  73. else if y eq '!S or y eq '!s then x := edits x
  74. else if y eq '! and not !*blanknotok!* or y eq '!X or y eq '!x
  75. then x := editn x
  76. else if y eq '! and !*blanknotok!* then go to a
  77. else if y eq !$eol!$ then go to a
  78. else lprim!* list(y,"Invalid editor character");
  79. go to a
  80. end;
  81. symbolic procedure editc x;
  82. if null cdr x then lprim!* "No more characters"
  83. else rplaca(x,readch());
  84. symbolic procedure editd x;
  85. if null cdr x then lprim!* "No more characters"
  86. else rplacw(x,cadr x . cddr x);
  87. symbolic procedure editf(x,bool);
  88. begin scalar y,z;
  89. y := cdr x;
  90. z := readch();
  91. if null y then return <<lprim!* list(z,"Not found"); x>>;
  92. while cdr y and not(z eq car y) do y := cdr y;
  93. return if null cdr y then <<lprim!* list(z,"Not found"); x>>
  94. else if bool then rplacw(x,car y . cdr y)
  95. else y
  96. end;
  97. symbolic procedure edith;
  98. <<prin2t "THE FOLLOWING COMMANDS ARE SUPPORTED:";
  99. prin2t " B move pointer to beginning";
  100. prin2t " C<character> replace next character by <character>";
  101. prin2t " D delete next character";
  102. prin2t " E end editing and reread text";
  103. prin2t
  104. " F<character> move pointer to next occurrence of <character>";
  105. prin2t
  106. " I<string><escape> insert <string> in front of pointer";
  107. prin2t " K<character> delete all chars until <character>";
  108. prin2t " P print string from current pointer";
  109. prin2t " Q give up with error exit";
  110. prin2t
  111. " S<string><escape> search for first occurrence of <string>";
  112. prin2t " positioning pointer just before it";
  113. prin2t " <space> or X move pointer right one character";
  114. terpri();
  115. prin2t
  116. "ALL COMMAND SEQUENCES SHOULD BE FOLLOWED BY A CARRIAGE RETURN";
  117. prin2t " TO BECOME EFFECTIVE">>;
  118. symbolic procedure editi x;
  119. begin scalar y,z;
  120. while (y := readch()) neq esc!* do z := y . z;
  121. rplacw(x,nconc(reversip z,car x . cdr x))
  122. end;
  123. symbolic procedure editn x;
  124. if null cdr x then lprim!* "NO MORE CHARACTERS"
  125. else cdr x;
  126. symbolic procedure editp u;
  127. <<editp1 u; terpri()>>;
  128. symbolic procedure editp1 u;
  129. for each x in u do if x eq !$eol!$ then terpri() else prin2 x;
  130. symbolic procedure edits u;
  131. begin scalar x,y,z;
  132. x := u;
  133. while (y := readch()) neq esc!* do z := y . z;
  134. z := reversip z;
  135. a: if null x then return <<lprim!* "not found"; u>>
  136. else if edmatch(z,x) then return x;
  137. x := cdr x;
  138. go to a
  139. end;
  140. symbolic procedure edmatch(u,v);
  141. % Matches list of characters U against V. Returns rest of V if
  142. % match occurs or NIL otherwise.
  143. if null u then v
  144. else if null v then nil
  145. else if car u=car v then edmatch(cdr u,cdr v)
  146. else nil;
  147. symbolic procedure lprim!* u; <<lprim u; terpri()>>;
  148. Comment Editing Function Definitions;
  149. remprop('editdef,'stat);
  150. symbolic procedure editdef u; editdef1 car u;
  151. symbolic procedure editdef1 u;
  152. begin scalar type,x;
  153. if null(x := getd u) then return lprim list(u,"not defined")
  154. else if codep cdr x or not eqcar(cdr x,'lambda)
  155. then return lprim list(u,"cannot be edited");
  156. type := car x;
  157. x := cdr x;
  158. if type eq 'expr then x := 'de . u . cdr x
  159. else if type eq 'fexpr then x := 'df . u . cdr x
  160. else if type eq 'macro then x := 'dm . u . cdr x
  161. else rederr list("strange function type",type);
  162. rprifn!* := 'add2buf;
  163. rterfn!* := 'addter2buf;
  164. crbuf!* := nil;
  165. x := errorset!*(list('rprint,mkquote x),t);
  166. rprifn!* := nil;
  167. rterfn!* := nil;
  168. if errorp x then return (crbuf!* := nil);
  169. crbuf!* := cedit 'fn;
  170. return nil
  171. end;
  172. symbolic procedure add2buf u; crbuf!* := u . crbuf!*;
  173. symbolic procedure addter2buf; crbuf!* := !$eol!$ . crbuf!*;
  174. put('editdef,'stat,'rlis);
  175. Comment Displaying past input expressions;
  176. put('display,'stat,'rlis);
  177. symbolic procedure display u;
  178. % Displays input stack in reverse order.
  179. % Modification to reverse list added by F. Kako.
  180. begin scalar x,w;
  181. u := car u;
  182. x := crbuflis!*;
  183. terpri();
  184. if not numberp u then u := length x;
  185. while u>0 and x do
  186. <<w := car x . w; x := cdr x; u := u - 1>>;
  187. for each j in w do
  188. <<prin2 car j; prin2 ": "; editp cdr j; terpri()>>
  189. end;
  190. endmodule;
  191. end;