# Tabs inside expression to format code

In a similar spirit to a question proffered several days back,and as that question stated,

Since the front-end is quite extendable my question is...

Does the front end provide any way to use tabs in code? A bit trivial, I admit, but I for one would find it very useful to use tabs to align parts of different expressions or the layout of a Grid to make the code easier to read and debug.

Edit to original question follows:

What I'd like to do is perhaps simpler and maybe just sillier.

A very simple example of a Grid[]

  Grid[{{"First" , "Second" , "Third", "Fourth", "Fifth" },
{"1st" , "2nd" , "3rd" , "4th" , "5th" }}]


What I'd like to see in either a StandardForm or InputForm styled cell would look like this:

I'd like the functionality of using a tab within any given line of code within any longer expression.

This draws a bit on one of the useful features of "table oriented programing".

I think this could make setting up complex Grid[]s or just reading complex code and functions easier and thereby facilitate more easily finding bugs and inconsistencies. I hope this makes the question clearer.

-
Perhaps your question is intentionally general but I wonder exactly how you expect tabs to behave in an interface that reflows text. Behavior of tabs in a Code cell would be straightforward, on the other hand. –  Mr.Wizard May 17 '12 at 14:31
I hadn't thought through the implications of text reflow. But given that now, code cells (at least on Macs) don't admit tabs at all, it would seem like a doable thing, but would likely require an additional layer of processing to strip out the tabs when the code got read for other purposes. Maybe an "Enable Tabs in Code" option. –  Jagra May 17 '12 at 14:51
Code cells should handle tabs fine. Note that Code style cells are different from Input cells. I can insert a code cell using Alt-8 on Windows (I don't know what's the equivalent on Mac, but you can go the Format -> Style menu item to check). –  Szabolcs May 17 '12 at 14:56
@Jagra Code cells allow tabs on Macs (mine does). I'm curious... my input cell allows tabs too. What exactly were you trying to do? –  rm -rf May 17 '12 at 15:09
Maybe what you're looking for can be found in this question: Programmatic formatting for Mathematica code - possible? –  Jens May 17 '12 at 15:12

I find great utility in setting up grids using Ctrl, which inserts a place holder at the cursor. The input is interpreted as a List and you can create additional rows using CtrlReturn. Here's a walk-through of your Grid example above:

• Start with Grid[ and enter the first element in the list. Then press Ctrl,, which produces:

• Next, enter the second element and press Ctrl, for the third, and so on. When you're done entering all the elements in that row, press CtrlReturn to create a new row of placeholders. This row will have as many elements as the row above:

Now enter the remaining elements. It resizes the spacing automatically to accommodate long words:

• When you're done entering, close the open bracket and evaluate:

The result is exactly the same. In fact, it is no different from entering it painstakingly as a list, but is easy to read and maintain.

-
A perfect solution to my unfortunately unclear question. I ought to have waited just a bit longer before selecting an answer. Which raises a question, can one concede an acceptance if a better answer appears later? –  Jagra May 17 '12 at 19:31
@Jagra You are allowed to change accepted answers anytime if you like a different answer. See this post for more guidance. In general, the advice that we give (to new users usually) is to wait a day or so (unless it is a slam-dunk/obvious answer) so as to not discourage others from answering. –  rm -rf May 17 '12 at 19:36

The following may not fully solve your problem, but seems to logically belong here and is too long for a comment.

I do use tabs in my code formatter. This question prompted me to write a palette for the formatter, which was long overdue (it surely can be improved). The palette should work with both "Input"-style and "Program"-style cells. The palette relies on the CodeFormatter package, so you will have to put it somewhere where Mathematica can find it, e.g. into $UserBaseDirectory/Applications. Anyways, here is the code: Clear[extractText]; extractText[] := First[FrontEndExecute[ FrontEndExportPacket[ NotebookSelection[SelectedNotebook[]], "InputText"]]]; Clear[getCellType]; getCellType[boxes_] := With[{prcells = Cases[boxes, Cell[___, "Program", ___], {0, Infinity}]}, "Program" /; prcells =!= {}]; getCellType[boxes_] := "Boxes"; Clear[extractBoxedCode]; extractBoxedCode[boxes_] := If[# === {}, {}, First@#] &@ Cases[boxes, Cell[BoxData[{b__}], ___] :> RowBox[{b}], {0, Infinity}] Clear[stringCodeToBoxes]; stringCodeToBoxes[code_String] := ToExpression[#, InputForm, MakeBoxes] &@ StringReplace[#, "\n" -> ""] &@code; ClearAll[writeCell]; writeCell[cellcont_, type_] := NotebookWrite[SelectedNotebook[], Cell[cellcont, type]]; ClearAll[throwError]; throwError[] := ( Message[formattingPalette::frmtfail]; Throw[$Failed, formattingPalette]
);

ClearAll[catchError];
SetAttributes[catchError, HoldAll];
catchError[code_] := Catch[code, formattingPalette];

ClearAll[makeFormatButton];
SetAttributes[makeFormatButton, HoldAll];
makeFormatButton[backup_Symbol] :=
Button["Format",
catchError@
boxedCode =
If[celltype === "Boxes",
(* else *)
stringCodeToBoxes[extractText[]]
];
If[boxedCode === {}, throwError[]];
formatted = Catch[CodeFormatterFullCodeFormat[boxedCode], _];
If[MatchQ[formatted , { $Failed, _}], throwError[]]; writeCell[BoxData[formatted], "Input"]; If[celltype === "Program", (* Create a "Program"-style cell with the same formatting *) SelectionMove[SelectedNotebook[], Previous, Cell]; writeCell["\<" <> extractText[] <> "\>", "Program"]; ] ]]; ClearAll[formattingPalette]; formattingPalette::frmtfail = "Formatting failed"; formattingPalette[] := Module[{}, If[Needs["CodeFormatter"] ===$Failed,
Return[\$Failed]
];
CreatePalette[
Module[{backup},
{
makeFormatButton[backup],
Button["Undo format",
NotebookWrite[SelectedNotebook[], backup]
]
}
]]];


To use it, you have to first select the code cell with the code you wish to format, then press the Format button. This will create a cell with formatted code in place of the original cell. If something goes wrong and / or you don't like the way the formatter formatted your code, select the cell with the resulting code again, and press the "Undo format" button on the palette - it should replace the cell's contents back to its original one.

The above code, of course, will eventually be placed in a package, perhaps becoming a part of the formatter. But, it hopefully can be used right now in its current form. Note that the formatter currently can not handle a lot of boxes, but if I start getting bug reports with particular pieces of code which it finds problematic, I will try to improve it and fix these bugs.

Just to test it, here is a block of code on which this does work decently:

ClearAll[selectJIT];
selectJIT[pred_, listType_] :=
selectJIT[pred, Verbatim[listType]] =
Block[{lst},
With[{decl = {Prepend[listType, lst]}},
Compile @@
Hold[decl, Select[lst, pred], CompilationTarget -> "C",
RuntimeOptions -> "Speed"]]];


Here is how the formatted text ("Program" style) cell looks:

-