10
$\begingroup$

The current documentation search doesn't allow for very sophisticate searching, can I write my own function to search through the docs?

$\endgroup$
10
$\begingroup$

Update

This code is no longer the most up-to-date. The properly up-to-date code is in the package on GitHub.

For a run-down of the changes between this and that see the discussion between b3m2a1 and Nasser that starts here and the commit messages.


The key here will be that all properly written documentation pages have a "Metadata" TaggingRule.

Then we can use the PacletManager to search and scrape all of this. First we'll build an index of all this stuff and put it in $helpSearcherDocData

loadDocumentationData[] :=
 $helpSearcherDocData =
  Append[#,
     "Pages" ->
      Apply[Join]@
       Map[FileNames["*.nb", Last[#], \[Infinity]] &, #["Directories"]]
     ] &@
   <|
    "Directories" ->
     Join[
      DeleteDuplicatesBy[#[[1]]["Name"] &]@
       Select[DirectoryQ@*Last]@
        Map[
         # -> FileNameJoin[{#["Location"], "Documentation"}] &,
         PacletFind["*"]
         ],
      {"System" -> FileNameJoin[{$InstallationDirectory, "Documentation"}]}
    |>

loadDocumentationMetadata[] :=
 (
  If[! AssociationQ@$helpSearcherDocData, loadDocumentationData[]];
  $helpSearcherDocData["Metadata"] =
   Association@
    Map[
     # :>
       Set[
        $helpSearcherDocData["Metadata", #],
        Append[
         Fold[Association@Lookup[#, #2, {}] &, 
          Options[Import[#]], {TaggingRules, "Metadata"}],
         "File" -> #
         ]
        ] &,
     $helpSearcherDocData["Pages"]
     ]
  )

ensureLoadedDocumentationMetadata[] :=

 If[! AssociationQ@$helpSearcherDocData || ! 
    KeyMemberQ[$helpSearcherDocData, "Metadata"],
  loadDocumentationMetadata[]
  ]

preLoadDocumentationMetadata[] :=

(ensureLoadedDocumentationMetadata[]; 
  Scan[Identity, $helpSearcherDocData["Metadata"]])

preLoadDocumentationMetadata[]

For convenience we can then cache all this, so it's quicker to load later:

loadCachedDocumentationData[] :=
  $helpSearcherDocData = 
   Get[LocalObject["docsDataCache"]];
cacheDocumentationData[] :=

  Put[$helpSearcherDocData, LocalObject["docsDataCache"]];

Then we can do simple searches on this "Metadata" dataset:

$helpSearcherDocMetadataDS :=
  $helpSearcherDocMetadataDS =
   (
    preLoadDocumentationMetadata[];
    Dataset@
     Select[Values@$helpSearcherDocData["Metadata"], KeyMemberQ["uri"]]
    );

$helpSearcherDocMetadataDS[
   Select[Length[#history] > 1 && 
      0 < ToExpression@#history[[1]] < 8 &],
   "context"
   ] // DeleteDuplicates // Normal

{"JLink`", "NETLink`", "WebServices`", "ClusterIntegration`", "", \
"GUIKit`"}

This gives us the contexts that were documented before version 8.

We can then do searches on any of the following properties:

$helpSearcherDocMetadataDS[All, Keys] // Flatten // 
  DeleteDuplicates // Normal

{"built", "history", "context", "keywords", "specialkeywords", \
"tutorialcollectionlinks", "index", "label", "language", "paclet", \
"status", "summary", "synonyms", "tabletags", "title", \
"titlemodifier", "windowtitle", "type", "uri", "File"}

For instance let's get all of the obsolete functions:

$helpSearcherDocMetadataDS[All, "status"] // Flatten // 
  DeleteDuplicates // Normal

{"None", "ObsoleteFlag"}

$helpSearcherDocMetadataDS[
  Select[#type === "Symbol" && #status === "ObsoleteFlag" &], 
  StringRiffle[URLParse[#["uri"], "Path"][[{1, -1}]], "`"] &
  ] // Normal

{"GUIKit`BindEvent", "GUIKit`CloseGUIObject", \
"GUIKit`ExposeWidgetReferences", "GUIKit`GUIInformation", \
"GUIKit`GUILoad", "GUIKit`GUIObject", "GUIKit`GUIObjectQ", \
"GUIKit`GUIResolve", "GUIKit`GUIRunModal", "GUIKit`GUIRun", \
"GUIKit`GUIScreenShot", "GUIKit`IncludedScriptContexts", \
"GUIKit`InitialArguments", "GUIKit`InvokeMethod", \
"GUIKit`InvokeThread", "GUIKit`InvokeWait", "GUIKit`Name", \
"GUIKit`PropertyValue", "GUIKit`ReleaseGUIObject", \
"GUIKit`ReleaseMethod", "GUIKit`ReturnScript", "GUIKit`Script", \
"GUIKit`ScriptSource", "GUIKit`SetPropertyValue", \
"GUIKit`SetWidgetReference", "GUIKit`SymbolicGUIKitXMLToWidget", \
"GUIKit`Tabs", "GUIKit`UnsetWidgetReference", "GUIKit`WidgetAlign", \
"GUIKit`WidgetFill", "GUIKit`WidgetGroup", "GUIKit`WidgetLayout", \
"GUIKit`Widget", "GUIKit`WidgetReference", "GUIKit`WidgetSpace", \
"GUIKit`WidgetToSymbolicGUIKitXML", "GUIKit`$GUIPath"}

From this data an update to the old help browser could even be rebuilt

Finally, here's a proper doc searcher that returns links to the proper doc pages:

helpSearch[selectionFunction_] :=

 Hyperlink[#, "paclet:" <> #2, 
    BaseStyle -> "Link"] & @@@
  $helpSearcherDocMetadataDS[
   Select[selectionFunction],
   {"title", "uri"}
   ]

Repeating that obsolescence search:

helpSearch[#type === "Symbol" && #status === "ObsoleteFlag" &]

search result

And clicking any of those links opens up the doc page:

click result

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.