13

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

Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
Nasser
  • 12,849
  • 6
  • 52
  • 104
  • 4
    That is one reason to use the `f@x` notation whenever you can – Dr. belisarius May 26 '11 at 11:31
  • 1
    The solution should work only if your initial expression is balanced, because if it is not, you could remove the wrong closer. – Dr. belisarius May 26 '11 at 11:45
  • 1
    @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 May 26 '11 at 13:12
  • That is the _whenever you can_ part :) – Dr. belisarius May 26 '11 at 13:27
  • 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 May 28 '11 at 21:51

6 Answers6

11

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
Community
  • 1
  • 1
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
  • 1
    Here is the variant I use for this common operation: Triple-click "Row", Ctrl+C, Triple-click "Text", Ctrl+V, done. – Andrew Moylan May 26 '11 at 12:42
  • @Andrew that works too. It's essentially equivalent. I tend to favor keyboard methods it seems. Actually, it's one step better because you eliminate Delete by pasting over. I am going to change my answer, and habits, accordingly. – Mr.Wizard May 26 '11 at 12:51
  • @Mr Wizard. Thanks, but when you say in the second step, press until everything is selected, well, this would still require visual/eye coordination to count things to find when one has reached the matching right "]". In long complicated expression, such as Grid[{{Row[{[.... etc... this will not help as one still need to make sure they got to the correct matching "]". I really thing this should be automated by the editor. Select the left token, and delete, then automatically the matching "]" is gone. If there is not matching "]", then may be a beep can be made or such. Thanks, Nasser – Nasser May 26 '11 at 13:19
  • @Nasser if there were a "Contract Selection" command then you could select the head and body of the function you want to remove and then "Contract" to get the part to keep, but I cannot find such a function. I am struggling to think of another method that can be used to automate this. Also, would you post an example of a complicated expression, and the part you want to delete? I am thinking it should not be that difficult to see because of the way the selection expands, but I also may not be thinking well. – Mr.Wizard May 26 '11 at 13:43
  • @Mr. Wizard: I'm not sure an automatic approach will be all that straightforward. To me it looks like a layer of complication on top of what was there for your earlier question on automatically converting `[[` to `〚`, but I could be wrong. – abcd May 26 '11 at 14:19
  • @yoda, I agree if this must be done via string processing, but I am still hopeful of a method that uses the FrontEnd tokens. – Mr.Wizard May 26 '11 at 14:25
4

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.

Abizern
  • 146,289
  • 39
  • 203
  • 257
magma
  • 626
  • 5
  • 15
  • magma: Have you created such a palette? It should be quite doable, but if you've already done it, then you can save the rest of us the effort and perhaps put the code in the [Mma toolbag question](http://stackoverflow.com/q/4198961/421225). – Simon Sep 06 '11 at 05:27
  • @Simon No I have not done a palette. Frankly I always used the Copy/paste technique described by Moylan/Mr Wizard – magma Sep 13 '11 at 16:20
3

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.)

astay13
  • 6,857
  • 10
  • 41
  • 56
  • I use a very similar sequence: backspace over `Text[`, right-arrow, ctrl+., ctrl+., right-arrow, backspace. This assumes that the inner expression is well-formed. This is in V7 and V8 -- earlier versions did not handle right-arrow over a selection very well. – WReach May 26 '11 at 14:11
3

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.

abcd
  • 41,765
  • 7
  • 81
  • 98
  • Congratulations on 6000 rep =) – Mr.Wizard May 26 '11 at 14:13
  • I go even farther. I usually even balance the curly brackets like the ones that you left on a line together with Row[ and its closing bracket – Sjoerd C. de Vries May 26 '11 at 14:29
  • @Sjoerd: Yes, that would be good to do for consistency. It's just a habit of mine from using LevelScheme. A lot of the figure commands open curly brackets right after, so I began to leave them on the same line as I consider them part of opening/closing the function block – abcd May 26 '11 at 14:35
  • By the way, while I see this as (not so?) common sense, it lets you down when dealing with procedurally generated code, such as the large expressions returned by a lot of Mathematica functions. – Mr.Wizard May 26 '11 at 14:38
  • @Mr.W I'm not sure whether I understand you there. Why would I like to balance the _output_ of certain functions? Which ones are you referring to? Normally, you suppress output, or if you want to inspect output you use functions like `TableForm` or `MatrixPlot`. – Sjoerd C. de Vries May 26 '11 at 16:04
  • 1
    @Sjoerd, what I mean is, if you have a big expression generated with `Solve` or any other of a myriad of functions, and you start manually editing it for whatever reason, you are not going to have the brackets nicely intended for you at the start (unless I am missing an option for that). I don't have much of a problem maintaining my own code that a type in, but rather that which is either generated, or I copy from somewhere else. – Mr.Wizard May 27 '11 at 00:51
3

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

Nasser
  • 12,849
  • 6
  • 52
  • 104
  • 1
    Nasser, respectfully, I don't think that is a solution to the problem. I believe this was a good question, and should remain open to a real, automatic solution in the future. – Mr.Wizard May 29 '11 at 07:58
  • OK, sure, I thought here I am supposed to close the question myself and not leave it open. Feel free to open it. I do not know how to do it. Do I delete the answer I made? – Nasser May 29 '11 at 22:32
  • 1
    I think you should make it clear that a "Code" cell does not solve the automatically deleting the bracket part of the question. It only stops the automatic code-wrapping / formatting that happens in "Input" cells. – Simon Sep 06 '11 at 05:25
2

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]}]]
Community
  • 1
  • 1
jens_bo
  • 133
  • 4
  • @belisarius: yes, I have, it is great. Isn't it possible to move old Mathematica questions like this one over there? Funfact: You welcomed me on my first answer. – jens_bo Jan 03 '13 at 08:47