home *** CD-ROM | disk | FTP | other *** search
- (*
- * Edit expressions, input lines and definitions:
- * Edit[expr___] allows editing of the values of expressions ``expr''.
- * EditIn[line_Integer:$Line-1] allows one to edit input lines ``line''.
- * EditDef[sym___Symbol] allows editing of the rules attached to ``sym''.
- * All of these functions use the environment variable EDITOR to determine
- * what editor to use, and default to vi.
- *
- *)
-
-
- (*
- * Global objects.
- *)
- Begin["System`"]
-
- Edit::usage = "Edit[expr___] allows one to edit the expressions expr."
-
- EditIn::usage = "EditIn[n__Integer] allows one to edit input lines n.
- EditIn[] edits the previous input line."
-
- EditDef::usage = "EditDef[syms___] allows one to edit the rules attached
- to the symbols syms."
-
- EditDefinition::usage = "EditDefinition[syms___] allows one to edit the
- rules attached to the symbols syms."
-
- Begin["EditPrivate`"]
-
- (*
- * Just edit a bunch of expressions.
- *)
-
- Edit[expr___] :=
- Block[{
- tmpfile = OpenTemporary[]
- },
- Scan[
- Write[tmpfile, #]&,
- { expr }
- ];
- Close[tmpfile];
- EditIO[tmpfile]
- ]
-
- EditString[expr___] :=
- Block[{
- tmpfile = OpenTemporary[]
- },
- Scan[
- WriteString[tmpfile, #]&,
- { expr }
- ];
- Close[tmpfile];
- EditIO[tmpfile]
- ]
-
-
- (*
- * Edit an input line.
- *)
-
- EditIn[] := EditIn[$Line - 1]
-
- (*
- EditIn[line_Integer] := EditInAux[ EditString[ InString[ line]]]
-
- -- TWJ Dec 90 EditString allways returns an Expression
- unless it really is a string
- *)
-
- EditIn[line_Integer] := EditString[ InString[ line]]
-
- EditIn[lines__Integer] :=
- Last[ Map[ EditIn, List[ lines]]]
- (*
- EditInAux[ x_String] := ToExpression[x]
-
- EditInAux[ x_] := x
-
- -- AB Dec 90 - I do not understand what was it for,
- -- but to put EditIn into infinite loop (bug 0962)
- *)
- EditInAux = ToExpression
-
- Attributes[EditDef] = HoldAll
-
- EditDef[syms___] :=
- Block[{
- tmpfile = OpenTemporary[],
- heldsyms = Map[ Hold, Hold[{syms}], {2} ][[1]]
- },
- Scan[ Apply[ WriteDef, # ]&, heldsyms ];
- Close[tmpfile];
- EditIO[tmpfile]
- ] /; AllSyms[syms]
-
-
- EditDefinition[syms___] := EditDef[syms]
-
-
- (*
- * WriteDef writes the definition of a symbol to the file tmpfile
- * (passed via dynamic scoping).
- *)
- Attributes[WriteDef] = HoldAll
-
- WriteDef[sym_Symbol] :=
- Block[{
- protected = MemberQ[Attributes[sym], Protected],
- locked = MemberQ[Attributes[sym], Locked],
- symname = ToString[HoldForm[InputForm[sym]]]
- },
- WriteString[tmpfile, " (* ", symname, " *)\n" ];
- If[protected || locked,
- WriteString[tmpfile, "(*\n",
- " * Warning: ", symname, " is ",
- If[protected,
- If[locked,
- "Protected and Locked.\n",
- "Protected.\n"
- ],
- "Locked.\n"
- ],
- " * The definition is commented out:\n\n"
- ];
- If[protected,
- WriteString[tmpfile,
- "Unprotect[", symname, "]\n"
- ]
- ];
- ];
- WriteString[tmpfile,
- "Clear[", symname, "]\n"
- ];
- Write[tmpfile, Definition[sym]];
- If[protected || locked,
- WriteString[tmpfile,
- "\n * End of commented definition of ",
- symname,
- ".\n",
- " *)\n"
- ]
- ];
- WriteString[tmpfile, "\n"]
- ]
-
-
- (*
- * AllSyms tests to make sure that all of its arguments are symbols.
- * Note, this is a bit tricky since the symbols may have values.
- *)
- Attributes[AllSyms] = HoldAll
-
- AllSyms[syms___] :=
- Block[{
- tmp
- },
- tmp = Map[ Hold, Hold[{syms}], {2} ][[1]];
- tmp = Select[ tmp, ! MatchQ[#, Hold[_Symbol]]& ];
- Scan[
- Message[ EditDef::edsym,
- Apply[ HoldForm, # ] ]&, tmp ];
- Length[tmp] == 0
- ]
-
- EditDef::edsym = "`1` is not a symbol."
-
-
- (*
- * Support routines for editing.
- *)
-
-
- (*
- * Edit a file (re-editing on errors), reading it into In/Out, and then
- * remove the file. The result is the result of evaluating the last
- * expression.
- *)
- EditIO[file_String] := (
- While[
- Run[Environment["EDITOR"], file];
- And[
- ! ReadIO[file],
- TrueQ[GetYesNo["Re-edit? "]]
- ]
- ];
- Run["del ", file];
- Out[--$Line]
- )
-
- EditIO[streamhead_Symbol[name_String, serialnumber_Integer]] := EditIO[name]
- (* bruce 17 Sep 90, for 2.0 compatibility *)
-
-
- (*
- * StreamFileName[stream] returns the filename part of a stream indicator,
- * and works in either 1.2 or 2.0. (bruce 17 Sep 90)
- *)
-
- StreamFileName[streamhead_Symbol[name_String, serialnumber_Integer]] := name
-
- StreamFileName[name_String] := name
-
-
- (*
- * GetYesNo prompts the user and reads in either yes (return True), no
- * (return False) or EndOfFile (return EndOfFile).
- *)
- GetYesNo[prompt_] :=
- Block[{
- resp
- },
- While[True,
- resp = InputString[prompt];
- If[MemberQ[{"y", "yes", "Y", "Yes"}, resp],
- Return[True],
- If[MemberQ[{"n", "no", "N", "No"}, resp],
- Return[False],
- If[SameQ[resp, EndOfFile],
- Return[EndOfFile]
- ]]]
- ]
- ]
-
-
- (*
- * Open a file, read it in setting In and Out and then close it.
- * If False is returned, it means that there was a syntax error,
- * otherwise True is returned.
- *)
- ReadIO[filename_String] :=
- Block[{
- value,
- result,
- stream
- },
- stream = OpenRead[filename];
- If[! SameQ[StreamFileName[stream], filename],
- Return[True] (* the file no longer exists *)
- ];
- While[
- value = Check[
- Read[
- stream,
- Hold[Expression]
- ],
- "Error"
- ];
- Switch[value,
- Hold[_],
- Apply[EvalIO, value];
- True,
- EndOfFile,
- result = True;
- False,
- "Error",
- result = False;
- False
- ]
- ];
- Close[stream];
- result
- ]
-
-
- (*
- * EvalIO causes its unevaluated argument to be the value of the current
- * input line and its evaluated argument to be the value of the current
- * output line. It then increments the current line number.
- *)
- Attributes[EvalIO] = HoldAll
-
- EvalIO[arg_] :=
- Block[{
- prot,
- value
- },
- prot = Unprotect[{"In", "Out"}];
- In[$Line] := arg;
- Out[$Line++] = arg;
- Scan[Protect, prot];
- ]
-
- (*
- * Protect all functions.
- *)
- Protect[{ Edit, EditIn, EditDef, WriteDef, AllSyms, EditIO,
- GetYesNo, ReadIO, EvalIO, StreamFileName }];
-
-
- End[]
-
- End[];
-