If you have been using Mathematica for a while you probably have grown attached to the documentation center. There is always something new that you find in those pages. Let it be options for a function or just some examples that at some point did not seem useful to you.
It is likely that you have written packages with your specialized functions that you use all the time. Sometimes you might think of a neat example to use with your function but it is likely that it ends up being forgotten somewhere in your hard disk. If you had written it to the documentation at the moment you thought of it maybe you wouldn't be looking for it desperately later on.
For this reason I would like to know how to integrate documentation for your own functions with Mathematica's documentation center programmatically. This question is here to explore how to adapt documentation. If you have written scripts that help you do this, please share it with the community.
Wolfram's Workbench is not an acceptable solution for this question. Everything must be done with the plain installation of Mathematica. There is a couple of points that the solution should cover:
Creating documentation for a function (Preferably a template).
Creating guides and tutorials (If they are deem useful).
Linking the notebooks to the documentation center.
Creating "usage" messages that display correctly in different enviroments.
In Mathematica Notebook ?Symbol
In Documentation Center Search: Symbol
This is a really broad topic, I have solutions for 1, 2, and 3. I'm missing point number 4. So tell us, how do you document your functions with the documentation center?
Update
I have added another answer. Hopefully this answer is more encouraging to users of Mathematica to write documentation pages with their packages. I think that writing documentation pages is beneficial to the application writer as well as the users of the application. If you download the package I wrote I suggest you follow the tutorial so that you can see what happens in every step. This will give you valuable experience for future projects.
Github (May 24, 2014)
Since I wrote the package there has been several people interested in this package. I have uploaded the package to Github: https://github.com/jmlopez-rod/ApplicationMaker. Please contact me if you would like to be a contributor to the repository.
To show how to create documentation that incorporates to the Documentation Center we will create a package that contains very simple functions and its documentation. Lets call our package SOPackage. This package will be stored in a folder of the same name and such folder should be stored in either $BaseDirectory or $UserBaseDirectory$. The SOPakage folder needs to have the following tree structure.
Notice that the root is the directory SOPackage.
SOPackage
Now we will create a new notebook file inside SOPackage: SOPackage.nb. These are the contents of the notebook
BeginPackage["SOPackage`"];
AddTwo::usage = "AddTwo[\!\(\*StyleBox[\"a\", \"TI\"]\), \!\(\*StyleBox[\"b\", \"TI\"]\)] returns \!\(\*StyleBox[\"a\", \"TI\"]\)+\!\(\*StyleBox[\"b\", \"TI\"]\).";
DotTwo::usage = "DotTwo[\!\(\*StyleBox[\"a\", \"TI\"]\), \!\(\*StyleBox[\"b\", \"TI\"]\)] returns \!\(\*StyleBox[\"a\", \"TI\"]\)*\!\(\*StyleBox[\"b\", \"TI\"]\).";
AddTwo::argnum = "AddTwo was called with `1` arguments. It expected 2.";
DotTwo::argnum = "DotTwo was called with `1` arguments. It expected 2.";
Begin["`Private`"];
AddTwo[a_, b_] := a + b
AddTwo[args___] := (Message[AddTwo::argnum, Length[{args}]]; $Failed)
DotTwo[a_, b_] := a*b
DotTwo[args___] := (Message[DotTwo::argnum, Length[{args}]]; $Failed)
End[];
EndPackage[];
Here is a screenshot of what you should see
Note that the usage messages usually format parameters in a special way. A shortcut to get this format (pointed out by #alexey-popkov) is to highlight the letter you want to format, press Command+0 (Alt+0 in windows) and enter "TI". Repeat this process for all the letters that need to be modified. Change the cell to an Initialization Cell via Cell->CellProperties->Initialization Cell. Now we save this notebook as SOPackage.nb. In case Mathematica did not ask you if you want to create a package because you forgot to change the cell to an initialization cell then you can go to Format->OptionInspector. Make sure you are selecting "Options for SOPackage.nb" otherwise the option that you need to set to true will be grayed out. Now click to Notebook Options->FileOptions->AutoGeneratedPackage and select Automatic. Close the options window and save the file. Every time you save SOPackage.nb the file SOPackage.m will get updated (Do not mess with this m file).
The Kernel directory should contain only one file: init.m. This file needs to have the next line:
Get["SOPackage`SOPackage`"];
After this we have a working package. You can try the following to make sure that everything is working fine:
<<SOPackage`
?AddTwo
?DotTwo
DotTwo[]
DotTwo[2, 3]
Documentation
Lets us start by creating the guide page. This will be the page that will show up when you type SOPackage in the doc center. Lets start by creating a notebook and saving it under SOPackage/Documentation/English/Guides as SOPackage_E.nb. The reason I'm giving it the extension "_E" is because this will be an editable copy. Notice that you cannot edit any of the documents in the documentation center. Well, you can but these changes never take effect. You will probably want to modify your documentation as you build your package so it is a good idea to have a copy that you can edit. For this example we can copy the contents of the Combinatorica guide, on the Doc center type Combinatorica/guide/CombinatoricaPackage select all with cells, copy and paste them in your SOPackage_E.nb file (alternatively, copy the file C:\Program Files\Wolfram Research\Mathematica\10.4\Documentation\English\Packages\Combinatorica\Documentation\English\Guides\CombinatoricaPackage.nb or something equivalent on other OSes). Make some changes just so that you know they are the ones you are making. In my case I substituted Combinatorica with SOPackage. In the case you can cannot modify some part of a text this is what you need to do:
1: Click on the text that you cannot modify.
2: Go to Cell->Show Expression or enter Command+Shift+E or something equivalent in windows.
3: Look for the second argument in the Cell expression (right before any options of the form A -> B). This is a style name. In some cases you will see "Usage", "Notes", "ObjectName" among others. Once you locate the style of the cell that you cannot modify go click on the notebook you are editing and enter Command+Shift+E to show back the expression.
4: Go to Format->Edit StyleSheet..., enter the style name you saw earlier under Enter a style name:.
5: A cell showing the style appears. Make sure this cell is selected and go to Format->Object Inspector. Make sure it says Show option values Selection.
6: Go to Editing Options and set Editable to true.
7: Modify the unmodifiable.
I suggest you first enter the name of all the styles that you want to be able to edit as I have shown in the screenshot. So far I have only changed the ones that I mentioned in step 3. Once you have them in the list select them all and set the to editable at once. Another important point is that this file can be a template. You should save this file somewhere and when you need to make a documentation just open it up, save it with another name in the right path and start copying cells from existing documentation notebooks.
It is up to you how you create this guide. For now lets just put nonsense. You'll see my screenshots. The next two files are the documentation for your functions. Copy and paste your template file to SOPackage/Documentation/English/ReferencePages/Symbols and name the files AddTwo_E.nb and DotTwo_E.nb. Look for some documentation that you like, take Sin for instance, and copy and paste the information to those files. I'll change the names just to show how they work.
The creation of the template file can surely be reduced. If someone knows how to do this programmatically please feel free to edit this section here and replace it with the code. You'll do us all a huge favor.
PacletInfo.m
This file goes right under the directory SOPackage and contains the following:
Paclet[
Name -> "SOPackage",
Version -> "0.0.1",
MathematicaVersion -> "8+",
Extensions -> {{
"Documentation",
Resources -> {
"Guides/SOPackage"
},
Language -> "English"
}}
]
There is one last thing we must do before we can have the documenation ready. We need to make all of the function documentation uneditable and we have to give it the same format as the rest of the documents. This time I wrote a script that does this. I call it MakeDoc because it will also build the index. Save this file under OSPackage. I will break this file intwo 4 parts so that you can get an explanation.
pname = "SOPackage";
Get[pname <> "`"];
basepath = $UserBaseDirectory<>"/Applications/"<>pname<>"/Documentation/English/ReferencePages/Symbols/";
$UserBaseDirectory <> "/Applications/" <> pname <> "/Documentation/English/ReferencePages/Symbols/";
We should make sure that we restart Mathematica before doing this. First we will load the package and set the root directory of all of the function documentation. On the next step we will basically copy an paste code, we will be doing the following for each function.
snname := "AddTwo";
nb = NotebookOpen[basepath <> snname <> "_E.nb"];
NotebookSave[nb, basepath <> snname <> ".nb"];
SetOptions[nb,
TaggingRules -> {
"ModificationHighlight" -> False,
"Metadata" -> {
"context" -> pname <> "`",
"keywords" -> {},
"index" -> True,
"label" -> "OSPackage Package Paclet Symbol",
"language" -> "en",
"paclet" -> "OSPackage Package",
"status" -> "",
"summary" -> AddTwo::usage,
"synonyms" -> {},
"title" -> "AddTwo",
"type" -> "Symbol",
"uri" -> pname <> "/ref/AddTwo"},
"SearchTextTranslated" -> ""
}
];
SetOptions[nb, Saveable -> False];
SetOptions[nb,
StyleDefinitions ->
FrontEnd`FileName[{"Wolfram"}, "Reference.nb"]];
NotebookSave[nb];
This block of code opens the editable function documentation. It saves it with the correct name. And then it changes its attributes so that its not editable and it gives it the same look as the rest of the documents. We do the same for each function. Notice that "summary" is set to the usage message of the function. This is what we will see when we search for the function.
snname := "DotTwo";
nb = NotebookOpen[basepath <> snname <> "_E.nb"];
NotebookSave[nb, basepath <> snname <> ".nb"];
SetOptions[nb,
TaggingRules -> {
"ModificationHighlight" -> False,
"Metadata" -> {
"context" -> pname <> "`",
"keywords" -> {},
"index" -> True,
"label" -> "OSPackage Package Paclet Symbol",
"language" -> "en",
"paclet" -> "OSPackage Package",
"status" -> "",
"summary" -> DotTwo::usage,
"synonyms" -> {},
"title" -> "DotTwo",
"type" -> "Symbol",
"uri" -> pname <> "/ref/DotTwo"},
"SearchTextTranslated" -> ""
}
];
SetOptions[nb, Saveable -> False];
SetOptions[nb,
StyleDefinitions ->
FrontEnd`FileName[{"Wolfram"}, "Reference.nb"]];
NotebookSave[nb];
Very important, we haven't modified the guide, this is all it takes:
snname := "SOPackage";
nb = NotebookOpen[guidepath <> snname <> "_E.nb"];
NotebookSave[nb, guidepath <> snname <> ".nb"];
SetOptions[nb, Saveable -> False];
SetOptions[nb, StyleDefinitions -> FrontEnd`FileName[{"Wolfram"}, "Reference.nb"]];
NotebookSave[nb];
And finally, we create the index like this:
indir = $UserBaseDirectory<>"/Applications/"<>pname<>"/Documentation/English/Index";
If[FileNames[indir] != {}, DeleteDirectory[indir, DeleteContents -> True]];
ind = DocumentationSearch`NewDocumentationNotebookIndexer[indir];
DocumentationSearch`AddDocumentationNotebook[ind, basepath <> "AddTwo.nb"];
DocumentationSearch`AddDocumentationNotebook[ind, basepath <> "DotTwo.nb"];
DocumentationSearch`CloseDocumentationNotebookIndexer[ind];
Notice that we need to a line with AddDocumenationNotebook for each function. After running MakeDoc.nb the files AddTwo.nb, DotTwo.nb and SOPackage.nb will be created. These files cannot be modifed. You will also see a folder named Index. This is all binary data that contains information for the doc center. If you ever make a modification to the documentation you should run MakeDoc.nb to make the changes take effect. Here is the document tree that we have now.
After this we should restart Mathematica and take our documentation for a ride.
This is what happens when you look for "SOPackage".
Lets look for the usage of AddTwo
Notice that an arrow with a link to the doc page was added automatically.
Unfortunately, if we search for AddTwo in the doc center this is what we obtain:
How can we make it so that the summary for the function isn't formatted?
Feel free to modify my code by downloading it from here.
Thank you for reading.
Manuel
It took me while but I have finally finished writing a documented Mathematica application to help Mathematica users write their documented packages.
This application is called ApplicationMaker. It contains three packages with various functions to help you create the application. By using these functions you can skip going through all the mess I had described in my previous answer.
If you download ApplicationMaker from my website you will find a detailed tutorial showing you how to create a complete application with its documentation.
Overview
To create a new application you start by calling NewApplication. This creates the directory tree I mentioned in the previous answer. To find more about Mathematica's file organization click here.
The next step is to create the packages. For that you call NewPackage. This function creates a template where you write your code.
When you finish writing your code you need to call UpdateInit. This updates the init file that Mathematica needs so that you can use the function Get (<<).
At this point you are ready to create the documentation. Simply call CreateReferencePages and this will create a basic document that you can edit to document the reference pages for each symbol in your application.
If you want to create a guide or a tutorial for your application then you can call NewGuide and NewTutorial.
When you are done doing your edits you need to build your application so that Mathematica can adapt it to its documentation center. You do this by calling BuildApplication.
At this point you are done. If you use Information on any of the symbols of your package you should see an arrow appended that leads you to the reference page for that symbol.
If you wish to share this application you should first deploy it. The current application contains the reference pages which work with the documentation center and those that you edit. By deploying it you obtain a directory with only the necessary files for your application to work.
Installation
All you have to do is drop the folder ApplicationMaker in $UserBaseDirectory/Applications/ or $BaseDirectory/Applications/.
To get started open up the documentation center and look for "ApplicationMaker". This should show you the guide showing all the functions that the package contains. At the very bottom you should see a link to the tutorial.
Final Words
This is the first application I have ever build for Mathematica. I will try to keep updating the package I as discover new things to make the package better. For now, I hope that this first version of ApplicationMaker is useful to anybody trying to document their Mathematica applications.
You may download ApplicationMaker here.
I have downloaded your ApplicationMaker and is testing it out using Mathematica 10 on Windows 7 64 Bit. Great work and well documented! I discovered a small error that needed a fix on my set up when creating a new application using NewApplication. It appears that the variable root in the function MakeDirectory cannot be a string with zero length (causes error in creating the directories). I fixed this by including a test in your original code:
MakeDirectory[root_, start_, main_, sub_] := Module[
{nm, ns, tmp},
nm = Position[main, start];
If[Length#nm != 0, nm = nm[[1, 1]]];
If[Length#sub[[nm]] != 0,
Do[
tmp =
If[StringLength[root] != 0,
FileNameJoin[{root, start, sub[[nm, i]]}],
FileNameJoin[{start, sub[[nm, i]]}]];
If[DirectoryQ[tmp],
Print[Style["Existing Directory : ", "MSG", Gray],
Style[tmp, "MSG", Bold]],
CreateDirectory[tmp];
Print[Style["Directory Created : ", "MSG", Blue],
Style[tmp, "MSG", Bold]]
];
, {i, Length#sub[[nm]]}]
];
Do[
MakeDirectory[
If[StringLength[root] != 0, FileNameJoin[{root, start}], start],
sub[[nm, i]], main, sub],
{i, Length#sub[[nm]]}
]
]
Related
class torch.FloatStorage[source]
byte()
Casts this storage to byte type
char()
Casts this storage to char type
Im trying to get some documentation done, i have managed to to get the format like the one shown above, But im not sure how to give that link of source code which is at the end of that function!
The link takes the person to the file which contains the code,But im not sure how to do it,
This is achieved thanks to one of the builtin sphinx extension.
The one you are looking for in spinx.ext.viewcode. To enable it, add the string 'sphinx.ext.viewcode' to the list extensions in your conf.py file.
In summary, you should see something like that in conf.py
extensions = [
# other extensions that you might already use
# ...
'sphinx.ext.viewcode',
]
I'd recommend looking at the linkcode extension too. Allows you to build a full HTTP link to the code on GitHub or such like. This is sometimes a better option that including the code within the documentation itself. (E.g. may have stronger permission on it than the docs themselves.)
You write a little helper function in your conf.py file, and it does the rest.
What I really like about linkcode is that it creates links for enums, enum values, and data elements, which I could not get to be linked with viewcode.
I extended the link building code to use #:~:text= to cause the linked-to page to scroll to the text. Not perfect, as it will only scroll to the first instance, which may not always be correct, but likely 80~90% of the time it will be.
from urllib.parse import quote
def linkcode_resolve(domain, info):
# print(f"domain={domain}, info={info}")
if domain != 'py':
return None
if not info['module']:
return None
filename = quote(info['module'].replace('.', '/'))
if not filename.startswith("tests"):
filename = "src/" + filename
if "fullname" in info:
anchor = info["fullname"]
anchor = "#:~:text=" + quote(anchor.split(".")[-1])
else:
anchor = ""
# github
result = "https://<github>/<user>/<repo>/blob/master/%s.py%s" % (filename, anchor)
# print(result)
return result
How could I read about:config entries for firefox version 30.0 using Python ? I tried to use what is pointed by this answer (in JavaScript) but it did not help.
Yeah, that's a problem. Firefox comes with default values for most preferences, and only stores values different from the default in the profile. Added to this, each add-on may come with additional default values and create new preferences at runtime.
The default pref files might be contained within zip files, which complicates matters a little.
Files
Files you'd have to check for default preferences (in a standard Firefox distribution)
$APPDIR/omni.ja:greprefs.js
$APPDIR/omni.ja:defaults/preferences/*.js
$APPDIR/browser/omni.ja:greprefs.js
$APPDIR/browser/omni.ja:defaults/preferences/*.js
$PROFILE/extensions/*/defaults/preferences/*.js
$PROFILE/extensions/*.xpi:defaults/preferences/*.js
While preferences that were overridden from the default reside in $PROFILE/prefs.js.
So first you need to figure out $APPDIR (installation path of Firefox) and then $PROFILE (Firefox user profile path).
Then you need to read some files either in some directories (easy) or in some zip files (hard). A major problem is that you cannot just use zipfile to read omni.ja (and potentially some of the xpi files) because a typical python zipfile implementation is too rigid in the interpretation of the zip structure and fails to open these files. So you'd need your own zipfile implementation that can deal with this.
Format
In the *.js files there are essentially two types of lines (+ blank lines, comment lines):
pref("name", value)
user_pref("name", value)
The pref lines are default preferences, user_pref lines are user preferences (overridden from default).
Values
value is a Javascript expression such as "abc", true, 1 or 2 * 3. The latter is a problem, as you'd need a JS engine to properly evaluate it. But this isn't really a problem in practice, as you won't find expressions computing something in the wild (usually).
Conclusion
Really replicating the preferences system (or about:config) isn't an easy task and full of obstacles. It is probably far easier just reading user pref.js to see what's overridden and knowing the default values.
Example (just prefs.js)
import re
import json
PROFILE = "/path/to/firefox/profile"
def read_user_prefs(preffile):
r = re.compile(r"\s*user_pref\(([\"'])(.+?)\1,\s*(.+?)\);")
rv = {}
for l in preffile:
m = r.match(l)
if not m:
continue
k, v = m.group(2), m.group(3)
try:
rv[k] = json.loads(v)
except Exception as ex:
print "failed to parse", k, v, ex
return rv
with open("{}/prefs.js".format(PROFILE), "rb") as p:
prefs = read_user_prefs(p)
for k, v in prefs.items():
print u"({type:<16}) {key}: {value}".format(
key=k, value=v, type=str(type(v)))
print
print "Chrome debugging enabled:",
print prefs.get("devtools.chrome.enabled", False)
print "Last sync:",
print prefs.get("services.sync.tabs.lastSync", 0.0)
print "Pref that might not exist:",
print prefs.get("does.not.exist", "default")
Alternatives
Write a firefox-addon that dumps interesting Preferences to a known file, or uses another form of IPC (sockets, whatever) to communicate with your python script.
Occasionally it would be preferable to have some initialization code for palettes (of buttons). For example, it could define some functions that are used by palette buttons.
What is the easiest and preferable way to define/run initialization code for a palette?
The initialization can run either when the palette is loaded or when any button is pressed for the first time (possible issue: what if the kernel is restarted after the palette was loaded?)
The definitions should be somehow localized (i.e. in their own context -- do unique notebook contexts help here?)
If possible, I'd prefer a minimal effort solution (i.e. extra code at the fewest possible places, self contained palette file with no extra package files, palette creation using the existing convenience tools of palettes menu or CreatePalette, etc.)
(You can assume that the initialization code runs fast, e.g. it consists of definitions only)
You're right to be concerned about the visibility of the Dynamic being an issue. The way to absolutely guarantee a Dynamic expression to be evaluated regardless of the visibility of any of the individual cells is to use NotebookDynamicExpression. Here's an example that illustrates NotebookDynamicExpression working while a Dynamic fails because it's hidden within a closed cell group:
cell1 = First # MakeBoxes[
TextCell["Click to open", "Title",
CellMargins -> 0, System`WholeCellGroupOpener -> True],
StandardForm];
cell2 = First # MakeBoxes[
ExpressionCell[DynamicWrapper["hidden cell", Print["DynamicWrapper"]]],
StandardForm];
CreatePalette[
Notebook[{Cell[CellGroupData[{cell1, cell2}, Closed]]},
NotebookDynamicExpression :>
Dynamic[Refresh[Print["NotebookDynamicExpression"], None]]]]
When you evaluate this, note that the Dynamic in NotebookDynamicExpression evaluates immediately. The DynamicWrapper never evaluates until you open the cell group, which you can do by clicking on the "Click to open" text.
In this example, incidentally, notice that I wrapped the NotebookDynamicExpression with Refresh. The function Refresh[#, None]& will make sure that the code evaluates only once -- when the notebook is first opened. Otherwise, the code would obey the standard properties of Dynamic and evaluate whenever any of the dependencies change.
NotebookDynamicExpression has been around since v6, but was only documented in v8. Also documented are its related cousins, CellDynamicExpression and FrontEndDynamicExpression.
A DynamicBox with Initialization is capable of the basic function. You can size the palette such that the object is not visible, and it will still operate.
Here is code for a small sample palette. It sets a value for var. The active code is offset with whitespace.
(* Beginning of Notebook Content *)
Notebook[{
Cell[BoxData[{
TagBox[GridBox[{
{
ButtonBox["\<\"TSV\"\>",
Appearance->Automatic,
ButtonFunction:>None,
Evaluator->Automatic,
Method->"Preemptive"]},
{
ButtonBox["\<\"CSV\"\>",
Appearance->Automatic,
ButtonFunction:>None,
Evaluator->Automatic,
Method->"Preemptive"]},
{
ButtonBox["\<\"Table\"\>",
Appearance->Automatic,
ButtonFunction:>None,
Evaluator->Automatic,
Method->"Preemptive"]}
},
GridBoxAlignment->{"Columns" -> {{Left}}},
GridBoxItemSize->{"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}],
"Column"], "\[IndentingNewLine]",
DynamicBox[Null,
Initialization :> ($CellContext`var = "It is done, Master.")
]
}], NotebookDefault,
CellMargins->{{0, 0}, {0, 0}},
CellBracketOptions->{"Color"->RGBColor[0.269993, 0.308507, 0.6]},
CellHorizontalScrolling->True,
PageBreakAbove->True,
PageBreakWithin->False,
ShowAutoStyles->True,
LineSpacing->{1.25, 0},
AutoItalicWords->{},
ScriptMinSize->9,
ShowStringCharacters->False,
FontFamily:>CurrentValue["PanelFontFamily"],
FontSize:>CurrentValue["PanelFontSize"]]
},
WindowSize->{55, 105},
WindowMargins->{{Automatic, 583}, {Automatic, 292}},
WindowFrame->"Palette",
WindowElements->{},
WindowFrameElements->{"CloseBox", "MinimizeBox"},
StyleDefinitions->"Palette.nb"
]
(* End of Notebook Content *)
My simple first Palette is suppose to:
Append my packages Path to $Path
ActionMenu["test",{"The Simple Packages Path":> AppendTo[$Path, ToFileName[{NotebookDirectory[], "02 Simple Packages"}]]}]
Get my packages
ActionMenu["Load Packages", {"Get my package":> Get["myPackage`"]}]
Place on the selected input cell (or on a new input cell), a given input expression, containing different place holders.
OpenerView[{"my Package", Button["construct", Paste[StandardForm#Defer#construct[Placeholder["description"],Placeholder["another description"]]]]}]
The problem is that I keep getting "shadow" messages when I click on the "get my package" action menu item. And I'm sure I'm not double loading the package intentionally. When I click on "construct", it writes Global`construct["description","another description"]. But I'm sure I didn't define it before getting the package (I killed the kernel on my tests).
Do you know what is wrong?
(I use Get on my packages, instead of Needs, to ensure a clean start of the package context)
Also: do you know of a simpler way of doing the Paste[StandardForm#Defer... that ensures both that the expression being paste isn't evaluated and that it goes into an input cell, even when there's no cell selected?
Ok, it seems that your problem is due to the interplay between parsing and interface creation. What you would like in this case is to delay the parsing of package symbols in your interface - constructing code (package symbols that you use in button action functions), from the interface - creation time, until the "press button" time (assuming that by that time, the package has been loaded). Here is one way to do it:
Column[{ActionMenu["Load Packages",
{"Get my package" :> Get["ANOVA`"]}],
OpenerView[{"ANOVA", Button["construct",
With[{sym = Symbol["ANOVA"]},
Paste[StandardForm#Defer#sym[Placeholder["DATA"]]]]]}]}]
What we did here is to use With to inject the symbol into the code for the button function. But, at the time your interface code is parsed, we prevent the creation of the Global symbol with this name - this is what happens otherwise, and this is what causes your problem.
EDIT
If you know for sure that you only use symbols (functions) from packages, and not from the Global' context, here is a version that will be "protected" from this problem: it will Remove the generated symbol if its context turns out to be Global' - and thus pressing button before the package has been loaded would result merely in a warning message (I use the symbol package to attach the message to - should be replaced by whatever is the name of your interface - making function):
package::noload = "Please load the package containing symbol `1`";
Column[{ActionMenu["Load Packages",
{"Get my package" :> Get["ANOVA`"]}],
OpenerView[{"ANOVA", Button["construct",
With[{sym = Symbol["ANOVA"]},
If[Context[sym] === "Global`",
Message[package::noload, Style[ToString[sym], Red]];
Remove[sym];,
(* else *)
Paste[StandardForm#Defer#sym[Placeholder["DATA"]]]]]]}]}]
Well, I don't have your package, so for testing I changed the action menu to get the ANOVA package:
ActionMenu["Load Packages", {"Get my package" :> Get["ANOVA`"]}]
ANOVA[{{1, 1}, {1, 2}, {2, 4}, {2, 3}}] now works without a hitch. No complaints about shadowing. This suggests that the cause of your shadowing problem lies somewhere else. I noticed, though, that the word ANOVA stays blue. This will be related to the problem you reported here.
I would like to accomplish the following: upon evaluation of an input cell, it should self-destruct (i.e. delete itself). I tried to hack something together with SelectionMove and NotebookDelete, but didn't quite get what I wanted.
Here are potential use cases:
the command might be a shorthand for a series of other commands that will be generated dynamically and inserted into the notebook
the command might only be used for side effects (e.g. to set a notebook option or to open a new notebook); leaving the command in the notebook after evaluation serves no purpose and creates clutter
Edit: As per Mr. Wizard, the answer is SelectionMove[EvaluationNotebook[], Previous, Cell]; NotebookDelete[];. I don't know why it wasn't working for me before. Here is some code that uses this idiom.
writeAndEval[nb_, boxExpr_] := (NotebookWrite[nb,
CellGroupData[{Cell[BoxData[boxExpr], "Input"]}]];
SelectionMove[nb, Previous, Cell];
SelectionMove[nb, Next, Cell];
SelectionEvaluate[nb]);
addTwoAndTwo[] := Module[{boxExpr},
boxExpr = RowBox[{"2", "+", "2"}];
SelectionMove[EvaluationNotebook[], Previous, Cell];
NotebookDelete[];
writeAndEval[EvaluationNotebook[], boxExpr];
]
Now, running addTwoAndTwo[] deletes the original input and makes it look as if you've evaluated "2+2". Of course, you can do all sorts of things instead and not necessarily print to the notebook.
Edit 2: Sasha's abstraction is quite elegant. If you are curious about "real-world" usage of this, check out the code I posted in the "what's in your toolbag" question: What is in your Mathematica tool bag?
To affect all Input cells, evaluate this is the notebook:
SetOptions[EvaluationNotebook[], CellEvaluationFunction ->
( (
SelectionMove[EvaluationNotebook[], All, EvaluationCell]; NotebookDelete[];
ToExpression##
)&)
]
If you only want to affect one cell, then select the cell and use the Options Inspector to set CellEvaluationFunction as above.
Or, building on Mr. Wizard's solution, you can create a function SelfDestruct, which will delete the input cell, if you intend to only do this occasionally:
SetAttributes[SelfDestruct, HoldAllComplete];
SelfDestruct[e_] := (If[$FrontEnd =!= $Failed,
SelectionMove[EvaluationNotebook[], All, EvaluationCell];
NotebookDelete[]]; e)
Then evaluating 2+3//SelfDestruct outputs 5 and deletes the input cell. This usage scenario seems more appealing to me.