G'day, all
If one performs a Find & Replace operation on a string to which a Comment is attached, the Comment is removed. How can one save the Comment and then have it attached to the replacement?
Cheers,
Adrian
Preserve Comment When Replacing Text
Preserve Comment When Replacing Text
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
macOS Ventura
Nisus Writer user since 1996
Re: Preserve Comment When Replacing Text
Hi Adrian,
I guess there is a variety of answers to your question.
First, note that F&R will only remove the comment (or comments) if the text where the comment is attached is entirely contained in the find expression. If they only partly overlap, the comment will remain attached to the leftover. If the find expression is a substring of the text where the comment is attached, then the substitution goes through unscathed. (I might be oversimplifying here. There are a lot of cases to consider.)
So one way to preserve the comment is to make sure the selection where the comment is attached does not completely overlap the find expression. That's really the best method.
You can use the macro language to save the text of the comment and then insert it into a new comment, but this will change the meta info on the comment, especially the dates.
So basically any attempt to solve this issue would need to be tailored very specifically to the case at hand. There is no general approach that I can think of.
I guess there is a variety of answers to your question.
First, note that F&R will only remove the comment (or comments) if the text where the comment is attached is entirely contained in the find expression. If they only partly overlap, the comment will remain attached to the leftover. If the find expression is a substring of the text where the comment is attached, then the substitution goes through unscathed. (I might be oversimplifying here. There are a lot of cases to consider.)
So one way to preserve the comment is to make sure the selection where the comment is attached does not completely overlap the find expression. That's really the best method.
You can use the macro language to save the text of the comment and then insert it into a new comment, but this will change the meta info on the comment, especially the dates.
So basically any attempt to solve this issue would need to be tailored very specifically to the case at hand. There is no general approach that I can think of.
philip
Re: Preserve Comment When Replacing Text
G'day, Philip et al
Thanks for that clear explanation of how things work, Philip.
Unfortunately, in my situation the commented string is a substring of the Find expression. In actual fact, the entire Find expression is a grep expression that has a string sandwiched between two (identical) integers (consisting of one or more digits). The Replace expression replaces each occurrence of the integer with another integer (the same in both cases).
Find and Replace '\d+(\t.+\t)\d+', $new_number & '\1' & $new_number, 'E-W'
Comments may sometimes be attached to one or more of the elements of the Find expression. I guess I could avoid attaching them to the integers, but I would like the ability to attach them to one or more words in the sandwiched string and still have them preserved. In line with your explanation, such Comments disappear.
Although the Comments are being used in a collaborative project, I don't think any of the meta info needs to be preserved — just the substance of each Comment.
I looked at the Macro Language, but baulked at figuring out how to construct a conditional that checked for the existence of Comments, saved them (in an array, maybe?), and then reapplied them appropriately after the replacement operation.
Help would, of course, be appreciated.
Cheers,
Adrian
Thanks for that clear explanation of how things work, Philip.
Unfortunately, in my situation the commented string is a substring of the Find expression. In actual fact, the entire Find expression is a grep expression that has a string sandwiched between two (identical) integers (consisting of one or more digits). The Replace expression replaces each occurrence of the integer with another integer (the same in both cases).
Find and Replace '\d+(\t.+\t)\d+', $new_number & '\1' & $new_number, 'E-W'
Comments may sometimes be attached to one or more of the elements of the Find expression. I guess I could avoid attaching them to the integers, but I would like the ability to attach them to one or more words in the sandwiched string and still have them preserved. In line with your explanation, such Comments disappear.
Although the Comments are being used in a collaborative project, I don't think any of the meta info needs to be preserved — just the substance of each Comment.
I looked at the Macro Language, but baulked at figuring out how to construct a conditional that checked for the existence of Comments, saved them (in an array, maybe?), and then reapplied them appropriately after the replacement operation.
Help would, of course, be appreciated.
Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
macOS Ventura
Nisus Writer user since 1996
Re: Preserve Comment When Replacing Text
So the first question is where are the comments and where do they go after the replace. Is that something that can be solved deterministically? (Also is this a one of kind action? How many F&R instances are we talking about?)
So for example if your want to replace the numbers before and after the middle part and the comments are on the middle part then I would suggest not replacing the middle part. That can be done like this:
So basically use find to find the number locations than replace just the numbers without touching the intervening stuff.
So for example if your want to replace the numbers before and after the middle part and the comments are on the middle part then I would suggest not replacing the middle part. That can be done like this:
Code: Select all
$doc = Document.active
$sels = $doc.text.findAll '\d+\t.+\t\d+', 'Ea'
foreach $sel in reversed $sels
$sel.substring.find '(?<num_1>\d+)(\t.+\t)(?<num_2>\d+)', 'E¢'
$num_2_range = Range.new $sel.bound - $num_1.length, $num_1.length
$sel.text.replaceInRange $num_2_range, $new_number
$num_1_range = Range.new $sel.location, $num_1.length
$sel.text.replaceInRange $num_1_range, $new_number
end
philip
Re: Preserve Comment When Replacing Text
The other type of approach is also possible. But I'm not sure if there are any simple ways to find a comment in a specific selection.
The most immediately obvious way to approach this is to use Document.allComments to get an array of all Comment objects then cycle through them to find any that overlap. Then you can extract the comment text, and if you have a suitable text selection range to put them, you can insert the comment back into the document.
The most immediately obvious way to approach this is to use Document.allComments to get an array of all Comment objects then cycle through them to find any that overlap. Then you can extract the comment text, and if you have a suitable text selection range to put them, you can insert the comment back into the document.
philip
Re: Preserve Comment When Replacing Text
G'day, Philip et al
Thanks for all that, Philip. Leave it with me while I study it, and I'll get back to you.
Cheers,
Adrian
Thanks for all that, Philip. Leave it with me while I study it, and I'll get back to you.
Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
macOS Ventura
Nisus Writer user since 1996
Re: Preserve Comment When Replacing Text
G'day, Philip et al
I was able to have a quick look at it just now, and it works!
The description in the second paragraph exactly fits my situation. I can't say I understand the code completely, but I can see that it is operating on the ranges of just the numbers, so that, as you say, Philip, the intervening string is untouched. And any Comments (even multiple overlapping ones) attached to all or part of that string are preserved after the number change.
Hard to say at this stage how many lines will require this operation; could be 30–100, say. And the new number assigned to each such line will actually be part of a sequence. I'd already written a tiny Macro that did this, but it didn't preserve Comments, did it? I'll now try to interweave the two and see what I come up with.
Thanks for your help with this so far, Philip.
Cheers,
Adrian
I was able to have a quick look at it just now, and it works!
The description in the second paragraph exactly fits my situation. I can't say I understand the code completely, but I can see that it is operating on the ranges of just the numbers, so that, as you say, Philip, the intervening string is untouched. And any Comments (even multiple overlapping ones) attached to all or part of that string are preserved after the number change.
Hard to say at this stage how many lines will require this operation; could be 30–100, say. And the new number assigned to each such line will actually be part of a sequence. I'd already written a tiny Macro that did this, but it didn't preserve Comments, did it? I'll now try to interweave the two and see what I come up with.
Thanks for your help with this so far, Philip.
Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
macOS Ventura
Nisus Writer user since 1996
Re: Preserve Comment When Replacing Text
G'day, Philip et al
I'm not quite sure why the loop needed to traverse the found text objects in the reverse order. When I replaced my incrementing $new_number variable with a decrementing one, everything works exactly as I wanted it. Thanks, Philip!
Cheers,
Adrian
I'm not quite sure why the loop needed to traverse the found text objects in the reverse order. When I replaced my incrementing $new_number variable with a decrementing one, everything works exactly as I wanted it. Thanks, Philip!
Code: Select all
$doc = Document.active
$sels = $doc.text.findAll '\d+\t.+\t\d+', 'Ea'
$sels_count = $sels.count
$new_number = $sels_count
foreach $sel in reversed $sels
$sel.substring.find '(?<num_1>\d+)(\t.+\t)(?<num_2>\d+)', 'E¢'
$num_2_range = Range.new $sel.bound - $num_1.length, $num_1.length
$sel.text.replaceInRange $num_2_range, $new_number
$num_1_range = Range.new $sel.location, $num_1.length
$sel.text.replaceInRange $num_1_range, $new_number
$new_number -= 1
end
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
macOS Ventura
Nisus Writer user since 1996
Re: Preserve Comment When Replacing Text
The reason one usually needs to work such things back to front, i.e., in reverse order, is that selection indexes are measured from the beginning of the document. If you replace a 5-digit number with a 4-digit number then all the following selections will be shifted by one. So if you work front to back, you would need to figure for each replacement (1) how much change this causes, and (2) keep track of all preceding changes. Then you would need to adjust the selections by that amount.
Working backwards means you don't have to worry about such issues.
philip
Re: Preserve Comment When Replacing Text
G'day, Philip et al
I was just about to post something pretty much along the same lines. So thanks for confirming that I'm at last starting to come to grips with this business of Ranges.
Cheers,
Adrian
I was just about to post something pretty much along the same lines. So thanks for confirming that I'm at last starting to come to grips with this business of Ranges.
Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
macOS Ventura
Nisus Writer user since 1996