NISUS Archives

December 2010

NISUS@LISTSERV.DARTMOUTH.EDU

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Reply To:
Date:
Wed, 29 Dec 2010 23:44:49 +0900
Content-Type:
text/plain
Parts/Attachments:
text/plain (157 lines)
Hello Nobumi,

On Dec 29, 2010, at 9:33 PM, Nobumi Iyanaga wrote:

> Instead of replying to them and asking you more questions, I think I would learn more, if I try to write more macros, and ask you questions about them.

That's a nice strategy ;-)

> Here is another essay: it adds at the beginning of each line (of the main body text) the line number followed by a tab.
> 
> ## add_line_numbers ##
> 
> $doc = Document.active
> 
> $sels = Array.new
> $sels = $doc.text.findAll '^', 'E', '-am'
> 
> $tab = "\t"
> $i = $sels.count
> $num = ''
> foreach $sel in reversed $sels
> 	$loc = $sel.location
> 	$num = "$i$tab"
> 	$num = Cast to string $num
> 	$sel.text.insertAtIndex $loc, $num
> 	$i = $i - 1
> end
> 
> ## end of macro ##
> 
> I tried this macro, because it "translates" somehow the pattern of the most common macros that we used to write for Classic Nisus Writer, that is:
> 1. Find locations of strings matching some pattern with a regex search;
> 2. visit in a loop all the found strings (with "SetSelect" in the Classic Nisus Writer macro), making some change(s) to each one.
> 
> This seems to work as expected. The most convenient thing here is the line:
> $sels = $doc.text.findAll '^', 'E', '-am'
> because it makes in a single line an array of all the "selectedTexts" which can be visited in the following loop. And this is very fast, because, I thing, it works in the variable (this would be the advantage of the "reference semantics"...??).

I think it is fast because findAll command does not create actual (real) selections. On the other hand,

	Find All '^', 'E'

does not work because you cannot create more than a single zero-width selection.


> However, when I tried to modify this macro, so that when there is a selection of several lines (the selection must begin either at the beginning of the body text, or just after a return character...), it would add line numbers only to these lines (from 1 to n...), I am stumbled because of many problems. I tried to write something like this:
> 
> $sel = TextSelection.active
> $sel_range = $sel.range
> $sel_location = $sel_range.location
> $if_slection_at_zero = false
> if $sel.length
> 	if $sel_location == 0
> 		Find All '^(.|\n)', 'Es', '-am'
> 		$sels = $doc.textSelections
> #		exit $sels.count
> 		$if_slection_at_zero = true
> 	else
> 		$previous_char = $the_text.characterAtIndex ($sel_location - 1)
> 		if $previous_char == 10
> 			Find All '^', 'Es', '-am'
> 			$sels = $doc.textSelections
> #			exit $sels.count
> 		else
> 			exit 'The selection should be done on whole lines...'
> 		end
> 	end
> else
> ...
> 
> My main problem is that the value of "$sels.count" cannot be what I expect (for example, when I select two or more lines in the middle of the document, the value of "$sels.count" is 1, instead of 2 or more...).

There is another problem. Find All '^(.|\n)', 'Es', '-am' will select two or more consecutive '^\n' (empty paragraphs) as a single selection. Probably you could solve this problem by calculating the length of selections but that would make the macro complicated.

Then, you can use containsSelection command to know which paragraph starts got by
	
	$doc.text.findAll '^', 'E', '-am'

are contained in selections you made. Something like this...

### begin macro ###

$doc = Document.active
$sels = $doc.textSelections

if ! $sels.firstValue.length  # i.e. $sels[0].length
	exit 'There is no visible selection, exiting...'
end

$paraStarts = $doc.text.findAll '^', 'E', '-am'

foreach $i, $start in reversed $paraStarts
	$contained = false
	foreach $sel in $sels
		if $sel.containsSelection $start
			$contained = true
			break  # you don't need testing the remaining values of $sels
		end
	end
	# if $contained remains false after testing $start against all values of $sels
	if $contained == false
		$paraStarts.removeValueAtIndex $i
	end
end

if ! $paraStarts.count
	exit 'No paragraph start in selection(s), exit...'
end

$tab = Cast to String "\t"
foreach $i, $start in reversed $paraStarts
	$num = $i + 1  # $i: index number
	$num &= $tab
	$start.text.insertAtIndex $start.location, $num
end

### end macro ###


As you see this is a question of how to do find (or replace) in selection without creating an actual selection. Another idea is to examine subtexts of the selections.


### begin macro ###

$doc = Document.active
$sels = $doc.textSelections

if ! $sels.firstValue.length  # i.e. $sels[0].length
	exit 'There is no visible selection, exiting...'
end

$paraStarts = Array.new
foreach $sel in $sels
	$founds = $sel.subtext.findAll '^', 'E'  # "where" argument does not work for subtext
	foreach $found in $founds
		if $found.text.documentContentType == 'body'  # it may be, for example, a table cell
			$range = Range.new $found.location + $sel.location, 0
			$start = TextSelection.new $sel.text, $range
			$paraStarts.appendValue $start
		end
	end
end

# the rest is the same

$tab = Cast to String "\t"
foreach $i, $start in reversed $paraStarts
	$num = $i + 1  # $i: index number
	$num &= $tab
	$start.text.insertAtIndex $start.location, $num
end

### end macro ###


Kino

ATOM RSS1 RSS2