WolframResearch / WolframLanguageForJupyter

Wolfram Language kernel for Jupyter notebooks
MIT License
1.05k stars 126 forks source link

Setting format type of new output cells to TraditionalForm #45

Closed vsht closed 5 years ago

vsht commented 5 years ago

The Jupyter interface obviously supports TraditionalForm, since one can do something like TraditionalForm@D[f[x],x] and get the desired result. However, there seems to be no simple way to set the format type of new output cells to TraditionalForm. Initially I asked this question on Mathematica.SE

https://mathematica.stackexchange.com/questions/199635/traditionalform-like-typesetting-in-jupyter-notebook

and together with other users we discovered that the usual front-end tricks like

toOut = toOutImage @* TraditionalForm;
toOut /: (toOut = _) := Null;

which works. It would be really nice if something like that would be supported by default.

My personal interest is that a quantum field theory package (@FeynCalc) we develop with @rolfmertig and @deltafunction makes an extensive use of TraditionalForm-typesetting (cf. e.g.
here). So we would naturally like all that stuff to work in the Jupyter interface just as it does in the front-end.

kubaPod commented 5 years ago

@cc-wr I forked hoping that $PreRead will be a low hanging fruit but soon after I found out that it is not the case. (*)

All "hooks" will affect both WLfJ loop and the loop of the kernel while only the former is expected to be changed. So the question is, what path do you plan to go @cc-wr ? Do you want to handle all those cases very carefully or should users be told how it works, to not touch $Pre and friends, and that there will be another way to specify loop hooks?

(*) I played with $PreRead = StringReplace["1"->"2"] but even before I touched implementation I received

StringReplace::strse: String or list of strings expected at position 1 in StringReplace[1 -> 2][12.1].

I am not sure where it comes from, here maybe?

cc-wr commented 5 years ago

[@kubaPod:] So the question is, what path do you plan to go @cc-wr ? Do you want to handle all those cases very carefully or should users be told how it works, to not touch $Pre and friends, and that there will be another way to specify loop hooks?

@kubaPod, I want to support the above idioms for setting a persistent format type — and the standard hooks in general — as fully as possible (i.e, your case by case path). I will create a provisional pull request for this.

I would like to add, however, that this is an open project: the goal is that more than just "my plans" will matter. Accordingly, I do want to achieve some kind of consensus for the decisions I (and others) suggest.

(*) I played with $PreRead = StringReplace["1"->"2"] but even before I touched implementation I received

StringReplace::strse: String or list of strings expected at position 1 in StringReplace[1 -> 2][12.1].

I am not sure where it comes from, here maybe?

It seems like you were setting $PreRead in one of the install sources. Was that intentional?

Also note that input generally does not seem to be routed through $PreRead when using WolframKernel directly, which the WolframLanguageForJupyter kernel does.

[@vsht:]

  • SetOptions[$Output, FormatType -> TraditionalForm]

Currently, this does not work because output for a Jupyter notebook is not sent through $Output.

  • $Post=TraditionalForm
  • $PrePrint=TraditionalForm

Currently, these do not work because output for a Jupyter notebook is not found where the standard hooks look, nor is output traditionally printed.

  • CurrentValue[$FrontEndSession, {CommonDefaultFormatTypes, "Output"}] = TraditionalForm

Currently, this command does not work because it requires the use of the front end, and by default, the front end is not automatically brought in for the evaluation of input. Perhaps that should change.

Wrapping this command with UsingFrontEnd would fix this problem, but the effect would only apply to image outputs.

kubaPod commented 5 years ago

@cc-wr

It seems like you were setting $PreRead in one of the install sources. Was that intentional?

Here is what I did, so nothing fancy:

image

I agree about other comments, is there a chat people could talk with you about plans? Since jupyter has potential somewhere between Mathematica Kernel and Mathematica itself then I think it should work, from users perspective, as close as possible to those environments.

cc-wr commented 5 years ago

@kubaPod, it is bizarre that this error occurs: I can reproduce it, and I am still looking into it.

Also, I created a provisional branch for the path I suggested here:

https://github.com/WolframResearch/WolframLanguageForJupyter/tree/feature/add-hooks-and-improve-multi-expression-input-handling

cc-wr commented 5 years ago

is there a chat people could talk with you about plans?

@kubaPod, it's possible there will be a public chat for the repository in the future, but for the moment, I don't see why we can't use Github Issues as discussion threads for whatever topics come up.

kubaPod commented 5 years ago

@cc-wr thanks, I will try to take a look, unfortunately my free time availability is random.

About chat, chatting in issues is fine but unless there is a clear 'issue/idea' I will hesitate to create an issue for a vague suggestion. That is where chats are better. Otoh I don't know how many would like to participate so I don't claim it is worth an effort. Btw, gitter sound reasonable, it works well for IntelliJ WL plugin even though there are only 2-3 regular visitors.

cc-wr commented 5 years ago

(*) I played with $PreRead = StringReplace["1"->"2"] but even before I touched implementation I received

StringReplace::strse: String or list of strings expected at position 1 in StringReplace[1 -> 2][12.1].

@kubaPod, so this seems to occur when $PreRead is set to the above, and the Front End is invoked to rasterize something. Accordingly, evaluating $PreRead = StringReplace["1"->"2"]; 2+2 should not cause the error. (But any further operations that rasterize something, with this $PreRead, should.)

In other words, our $PreRead setting is "leaked" to a Front End invocation, where it is actually put to use. You should see a similar error using wolframscript with something like $PreRead = StringReplace["1"->"2"]; UsingFrontEnd[Rasterize["text"]].

However, this all really occurs because StringReplace["1"->"2"] is not a robust setting for $PreRead. For one, $PreRead can apply to box structures — a case that would trip up StringReplace["1"->"2"] most of the time. Secondly, while I would have initially expected the boxes to only comprise input fragments that are strings, it appears this is not so: here, the Front End seems to call ToExpression with the Real 12., which is then forwarded to $PreRead, still as a Real. (You should see another similar error running something like $PreRead = StringReplace["1"->"2"]; ToExpression[12.] in WolframKernel with the option -rawterm.)

cc-wr commented 5 years ago

@kubaPod, I am moving our discussion of hooks in the evaluation loop, outside of their usefulness in setting a persistent format type, to #47.

cc-wr commented 5 years ago
  • SetOptions[$Output, FormatType -> TraditionalForm]
  • $Post=TraditionalForm
  • $PrePrint=TraditionalForm
  • CurrentValue[$FrontEndSession, {CommonDefaultFormatTypes, "Output"}] = TraditionalForm

@vsht, #46 should make these work.

(However, the last command only applies to outputs that would have been rasterized by the Front End before TraditionalForm was applied. Of course, this can be changed if you or others think such behavior is a bad idea.)

cc-wr commented 5 years ago

A general request for comments on the pull request for addressing this issue, #46, is at #48.

vsht commented 5 years ago

Thank you very much, now the Jupyter Notebook indeed seems to behave more like the real front-end. I guess I'l stick to that feature branch until the fix goes into master.

BTW, it would be also nice to have some possibility to input traditional form expressions like Esc mu Esc for the µ, but I guess this is like asking too much at this stage of the development.

cc-wr commented 5 years ago

@vsht, would something like the following work well enough for you, at least for the moment?

It uses Jupyter's tab-completion functionality to rewrite the input cell at certain points that indicate named characters — here, at vertical ellipses and \[s. Complete names (for the named characters) would have the character they correspond with listed once in the completion suggestions, and incomplete names would have possible characters that could complete them suggested.

The limitations are that it cannot handle template/box structure replacements, nor, currently, Mathematica's private-use-area characters. It also uses some custom javascript to redirect escapes to '⋮' (the vertical ellipsis character).


Named character rewrite GIF:

named-character-rewrite

vsht commented 5 years ago

It definitely looks good enough for me. Is this already implemented or just something you test in a private branch?

Unfortunately I really have almost no experience with Jupyter, so for me it is sometimes difficult to estimate what can work almost out-of-the-box and what not in relation to the Wolfram Kernel. Perhaps having some webpage with Jupyter crash course for Mathematica users would be nice.

cc-wr commented 5 years ago

@vsht, it's on a private branch, but I will create a pull request here for it soon.

cc-wr commented 5 years ago

@vsht, you can find support for named characters, limited tab-completion to that end, and all the rest of the above at the pull request #51.

cc-wr commented 5 years ago

A review for this (#51) will be created soon for merging this into master.

cc-wr commented 5 years ago

The pull request for this (#51) should be in master.

(No request for comments was made for this fix, but they will be present for future pull requests.)