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?
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.
There is an installer script in the project, you will only need to execute
Note that this will install the following projects
ProjectInstaller CodeFormatter SEFormatter
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.
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
How to use
Step 0. Create a palette (normally, once per session)
Once you installed the project, you load it using
The code formatting palette is created using
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:
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:
Step 2. Press
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
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:
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:
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):
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
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
Can not take code with vertical spaces between definitions
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
x ~ g ~ y
will look like
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.
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.
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 ModJun 19, 2013 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]. Jun 19, 2013 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[...]Jun 19, 2013 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. Jun 19, 2013 at 11:58
Pardon me for asking without trying it, but does this support copying Unicode characters for e.g.
\[Alpha]? Jun 19, 2013 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? Jun 19, 2013 at 16:09
Correct. Do you think it will be possible to extend this to copy-as-Unicode or do you foresee an incompatibility? Jun 19, 2013 at 17:08
@Mr.Wizard I think this should be doable. I will certainly look into this. Jun 19, 2013 at 17:21
\[Alpha]) alone would be a great improvement.