6
$\begingroup$

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:

I didn't realize until I saw Leonid's answer that what I thought I had asked and what everyone else thought I asked had little resemblance.

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:

enter image description here

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.

$\endgroup$
9
  • 1
    $\begingroup$ 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. $\endgroup$
    – Mr.Wizard
    Commented May 17, 2012 at 14:31
  • $\begingroup$ 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. $\endgroup$
    – Jagra
    Commented May 17, 2012 at 14:51
  • $\begingroup$ 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). $\endgroup$
    – Szabolcs
    Commented May 17, 2012 at 14:56
  • $\begingroup$ @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? $\endgroup$
    – rm -rf
    Commented May 17, 2012 at 15:09
  • $\begingroup$ Maybe what you're looking for can be found in this question: Programmatic formatting for Mathematica code - possible? $\endgroup$
    – Jens
    Commented May 17, 2012 at 15:12

2 Answers 2

2
$\begingroup$

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:

    enter image description here

  • 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:

    enter image description here

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

    enter image description here

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

    enter image description here

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.

enter image description here

$\endgroup$
2
  • $\begingroup$ 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? $\endgroup$
    – Jagra
    Commented May 17, 2012 at 19:31
  • $\begingroup$ @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. $\endgroup$
    – rm -rf
    Commented May 17, 2012 at 19:36
5
$\begingroup$

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[
      FrontEnd`ExportPacket[
          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@
      Module[{read, celltype, boxedCode, formatted},
        backup = read =  NotebookRead[SelectedNotebook[]];
        celltype = getCellType[read];
        boxedCode = 
          If[celltype === "Boxes", 
             extractBoxedCode[read],
             (* else *)
             stringCodeToBoxes[extractText[]]
          ];
        If[boxedCode === {}, throwError[]];
        formatted = Catch[CodeFormatter`FullCodeFormat[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:

enter image description here

$\endgroup$
4
  • $\begingroup$ I didn't realize until I saw your answer that what I thought I had asked and what everyone else thought I asked had little resemblance. Please see additions to my original question above. $\endgroup$
    – Jagra
    Commented May 17, 2012 at 17:58
  • $\begingroup$ @Jagra Please see my comment addressing your additions :) $\endgroup$ Commented May 17, 2012 at 17:59
  • $\begingroup$ Sorry to change my acceptance, but @R.M. came up with a simple and elegant solution to my dilemma and in his words "...a slam dunk..." $\endgroup$
    – Jagra
    Commented May 17, 2012 at 19:44
  • $\begingroup$ @Jagra Not a problem at all. As I stated in my answer, your question prompted me to do something I had to do long ago, and also my answer is not really an answer but rather an extended comment. I just used this opportunity to post this code, since I think it may be useful for those who decide to use the code formatter. Perhaps I will move this code to some other location in the future. $\endgroup$ Commented May 17, 2012 at 20:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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