13
votes

In Mathematica editor (i.e. notebook), one of the hardest things I always found is when I want to edit some long expression, and go and remove the left end "[" of some expression then before I get the chance to remove the right "]", the code in the cell will get all messed up, since it is no longer balanced, making it really hard to go chase the, now hanging, right end "]" since it is no longer in its original place!

Here is a simple example, suppose we have this

Text[Row[{PaddedForm[currentTime, {6, 3}, NumberSigns -> {"", ""}, NumberPadding -> {"0", "0"}]}]]

now say I wanted to remove the outside Text[] call. So I delete "Text[" and before I get a chance to delete the other side "]", the notebook will now juggle things all over the place, making it hard to find the right "]". For long cell (which is the case for demonestrations work), the code can shift by large amount, and the right "]" can go out of view as well, has to scroll down and up looking for it.

Is there a way to set it, via an option or such, so that when I delete the left "[", Mathematica will automatically delete the matching right "]"? This applies for "(" and ")" as well.

This is really a big problem with the use of the notebook editor for me. Can't tell you how much time I spend just looking the hanging "]".

thanks --Nasser

6
That is one reason to use the f@x notation whenever you canDr. belisarius
The solution should work only if your initial expression is balanced, because if it is not, you could remove the wrong closer.Dr. belisarius
@belisarius , Yes, I use f@ when I can, but f@ can not be used if I want to pass a second argument to f, as in f[x,3]. Then f@x will not work, at least I do not know how it would in such case.Nasser
That is the whenever you can part :)Dr. belisarius
Ok, update, There is a way to do that I want, so this is no longer an issue to me, problem is solved. Do I close this question? not sure how. Any way, this is the solution, thanks to WReach, I found when I changed the style of the cell to CODE instead of input, then now Mathematica no longer does automatic formatting, hence when I remove the left "[", the code does not automatically changes layout on me in the middle of editing. So, now I can see where the right end "]" is, since it did jump around as before. So, problem solved. Will use code style from now on. Like it much more than input.Nasser

6 Answers

11
votes

I shall think about an automatic method, but I currently handle this with:

  1. place the cursor on the first token inside the function you want to delete (in this case Row)

  2. press Ctrl+. until everything inside is selected (twice, in this case)

  3. Copy

  4. press Ctrl+. once to include the function to delete in the selection

  5. Paste

It is really quite fast once you do it a few times.


Andrew Moylan suggests this mouse variation:

Here is the variant I use for this common operation:

  • Triple-click "Row", Ctrl+C, Triple-click "Text", Ctrl+V, done
4
votes

I just registered here and I do not have MMA with me now, so this is just an outline of the proposed solution. This is my first answer here, so bear with me please. By the way...nice to see many mathgroupers here too. :-)

Nasser's question/problem is very common. I personally use the same technique described by Andrew. It is not difficult however solve this problem more elegantly with a button.

Create a small button palette with an action button. It would work like this:

  1. you double-click the outermost function (the one you want to delete). Since you double-click it you will select everything up to the rightmost ].
  2. you click on the action button. The code in the button will simply get the selection and extract the argument within the [] pair, then it will paste the argument onto the selection in the notebook. Without evaluating the argument of course.

That's it. Couple of lines of code.

Since you are at it, you might add a few more buttons to the palette. For example:

  • a button to comment/uncommnent a selection
  • a button to wrap {} or () to a selection
  • a button to wrap fun[] to a selection (fun can be left selected so it can later be overwritten with an appropriate function)

So you end up creating your own programming palette.

3
votes

If you are deleting a function with only one argument, you can

  • delete the function name
  • use (Ctrl + ., Ctrl + .) on the inside function to select its extents
  • go to the end of that extent and delete the ]

This website also has more information about balancing brackets in Mathematica: http://reference.wolfram.com/mathematica/howto/BalanceBracketsAndBraces.html

(If you are deleting a function with more than one argument, auto balancing probably doesn't help anyway since you still have to chase the extra arguments.)

3
votes

I don't know how to do it automatically, but here's a suggestion that can help you keep track of the brackets/parentheses visually and aid you in deleting them manually.

Break up your code into multiple lines, so that each function block opens and closes on a separate line (kinda like C, C++). For e.g., your above code will look like

Text[
 Row[{
   PaddedForm[
    currentTime, {6, 3},
    NumberSigns -> {"", ""},
    NumberPadding -> {"0", "0"}
    ]
   }]
 ]

I use this in blocks of code that are longer than a line or so, and especially in plotting, where it's real easy to keep track of the options you supply.

3
votes

I am answering my own question here. Using CODE as cell type instead of INPUT solved this issue for me. closing.

2
votes

The following will add the keyboard shortcut Shift+Backspace to remove the closest enclosing brackets of the current cursor position. It also adds a menu item to the edit menu.

This function takes the current clipboard content and removes the first and last "word".

cutClipboardBrackets:=Module[{nb},
 nb=CreateDocument[{},Visible->False,WindowSelected->False];
 NotebookWrite[nb,NotebookGet@ClipboardNotebook[]]
 SelectionMove[nb,All,CellContents];
 FrontEndExecute[FrontEndToken[nb,"MoveCellBeginning"]]          
 SelectionMove[nb,All,Word,1];
 NotebookDelete[nb];
 FrontEndExecute[FrontEndToken[nb,"MoveCellEnd"]];
 SelectionMove[nb,All,Word,1];
 NotebookDelete[nb];
 SelectionMove[nb,All,CellContents];
 FrontEndExecute[FrontEndToken[nb,"Copy"]];
];

This can be used to remove brackets, since they are the first and last word when copying FrontEndExecute[FrontEndToken[nb,"Balance"]]. The function that selects, cuts, removes the additional brackets and pastes is:

RemoveBrackets[nb_]:= ( 
 FrontEndExecute[FrontEndToken[nb,"Balance"]];
 FrontEndExecute[FrontEndToken[nb,"Cut"]];
 cutClipboardBrackets;
 FrontEndExecute[FrontEndToken[nb,"Paste"]];
);

Finally we can protect the functions and add a keyboard shortcut (like here):

 Protect[cutClipboardBrackets,ClipboardBrackets];

 FrontEndExecute[
  FrontEnd`AddMenuCommands[
   "SelectAll",{Delimiter,MenuItem["Delete Outer Brackets",
     FrontEnd`KernelExecute[nb=CreateDocument[Null,Visible->False,WindowSelected->True];
  NotebookWrite[nb,Cell[BoxData[RowBox[{"RemoveBrackets[SelectedNotebook[]]"}]],"Input"]];
  SelectionMove[nb,Previous,Cell];
  SelectionEvaluate[nb];
  NotebookClose[nb]],
  MenuKey["Backspace",Modifiers->{"Shift"}],System`MenuEvaluator->Automatic]}]]