Как создать блокнот с правильно отформатированным выражением
У меня есть выражение Mathematica, сгенерированное другой программой, которое я хотел бы открыть в записной книжке, правильно отформатированный. Например, другая программа генерирует это:
Plot[{Exp[x],Interpolation[Table[{k/5,Exp[(k-1/2)/5]},{k,0,5}],
InterpolationOrder->0][x]},{x,0,1},Filling->{1->{{2},{Yellow,Orange}}},
PlotLabel->Style["Formatting",Blue,FontFamily->"Courier"]]
Текст записывается в файл с грубым суффиксом ".nb" и запускается, а выражение открывается в блокноте без форматирования. Чтобы добиться форматирования, написание файла вручную с помощью BoxData представляется непрактичным.
Файл на самом деле запускается из.Net с использованием Process.Start("filename.nb"), но запуск из командной строки кажется не менее проблематичным.
4 ответа
Вот решение, которое я принял. Спасибо за помощь.
Основным шагом решения является форматирование команды через ядро:
FullForm[ToBoxes[
Defer[Plot[{Exp[x],
Interpolation[Table[{k/5, Exp[(k - 1/2)/5]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel ->
Style["Formatting", Blue, FontFamily -> "Courier"]]]]]
Затем отформатированные данные инкапсулируются для создания блокнота:
Notebook[{Cell[BoxData[
... ( inserted box-formatted output ) ...
], "Input"]
},
WindowSize->{615, 750},
WindowMargins->{{328, Automatic}, {Automatic, 76}},
StyleDefinitions->"Default.nb"
]
Это записывается в файл с суффиксом ".nb". Все отлично и денди.
Этот подход хорошо работает для блоков кода с несколькими утверждениями, но была включена некоторая дополнительная обработка для форматирования одного вызова функции в форме Function[expression, options], чтобы добавить разрыв строки перед каждым параметром. Вот код C#, используемый для получения обоих типов выходных данных:
public static class MathematicaHelpers
{
public static string CreateNotebook(string mathCommand, string fileLocation, MathKernel kernel, bool addNewLines)
{
if (addNewLines) {
mathCommand = string.Format("{0}{1}{2}", "Module[{boxoutput,b2},boxoutput=FullForm[ToBoxes[Defer[", mathCommand, "]]];b2=boxoutput[[1,1,3,1]];boxoutput[[1,1,3,1]]=Join[Flatten[Riffle[Partition[b2,2],\"\\[IndentingNewLine]\"],1],{\"\\[IndentingNewLine]\",Last[b2]}];boxoutput]");
} else {
mathCommand = string.Format("{0}{1}{2}", "FullForm[ToBoxes[Defer[", mathCommand, "]]]");
}
fileLocation = Path.ChangeExtension(fileLocation, ".nb");
mathCommand = ComputeMathCommand(mathCommand, kernel);
mathCommand = string.Format("{0}{1}{2}", "Notebook[{Cell[BoxData[", mathCommand,
"], \"Input\"]},WindowSize->{615, 750}, WindowMargins->{{328, Automatic}, {Automatic, 76}},StyleDefinitions->\"Default.nb\"]");
File.WriteAllText(fileLocation, mathCommand);
return fileLocation;
}
private static string ComputeMathCommand(string command, MathKernel kernel)
{
kernel.Compute(command);
return kernel.Result.ToString();
}
}
Как насчет этого:
Export["C:\\Temp\\formatTest1.nb",
ToExpression[Import["C:\\Temp\\formatTest.nb", "Text"], InputForm, MakeBoxes]]
Я проверил его, и он, кажется, работает (импорт из простого файла, экспорт в тот, который вы затем откроете). Это создает явные блоки, но с очень небольшим усилием на стороне пользователя. Я не тестировал, но вы должны иметь возможность запускать этот код в режиме сценария из командной строки.
РЕДАКТИРОВАТЬ
Чтобы проверить из Mathematica, вы можете использовать, например,
Export["C:\\Temp\\formatTest.nb",
ToString@HoldForm@FullForm@
Plot[{Exp[x],Interpolation[Table[{k/5, Exp[(k - 1/2)/5]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel -> Style["Formatting", Blue, FontFamily -> "Courier"]],
"Text"]
перед запуском кода выше.
Вы можете использовать следующую упаковку:
nb = CreateWindow[
DocumentNotebook[{
Plot[{Exp[x],
Interpolation[Table[{k/5, Exp[(k - 1/2)/5]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel ->
Style["Formatting", Blue, FontFamily -> "Courier"]]
}]]
тогда команды NotebookSave и NotebookClose могут быть использованы для сохранения и закрытия вещи;)
Если вы не создаете BoxData
В выражениях явно нет способа отформатировать выражение, не вызывая хотя бы Mathematica FrontEnd.
Самое близкое, что я могу придумать, - это добавить следующее:
SelectionMove[EvaluationNotebook[], Next, EvaluationCell];
FrontEndExecute[{FrontEndToken[FrontEnd`InputNotebook[],
"SelectionConvert", "StandardForm"]}];
Plot[{Exp[x], Interpolation[Table[{k/5, Exp[(1/5)*(k - 1/2)]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel -> Style["Formatting", Blue, FontFamily -> "Courier"],
Evaluated -> True]
SelectionMove[EvaluationNotebook[], After, GeneratedCell];
который автоматически форматирует Plot
команда, когда ячейка оценивается.
(Кстати: вы, вероятно, должны добавить Evaluate
перед списком или добавить (не очень хорошо задокументировано) Evaluate->True
вариант.