home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / e / e031 / 3.ddi / MATHZIP2 / STARTUP / EDIT.M < prev    next >
Encoding:
Text File  |  1991-06-17  |  6.0 KB  |  295 lines

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