wenzelm@34276: /* Title: Pure/Thy/text_edit.scala wenzelm@34276: Author: Fabian Immler, TU Munich wenzelm@34276: Author: Makarius wenzelm@34276: wenzelm@34276: Basic edits on plain text. wenzelm@34276: */ wenzelm@34276: wenzelm@34276: package isabelle wenzelm@34276: wenzelm@34276: wenzelm@34276: sealed abstract class Text_Edit wenzelm@34276: { wenzelm@34276: val start: Int wenzelm@34286: def after(offset: Int): Int wenzelm@34276: def before(offset: Int): Int wenzelm@34286: def edit(string: String, shift: Int): (Option[Text_Edit], String) wenzelm@34276: } wenzelm@34276: wenzelm@34276: wenzelm@34276: object Text_Edit wenzelm@34276: { wenzelm@34286: /* transform offsets */ wenzelm@34286: wenzelm@34286: private def after_insert(start: Int, text: String, offset: Int): Int = wenzelm@34286: if (start <= offset) offset + text.length wenzelm@34286: else offset wenzelm@34286: wenzelm@34286: private def after_remove(start: Int, text: String, offset: Int): Int = wenzelm@34286: if (start > offset) offset wenzelm@34286: else (offset - text.length) max start wenzelm@34286: wenzelm@34286: wenzelm@34286: /* edit strings */ wenzelm@34286: wenzelm@34286: private def insert(index: Int, text: String, string: String): String = wenzelm@34286: string.substring(0, index) + text + string.substring(index) wenzelm@34286: wenzelm@34286: private def remove(index: Int, count: Int, string: String): String = wenzelm@34286: string.substring(0, index) + string.substring(index + count) wenzelm@34286: wenzelm@34286: wenzelm@34286: /* explicit edits */ wenzelm@34286: wenzelm@34276: case class Insert(start: Int, text: String) extends Text_Edit wenzelm@34276: { wenzelm@34286: def after(offset: Int): Int = after_insert(start, text, offset) wenzelm@34286: def before(offset: Int): Int = after_remove(start, text, offset) wenzelm@34276: wenzelm@34286: def can_edit(string_length: Int, shift: Int): Boolean = wenzelm@34286: shift <= start && start <= shift + string_length wenzelm@34286: wenzelm@34286: def edit(string: String, shift: Int): (Option[Insert], String) = wenzelm@34286: if (can_edit(string.length, shift)) (None, insert(start - shift, text, string)) wenzelm@34286: else (Some(this), string) wenzelm@34276: } wenzelm@34276: wenzelm@34276: case class Remove(start: Int, text: String) extends Text_Edit wenzelm@34276: { wenzelm@34286: def after(offset: Int): Int = after_remove(start, text, offset) wenzelm@34286: def before(offset: Int): Int = after_insert(start, text, offset) wenzelm@34286: wenzelm@34286: def can_edit(string_length: Int, shift: Int): Boolean = wenzelm@34286: shift <= start && start < shift + string_length wenzelm@34276: wenzelm@34286: def edit(string: String, shift: Int): (Option[Remove], String) = wenzelm@34286: if (can_edit(string.length, shift)) { wenzelm@34286: val index = start - shift wenzelm@34286: val count = text.length min (string.length - index) wenzelm@34286: val rest = wenzelm@34286: if (count == text.length) None wenzelm@34286: else Some(Remove(start, text.substring(count))) wenzelm@34286: (rest, remove(index, count, string)) wenzelm@34286: } wenzelm@34286: else (Some(this), string) wenzelm@34276: } wenzelm@34276: } wenzelm@34276: