A macro to do macros

Get help using and writing Nisus Writer Pro macros.
Post Reply
Pat
Posts: 28
Joined: 2009-09-04 13:11:25

A macro to do macros

Post by Pat »

Hi,
I use the macroize function a lot. I would like to have a macro that would individually macroize all the different words in a text selection. I would like to be able to produce series of "find and replace macros" in just one click. Is that possible?
Thank you,

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

Re: A macro to do macros

Post by phspaelti »

Hello Pat,
what you want is not really too difficult, but the way you state your request is still underspecified. Here first a hint at how one can make such a macro. You can do it using the macroize function :o
  1. Open the Find box, switch to Powerfind
  2. Write "hello" in the find box and "bye" in the replace box
  3. Use macroize: Select "Replace all" and "Copy to Clipboard"
  4. Paste the result in the replace box
  5. Now change the "hello" in the find box to the [AnyWord] wildcard
  6. Replace the "hello" in the middle of the expression in the replace box with [Found] from the match menu
  7. Use macroize on this result, and save as a macro
The resulting macro will look something like this (here in PowerfindPro for portability):

Code: Select all

Find and Replace '(?:\b\w+\b)', 'Find and Replace \'\0\', \'bye\', \'ea\'\n', 'Esa'
This macro will change your selection into a series of Find and Replace statements one for each word. The replacement will however be "bye" for all of them. So this is not a very useful macro. And that is the rub. How do you want to determine what should replace what ? What are you trying to achieve?
Depending on your answers one might be able to tweak the above to something useful, or perhaps try a completely different approach…
philip
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: A macro to do macros

Post by martin »

Like Philip, I'm not sure what you're trying to achieve Pat. Perhaps you could give us an example?
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: A macro to do macros

Post by phspaelti »

After yesterday's macro writing lesson here a different approach. The following macro will create a "Find and Replace" macro for each word in the selection. It isn't really "one click" though. The user will be prompted to give a replacement for each unique word in the selection. So don't try it on your just finished book, or you'll be spending a couple hours answering prompts :) (Well ok. You can always use the "stop macro" button.)

Code: Select all

# Macroize all
# This macro “macroizes” all words in the current selection(s).
# It asks the user to provide a replacement for each word
# and saves the pair as a find/replace macro in the macro subfolder “Macroized”
#
$doc = Document.active
$sels = $doc.textSelections
$found = Find All '(?:\b\w+\b)', 'Esa'
if ! $found
exit
end
$words = $doc.selectedSubstrings
$doc.setSelections $sels
$findReplacePairs = Hash.new
$macroFolderPath = User Property “macros folder path”
$macroFolderPath &= “/Macroized/”
foreach $word in $words
if $findReplacePairs.definesKey $word
else
$find = $word
$replace = prompt Input ‘Macroize’, “Replace \‘$find\’ with …”, ‘Macroize’, $find 
if $replace != $find
$findReplacePairs{$find} = $replace
$macro = “Find and Replace \’$find\’, \’$replace\’, \’aw\’”
$macroName = “Find \‘$find\’ and Replace with \‘$replace\’.nwm”
$macroPath = $macroFolderPath & $macroName
File.writeDataToPath $macro, $macroPath
end
end
end
Refresh Macro Menu
philip
Pat
Posts: 28
Joined: 2009-09-04 13:11:25

Re: A macro to do macros

Post by Pat »

Hi,

Thank you for these examples. But, that is not what I'm looking for. Let me explain.


I'm learning a new language. I give certain attributes to words to indicate their gender. (So when I read a text, I don't have to ask myself, if a word is feminine or masculine.) Then I macroize those words so I don't have to do it again. But Macroizing each word takes too much time. Especially in the beginning when you don't know many words. So I want a macro to do all the work in one clic after I am done with a text. The macro should also be able to skip words that already have a macro. Is this possible?

Also. I've so many macros already. I wonder if there is a limit to the number of macros of this type that Nisus can manage...
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: A macro to do macros

Post by phspaelti »

Hello Pat,
well it helps to know what you are trying to achieve. Here are some comments:

You ask whether there is a limit to the number of macros that Nisus can load. Martin probably should answer that question, but I am pretty sure that the only limit is the amount of memory your computer has. However if you really have thousands of macros it might affect start-up time of Nisus, so that's a really wasteful approach. Also the macro menu would be so long you wouldn't find anything any more. :o

But macroizing single words is a bad approach for another reason. As the number of words grows each macro will be less and less applicable. Linguistically speaking the frequency of most words is 0, so you will have to run a lot of macros that do nothing!

The approach you really want is to create a word list, or two in your case: one for feminine words and another for masculine words. It is very easy to create a word list with Nisus. Here is the basic approach:

First you say you use "attributes" for the different types of words. I would suggest you use Character Styles. The styles can have any attributes at all, including possibly no attributes.
Assuming you have a character style "feminine", you can use "Select All Style" from the character style menu to select all the feminine words in your document. Copy and Paste the selected words into a new document. Sort the words and eliminate the doubles. This can easily be made into a macro.

Then, once you have such a list, you need a macro that checks any given file and selects all the words in the file against the word list and selects all occurrences of those words. Here is a macro that does that. This macro works with a word list called "wordlist.rtf" located in the "Nisus Documents" folder. Obviously the name and path would need to be adapted to the situation. But here is the macro:

Code: Select all

# Macro Find All Words in List
# remember the active document
$doc = Document.active

# Locate and open the word list document
# Adjust the file path as appropriate
$wordListPath = ‘~/Documents/Nisus Documents/wordlist.rtf’
$wordListAvailable = File.existsAtPath $wordListPath
if $wordListAvailable
	$wordListFile = Document.open $wordListPath, FALSE
else
	prompt ‘Can\’t find the word list file.’
	exit
end
# retrieve the word list from the word list document
$wordList = Array.new
$foundWords = $wordListFile.text.findAll '(?:\b\w+\b)', 'Ea'
foreach $foundWord in $foundWords
	$word = $wordListFile.text.substringInRange $foundWord.range
	$wordList.push $word
end
# close the word list document [Doesn’t seem to work :-( ]
$wordListFile.close

# Find all the words in the document and
# select those that are in the word list.
Document.setActive $doc
$text = $doc.text
$words = $text.findAll '(?:\b\w+\b)', 'Ea'
$foundWords = Array.new
ForEach $word in $words
	$wordString = $text.substringInRange $word.range
	if $wordList.containsValue $wordString
		$foundWords.push $word
	End
End
$doc.setSelections $foundWords
Finally one could also easily combine the list making/and finding in another file into a single macro as well, to make a "one click solution" as you desire. Before doing that it might be a good idea to decide how specific one wants to make it. For instance you could write the macro to open all the word lists for the different genders in sequence and then looking for the words and applying the character style. In that case the macro would need to know the names for all the files and the styles.
philip
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: A macro to do macros

Post by martin »

phspaelti wrote:You ask whether there is a limit to the number of macros that Nisus can load. Martin probably should answer that question, but I am pretty sure that the only limit is the amount of memory your computer has. However if you really have thousands of macros it might affect start-up time of Nisus, so that's a really wasteful approach. Also the macro menu would be so long you wouldn't find anything any more. :o
Philip is correct, there's no hard limit on the number of macros. And his other point is more pertinent: you'll run out of menu space (and patience) before you exhaust your RAM. It's a much better idea to build a single macro that deals with loading/marking these words in batches.
# close the word list document [Doesn’t seem to work :-( ]
$wordListFile.close
This looks like a bug. It's triggered by passing false to the open document command earlier. If you pass true (to show the document) then the close command does its job. However, rather than using files, you might use the Registry object to store the two word arrays. The code will likely be simpler.
Pat
Posts: 28
Joined: 2009-09-04 13:11:25

Re: A macro to do macros

Post by Pat »

Thanks again for these new solutions.

But I think I would like to put all my data into some kind of database. This database could store all the attributes and the definition of each word. And I would like to be able to use this database to analyze new texts.

Is this possible? What should I use to do this?
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: A macro to do macros

Post by phspaelti »

Hello again,
I'm not really sure what you are aiming for now. This "database" do you want to do this in Nisus? (Not that Nisus can't do it. You could probably write a C-compiler in the Nisus macro language. It just wouldn't be a good idea :lol: )
So I am going to return here one more time to the previous idea. I am providing here a folder with several macros, but mainly two. Under this approach the words are stored in a "database". For the attributes I chose character styles. You can apply as many character styles as you want. Each character style defines a set, and the words in that set are entered together into the database. One macro adds words to the database, and the other is used to apply the character styles to further instances of those words in your files. A slightly more elaborate explanation is provided in a "help" file.
But for the relevant example. Start with a file. Define two character styles "masculine" and "feminine". Apply the styles to some words. Run the first macro. This will enter those words in the database. Run the second macro this will look for further instances of those words and apply the style. Keep alternating between tagging and running the macros, and gradually the database will grow to include lots of words stored as "masculine" or "feminine" respectively.
Attachments
Database.zip
(19.34 KiB) Downloaded 723 times
philip
Pat
Posts: 28
Joined: 2009-09-04 13:11:25

Re: A macro to do macros

Post by Pat »

Thank you very much. I'm very grateful. I will read this and do my best to understand. What is my goal? I didn't ask myself that question seriously up to now. My poor knowledge in programming certainly limits my ambitions... and learning to speak the language I'm studying is already difficult. I will try the new macros and I will come back here as soon as I'm able to make them work...
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: A macro to do macros

Post by phspaelti »

Hello Pat
here is one more version of a macro. This one is actually considerably simpler. This one works as follows:
Assuming you have a file named "database.rtf" which contains individually formatted words, the macro will look for all instances of those words in the current file and apply the same formatting to those words. (NB: One could easily change the source of the formatted words to something else. I just used that because it was the quickest thing for me to try out. However one could also have the source file come from some other program, such as Filemaker, etc.)

Here is the code:

Code: Select all

$doc = Document.active
$dbPath = ‘~/Documents/Nisus Documents/database.rtf’
$dbAvailable = File.existsAtPath $dbPath
if $dbAvailable
	$dbDoc = Document.open $dbPath
else
	prompt ‘Can\’t find the corpus file.’
	exit
end
Find All ‘\b[[:alpha:]]+\b’, ‘E’
$words = $dbDoc.selectedSubtexts
$doc.show
foreach $word in $words
	Find and Replace $word, $word, 'a-uU'
end
In fact as you can see, assuming the formatted words are in an array called $words, then the actual macro is as simple as this:

Code: Select all

foreach $word in $words
	Find and Replace $word, $word, 'a-uU'
end
This it turns out is the "one click macro" that you had been asking about in the first place. :)
philip
Pat
Posts: 28
Joined: 2009-09-04 13:11:25

Re: A macro to do macros

Post by Pat »

Bingo. That's exactly what I wanted. Thank you. I changed 'a-uU' for 'EawUm' and it works perfectly well.
Post Reply