How to match a footnote reference number

Get help using and writing Nisus Writer Pro macros.
Post Reply
allenwatson
Posts: 14
Joined: 2005-10-05 15:05:51
Location: Portland, OR
Contact:

How to match a footnote reference number

Post by allenwatson » 2017-05-29 21:09:21

I have a Powerfind Pro macro that includes code to match all text up to a certain string. This works fine unless there is a footnote reference in the text, at which time the match fails. If I delete the footnote reference (and footnote itself, of course), the match succeeds.

Is there any way to include an optional match for a footnote reference number in an expression like this: "[^\n\f]+"?

User avatar
phspaelti
Posts: 916
Joined: 2007-02-07 00:58:12
Location: Japan

Re: How to match a footnote reference number

Post by phspaelti » 2017-05-29 21:43:49

Hello Allen,
if you are trying to use your expression in a macro, you can do the following:

Code: Select all

Find '[^\n\f]+', 'En'
The "n" option will tell Nisus to match across the footnote marker.
philip

User avatar
phspaelti
Posts: 916
Joined: 2007-02-07 00:58:12
Location: Japan

Re: How to match a footnote reference number

Post by phspaelti » 2017-05-29 21:59:56

The tip above may do what you want, but depending on what you are trying to achieve there may be better methods. For instance Nisus can directly locate what you are looking for and then construct a selection to include the parts you want. For that reason it might be an idea to describe the overall task you are trying to accomplish, that way we could give you tips for features that Nisus has to accomplish those things. On the other you might enjoy more discovering them yourself. :wink:
philip

allenwatson
Posts: 14
Joined: 2005-10-05 15:05:51
Location: Portland, OR
Contact:

Re: How to match a footnote reference number

Post by allenwatson » 2017-05-31 18:17:49

Philip, thanks for the tip. I'll try it out. I don't know if I can describe in full what I'm trying to do; it's complex. An overview: I have a book-length document that is divided as follows:
Chapters<Sections<Paragraphs<Sentences.

The chapters are numbered with Arabic numbers; the sections with Roman numerals; the paragraphs with arabic numbers; and the sentences also with Arabic.A reference to a particular sentence might be like 23.V.3:4.

I'm trying to start with randomly selected text with certain assumptions such as only complete sentences will be selected, and the selection will never include material from more than one section, and automatically construct a reference.

The problem comes in with exceptions. First sentences of paragraphs are NOT preceded with a number; all subsequent sentences are. Likewise, first paragraphs of a section are not numbered. And the text contains numerous footnote references (also numeric), so those need to be ignored when searching for digits. And there are other complications, special cases, that must be taken into account.

I have one simple question right now: How can I determine whether the first character of a selection is a digit or an alphabetic character? A Find within the selection seems to target the first matching character. I don't know how to tell it "Must be at beginning of selection." I know how to do that for beginning of line...Is there a way of extracting a substring from a selection?

User avatar
phspaelti
Posts: 916
Joined: 2007-02-07 00:58:12
Location: Japan

Re: How to match a footnote reference number

Post by phspaelti » 2017-06-01 02:29:44

Hi Allen,
right, so you want to identify, for a given location, the chapter/section/sub-section that you are currently located in. One approach is indeed to just search backward to the nearest heading and report.

The alternative in macro language will be to find all the headings and determine which is the closest (by comparing the locations in a loop).

The latter approach may strike you as excessively complicated, but due to some powerful constructs that Nisus Macro language has you can probably write it in a half-dozen lines. But what I was really driving at was actually the question: "Why are you starting from a given selection?". Is it because you want a macro that the user can trigger at any given moment for just one location, or is it just because you are trying to divide and conquer a bigger task? If the latter, than obviously you could write a macro to do just one case, and then put that in a loop that runs a hundred times, but that would be very inefficient. Instead it would be much better to create a macro that processes hundreds of locations in one go. In that case the macro language approach will be far superior.

Anyhow let me start with your last question, which can serve as an introduction into how the macro language approach works:
allenwatson wrote:How can I determine whether the first character of a selection is a digit or an alphabetic character?
If your current selection is only one paragraph long, you could use Find like this:

Code: Select all

if Find '^\d+', 'Es'
    prompt 'Starts with a digit'
end
By adding the '^' (caret) to the search expression, I am asking it to find only characters at the beginning of the line, and by limiting the search to the selection, I stop Nisus from finding matches outside of the selection. But this approach will probably not quite do what you are looking for. For example it won't work, if the selection does not start at the beginning of a line.

The alternative is to directly ask what the character is at the beginning of the selection. You can do this like this:

Code: Select all

$sel = TextSelection.active
$firstChar = $sel.text.characterAtIndex $sel.location
prompt $firstChar
This will show you the first character, but it will show it as a character value (so "1" will give the result "49"). So if you want to know if it's a digit you will have to check, whether the character value is between 48 and 57 inclusive.
Instead you could get the actual first character as a string and then check to see if it contains any digits. That would look like this:

Code: Select all

$sel = TextSelection.active
$range = Range.new 0,1
$firstChar = $sel.substring.substringInRange $range
if $firstChar.find('\d', 'E')
prompt 'First Character is a digit'
end
This code starts by creating a range object which it uses to "slice out" the first character from the selection. It then runs a Find command on just that sliced out bit.
philip

allenwatson
Posts: 14
Joined: 2005-10-05 15:05:51
Location: Portland, OR
Contact:

Re: How to match a footnote reference number

Post by allenwatson » 2017-06-02 15:05:30

Again, thanks, Philip. You continue to offer me extremely useful and helpful examples.

To explain my needs a bit more clearly: Yes, I am trying to determine the reference for a short section of selected text in a larger document. Think of the Bible. Suppose I did a search on the words, "For God so loved the world," and it matched the text in the Gospel of John. I'd expand the selection to include the verse number, "16," and then run my macro, which would return the result, "John 3:16". In my case I'm searching a similar spiritual document called "A Course in Miracles." It's all one book (the Text portion of this course). I want to copy the selection (which can be anything from a single sentence to half a page) and run a macro that gives me the reference, so I can insert the material in an article I'm writing with the quotation and its reference. So the selection may start at the beginning of a paragraph but most often will not. Since this is for my personal use, I'm stipulating that the selection must start with a sentence number (with an optional leading space); however, the first sentence of each paragraph is not numbered, so there is no number to select! So I need to determine if the first character selected is a digit; if not, I can assume I am located at sentence 1 of a paragraph (unless I've been sloppy in my selecting, but I can live with that).

I think either of your final two code snippets will work for me. This will be very helpful.

I took a couple of days off from working on the macro to let it ferment, but I expect to get back to it tomorrow or Monday.

User avatar
phspaelti
Posts: 916
Joined: 2007-02-07 00:58:12
Location: Japan

Re: How to match a footnote reference number

Post by phspaelti » 2017-06-03 00:20:09

Ok. Then here one more code bit. This is how I would approach your problem.

Assume we have a file with headings that have a style applied called "Heading". The rest of the text is between the headings and has the style "Normal" (or some other name). Now the following code will give you the name of the closest heading preceding the current selection. It will do this without changing the selection.

Code: Select all

$doc = Document.active
$headingStyle = $doc.styleWithName 'Heading'
$headings = $doc.text.findAll $headingStyle
$currentSelection = $doc.textSelection
$lastHeading = @undefined
foreach $heading in $headings
    if $heading.location > $currentSelection.location
        break
    end
    $lastHeading = $heading
end
if Defined $lastHeading
    prompt $lastHeading.substring
end
So if you wanted to apply this to the Bible, you would have a file where all the book names, chapter names, verse numbers, etc. have special styles. Then you can use code like this to query the closest book, chapter, etc. Alternately you can also search for paragraphs that start with a number (instead of searching by style). In that case you change the .findAll command as appropriate. Further details to all of this can be found in the "Macro Language Reference" in the Help menu of Nisus, but you can also just ask here if something is unclear.
philip

Post Reply