0

Background

I am writing a syntax marker kind of tool in swift. I parse the text, then save the marking info, I call it a Mark (a name as a String with a range as a Range<String.Index>). I choose the Range<String.Index> over NSRange for future proof the interface.

Problem

In order to support on the fly parsing, I need to be able to manipulate the range. E.g. the text has been edited in a text view, instead of re-parse the whole text, I want to only parse the edited chunk for performance gain. The problem is how do I shift the Marks after the edited range? Since they are never changed, the only thing that changes are the ranges.

I've tried the index function like this:

let newStartIndex = string.index(oldStartIndex, offsetBy: changeInLength)

But the problem with that is that the oldStartIndex is very possible to be out of bound of the new string. Then it will throw a fatal error. Even if I kept a copy of the old text and use that to do the index offset, I think the old index within the modified string might not necessarily maintain it's integrity.

With NSRange, things are much simpler, just shift the location property. But the key here is to future proof the interface by using Range<String.Index>.

dawnstar
  • 507
  • 5
  • 10
  • It sounds like what you want is more along the lines of a tree structure rather than a linear structure. Maybe something similar to a [parse tree](https://en.wikipedia.org/wiki/Parse_tree)? What kind of syntax marking are you doing? –  Jun 28 '17 at 01:51
  • just manipulate your ranges in reverse order – Leo Dabus Jun 28 '17 at 01:58
  • @ColGraff [org-mode](http://orgmode.org) syntax. It's not a programming language, but it can get pretty complex. Part of it needs to be a tree structure but it can still be flatten out in a bigger scope. It doesn't matter, the point is to shift `Range`. – dawnstar Jun 28 '17 at 03:34
  • @LeoDabus can you be more specific? An example would be nice. – dawnstar Jun 28 '17 at 03:35
  • If you would like to execute multiple replace/remove using your ranges just iterate from the least occurrence (range) to the first. If you have an array with your string ranges `for range in ranges.reversed() {` you can remove all your string subranges without any issue. – Leo Dabus Jun 28 '17 at 03:53
  • @LeoDabus but I don't want to remove them, I want to adjust(shift) them. E.g., I have 3 marks, their ranges are: `0..<3`, `3..<6`, `6..<9`, now I deleted 1 char at index 4. the range needs to be `0..<3`, `3..<5`, `5..<8`. – dawnstar Jun 28 '17 at 03:59
  • Does it matter? Whatever you do do it starting at the end – Leo Dabus Jun 28 '17 at 04:00
  • @LeoDabus Now the problem is how do I shift `6..<9` to `5..<8`. of course the integer in the example is just for illustration purpose, `String.Index` is not a integer. – dawnstar Jun 28 '17 at 04:06
  • you can use index offsetBy to the start and end indexes (lower and upper) and form a new range with it – Leo Dabus Jun 28 '17 at 04:08
  • if you need some code example on how to use index offsetBy https://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language/38215613#38215613 and if you need to get your string ranges https://stackoverflow.com/a/32306142/2303865 – Leo Dabus Jun 28 '17 at 04:10
  • @LeoDabus I've tried it, to shift the upper of 6..<9, you do string.index(`9`, offsetBy: -1), but your string.characters.count == 8, so `9` is an invalid index. Which is exactly the problem I described in the question. – dawnstar Jun 28 '17 at 04:22
  • Post your code (minimum verifiable example) – Leo Dabus Jun 28 '17 at 04:40

0 Answers0