How to create a variable for "Any digit"?
How to create a variable for "Any digit"?
I need to find out whether the character that precedes the insertion point is a number or not. In case it's a number, the macro will do some stuff. In case it's not, the macro will do some other stuff. How can I do that?
I tried
$theFoundCharacter = Find @Text<\X>, 'rE'
#$theFoundCharacter = Find "(AnyCharacter)", 're'
Select End
if $theFoundCharacter = ?
…
else
…
end
How can I replace the question mark with something that indicates "Any digit" or that a digit was found?
And another question. Could I also use the instruction Read Selection to build the variable?
Find @Text<\X>, 'rE'
#Find "(AnyCharacter)", 're'
$theFoundCharacter = Read Selection
Select End
if $theFoundCharacter = ?
…
else
…
end
Will the variable $theFoundCharacter have the same value in both cases?
I tried
$theFoundCharacter = Find @Text<\X>, 'rE'
#$theFoundCharacter = Find "(AnyCharacter)", 're'
Select End
if $theFoundCharacter = ?
…
else
…
end
How can I replace the question mark with something that indicates "Any digit" or that a digit was found?
And another question. Could I also use the instruction Read Selection to build the variable?
Find @Text<\X>, 'rE'
#Find "(AnyCharacter)", 're'
$theFoundCharacter = Read Selection
Select End
if $theFoundCharacter = ?
…
else
…
end
Will the variable $theFoundCharacter have the same value in both cases?
Re: How to create a variable for "Any digit"?
This will not give you what you want. The Find command will return the number of find hits, which in this case should always be 1.Þorvarður wrote: ↑2021-03-29 05:50:26 I need to find out whether the character that precedes the insertion point is a number or not. In case it's a number, the macro will do some stuff. In case it's not, the macro will do some other stuff. How can I do that?
I tried
$theFoundCharacter = Find @Text<\X>, 'rE'
This will work, as you could easily check with the following command:
Code: Select all
prompt $theFoundCharacter
philip
Re: How to create a variable for "Any digit"?
Here the first thing to note is that if you want to test a variable you will need to use the double equal sign "==", not just a single one. So you could test whether the found character is the digit '1' (one) like this:
Code: Select all
if $theFoundCharacter == '1'
prompt "You found a one!"
end
Also possible would be to use the the character code value and test whether it is between 30 and 39. But again this is rather ugly.
Since we are in Nisus the better method is to use Find, or actually (macro language) .find, like this:
Code: Select all
if $theFoundCharacter.find('\d','E')
…
else
…
end
Code: Select all
$sel = TextSelection.active
$theFoundCharacterRange = Range.new $sel.location - 1, 1
$theFoundCharacter = $sel.text.substringInRange $theFoundCharacterRange
philip
Re: How to create a variable for "Any digit"?
If you understood all that you can now squeeze the whole logic into one statement like this:
But whether that's recommended is another question
Code: Select all
$sel = TextSelection.active
if $sel.text.substringInRange(Range.new($sel.location - 1, 1)).find('\d','E')
prompt 'digit'
else
prompt 'not a digit'
end
philip
- martin
- Official Nisus Person
- Posts: 5228
- Joined: 2002-07-11 17:14:10
- Location: San Diego, CA
- Contact:
Re: How to create a variable for "Any digit"?
There are many ways to skin this cat I'd probably want to ask myself: how can I leverage the power of regular expressions (regex). Philip already provided a nice solution that lets you use \d to match any digit.
However, I'd prefer to generalize this so your code doesn't have to care about the length of text you want to match, eg: one or more characters. You can instead just search backwards from the current selection location for any regex:
If your macro does this often enough, it's probably worth turning the code chunk into a handy function:
However, I'd prefer to generalize this so your code doesn't have to care about the length of text you want to match, eg: one or more characters. You can instead just search backwards from the current selection location for any regex:
Code: Select all
$selection = TextSelection.active
$searchRange = Range.new(0, $selection.location)
$foundSelection = $selection.text.find('\d+', 'Er', $searchRange)
If $foundSelection && ($foundSelection.bound == $selection.location)
Prompt "Found the digit."
Else
Prompt "Did not find a digit."
End
Code: Select all
Define Command IsSelectionPrecededBy($pattern)
$selection = TextSelection.active
$searchRange = Range.new(0, $selection.location)
$foundSelection = $selection.text.find($pattern, 'Er', $searchRange)
Return $foundSelection && ($foundSelection.bound == $selection.location)
End
If IsSelectionPrecededBy('\d+')
Prompt "Found the digit."
Else
Prompt "Did not find a digit."
End
Re: How to create a variable for "Any digit"?
That's been one of those features that I have been looking for for some time now. Seems it was introduced in NW 3.0 but it slipped by me for some reason.
philip
Re: How to create a variable for "Any digit"?
Hello Philip and Martin,
Thank you both for valuable help. Before I jump in at the deep end, I would first like to address some of Philips corrections and suggestions.
$number = Find @Text<\X>, 'E'
if $number == "1||2||3||4||5||6||7||8||9||0"
prompt "It's a number!!"
end
I found this double pipe only twice in the Macro Language Reference, and there was no mention of OR in connection with the double pipe, or I didn't understand it. I know a single pipe in regex means OR. Where can I learn more about a double pipe and how to use it?
This truly reminds me of Mark Twain's essay The Awful German Language (1880):
"There are ten parts of speech, and they are all troublesome. An average sentence, in a German newspaper, is a sublime and impressive curiosity; it occupies a quarter of a column; it contains all the ten parts of speech — not in regular order, but mixed; it is built mainly of compound words constructed by the writer on the spot, and not to be found in any dictionary — six or seven words compacted into one, without joint or seam — that is, without hyphens; it treats of fourteen or fifteen different subjects, each inclosed in a parenthesis of its own, with here and there extra parentheses which reinclose three or four of the minor parentheses, making pens within pens: finally, all the parentheses and reparentheses are massed together between a couple of king-parentheses, one of which is placed in the first line of the majestic sentence and the other in the middle of the last line of it — after which comes the VERB, and you find out for the first time what the man has been talking about; and after the verb — merely by way of ornament, as far as I can make out — the writer shovels in "haben sind gewesen gehabt haben geworden sein," or words to that effect, and the monument is finished."
Thank you both for valuable help. Before I jump in at the deep end, I would first like to address some of Philips corrections and suggestions.
It seems I had forgotten about that. Thanks for reminding me.
A cardinal sin. I will remember that.if you want to test a variable you will need to use the double equal sign "==", not just a single one.
I tried this, and although a number was found, it doesn't work. What am I doing wrong this time?And you could of course use logical OR (written with a double pipe '||') to test all 10 digits
$number = Find @Text<\X>, 'E'
if $number == "1||2||3||4||5||6||7||8||9||0"
prompt "It's a number!!"
end
I found this double pipe only twice in the Macro Language Reference, and there was no mention of OR in connection with the double pipe, or I didn't understand it. I know a single pipe in regex means OR. Where can I learn more about a double pipe and how to use it?
I'd also like to point out that a more direct way to get the character you want to test is to use the macro language:
$sel = TextSelection.active
$theFoundCharacterRange = Range.new $sel.location - 1, 1
$theFoundCharacter = $sel.text.substringInRange $theFoundCharacterRange
If you understood all that you can now squeeze the whole logic into one statement like this:
$sel = TextSelection.active
if $sel.text.substringInRange(Range.new($sel.location - 1, 1)).find('\d','E')
prompt 'digit'
else
prompt 'not a digit'
end
But whether that's recommended is another question
This truly reminds me of Mark Twain's essay The Awful German Language (1880):
"There are ten parts of speech, and they are all troublesome. An average sentence, in a German newspaper, is a sublime and impressive curiosity; it occupies a quarter of a column; it contains all the ten parts of speech — not in regular order, but mixed; it is built mainly of compound words constructed by the writer on the spot, and not to be found in any dictionary — six or seven words compacted into one, without joint or seam — that is, without hyphens; it treats of fourteen or fifteen different subjects, each inclosed in a parenthesis of its own, with here and there extra parentheses which reinclose three or four of the minor parentheses, making pens within pens: finally, all the parentheses and reparentheses are massed together between a couple of king-parentheses, one of which is placed in the first line of the majestic sentence and the other in the middle of the last line of it — after which comes the VERB, and you find out for the first time what the man has been talking about; and after the verb — merely by way of ornament, as far as I can make out — the writer shovels in "haben sind gewesen gehabt haben geworden sein," or words to that effect, and the monument is finished."
- martin
- Official Nisus Person
- Posts: 5228
- Joined: 2002-07-11 17:14:10
- Location: San Diego, CA
- Contact:
Re: How to create a variable for "Any digit"?
I'm glad you'll get some mileage from this new(ish) feature! Thanks for all you do to share your expertise with everyone here
- martin
- Official Nisus Person
- Posts: 5228
- Joined: 2002-07-11 17:14:10
- Location: San Diego, CA
- Contact:
Re: How to create a variable for "Any digit"?
The double pipe "or" operator is covered only briefly in the Nisus Writer macro language reference. The guide doesn't do a great job explaining how to use the operator. You can use it to combine multiple boolean ("truth") tests. You don't use it inside a string. You use it to join together bits of code like so:
Code: Select all
$number = Prompt Input "Enter a number between 1 and 10"
If ($number < 0) || ($number > 10)
Prompt "Your number ($number) is out of bounds."
End
It's always fun to read something sharp from Twain (I like Ambrose Bierce too). I have German some heritage myself, but I certainly don't take any offense! I do find German compound words to be very practical (especially coming from a programming background which leverages the same technique) but I know they can be unwieldy.This truly reminds me of Mark Twain's essay The Awful German Language (1880):
- martin
- Official Nisus Person
- Posts: 5228
- Joined: 2002-07-11 17:14:10
- Location: San Diego, CA
- Contact:
Re: How to create a variable for "Any digit"?
I think we're a bit beyond this original question now, but I just remembered something related that is very useful. You can use the $ or ¢ find option in Nisus Writer to automatically turn find/regex captures into macro variables. Your code to find, select, and extract the prior character could be:Þorvarður wrote: ↑2021-03-29 05:50:26 I need to find out whether the character that precedes the insertion point is a number or not. In case it's a number, the macro will do some stuff. In case it's not, the macro will do some other stuff. How can I do that?
I tried
$theFoundCharacter = Find @Text<\X>, 'rE'
Code: Select all
If Find @Text{(\X)}, 'rE$'
$theFoundCharacter = $1
Prompt $theFoundCharacter
End
Code: Select all
If Find @Text{(?<theFoundCharacter>\X)}, 'rE$'
Prompt $theFoundCharacter
End
Re: How to create a variable for "Any digit"?
… and with the added wrinkle that you will need to further combine the expressions pairwise with further parentheses.
That's one of my favorites too!
philip
Re: How to create a variable for "Any digit"?
Thanks for explaining the double pipe "or" operator, Martin. Very well explained.
In the text I quoted we find keen linguistic observation and hyperbolic nonsense side by side. ""haben sind gewesen gehabt haben geworden sein," or words to that effect" is an echo of true common closing phrases, but in this form here the phrase is grammatically completely unacceptable, and that's what is funny for those who know German well. It also shows that the writer (Twain) doesn't understand the construction, and falsely interprets it as an ornament. Here I saw a close resemblance between Twain and myself (regarding the macro language. :–)
Twain also makes fun of the German verb syntax; the distance between the auxiliary verb and the main verb can indeed be considerable. Examples can be found where, let's say, a sentence begins on page 5 and you have to turn over to page 6 to know what the author actually intends to say because the verb is at the end–it's the grand finale, so to say. This is the exception though, and such monster sentences can only be found in the written language. But there is a reason that people still keep telling jokes like this one:
A foreign ambassador to Germany visits the German Chancellor Bismarck. Bismarck gives a speech. He speaks loud and is obviously full of emotion. The interpreter remains silent. After five minutes the ambassador whispers to the interpreter: "What's he saying?" The interpreter leans towards the ambassador and whispers back: "I don't know. I'm waiting for the verb."
The Twain text was actually meant for Philip, because this satire is only funny for those who know German very well, and since Philip is a linguist I assumed he knows German. But I may be wrong.It's always fun to read something sharp from Twain […] I have German some heritage myself, but I certainly don't take any offense! I do find German compound words to be very practical
In the text I quoted we find keen linguistic observation and hyperbolic nonsense side by side. ""haben sind gewesen gehabt haben geworden sein," or words to that effect" is an echo of true common closing phrases, but in this form here the phrase is grammatically completely unacceptable, and that's what is funny for those who know German well. It also shows that the writer (Twain) doesn't understand the construction, and falsely interprets it as an ornament. Here I saw a close resemblance between Twain and myself (regarding the macro language. :–)
Twain also makes fun of the German verb syntax; the distance between the auxiliary verb and the main verb can indeed be considerable. Examples can be found where, let's say, a sentence begins on page 5 and you have to turn over to page 6 to know what the author actually intends to say because the verb is at the end–it's the grand finale, so to say. This is the exception though, and such monster sentences can only be found in the written language. But there is a reason that people still keep telling jokes like this one:
A foreign ambassador to Germany visits the German Chancellor Bismarck. Bismarck gives a speech. He speaks loud and is obviously full of emotion. The interpreter remains silent. After five minutes the ambassador whispers to the interpreter: "What's he saying?" The interpreter leans towards the ambassador and whispers back: "I don't know. I'm waiting for the verb."
Last edited by Þorvarður on 2021-03-31 08:42:14, edited 1 time in total.
- martin
- Official Nisus Person
- Posts: 5228
- Joined: 2002-07-11 17:14:10
- Location: San Diego, CA
- Contact:
Re: How to create a variable for "Any digit"?
It's a good joke! I'm reminded of a passage from Sherlock Holmes:Þorvarður wrote: ↑2021-03-30 13:04:47 A foreign ambassador to Germany visits the German Chancellor Bismarck. Bismarck gives a speech. He speaks loud and is obviously full of emotion. The interpreter remains silent. After five minutes the ambassador whispers to the interpreter: "What's he saying?" The interpreter leans towards to the ambassador and whispers back: "I don't know. I'm waiting for the verb."
And the man who wrote the note is a German. Do you note the peculiar construction of the sentence—‘This account of you we have from all quarters received.’ A Frenchman or Russian could not have written that. It is the German who is so uncourteous to his verbs.