136 |
136 |
137 /* phase 2: recover command spans */ |
137 /* phase 2: recover command spans */ |
138 |
138 |
139 @tailrec def recover_spans(commands: Linear_Set[Command]): Linear_Set[Command] = |
139 @tailrec def recover_spans(commands: Linear_Set[Command]): Linear_Set[Command] = |
140 { |
140 { |
141 commands.iterator.find(_.is_unparsed) match { |
141 commands.iterator.find(cmd => !cmd.is_defined) match { |
142 case Some(first_unparsed) => |
142 case Some(first_unparsed) => |
143 val first = |
143 val first = |
144 commands.reverse_iterator(first_unparsed). |
144 commands.reverse_iterator(first_unparsed). |
145 dropWhile(_.newlines == 0).find(_.is_command) getOrElse commands.head |
145 dropWhile(_.newlines == 0).find(_.is_command) getOrElse commands.head |
146 val last = |
146 val last = |
166 val new_commands = |
166 val new_commands = |
167 commands.delete_between(before_edit, after_edit).append_after(before_edit, inserted) |
167 commands.delete_between(before_edit, after_edit).append_after(before_edit, inserted) |
168 recover_spans(new_commands) |
168 recover_spans(new_commands) |
169 |
169 |
170 case None => commands |
170 case None => commands |
|
171 } |
|
172 } |
|
173 |
|
174 |
|
175 /* command perspective */ |
|
176 |
|
177 def command_perspective(node: Document.Node, perspective: Text.Perspective) |
|
178 : Command.Perspective = |
|
179 { |
|
180 if (perspective.isEmpty) Nil |
|
181 else { |
|
182 val result = new mutable.ListBuffer[Command] |
|
183 @tailrec |
|
184 def check_ranges(ranges: List[Text.Range], commands: Stream[(Command, Text.Offset)]) |
|
185 { |
|
186 (ranges, commands) match { |
|
187 case (range :: more_ranges, (command, offset) #:: more_commands) => |
|
188 val command_range = command.range + offset |
|
189 range compare command_range match { |
|
190 case -1 => check_ranges(more_ranges, commands) |
|
191 case 0 => |
|
192 result += command |
|
193 check_ranges(ranges, more_commands) |
|
194 case 1 => check_ranges(ranges, more_commands) |
|
195 } |
|
196 case _ => |
|
197 } |
|
198 } |
|
199 val perspective_range = Text.Range(perspective.head.start, perspective.last.stop) |
|
200 check_ranges(perspective, node.command_range(perspective_range).toStream) |
|
201 result.toList |
171 } |
202 } |
172 } |
203 } |
173 |
204 |
174 |
205 |
175 /* resulting document edits */ |
206 /* resulting document edits */ |
208 } |
239 } |
209 if (update_header) { |
240 if (update_header) { |
210 doc_edits += (name -> Document.Node.Header(header)) |
241 doc_edits += (name -> Document.Node.Header(header)) |
211 nodes += (name -> node.copy(header = header)) |
242 nodes += (name -> node.copy(header = header)) |
212 } |
243 } |
|
244 |
|
245 case (name, Document.Node.Perspective(text_perspective)) => |
|
246 val node = nodes(name) |
|
247 val perspective = command_perspective(node, text_perspective) |
|
248 if (!Command.equal_perspective(node.perspective, perspective)) { |
|
249 doc_edits += (name -> Document.Node.Perspective(perspective)) |
|
250 nodes += (name -> node.copy(perspective = perspective)) |
|
251 } |
213 } |
252 } |
214 (doc_edits.toList, Document.Version(Document.new_id(), nodes)) |
253 (doc_edits.toList, Document.Version(Document.new_id(), nodes)) |
215 } |
254 } |
216 } |
255 } |
217 } |
256 } |