I wanted to add a few methods to your wonderful code that make it easier to navigate through the text. The 5 methods are as follows, and they are to be added to NoodeLineNumberView.m:

1) physicalLineAtInsertion: returns the physical line in the text document where the insertion point is positioned in the textView.

2) logicalLineAtInsertion: returns the logical line in the textView where the insertion point is positioned in the text view

3) indexOfPhysicalLine: returns the character index of line corresponding to line number.

4) logicalLineIndexAtPhysicalCharacterIndex: returns the index of the wrapped line of text in the text view corresponding to the physical line index obtained from 3.

5) gotoLine: uses 3 & 4 to position the insertion point in the text view at the beginning of

There may be a more optimal way of doing things, but these work on small texts nicely...

Thank you for your line number contribution....

Bruce

Code:
-----------------------------------------------------------
-(unsigned) logicalLineAtInsertion
{
NSTextView* tview = [self clientView];
NSLayoutManager *layoutManager = [tview layoutManager];
NSRange lineRange;
unsigned numberOfLines, index, numberOfGlyphs = NSMaxRange([layoutManager glyphRangeForCharacterRange:NSMakeRange(0,[tview selectedRange].location) actualCharacterRange:NULL]);
for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
(void) [layoutManager lineFragmentRectForGlyphAtIndex:index
effectiveRange:&lineRange];
index = NSMaxRange(lineRange);
}

return numberOfLines;

}

-(unsigned) physicalLineAtInsertion
{
NSTextView* tview = [self clientView];
unsigned physical = [self lineNumberForCharacterIndex:[tview selectedRange].location inText:[tview string]] + 1;
return physical;

}

-(unsigned) indexOfPhysicalLine:(unsigned) linenumber
{

if (linenumber == 1) return 0;
NSString *string = [[self clientView] string];
unsigned numberOfLines, index, stringLength = [string length];
for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
{
index = NSMaxRange([string lineRangeForRange:NSMakeRange(index, 0)]);
if (numberOfLines == linenumber- 2) break;
}

return index;

}

-(unsigned) logicalLineIndexAtPhysicalCharacterIndex:(unsigned) physicalindex
{
NSTextView* tview = [self clientView];
NSLayoutManager *layoutManager = [tview layoutManager];
NSRange lineRange;
unsigned numberOfLines, index, numberOfGlyphs = NSMaxRange([layoutManager glyphRangeForCharacterRange:NSMakeRange(0,physicalindex) actualCharacterRange:NULL]);
for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
(void) [layoutManager lineFragmentRectForGlyphAtIndex:index
effectiveRange:&lineRange];
index = NSMaxRange(lineRange);
}

return index;

}

-(void) gotoLine:(unsigned) lineNumber
{

NSTextView* tview = [self clientView];
unsigned insertionLocation = [self logicalLineIndexAtPhysicalCharacterIndex:[self indexOfPhysicalLine:lineNumber]];
[tview setSelectedRange:NSMakeRange(insertionLocation,0)];
[tview scrollRangeToVisible:NSMakeRange(insertionLocation,0)];
}