home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / e / e032 / 3.ddi / FILES / PRELOAD.PAK / EDIT.M < prev    next >
Encoding:
Text File  |  1992-07-29  |  5.7 KB  |  285 lines

  1.  
  2. (*
  3.  * Edit expressions, input lines and definitions:
  4.  *    Edit[expr___] allows editing of the values of expressions ``expr''.
  5.  *    EditIn[line_Integer:$Line-1] allows one to edit input lines ``line''.
  6.  *    EditDefinition[sym___Symbol] allows editing of the rules attached to ``sym''.
  7.  * All of these functions use the environment variable EDITOR to determine
  8.  * what editor to use, and default to vi.
  9.  *
  10.  *)
  11.  
  12.  
  13. (*
  14.  * Global objects.
  15.  *)
  16. Begin["System`"]
  17.  
  18. Edit::usage = "Edit[expr___] lets you edit the expressions expr."
  19.  
  20. EditIn::usage = "EditIn[n__Integer] lets you edit input lines n.
  21.     EditIn[] edits the previous input line."
  22.  
  23. EditDefinition::usage = "EditDefinition[syms___] lets you edit the rules
  24.     attached to the symbols syms."
  25.      
  26. EditDef::usage = "EditDef is the obsolete name of EditDefinition."
  27. Begin["EditPrivate`"]
  28.  
  29. (*
  30.  * Just edit a bunch of expressions.
  31.  *)
  32.  
  33. Edit[expr___] :=
  34.     Block[{
  35.         tmpfile = OpenTemporary[]
  36.         },
  37.         Scan[
  38.             Write[tmpfile, #]&,
  39.             { expr }
  40.         ];
  41.         Close[tmpfile];
  42.         EditIO[tmpfile]
  43.     ]
  44.  
  45. EditString[expr___] :=
  46.     Block[{
  47.         tmpfile = OpenTemporary[]
  48.         },
  49.         Scan[
  50.             WriteString[tmpfile, #]&,
  51.             { expr }
  52.         ];
  53.         Close[tmpfile];
  54.         EditIO[tmpfile]
  55.     ]
  56.  
  57.  
  58. (*
  59.  * Edit an input line.
  60.  *)
  61.  
  62. EditIn[] := EditIn[$Line - 1]
  63.  
  64. (*
  65. EditIn[line_Integer] := EditInAux[ EditString[ InString[ line]]]
  66. *)
  67.  
  68. EditIn[line_Integer] := EditString[ InString[ line]] /; line < $Line
  69.  
  70. EditIn[lines__Integer] :=
  71.         Last[ Map[ EditIn, List[ lines]]]
  72. (*
  73. EditInAux[ x_String] := ToExpression[x]
  74. EditInAux[ x_] := x 
  75. *)
  76.  
  77. EditInAux = ToExpression
  78.  
  79. Attributes[EditDefinition] = HoldAll
  80.  
  81. EditDefinition[syms___] :=
  82.     Block[{
  83.         tmpfile = OpenTemporary[],
  84.         heldsyms = Map[ Hold, Hold[{syms}], {2} ][[1]]
  85.         },
  86.         Scan[ Apply[ WriteDef, # ]&, heldsyms ];
  87.         Close[tmpfile];
  88.         EditIO[tmpfile]
  89.     ] /; AllSyms[syms]
  90.  
  91. EditDef = EditDefinition
  92.  
  93. (*
  94.  * WriteDef writes the definition of a symbol to the file tmpfile
  95.  * (passed via dynamic scoping).
  96.  *)
  97. Attributes[WriteDef] = HoldAll
  98.  
  99. WriteDef[sym_Symbol] :=
  100.     Block[{
  101.         protected = MemberQ[Attributes[sym], Protected],
  102.         locked = MemberQ[Attributes[sym], Locked],
  103.         symname = ToString[HoldForm[InputForm[sym]]]
  104.         },
  105.         WriteString[tmpfile, "    (* ", symname, " *)\n" ];
  106.         If[protected || locked,
  107.             WriteString[tmpfile, "(*\n",
  108.                 " * Warning: ", symname, " is ",
  109.                 If[protected,
  110.                     If[locked,
  111.                         "Protected and Locked.\n",
  112.                         "Protected.\n"
  113.                     ],
  114.                     "Locked.\n"
  115.                 ],
  116.                 " * The definition is commented out:\n\n"
  117.             ];
  118.             If[protected,
  119.                 WriteString[tmpfile,
  120.                     "Unprotect[", symname, "]\n"
  121.                 ]
  122.             ];
  123.         ];
  124.         WriteString[tmpfile,
  125.             "Clear[", symname, "]\n"
  126.         ];
  127.         Write[tmpfile, Definition[sym]];
  128.         If[protected || locked,
  129.             WriteString[tmpfile,
  130.                 "\n * End of commented definition of ",
  131.                 symname,
  132.                 ".\n",
  133.                 " *)\n"
  134.             ]
  135.         ];
  136.         WriteString[tmpfile, "\n"]
  137.     ]
  138.  
  139.  
  140. (*
  141.  * AllSyms tests to make sure that all of its arguments are symbols.
  142.  * Note, this is a bit tricky since the symbols may have values.
  143.  *)
  144. Attributes[AllSyms] = HoldAll
  145.  
  146. AllSyms[syms___] :=
  147.     Block[{
  148.         tmp
  149.         },
  150.         tmp = Map[ Hold, Hold[{syms}], {2} ][[1]];
  151.         tmp = Select[ tmp, ! MatchQ[#, Hold[_Symbol]]& ];
  152.         Scan[
  153.             Message[ EditDefinition::edsym,
  154.                  Apply[ HoldForm, # ] ]&, tmp ];
  155.         Length[tmp] == 0
  156.     ]
  157.  
  158. EditDefinition::edsym = "`1` is not a symbol."
  159.  
  160.  
  161. (*
  162.  * Support routines for editing.
  163.  *)
  164.  
  165.  
  166. (*
  167.  * Edit a file (re-editing on errors), reading it into In/Out, and then
  168.  * remove the file.  The result is the result of evaluating the last
  169.  * expression.
  170.  *)
  171. EditIO[file_String] := (
  172.     While[
  173.         Run["${EDITOR-vi} ", file];
  174.         And[
  175.             ! ReadIO[file],
  176.             TrueQ[GetYesNo["Re-edit? "]]
  177.         ]
  178.     ];
  179.     Run["rm ", file];
  180.     Out[--$Line]
  181. )
  182.  
  183. EditIO[streamhead_Symbol[name_String, serialnumber_Integer]] := EditIO[name]
  184.  
  185.  
  186. (*
  187.  * StreamFileName[stream] returns the filename part of a stream indicator,
  188.  * and works in either 1.2 or 2.0. 
  189.  *)
  190.  
  191. StreamFileName[streamhead_Symbol[name_String, serialnumber_Integer]] := name
  192.  
  193. StreamFileName[name_String] := name
  194.  
  195.  
  196. (*
  197.  * GetYesNo prompts the user and reads in either yes (return True), no
  198.  * (return False) or EndOfFile (return EndOfFile).
  199.  *)
  200. GetYesNo[prompt_] :=
  201.     Block[{
  202.         resp
  203.         },
  204.         While[True,
  205.             resp = InputString[prompt];
  206.             If[MemberQ[{"y", "yes", "Y", "Yes"}, resp],
  207.                 Return[True],
  208.             If[MemberQ[{"n", "no", "N", "No"}, resp],
  209.                 Return[False],
  210.             If[SameQ[resp, EndOfFile],
  211.                 Return[EndOfFile]
  212.             ]]]
  213.         ]
  214.     ]
  215.  
  216.  
  217. (*
  218.  * Open a file, read it in setting In and Out and then close it.
  219.  * If False is returned, it means that there was a syntax error,
  220.  * otherwise True is returned.
  221.  *)
  222. ReadIO[filename_String] :=
  223.     Block[{
  224.         value,
  225.         result,
  226.         stream
  227.         },
  228.         stream = OpenRead[filename];
  229.         If[! SameQ[StreamFileName[stream], filename],
  230.             Return[True]    (* the file no longer exists *)
  231.         ];
  232.         While[
  233.             value = Check[
  234.                     Read[
  235.                         stream,
  236.                         Hold[Expression]
  237.                     ],
  238.                     "Error"
  239.             ];
  240.             Switch[value,
  241.                 Hold[_],
  242.                     Apply[EvalIO, value];
  243.                     True,
  244.                 EndOfFile,
  245.                     result = True;
  246.                     False,
  247.                 "Error",
  248.                     result = False;
  249.                     False
  250.             ]
  251.         ];
  252.         Close[stream];
  253.         result
  254.     ]
  255.  
  256.  
  257. (*
  258.  * EvalIO causes its unevaluated argument to be the value of the current
  259.  * input line and its evaluated argument to be the value of the current
  260.  * output line.  It then increments the current line number.
  261.  *)
  262. Attributes[EvalIO] = HoldAll
  263.  
  264. EvalIO[arg_] :=
  265.     Block[{
  266.         prot,
  267.         value
  268.         },
  269.         prot = Unprotect[{"In", "Out"}];
  270.         In[$Line] := arg;
  271.         Out[$Line++] = arg;
  272.         Scan[Protect, prot];
  273.     ]
  274.  
  275. (*
  276.  * Protect all functions.
  277.  *)
  278. Protect[{ Edit, EditIn, EditDefinition, WriteDef, AllSyms, EditIO,
  279.         GetYesNo, ReadIO, EvalIO, StreamFileName }];
  280.  
  281.  
  282. End[]
  283.  
  284. End[];
  285.