I'm trying to write some code to programmatically replace a particular expression in my init.m file with a different expression. (It'll probably be some multi-line construct wrapped in a Module[{someTag}, ...] (where someTag is chosen to be unique and descriptive).)

I was naively thinking Import["init.m", "HeldExpressions"] was going to be just what I needed, and would roundtrip nicely with an Export[], but Import[] doesn't seem to help me preserve white space or comments.

So I think I'm going to have to do this as text, and not as a list of expressions. I'm prepared to write my own (simple) expression splitter, but I'd be thrilled if there's some way for me to avoid going down that path.

This might be crazy talk, but is there any good way to enlist the help of Mathematica's parser to spot where an expression begins and ends?

  • $\begingroup$ Why not use myComment["this is it"]; instead of (* this is it *)? Then you preserve comments also with "HeldExpressions". And whitespace you could code as mySpace[" "]; And if you want just write a small M-script which then creates a nice-looking init.m file. $\endgroup$ Jan 9, 2013 at 20:33
  • $\begingroup$ That'd be fine if we were talking about a script to update just my carefully controlled init.m. But I'd like my init munger to also work with somebody else's pre-existing init.m without them having to rewrite it. $\endgroup$
    – sblom
    Jan 9, 2013 at 23:49
  • $\begingroup$ Probably too much work, but you could try to call (via JLink) the source code formatter of Eclipse (Wolfram Workbench) to do the formatting. $\endgroup$ Jan 10, 2013 at 2:50
  • $\begingroup$ Why do you want to do this? init.m files are non-portable, and one tends to forget that they are there and all kind of hell can break loose and pseudo-bugs appear (not that there are not already enough deficiencies ...) $\endgroup$ Jan 10, 2013 at 2:52
  • $\begingroup$ @RolfMertig, good point about init.m being a possible source of confusion. But what do you mean by non-portable? It seems to me that an init.m file is exactly as portable as its author makes it. $\endgroup$
    – sblom
    Jan 11, 2013 at 15:42

1 Answer 1


Figured out what I'm going to do:

  1. Read a line from the file.
  2. Try converting it to an expression (ToExpression[]).
  3. If successful, I've found an expression (or a comment or a blank line).
  4. If not, grab additional lines and concatenate them with the line that failed to parse until I find a series of lines that succeeds.

The code:


breakExpressions[lines_, exprs_: {}, expr_: ""] /; Length[lines] == 0 := 
 If[expr == "", Flatten[exprs], Flatten[{exprs, expr}]];

breakExpressions[lines0_, exprs_: {}, expr0_: ""] := 
  With[{expr = expr0 <> First[lines0] <> "\n", lines = Rest[lines0]}, 
       Check[ToExpression[expr, InputForm, Hold], 
         {ToExpression::sntxi, ToExpression::sntx}],
       {ToExpression::sntx, ToExpression::sntxi}],
     breakExpressions[lines, exprs, expr], 
     breakExpressions[lines, {exprs, expr}, ""]]];

 ReadList[FileNameJoin[{$UserBaseDirectory, "Kernel", "init.m"}], 
  String, NullRecords -> True]]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.