<<>> <> <> <> <> <> <<>> DIRECTORY Rope, TextFind, TextReplace; TextReplaceImpl: CEDAR PROGRAM IMPORTS Rope, TextFind EXPORTS TextReplace = { OPEN TextReplace; <> <<>> <> Apply: PUBLIC PROC [s: RopeMap, r: ROPE] RETURNS [mapped: ROPE] = {mapped ¬ s.Map[s.data, r]}; id: PUBLIC RopeMap ¬ NEW [RopeMapRep ¬ [Id, NIL]]; Id: PROC [data: REF ANY, name: ROPE] RETURNS [value: ROPE] = {value ¬ name}; addBrackets: PUBLIC RopeMap ¬ NEW [RopeMapRep ¬ [AddBrackets, NIL]]; AddBrackets: PROC [data: REF ANY, name: ROPE] RETURNS [value: ROPE] = {value ¬ Rope.Cat["<", name, ">"]}; Constant: PUBLIC PROC [result: ROPE] RETURNS [rm: RopeMap] = { rm ¬ NEW [RopeMapRep ¬ [MapToConstant, result]]; }; MapToConstant: PROC [data: REF ANY, arg: ROPE] RETURNS [result: ROPE] = { constant: ROPE = NARROW[data]; result ¬ constant; }; Catted: TYPE = REF CattedRep; CattedRep: TYPE = RECORD [first, second: RopeMap]; Cat: PUBLIC PROC [first, second: RopeMap] RETURNS [catted: RopeMap] = { catted ¬ NEW [RopeMapRep ¬ [ MapCatted, NEW [CattedRep ¬ [first, second]] ]]; }; MapCatted: PROC [data: REF ANY, name: ROPE] RETURNS [value: ROPE] = { c: Catted ¬ NARROW[data]; mid: ROPE ¬ c.first.Map[c.first.data, name]; value ¬ c.second.Map[c.second.data, mid]; }; Layered: TYPE = REF LayeredRep; LayeredRep: TYPE = RECORD [first, later: RopeMap]; Layer: PUBLIC PROC [first, later: RopeMap] RETURNS [layered: RopeMap] = { layered ¬ NEW [RopeMapRep ¬ [ MapLayered, NEW [LayeredRep ¬ [first, later]] ]]; }; MapLayered: PROC [data: REF ANY, name: ROPE] RETURNS [value: ROPE] = { l: Layered ¬ NARROW[data]; value ¬ l.first.Map[l.first.data, name]; IF value = NIL THEN value ¬ l.later.Map[l.later.data, name]; }; ProcessedPairList: TYPE = LIST OF ProcessedPair; ProcessedPair: TYPE = RECORD [ target: TextFind.Target, case: BOOL, word: BOOL, replace: ROPE, pattern: BOOL ]; RopeMapFromPairs: PUBLIC PROC [pl: PairList] RETURNS [s: RopeMap] = { ppl: ProcessedPairList ¬ Process[pl]; s ¬ NEW [RopeMapRep ¬ [MapPairs, ppl]]; }; Process: PROC [pl: PairList] RETURNS [ppl: ProcessedPairList] = { IF pl = NIL THEN RETURN [NIL]; ppl ¬ CONS[ [ target: TextFind.TargetFromRope[rope: pl.first.match, pattern: NOT pl.first.literal], case: NOT pl.first.ignoreCase, word: pl.first.word, replace: pl.first.replace, pattern: NOT pl.first.literal ], Process[pl.rest]]; }; MapPairs: PROC [data: REF ANY, name: ROPE] RETURNS [value: ROPE] = { value ¬ name; FOR ppl: ProcessedPairList ¬ NARROW[data], ppl.rest WHILE ppl # NIL DO pp: ProcessedPair ~ ppl.first; start: INT ¬ 0; DO found: BOOL; selStart, selEnd: INT; subs: TextFind.Subs; [found: found, selStart: selStart, selEnd: selEnd, subs: subs] ¬ TextFind.RopeSearch[ direction: forward, target: pp.target, rope: value, start: start, case: pp.case, word: pp.word]; IF found THEN { rem: INT ~ Rope.Length[value]-selEnd; value ¬ TextFind.RopeReplace[rope: value, start: selStart, len: selEnd-selStart, with: pp.replace, pattern: pp.pattern, subs: subs]; start ¬ Rope.Length[value]-rem; } ELSE EXIT; ENDLOOP; ENDLOOP; }; }.