18

It would be nice to have tools to automate the code formatting for our posts, so that we don't spend too much time formatting our code by hand. What tools can we (as a community) currently offer?

  • 2
    Correct parsing of greek letters and similar characters (for example: \[Alpha]) alone would be a great improvement. – shrx Jun 18 '13 at 23:56
  • @shrx Thanks for pointing this out. I will look into it. – Leonid Shifrin Jun 19 '13 at 12:15
17

Preamble

I was hesitating to post this at this time, but then I thought that what I currently have can be useful to people right now, while it is not clear how soon I will have it in a more complete form. Besides, I count on feedback to move this along. In particular, I want to know if it sucks and / or is full of bugs. Anyway, here goes.

I have updated the code formatter, fixing some bugs and making it possible to use spaces in place of tabs and also have variable-width tabs and an overall offset. Further, I have written a package which creates a palette to format code and copy-paste it to SE. The package lives here.

Note that neither the current place for it nor the design are final. This is just the first step, a minimally working version. It does not install a palette permantnely, and it does not check for updates. Partly this is due to a lack of time to add these features at this time, but mostly because I think it is a bit too early for this - I just want to first get a basic feedback.

So, here is the main message I have about the status of this project: I am not offering a complete and fully tested solution. I am offering a solution that works reasonably well for me, and basically anyone who is willing to try it will exchange a (possible) convenience of automatic formatting for a pain of being a beta-tester. Also, while I will try to fix the bugs as they get discovered, I can not promise that the turnaround will be very fast.

Installation

Initial installation

There is an installer script in the project, you will only need to execute

Import["https://gist.github.com/lshifr/5808568/raw/install.m"]

Note that this will install the following projects

ProjectInstaller
CodeFormatter
SEFormatter

to your $UserBaseDirectory/Applications.

If for any reason the installation fails, the installation script returns $Failed. Note that I did not yet add any logging and / or diagnostics for the reason of failure, but I will do so if problems are found.

Note also that so far I made no effort to remove already installed projects, so if e.g. ProjectInstaller and CodeFormatter have been successfully installed but SEFormatter has not, then the first two will still remain in the installation directory.

Installation of new version (re-installation)

Every now and then you may want to install a more recent version of the SEFormatter. Until the palette gets the features such as automatic checks for updates and automated updating, you can execute this code:

Needs["ProjectInstaller`"];
ProjectUninstall["SEFormatter"];
ProjectInstall[URL["https://gist.github.com/lshifr/5808568/download"]];

which should install the current version of SEFormatter.

How to use

Step 0. Create a palette (normally, once per session)

Once you installed the project, you load it using

Needs["SEFormatter`"]

The code formatting palette is created using

SEFormatterPalette[]

where you can pass a number of options which can customize it, but I hope that I have the right defaults so that in most cases those won't be necessary.

Here is how the empty palette looks like:

enter image description here

Step 1. Select the code cell

To get the code in there, you need to select the code cell with code you want to format, and then press the "Format" button on the palette. Here is an example:

enter image description here

Step 2. Press "Format" button

After pressing the "Format" button, you should have the fomratted code inserted into the code preview area in the palette. In the example I considered, you should see something like

enter image description here

Step 3. Play with settings

Now you can change the settings: Line width, tab width, and overall offset, to your liking. Note that font size setting is for viewing convenience only.

For SE, normally the overall offset should be 4, which is the default. In practice, you will likely find the convenient tab width value to be between 2 and 4. The line width setting can control, to an extent, the line-breaking in the formatted code. To give you an idea how different the results can be, here is a screenshot for a different (rather extreme) set of settings:

enter image description here

Step 4. Copy code to the clipboard, and paste anywhere you need it

Once you are satisfied with the way the formatted code looks, press the "Copy" button, to copy the code string to the clipboard. After that, you can paste it anywhere you want, be it some desktop code editor, or your SE code editor window.

This is, for example, how the code looks when pasted to the Program - style cell:

enter image description here

Formatting Errors

The current version of code formatter has a number of limitations regarding the code it can handle. If you have run into one of those, the formatter will return an error. This is how it may look in the palette (the formatter can not currently handle typeset boxes, in particular a square root):

enter image description here

and

enter image description here

where I pressed the "Verbose" button on error-reporting regime setter in the palette. The code in pink is the box expression that gives trouble to the formatter. I would appreciate if you could report such cases, as issues on the Github project page for the formatter. Not all of them are easy to fix, but eventually we'll get there.

Some existing issues

Here I will list existing issues. As they get fixed, I will move them to another list at the bottom of the post. If you see some issue listed in the fixed issues list, this will likely mean that you need to install the latest version of the SEFormatter`.

Multiplication operator gets ignored

This is a plain bug, will be dealt with very soon. Currently, the minimal example is

a * b

which after the formatting becomes just

ab

without spaces.

Can not take code with vertical spaces between definitions

Simple example:

f[x_] := x^2;

g[x_] := x^4

This will be fixed very soon. For now, you can manually remove vertical space before formatting, like

f[x_] := x^2;
g[x_] := x^4

This error is not on the formatter but on the palette level, so it does not prompt the formatting error message. So, if your code does not format without any message, vertical spaces may be the reason.

Does not preserve prefix, postfix and infix notation in code

Code like

x ~ g ~ y

will look like

g[x,y]

after formatting. The same situation with the other forms.

This likely can be fixed, and hopefully will be fixed soon enough.

No support yet for copying unicode characters

This should be doable, and hopefully will be added soon.

Dynamic updating breaks

Sometimes, for some reason yet unknown to me, the palette stops reacting on changes in the settings. So far, this behavior did not have a clear reproducible pattern. When this happens, I simply close the current instance of the palette and call SEFormatterPalette[] once again, and the repeat the rest of the procedure. In my experience, this does not happen very often.

Reporting issues

Currently, the palette project is stored as a Github gist, rather than a full-fledged repository. I am not sure when and if I am going to change this, since gists provide their own convenience that full repositories lack, but one way you can let me know about the issues is to leave comments in the project's gist. This is admittedly an inferior option to the separate issues page that full repos offer, but I think we can live with that for the time being.

The second way to report issues is the one many of us are already familiar with, which is - leave a new answer on this page, indicating the issue. This is a mild form of a site abuse, but, at least initially, it is an effective form of communication, and this method has been used successfully before, for other projects of a similar nature.

Further developments

It is quite likely that the palette eventually become properly installable and will have some other features such as automatic checks for updates, like those implemented in the SE Image Uploader.

Perhaps more importantly right now, I will try to fix the bugs of the formatter, although I can't promise a very short turnaround given current time limitations. The priority of bugs will be partly decided from the total votes that the bug receives, if the separate answer mechanism is used to report it.

So, have fun, and I hope it will be of at least some use to the community. I also hope for the feedback, and will try to not keep the issues unresolved for too long.

  • Can you perhaps remove the "always on top" nature of it? It's cumbersome to not be able to select the notebook below and work in it. Still playing with it... might have some more comments. – rm -rf Jun 19 '13 at 9:21
  • @rm-rf I have two screens, so for me this is more of an advantage. If you don't want it, just use SEFormatterPalette[WindowFloating -> False]. – Leonid Shifrin Jun 19 '13 at 10:13
  • @Leonid Thanks - it's very promising - when it works, it's great. But it seems it doesn't support all Mathematica code yet? (e.g. Graphics[...] – cormullion Jun 19 '13 at 11:54
  • @cormullion Yes, a number of boxes (Graphics[...] in particular) are not yet supported. For those case, what I would really like to have is a set of minimal examples where it breaks - this is where the community can help. – Leonid Shifrin Jun 19 '13 at 11:58
  • Pardon me for asking without trying it, but does this support copying Unicode characters for e.g. \[Alpha]? – Mr.Wizard Jun 19 '13 at 16:07
  • @Mr.Wizard I just tried and the answer seems to be that the symbol is copied as \[Alpha]. So, this is probably not what you would like, right? – Leonid Shifrin Jun 19 '13 at 16:09
  • Correct. Do you think it will be possible to extend this to copy-as-Unicode or do you foresee an incompatibility? – Mr.Wizard Jun 19 '13 at 17:08
  • @Mr.Wizard I think this should be doable. I will certainly look into this. – Leonid Shifrin Jun 19 '13 at 17:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .