<> <> <> <> DIRECTORY Atom, Commander, CommanderOps, Convert, FS, IO, NodeProps, PFS, Rope, Scheme, SchemePrettyRead, SchemePrinting, StructuredStreams, TextNode, TiogaFileOps, TiogaIO, TiogaStreams, UnparserBuffer, UserProfile; SchemePrettyFileImpl: CEDAR PROGRAM IMPORTS Atom, Commander, CommanderOps, Convert, FS, IO, NodeProps, PFS, Rope, Scheme, SchemePrettyRead, SchemePrinting, StructuredStreams, TextNode, TiogaFileOps, TiogaIO, TiogaStreams, UnparserBuffer, UserProfile = BEGIN OPEN Scheme, SchemePrettyRead, SchemePrinting, SS:StructuredStreams, TS:TiogaStreams, UB:UnparserBuffer; defaultHow: How ¬ []; defaultMargin: INT ¬ 80; plainWidths: REF ARRAY CHAR OF INTEGER ¬ NEW[ARRAY CHAR OF INTEGER ¬ ALL[1]]; tabWidth: INTEGER ¬ plainWidths['\t] ¬ 8; plainSpacers: LIST OF CHAR ¬ LIST['\t, ' ]; PrettyPrintFileCmd: PROC [cmd: Commander.Handle] RETURNS [result: REF ANY ¬ NIL, msg: ROPE ¬ NIL] --Commander.CommandProc-- ~ { PPLocal: PROC ~ {}; argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd]; how: How ¬ defaultHow; margin: INT ¬ defaultMargin; barfum: ROPE ¬ NIL; context: ATOM ¬ $exprs; debugSS, debugRead, plainOut: BOOL ¬ FALSE; debugLog: IO.STREAM ¬ NIL; i: NAT ¬ 1; outName: ROPE ¬ NIL; extStack: INT ¬ 0; msg ¬ NIL; WHILE i < argv.argc DO ENABLE { Complain => {barfum ¬ msg; GOTO Abort}; Convert.Error => {barfum ¬ "Conversion error on command line"; GOTO Abort}; }; arg: ROPE ~ argv[i]; IF arg.Length[]<1 THEN LOOP; SELECT TRUE FROM arg.Fetch[0]='- => IF i.SUCC=argv.argc THEN RETURN [$Failure, "switch arg missing"] ELSE SELECT TRUE FROM arg.Equal["-margin", FALSE] => {margin ¬ Convert.IntFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-sia", FALSE] => {how.sia ¬ Convert.IntFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-simplelen", FALSE] => {how.simpleLen ¬ Convert.IntFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-simplequote", FALSE] => {how.simpleQuote ¬ Convert.BoolFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-debug", FALSE] => {debugLog ¬ IF Convert.BoolFromRope[argv[i.SUCC]] THEN cmd.err ELSE NIL; i ¬ i+2}; arg.Equal["-plainOut", FALSE] => {plainOut ¬ Convert.BoolFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-debugss", FALSE] => {debugSS ¬ Convert.BoolFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-debugRead", FALSE] => {debugRead ¬ Convert.BoolFromRope[argv[i.SUCC]]; i ¬ i+2}; arg.Equal["-context", FALSE] => {context ¬ Atom.MakeAtom[argv[i.SUCC]]; i ¬ i+2}; ENDCASE => RETURN [$Failure, Rope.Concat["unrecognized switch: ", arg]]; i.SUCC {outName ¬ arg; i ¬ i+2}; ENDCASE => { ENABLE { PFS.Error => { barfum ¬ IO.PutFR["PFS.Error[%g, %g] while processing %g", [atom[error.code]], [rope[error.explanation]], [rope[arg]] ]; GOTO Abort}; TiogaIO.Error => { barfum ¬ IO.PutFR1["TiogaIO.Error while reading %g", [rope[arg]] ]; GOTO Abort}; Complain => {barfum ¬ msg; GOTO Abort}; Warning => {cmd.err.PutRope[message.Concat["\n"]]; RESUME}}; tfoRoot: TiogaFileOps.Ref; raRoot: REF ANY; tnRoot: TextNode.Ref; buff: IO.STREAM; ubh: UB.Handle; out: IO.STREAM; head: Pair ~ Cons[NIL, NIL]; tail: Pair ¬ head; inFilePath: PFS.PATH ¬ PFS.PathFromRope[arg]; inRoot: TextNode.Ref ¬ TiogaIO.FromFile[inFilePath].root; inLoc: TextNode.Location ¬ [TextNode.FirstChild[inRoot], 0]; inDex: INT ¬ TextNode.LocOffset[[inRoot, 0], inLoc]; posns: FormToSource ¬ NIL; lextStack: INT; IF outName=NIL THEN outName ¬ arg; IF plainOut THEN { buff ¬ FS.StreamOpen[outName, create]; ubh ¬ UB.Create[ publics: [margin: margin, width: plainWidths­, spacers: plainSpacers, output: [stream[buff]]], newline: "\n"]; } ELSE { tfoRoot ¬ TiogaFileOps.CreateRoot[]; raRoot ¬ tfoRoot; tnRoot ¬ NARROW[raRoot]; buff ¬ TS.CreateOutput[to: tfoRoot, breakAtNewline: TRUE, defaultFormat: "scheme", flexilevel: TRUE, normalNestIndent: 3, minFmtIndent: 1, maxFmtIndent: 20, commentHandling: [FALSE[]] ]; TiogaFileOps.SetStyle[tfoRoot, "scheme"]; NodeProps.PutProp[tnRoot, $Comment, NodeProps.ValueFromBool[TRUE]]; ubh ¬ UB.Create[publics: [margin: margin, output: [stream[buff]]], newline: "\n"]; }; out ¬ SS.Create[ubh]; DO arg, anc: Any; posns: FormToSource; this: Pair; IF debugRead THEN cmd.err.PutF1["Read[%g] => ", [integer[inDex]] ]; [arg, anc, posns, lextStack, inLoc, inDex] ¬ TiogaRead[start: inLoc, stackBase: LOOPHOLE[PPLocal], addTo: posns, deltaIndex: inDex]; IF debugRead THEN { InfoPrint[cmd.err, arg]; cmd.err.PutF1[" [%g]\n", [integer[inDex]] ]}; extStack ¬ MAX[extStack, lextStack]; IF arg=endOfFile THEN EXIT; IF anc=endOfFile AND head#tail THEN { cmtd: Commented ~ NARROW[arg]; tail.car ¬ AffixVector[tail.car, cmtd.prefix]; EXIT}; this ¬ Cons[arg, NIL]; tail.cdr ¬ this; tail ¬ this; IF anc=endOfFile THEN EXIT; ENDLOOP; PrettyPrint[out, head.cdr, how, context, posns, debugLog]; IO.Close[out]; IF plainOut THEN IO.Close[buff] ELSE { IO.Close[buff]; --adds a nodebreak non-idempotently IF FALSE THEN TS.EndNode[buff, reset, TRUE]; TiogaFileOps.Store[tfoRoot, outName]; }; i ¬ i + 1; outName ¬ NIL}; REPEAT Abort => RETURN [$Failure, barfum]; ENDLOOP; IF UserProfile.Boolean["SchemePretty.ViewStackDepth", FALSE] THEN msg ¬ IO.PutFR1["max read stack depth = %xH", [integer[extStack]]]; RETURN}; DoProfile: Commander.CommandProc ~ {NoteProfile[edit]}; Fmt: PROC [a: Any] RETURNS [ROPE] ~ { buf: IO.STREAM ~ IO.ROS[]; Print[a, buf]; RETURN buf.RopeFromROS[]}; FmtScheme: PROC [a: Any] RETURNS [ROPE] ~ { buf: IO.STREAM ~ IO.ROS[]; Print[a, buf !Complain => GOTO Abort]; RETURN buf.RopeFromROS[]; EXITS Abort => RETURN ["(can't print)"]}; FmtInfo: PROC [a: Any] RETURNS [ROPE] ~ { buf: IO.STREAM ~ IO.ROS[]; InfoPrint[buf, a !Complain => GOTO Abort]; RETURN buf.RopeFromROS[]; EXITS Abort => RETURN ["(can't print)"]}; NoteProfile: PROC [reason: UserProfile.ProfileChangeReason] --UserProfile.ProfileChangedProc--~ { defaultMargin ¬ UserProfile.Number["SchemePretty.margin", 80]; defaultHow ¬ [ sia: UserProfile.Number["SchemePretty.sia", 2], simpleLen: UserProfile.Number["SchemePretty.simpleLen", 2], simpleQuote: UserProfile.Boolean["SchemePretty.simpleQuote", TRUE] ]; }; UserProfile.CallWhenProfileChanges[NoteProfile]; Commander.Register[key: "SchemePrettyPrintFile", proc: PrettyPrintFileCmd, doc: "( [ _] | ) *\n = -margin \n| -sia \n| -simplelen \n| -simplequote \n| -debug \n| -debugss \n| -context \n| -plainOut "]; END.