Extend Line to Right Line Indent

Get help using and writing Nisus Writer Pro macros.
Post Reply
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Extend Line to Right Line Indent

Post by adryan »

G'day, all

I sometimes want to interrupt the flow of text in a document by inserting a new Section with different properties. But I want the text succeeding the Section to continue the flow of the text preceding the Section. Problems arise when the new Section splits an indented paragraph into two parts.

The first problem is that fully justified text may not extend to the Right Line Indent (assuming left-to-right direction) in the line immediately preceding the new Section. This is because NWP treats that line as the last line of a paragraph.

The second problem is that the first line immediately following the new Section is indented. This is because NWP treats that line as the first line of a paragraph.

The second problem is easily remedied by adjusting the Ruler. But the first problem requires adjustment of kerning where spaces occur in the unsightly line (unless someone can think of a better solution).

Adjusting the kerning is not difficult, but it's tedious to increase it little by little until text jumps to the next page and you know the previous value is the one you need. So I'm wondering whether someone could come up with a Macro that expedites the process. I think it's difficult for the Macro Language to process text linewise, so it may be necessary for the user to select the entire line in question before invoking the Macro, rather than the Macro start by finding all text in the line containing the cursor. But that's OK. I envisage the Macro looping through kern increase until the number of pages in the document increases, then settling on the previous kern value, so that no additional pages are added and everything looks the way it should.

Thanks for any help with this.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Extend Line to Right Line Indent

Post by phspaelti »

adryan wrote: 2022-12-15 15:34:24 I think it's difficult for the Macro Language to process text linewise, so it may be necessary for the user to select the entire line in question before invoking the Macro, rather than the Macro start by finding all text in the line containing the cursor. But that's OK.
Selecting the (layout) line is a feature provided by the macro language:

Code: Select all

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel
Using that you can achieve what you are trying to do like this:

Code: Select all

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$loc = $range.location
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel
$newRange = $range
while $newRange == $range
   Kern:Loosen
   $newRange = $doc.text.rangeOfLineAtIndex $loc
end
Kern:Tighten
But I'm not sure the effect is quite what you really want. The end result will still not look like a justified line.
philip
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Extend Line to Right Line Indent

Post by phspaelti »

This is still not great, but it might be a bit better:

Code: Select all

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$loc = $range.location
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel
$newRange = $range
$kern = 0.0
while $newRange == $range
   Set Kerning $kern
   $newRange = $doc.text.rangeOfLineAtIndex $loc
   $kern += 0.05
end
$kern -= 0.1
Set Kerning $kern
philip
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Extend Line to Right Line Indent

Post by phspaelti »

Instead of using kerning, how about a different kludge; add a dummy phrase at the end of the line and color it white. Of course this kludge depends on. you having the extra space for the line with the dummy.
philip
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, Philip et al

That was quick! Thanks, Philip.

Yes, the second version is better and looks like it does what I want. However, if the line ends on a period, the period may not end up at the Right Line Indent.

Your "different kludge" wouldn't work here because, if I understand it correctly, it would still leave the appearance of trailing blank space at the end of the line. So I think you're very close with your second kerning Macro.

BTW, I liked your simple Tighten command at the end, rather than use the specific value from the iterative procedure.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, Philip et al

I've had a bit of a closer look at this.

It is immaterial whether the line ends with a period or not. The discrepancy just happened to show in a line I had that ended with a period.

The reason we can still end up with a bit of white space at the end of a line is that progressive kern loosening makes the terminal character move progressively rightwards, reducing the amount of trailing white space as it does so. However, just before line wrap enforcement, there may still be more white space than we'd like, but NWP then just reverts to its default behavior in regarding the line as the last one in a paragraph and so the white space remains. (Obviously, you know this, Philip: I'm just explaining the situation for others who may be following the discussion.)

One way around this would be to set the first and last characters of the line at the left and right line indents respectively, and then interpolate the kern loosening throughout the line. But I'm not sure whether such indent positioning for a single line is possible. And a Macro wouldn’t know when things were too squished for comfort.

I notice, too, that Philip's Macro adjusts the kerning between every character in the line, whereas I had thought it should only be done where spaces occurred. My rationale was twofold; viz, it would be more akin to how text justification seems to work, and reducing the number of affected points allows for more fine-grained control on each iteration of the loop.

If the indent positioning idea cannot be implemented, it may be that kerning adjustment (whether characterwise or spacewise) on the final iteration needs to be non-uniform, affecting a proper subset of possible arguments. This is what one would have to end up doing manually anyway, in order to achieve the desired appearance (ie, extension to the indent). But it would be nice to have it all taken care of by a Macro, if that were possible.

I'd be interested to get your thoughts on this, Philip.

Oh, and thanks for that snippet of code that allows one to select a whole line. I've filed it away as a separate Macro for future reference.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G’day, all

Maybe a better approach would be to find the amount of trailing white space (in points, presumably) and then distribute that among appropriate locations (eg, spaces) in the line. Differential adjustments may need to be made, but the discrepancies may not be obvious to the reader.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, all

Pursuing the idea in my previous posting, I see that the Macro Language contains a .tailIndent Attribute and a Set Tail Indent command.

It may be that one could use the former to retrieve the current setting of the Right Line Indent and the latter to progressively shift it leftwards until text wrap occurs. This would allow calculation of the width (in points) of the trailing white space. Kern loosening could then be applied progressively to the spaces until the total kerning width equals the width of the trailing white space — possibly with the refinement to exempt one or more spaces from loosening in the final iteration.

Anyway, that's a suggested method, but I'm afraid implementation is beyond my pay grade.

I really think this is a worthwhile project (howsoever it's implemented). I've faced this situation on a number of occasions now, and it's so finicky adjusting the appearance of the text manually. It would be great if it could be accomplished with a Macro, or even via a paragraph formatting setting in the application itself.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, all

A different approach!

The problem lies with overinclusive kerning. Rather than adjusting the kerning at multiple locations at once, we need to do it one location at a time. Loosen the kerning at the first space in the line; if that's not enough, leave it loosened there and loosen also at the next space. Work your way along the line until you've either loosened sufficiently or you've reached the last space. If you still haven't reached the Right Line Indent, return to the first space in the line and loosen the kerning there a bit more, and so on. That should do what we want. If the loosen increment is sufficiently small, any discrepancy in the appearance of the spaces (due to some being loosened more than others) should be minimal and acceptable.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Extend Line to Right Line Indent

Post by phspaelti »

Code: Select all

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$start = $range.location
$end = $range.bound - 1
$sel = TextSelection.new $doc.text, $range
$spaceSels = $sel.text.find '. +.', 'Ea', $sel.range
$kern = 0.05
$i = 0
while $doc.text.lineNumberAtIndex($start) == $doc.text.lineNumberAtIndex($end)
   $doc.setSelection $spaceSels[$i]
   Set Kerning $kern
   $i += 1
   if $i >= $spaceSels.count
      $i = 0
      $kern += 0.05
   end
end
Kern:Tighten
philip
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, Philip et al

I tried to implement this idea, but I couldn't get the syntax to work for me, so I’m grateful for your latest contribution, Philip.

It seems to work except for one small problem. In addition to loosening the kerning at spaces, it loosens the kerning between the first and second characters of each word in the line apart from the first word. I'm not sure, but it may be that the first command in the while loop needs adjusting somehow.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, Philip et al

No, the problem lies in the definition of $spaceSels. It should just find each space, without the characters either side of it.

Code: Select all

$spaceSels = $sel.text.find ' ', 'Ea', $sel.range
Then it works!

I can see why you might have wanted to find those adjacent characters, Philip, but I make sure there are no redundant spaces and I delete the trailing space at the end of the line before altering the kerning. For more general usage by other people, the Macro could perhaps attend to these housekeeping tasks before searching just for spaces and then doing the loosening.

Thanks for your help with this, Philip. It's going to be very useful for me.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, Philip et al

Here's my version of Philip's Macro.

Code: Select all

#NisusMacroProperty Name: Extend Line to Right Line Indent
# Code mostly thanks to Philip Spaelti.

# Select the line containing the insertion point.

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel

# Delete any trailing spaces.

Find and Replace " +(?!.)", "", 'Esa'

# Select the entire line again.

$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel

# Delete any redundant spaces.

Find and Replace " +", " ", 'Esa'

# Select the entire line again.

$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$start = $range.location
$end = $range.bound - 1
$sel = TextSelection.new $doc.text, $range

# Starting at the beginning of the line and working from left to right, loosen kerning at each space in the line until the line extends to the Right Line Indent.
# Repeat this procedure as often as necessary.

$spaceSels = $sel.text.find ' ', 'Ea', $sel.range
$kern = 0.05
$i = 0
while $doc.text.lineNumberAtIndex($start) == $doc.text.lineNumberAtIndex($end)
   $doc.setSelection $spaceSels[$i]
   Set Kerning $kern
   $i += 1
   if $i >= $spaceSels.count
      $i = 0
      $kern += 0.05
   end
end
Kern:Tighten
I'm not sure if it's possible to combine some of the steps, but at least it seems to work!

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, all

Here is a Macro that addresses my original problem which was to preserve paragraph formatting (specifically, alignment at the Right Line Indent) when a paragraph is interrupted by an interposed Section.

I have named this more comprehensive Macro "Paragraph Straddling Section”.

Code: Select all

#NisusMacroProperty Name: Paragraph Straddling Section
# Code mostly thanks to Philip Spaelti.

# Save the paragraph formatting of the paragraph containing the insertion point.

Copy Paragraph Formatting

# Select the line containing the insertion point.

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel

# Delete any trailing spaces.

Find and Replace " +(?!.)", "", 'Esa'

# Select the entire line again.

$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel

# Delete any redundant spaces.

Find and Replace " +", " ", 'Esa'

# Select the entire line again.

$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$start = $range.location
$end = $range.bound - 1
$sel = TextSelection.new $doc.text, $range

# Starting at the beginning of the line and working from left to right, loosen kerning at each space in the line until the line extends to the Right Line Indent.
# Repeat this procedure as often as necessary.

$spaceSels = $sel.text.find ' ', 'Ea', $sel.range
$kern = 0.05
$i = 0
while $doc.text.lineNumberAtIndex($start) == $doc.text.lineNumberAtIndex($end)
   $doc.setSelection $spaceSels[$i]
   Set Kerning $kern
   $i += 1
   if $i >= $spaceSels.count
      $i = 0
      $kern += 0.05
   end
end
Kern:Tighten

# Find the first character in the following Section.

Find @Text{(?<=\x0C).}, 'E'

# Find the first character in the Section after that. We will then be in the continuation of the text we began with.

Find @Text{(?<=\x0C).}, 'E'

# Apply the paragraph formatting of the paragraph we began with.

Paste Paragraph Formatting

# Set the First Line Indent to the Hanging Indent (ie, to the same as in subsequent lines in the paragraph).

$doc = Document.active
$loc = $doc.textSelection.location

$attributes = $doc.text.displayAttributesAtIndex $loc
$mainindent = $attributes.headIndent

Set First Line Head Indent $mainindent
You position the insertion point in the line immediately preceding the Section, then run the Macro. The Macro deals with any redundant or trailing spaces in the line before adjusting kerning to extend the line to the Right Line Indent. It then applies to the paragraph immediately succeeding the Section the same formatting as in the paragraph immediately preceding it. It concludes by bringing the First Line Indent of the paragraph immediately succeeding the Section into alignment with the Left Line Indent of subsequent lines in that paragraph.

A joy to behold in operation!

Thanks again, Philip, for your invaluable assistance with this project.

Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
adryan
Posts: 561
Joined: 2014-02-08 12:57:03
Location: Australia

Re: Extend Line to Right Line Indent

Post by adryan »

G'day, Philip et al

I'd been successfully using our "Paragraph Straddling Section" Macro until I changed from manual hyphenation to automatic hyphenation, whereupon the line preceding the interposed Section failed to be extended to the Right Line Indent.

If automatic hyphenation is enabled, loosening the kern in the line preceding the interposed Section can cause the last word in the line to become hyphenated, in which case the line will have fewer characters than it started with and things don't work as they should.

So I have amended the Macro so it now does running checks on the number of characters in that line in order to determine control flow. It appears that both while loops are required.

Code: Select all

#NisusMacroProperty Name: Paragraph Straddling Section
# Code mostly thanks to Philip Spaelti.

# Save the paragraph formatting of the paragraph containing the insertion point.

Copy Paragraph Formatting

# Select the line containing the insertion point.

$doc = Document.active
$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel

# Delete any trailing spaces.

Find and Replace " +(?!.)", "", 'Esa'

# Select the entire line again.

$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$sel = TextSelection.new $doc.text, $range
$doc.setSelection $sel

# Delete any redundant spaces.

Find and Replace "  +", " ", 'Esa'

# Select the entire line again.

$loc = $doc.textSelection.location
$range = $doc.text.rangeOfLineAtIndex $loc
$start = $range.location
$end = $range.bound - 1
$sel = TextSelection.new $doc.text, $range

# Find all the spaces in the line.
$spaceSels = $sel.text.find ' ', 'Ea', $sel.range

# Starting at the beginning of the line and working from left to right, loosen the kern at each space in the line until the line extends to the Right Line Indent.
# If automatic hyphenation is enabled, loosening the kern in the line preceding the interposed Section can cause the last word in the line to become hyphenated, in which case the line will have fewer characters than it started with and things don’t work as they should. So we do running checks on the number of characters in that line.

$kern = 0.05
$i = 0
$lineEnd = $end

while $lineEnd == $end
   while $doc.text.lineNumberAtIndex($start) == $doc.text.lineNumberAtIndex($end)
      $doc.setSelection $spaceSels[$i]
      Set Kerning $kern
      $i += 1
      if $i >= $spaceSels.count
         $i = 0
         $kern += 0.05
      end
   end
   $lineRange = $doc.text.rangeOfLineAtIndex $loc
   $lineEnd = $lineRange.bound - 1
end

Kern:Tighten

# Find the Section Break at the end of the line.

Find @Text<\x0C>, 'E'

# Find the next Section Break.

Find @Text<\x0C>, 'E'

# Find the first character in the succeeding Section, removing any paragraph returns or spaces that may occur between it and the preceding Section Break.

Find and Replace @Text<\n* *(.)>, @Text<\1>, 'E'

# We are now in the continuation of the text we began with.
# Apply the paragraph formatting of the text we began with.

Paste Paragraph Formatting

# Set the First Line Indent to the Hanging Indent (ie, to the same as in subsequent lines in the paragraph).

$doc = Document.active
$loc = $doc.textSelection.location

$attributes = $doc.text.displayAttributesAtIndex $loc
$mainindent = $attributes.headIndent

Set First Line Head Indent $mainindent
Cheers,
Adrian
MacBook Pro (M1 Pro, 2021)
macOS Ventura
Nisus Writer user since 1996
Post Reply