# Finding a Specific Line in a Package

In a package I am developing, I accidentally left this line

Protect[


uncompleted prior to running the package. Mathematica produced this error message

Syntax::sntup: Unexpected end of file (probably unclosed parenthesis)
(line 102 of "DataListPlot").


which includes the line number of the error. Since the code was short and it was the only thing in that cell, it was straightforward to find. But, in general, how would one find a specific line in a package? Also, is it possible in the standard package interface to add line numbers, like in WorkBench?

-
Open the .m file in an editor and go to that line? Although in this case, the line mentioned would not have helped much because it was the end of the file (not hard to find anyway), while the error was much earlier (but a good editor with paren matching would probably have helped with that problem, too). –  celtschk Apr 2 '12 at 17:49
@celtschk that is definitely an option, but since mma gave me the error message wherein it discusses a line number, I was hoping for a solution within mma. –  rcollyer Apr 2 '12 at 17:58
Just a wild thought... If we can have some code indenting and formatting rules for the package files, then we can talk about "line 142 under Kernel style", "line 120 under GNU style", etc., and we can have a LineNumberConvert function to convert between different styles... Just a wild thought... :) –  Silvia Aug 4 at 6:39

There is a certain impedance mismatch between lines of code and Mathematica expressions, because Mathematica code is written more or less directly in the parse trees, and the syntax (which encourages nested expressions) was not particularly designed to make lines a really good concept here. That said, this would be a problem in any language, to various extents, because, while you know what you meant in the code and what the error is, the parser may interpret things differently (this is the difference between syntax and semantics). For example, your particular error which you mentioned in the question will be interpreted as a bracket not closed at the end of file, not where you think it really happens (because the parser thinks that the rest of the code is within an opening bracket of Protect).

In any case, the following function will (hopefully) at least tell you what parser thinks, in terms of line numbers:

ClearAll[getErrorLine];
getErrorLine[filename_String] :=
Module[{code, lengths},
code = Import[filename, "Text"];
lengths = StringLength /@ StringSplit[code, "\n"] + 1;
With[{sl = SyntaxLength[code]},
LengthWhile[Accumulate[lengths], # < sl &]
]
]


For a test package like this (all new lines intact):

BeginPackage["SyntaxTest"]

f::usage;

Begin["Private"]

g[x_]:= x^2;

f[x_]:=Sin[g[x]

End[]

EndPackage[]


it gives

getErrorLine["C:\\Temp\\SyntaxTest.m"]


13

which is, at the end of the package. And this is correct, since you can not assign a well-defined semantics to a syntactically broken code, so you can only ask what parser thinks.

-
In an attempt to impose some organization on my code, my packages are broken up into cells, and that particular statement is in a separate cell. So, as far as I am aware, the parser should not cross cell boundaries when interpreting the code. This, of course, improves the likelihood of being able to find the bad code. –  rcollyer Apr 2 '12 at 18:08
@rcollyer When you look at your package in a usual text editor, how do these cells manifest themselves? What kind of special symbols or separators are there to tell the parser where one cell ends and another one starts? –  Leonid Shifrin Apr 2 '12 at 18:13
@rcollyer: AFAIK the .m file does not contain the cell structure (if you edited it directly from Mathematica, it contains comments from which the cell structure can be inferred, but of course the parser ignores comments). –  celtschk Apr 2 '12 at 18:14
@celtschk Ha! It uses double spaces, not comments. Prior, I was just using single spaces within a "cell," but upon adding a double space and reloading, it split the cell. And, it appears Leonid is correct, it runs to the end of the file before stopping. –  rcollyer Apr 2 '12 at 18:31
@Ajasja I don't think it's possible within the notebook interface (or at least not without much extra effort), but I may be wrong. –  Leonid Shifrin Apr 3 '12 at 17:51