git.iko.soy/rowtype-yoga/purescript-docs-search
on master help sign in
Add --package-name flag:

- Allows to specify current package name that will be used in the results; Add Meta: - Allows to store some static info, as for now - just local package name; Code style improvements.

commit86304888a4991ef7f1e36e0587ff3622f51cfdff authorklntsky <klntsky@gmail.com> dateMon 3 Aug 2020, 13:59 (6 years ago) parent6350561
11 files changed+191−52
src/Docs/Search/App.purs+7−1 src/Docs/Search/App/SearchResults.purs+20−14 src/Docs/Search/Config.purs+10 src/Docs/Search/Engine.purs+5−5 src/Docs/Search/IndexBuilder.purs+18−6 src/Docs/Search/Interactive.purs+17−13 src/Docs/Search/Loader.js+26 src/Docs/Search/Loader.purs+37 src/Docs/Search/Main.purs+24−13 src/Docs/Search/Meta.purs+21 src/Docs/Search/Types.purs+6
src/Docs/Search/App.purs+7−1
@@ -16,6 +16,7 @@ import Docs.Search.Config (config)
1616import Docs.Search.Extra (whenJust)
1717import Docs.Search.ModuleIndex as ModuleIndex
1818import Docs.Search.PackageIndex as PackageIndex
19+import Docs.Search.Meta as Meta
1920import Effect (Effect)
2021import Effect.Aff (launchAff_)
2122import Halogen as H
@@ -63,6 +64,7 @@ main = do
6364 HA.runHalogenAff do
6465 packageIndex <- PackageIndex.loadPackageIndex
6566 moduleIndex <- ModuleIndex.unpackModuleIndex <$> ModuleIndex.loadModuleIndex
67+ meta <- Meta.load
6668 let scores = PackageIndex.mkScoresFromPackageIndex packageIndex
6769
6870 let initialSearchEngineState = { packageIndex
@@ -73,7 +75,11 @@ main = do
7375 }
7476
7577 resultsComponent =
76− SearchResults.mkComponent initialSearchEngineState pageContents markdownIt
78+ SearchResults.mkComponent
79+ initialSearchEngineState
80+ pageContents
81+ markdownIt
82+ meta
7783
7884 sfio <- runUI SearchField.component unit searchField
7985 srio <- runUI resultsComponent unit searchResults
src/Docs/Search/App/SearchResults.purs+20−14
@@ -14,7 +14,8 @@ import Docs.Search.PackageIndex (PackageResult)
1414import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
1515import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), Kind(..), QualifiedName(..), Type(..), TypeArgument(..), joinForAlls, joinRows)
1616import Docs.Search.TypeIndex (TypeIndex)
17−import Docs.Search.Types (ModuleName(..), Identifier(..))
17+import Docs.Search.Types (Identifier(..), ModuleName(..), PackageName)
18+import Docs.Search.Meta (Meta)
1819
1920import Prelude
2021
@@ -56,6 +57,7 @@ type State = { engineState :: EngineState
5657 , resultsCount :: Int
5758 , mode :: Mode
5859 , markdownIt :: MD.MarkdownIt
60+ , localPackageName :: PackageName
5961 }
6062
6163
@@ -73,8 +75,9 @@ mkComponent
7375 . EngineState
7476 -> Element
7577 -> MD.MarkdownIt
78+ -> Meta
7679 -> H.Component HH.HTML Query i o Aff
77−mkComponent initialEngineState contents markdownIt =
80+mkComponent initialEngineState contents markdownIt { localPackageName } =
7881 H.mkComponent
7982 { initialState: const { engineState: initialEngineState
8083 , results: []
@@ -83,6 +86,7 @@ mkComponent initialEngineState contents markdownIt =
8386 , resultsCount: config.resultsCount
8487 , mode: Off
8588 , markdownIt
89+ , localPackageName
8690 }
8791 , render
8892 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery
@@ -191,13 +195,12 @@ render state@{ mode: Active, results: [] } =
191195 , HH.text " did not yield any results."
192196 ]
193197 ]
194−
195198render state@{ mode: Active } =
196199 renderContainer $
197200 [ HH.h1_ [ HH.text "Search results" ]
198201
199202 , HH.div_ $
200− Array.concat $ shownResults <#> renderResult state.markdownIt
203+ Array.concat $ shownResults <#> renderResult state
201204
202205 , HH.div [ HP.class_ (wrap "load_more"), HP.id_ "load-more" ]
203206 [ if Array.length shownResults < Array.length state.results
@@ -211,7 +214,6 @@ render state@{ mode: Active } =
211214 where
212215 shownResults = Array.take state.resultsCount state.results
213216
214−
215217renderContainer :: forall a b. Array (HH.HTML b a) -> HH.HTML b a
216218renderContainer =
217219 HH.div [ HP.classes [ wrap "container", wrap "clearfix" ] ] <<<
@@ -229,13 +231,17 @@ renderSummary text =
229231
230232renderResult
231233 :: forall a
232− . MD.MarkdownIt
234+ . State
233235 -> Result
234236 -> Array (HH.HTML a Action)
235−renderResult markdownIt (DeclResult r) = renderSearchResult markdownIt r
236−renderResult markdownIt (TypeResult r) = renderSearchResult markdownIt r
237−renderResult markdownIt (PackResult r) = renderPackageResult r
238−renderResult markdownIt (MdlResult r) = renderModuleResult r
237+renderResult state (DeclResult r) =
238+ renderSearchResult state r
239+renderResult state (TypeResult r) =
240+ renderSearchResult state r
241+renderResult state (PackResult r) =
242+ renderPackageResult r
243+renderResult state (MdlResult r) =
244+ renderModuleResult r
239245
240246
241247renderPackageResult
@@ -291,10 +297,10 @@ renderModuleResult { name, package } =
291297
292298renderSearchResult
293299 :: forall a
294− . MD.MarkdownIt
300+ . State
295301 -> SearchResult
296302 -> Array (HH.HTML a Action)
297−renderSearchResult markdownIt (SearchResult result) =
303+renderSearchResult state (SearchResult result) =
298304 -- class names here and below are from Pursuit.
299305 [ HH.div [ HP.class_ (wrap "result") ]
300306 [ HH.h3 [ HP.class_ (wrap "result__title") ]
@@ -311,7 +317,7 @@ renderSearchResult markdownIt (SearchResult result) =
311317 , HH.div [ HP.class_ (wrap "result__body") ] $
312318 renderResultType result <>
313319
314− result.comments >#> pure <<< MDH.render_ markdownIt
320+ result.comments >#> pure <<< MDH.render_ state.markdownIt
315321
316322 , HH.div [ HP.class_ (wrap "result__actions") ]
317323
@@ -322,7 +328,7 @@ renderSearchResult markdownIt (SearchResult result) =
322328 , HP.title "Package"
323329 ]
324330 [ HH.text "P" ]
325− , HH.text $ packageInfoToString result.packageInfo
331+ , HH.text $ packageInfoToString state.localPackageName result.packageInfo
326332 ]
327333
328334 , HH.span [ HP.class_ (wrap "result__actions__item") ]
src/Docs/Search/Config.purs+10
@@ -2,6 +2,8 @@ module Docs.Search.Config where
22
33import Prelude
44
5+import Docs.Search.Types (PackageName(..))
6+
57-- | Some magic constants.
68config ::
79 { version :: String
@@ -10,6 +12,9 @@ config ::
1012 , mkIndexPartPath :: Int -> String
1113 , moduleIndexPath :: String
1214 , moduleIndexLoadPath :: String
15+ , metaPath :: String
16+ , metaLoadPath :: String
17+ , metaItem :: String
1318 , groupModulesItem :: String
1419 , packageInfoPath :: String
1520 , packageInfoLoadPath :: String
@@ -28,6 +33,7 @@ config ::
2833 , requiredDirectories :: Array String
2934 , resultsCount :: Int
3035 , typeIndexDirectory :: String
36+ , defaultPackageName :: PackageName
3137 }
3238config =
3339 { version: "0.0.9"
@@ -51,6 +57,9 @@ config =
5157 , moduleIndexPath: "generated-docs/html/index/modules.js"
5258 , moduleIndexLoadPath: "./index/modules.js"
5359 -- ^ Used to load mode index to the browser scope.
60+ , metaPath: "generated-docs/html/index/meta.js"
61+ , metaLoadPath: "./index/meta.js"
62+ , metaItem: "DocsSearchMeta"
5463 , groupModulesItem: "PureScriptDocsSearchGroupModules"
5564 -- ^ localStorage key to save sidebar checkbox value to.
5665 , packageInfoPath: "generated-docs/html/index/packages.js"
@@ -69,4 +78,5 @@ config =
6978 }
7079 -- ^ Penalties used to determine how "far" a type query is from a given type.
7180 -- See Docs.Search.TypeQuery
81+ , defaultPackageName: PackageName "<local package>"
7282 }
src/Docs/Search/Engine.purs+5−5
@@ -160,8 +160,8 @@ sortByDistance typeQuery =
160160 Array.sortWith (map (penalty typeQuery) <<< typeOfResult)
161161
162162
163−packageInfoToString :: PackageInfo -> String
164−packageInfoToString (Package (PackageName p)) = p
165−packageInfoToString Builtin = "<builtin>"
166−packageInfoToString LocalPackage = "<local package>"
167−packageInfoToString UnknownPackage = "<unknown package>"
163+packageInfoToString :: PackageName -> PackageInfo -> String
164+packageInfoToString _ (Package (PackageName p)) = p
165+packageInfoToString _ Builtin = "<builtin>"
166+packageInfoToString localPackageName LocalPackage = unwrap localPackageName
167+packageInfoToString _ UnknownPackage = "<unknown package>"
src/Docs/Search/IndexBuilder.purs+18−6
@@ -10,6 +10,8 @@ import Docs.Search.PackageIndex (PackageInfo, mkPackageInfo)
1010import Docs.Search.Score (mkScores)
1111import Docs.Search.SearchResult (SearchResult)
1212import Docs.Search.TypeIndex (TypeIndex, mkTypeIndex)
13+import Docs.Search.Types (PackageName)
14+import Docs.Search.Meta (Meta)
1315
1416import Prelude
1517import Data.Argonaut.Core (stringify)
@@ -49,6 +51,7 @@ type Config =
4951 , bowerFiles :: Array String
5052 , generatedDocs :: String
5153 , noPatch :: Boolean
54+ , packageName :: PackageName
5255 }
5356
5457
@@ -67,12 +70,15 @@ run' cfg = do
6770 docsJsons <- decodeDocsJsons cfg
6871 packageMetas <- decodeBowerJsons cfg
6972
73+ let countOfPackages = Array.length packageMetas
74+ countOfModules = Array.length docsJsons
75+
7076 liftEffect do
7177 log $
7278 "Indexing " <>
73− show (Array.length docsJsons) <>
79+ show countOfModules <>
7480 " modules from " <>
75− show (Array.length packageMetas) <>
81+ show countOfPackages <>
7682 " packages..."
7783
7884 let scores = mkScores packageMetas
@@ -80,6 +86,7 @@ run' cfg = do
8086 typeIndex = mkTypeIndex scores docsJsons
8187 packageInfo = mkPackageInfo scores packageMetas
8288 moduleIndex = mkPackedModuleIndex index
89+ meta = { localPackageName: cfg.packageName }
8390
8491 createDirectories cfg
8592
@@ -88,15 +95,13 @@ run' cfg = do
8895 <*> parallel (writeTypeIndex cfg typeIndex)
8996 <*> parallel (writePackageInfo packageInfo)
9097 <*> parallel (writeModuleIndex moduleIndex)
91− <*> parallel (if cfg.noPatch
92− then pure unit
93− else patchDocs cfg)
98+ <*> parallel (writeMeta meta)
99+ <*> parallel (when (not cfg.noPatch) $ patchDocs cfg)
94100 <*> parallel (copyAppFile cfg)
95101
96102 let countOfDefinitions = Trie.size $ unwrap index
97103 countOfTypeDefinitions =
98104 sum $ fromMaybe 0 <$> map Array.length <$> Map.values (unwrap typeIndex)
99− countOfPackages = Array.length packageMetas
100105
101106 liftEffect do
102107 log $
@@ -231,6 +236,13 @@ writeModuleIndex moduleIndex = do
231236 where
232237 header = "window.DocsSearchModuleIndex = "
233238
239+writeMeta :: Meta -> Aff Unit
240+writeMeta meta = do
241+ writeTextFile UTF8 config.metaPath $
242+ header <> stringify (encodeJson meta)
243+ where
244+ header = "window." <> config.metaItem <> " = "
245+
234246-- | Get a mapping from index parts to index contents.
235247getIndex :: Declarations -> Map Int (Array (Tuple String (Array SearchResult)))
236248getIndex (Declarations trie) =
src/Docs/Search/Interactive.purs+17−13
@@ -16,7 +16,7 @@ import Docs.Search.Terminal (bold, cyan, green, yellow)
1616import Docs.Search.TypeDecoder (Constraint, FunDeps, Kind, QualifiedName, Type, TypeArgument)
1717import Docs.Search.TypeIndex (resultsWithTypes)
1818import Docs.Search.TypePrinter (keyword, showConstraint, showFunDeps, showKind, showType, showTypeArgument, space, syntax)
19−import Docs.Search.Types (ModuleName, PackageInfo, Identifier)
19+import Docs.Search.Types (ModuleName, PackageName, PackageInfo, Identifier)
2020
2121import Prelude
2222
@@ -38,6 +38,7 @@ import Node.ReadLine (createConsoleInterface, question)
3838type Config =
3939 { docsFiles :: Array String
4040 , bowerFiles :: Array String
41+ , packageName :: PackageName
4142 }
4243
4344
@@ -88,7 +89,7 @@ run cfg = launchAff_ $ do
8889 Console.log $
8990 if total > 0 then do
9091 Array.intercalate "\n\n\n" $
91− showResult <$> Array.reverse results
92+ showResult cfg <$> Array.reverse results
9293 else
9394 "Your search for " <> bold input <> " did not yield any results."
9495
@@ -114,16 +115,16 @@ mkCompleter index input = do
114115 pure { completions: paths, matched: input }
115116
116117
117−showResult :: Result -> String
118−showResult = case _ of
119− DeclResult r -> showSearchResult r
120− TypeResult r -> showSearchResult r
118+showResult :: Config -> Result -> String
119+showResult cfg = case _ of
120+ DeclResult r -> showSearchResult cfg r
121+ TypeResult r -> showSearchResult cfg r
121122 PackResult r -> showPackageResult r
122123 MdlResult r -> showModuleResult r
123124
124125
125−showSearchResult :: SearchResult -> String
126−showSearchResult (SearchResult result@{ name, comments, moduleName, packageInfo }) =
126+showSearchResult :: Config -> SearchResult -> String
127+showSearchResult cfg (SearchResult result@{ name, comments, moduleName, packageInfo }) =
127128 showSignature result <> "\n" <>
128129
129130 (fromMaybe "\n" $
@@ -131,10 +132,10 @@ showSearchResult (SearchResult result@{ name, comments, moduleName, packageInfo
131132 "\n" <> leftShift 3 (String.trim comment) <> "\n\n") <>
132133
133134 bold (
134− cyan (rightPad 40 $ packageInfoToString packageInfo)
135+ cyan (rightPad 40 $ packageInfoToString cfg.packageName packageInfo)
135136 ) <>
136137 space <>
137− bold (green $ unwrap moduleName)
138+ showModuleName moduleName
138139
139140
140141showPackageResult :: PackageResult -> String
@@ -146,7 +147,11 @@ showPackageResult { name, description } =
146147
147148showModuleResult :: ModuleResult -> String
148149showModuleResult { name, package } =
149− bold (cyan "module") <> " " <> bold (green $ unwrap name)
150+ bold (cyan "module") <> " " <> showModuleName name
151+
152+
153+showModuleName :: ModuleName -> String
154+showModuleName = bold <<< green <<< unwrap
150155
151156
152157showSignature
@@ -204,8 +209,7 @@ showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName }
204209 superclasses <#> showConstraint
205210 )
206211 ) <>
207− syntax ")" <>
208− space <>
212+ syntax ") " <>
209213 syntax "<="
210214 ) <>
211215 space <>
src/Docs/Search/Loader.jsnew file+26
@@ -0,0 +1,26 @@
1+/* global exports */
2+
3+exports.loadFromScript = function (globalIdentifier) {
4+ return function (url) {
5+ return function () {
6+ return new Promise(function (resolve, reject) {
7+ if (typeof window[globalIdentifier] === 'undefined') {
8+ var script = document.createElement('script');
9+ script.type = 'text/javascript';
10+ script.src = url;
11+ script.addEventListener('load', function () {
12+ if (typeof window[globalIdentifier] === 'undefined') {
13+ reject(new Error("Couldn't load package index."));
14+ } else {
15+ resolve(window[globalIdentifier]);
16+ }
17+ });
18+ script.addEventListener('error', reject);
19+ document.body.appendChild(script);
20+ } else {
21+ resolve(window[globalIdentifier]);
22+ }
23+ });
24+ };
25+ };
26+};
src/Docs/Search/Loader.pursnew file+37
@@ -0,0 +1,37 @@
1+module Docs.Search.Loader where
2+
3+import Docs.Search.Types (GlobalIdentifier, URL)
4+
5+import Prelude
6+
7+import Control.Monad.Error.Class (throwError)
8+import Control.Promise (Promise, toAffE)
9+import Data.Argonaut.Core (Json)
10+import Data.Argonaut.Decode.Class (class DecodeJson, decodeJson)
11+import Data.Either (either)
12+import Data.Newtype (unwrap)
13+import Effect (Effect)
14+import Effect.Aff (Aff)
15+import Effect.Exception (error)
16+
17+
18+
19+load
20+ :: forall a
21+ . DecodeJson a
22+ => GlobalIdentifier
23+ -> URL
24+ -> Aff a
25+load globalIdentifier url = do
26+ json <- toAffE (loadFromScript globalIdentifier url)
27+ either throw pure $ decodeJson json
28+ where
29+ throw err = throwError $ error $
30+ "Couldn't load content from window." <>
31+ unwrap globalIdentifier <> ": " <> err
32+
33+
34+foreign import loadFromScript
35+ :: GlobalIdentifier
36+ -> URL
37+ -> Effect (Promise Json)
src/Docs/Search/Main.purs+24−13
@@ -6,12 +6,14 @@ import Prelude
66import Docs.Search.IndexBuilder as IndexBuilder
77import Docs.Search.Interactive as Interactive
88import Docs.Search.Config (config)
9+import Docs.Search.Types (PackageName(..))
910
1011import Data.Generic.Rep (class Generic)
1112import Data.Generic.Rep.Show (genericShow)
1213import Data.List as List
1314import Data.List.NonEmpty as NonEmpty
1415import Data.Maybe (Maybe, fromMaybe, optional)
16+import Data.Newtype (unwrap)
1517import Data.Unfoldable (class Unfoldable)
1618import Effect (Effect)
1719import Effect.Console (log)
@@ -23,7 +25,10 @@ main :: Effect Unit
2325main = do
2426
2527 args <- getArgs
26− let defaultCommands = Search { docsFiles: defaultDocsFiles, bowerFiles: defaultBowerFiles }
28+ let defaultCommands = Search { docsFiles: defaultDocsFiles
29+ , bowerFiles: defaultBowerFiles
30+ , packageName: config.defaultPackageName
31+ }
2732
2833 case fromMaybe defaultCommands args of
2934 BuildIndex cfg -> IndexBuilder.run cfg
@@ -42,16 +47,8 @@ getArgs = execParser opts
4247
4348
4449data Commands
45− = BuildIndex
46− { docsFiles :: Array String
47− , bowerFiles :: Array String
48− , generatedDocs :: String
49− , noPatch :: Boolean
50− }
51− | Search
52− { docsFiles :: Array String
53− , bowerFiles :: Array String
54− }
50+ = BuildIndex IndexBuilder.Config
51+ | Search Interactive.Config
5552 | Version
5653
5754
@@ -88,6 +85,8 @@ buildIndex = ado
8885
8986 bowerFiles <- bowerFilesOption
9087
88+ packageName <- packageNameOption
89+
9190 generatedDocs <- strOption
9291 ( long "generated-docs"
9392 <> metavar "DIR"
@@ -99,7 +98,8 @@ buildIndex = ado
9998 <> help "Do not patch the HTML docs, only build indices"
10099 )
101100
102− in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch }
101+
102+ in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch, packageName }
103103
104104
105105startInteractive :: Parser Commands
@@ -109,7 +109,9 @@ startInteractive = ado
109109
110110 bowerFiles <- bowerFilesOption
111111
112− in Search { docsFiles, bowerFiles }
112+ packageName <- packageNameOption
113+
114+ in Search { docsFiles, bowerFiles, packageName }
113115
114116
115117docsFilesOption :: Parser (Array String)
@@ -136,6 +138,15 @@ bowerFilesOption = fromMaybe defaultBowerFiles <$>
136138 )
137139
138140
141+packageNameOption :: Parser PackageName
142+packageNameOption =
143+ PackageName <$> strOption
144+ ( long "package-name"
145+ <> metavar "PACKAGE"
146+ <> value (unwrap $ config.defaultPackageName)
147+ )
148+
149+
139150defaultDocsFiles :: Array String
140151defaultDocsFiles = [ "output/**/docs.json" ]
141152
src/Docs/Search/Meta.pursnew file+21
@@ -0,0 +1,21 @@
1+module Docs.Search.Meta where
2+
3+import Docs.Search.Config (config)
4+import Docs.Search.Loader as Loader
5+import Docs.Search.Types (GlobalIdentifier(..), PackageName)
6+
7+import Prelude
8+
9+import Effect.Aff (Aff, catchError)
10+
11+
12+type Meta =
13+ { localPackageName :: PackageName
14+ }
15+
16+
17+load :: Aff Meta
18+load =
19+ Loader.load (GlobalIdentifier config.metaItem) config.metaLoadPath
20+ `catchError` const (pure defaultMeta)
21+ where defaultMeta = { localPackageName: config.defaultPackageName }
src/Docs/Search/Types.purs+6
@@ -74,3 +74,9 @@ derive newtype instance ringPackageScore :: Ring PackageScore
7474derive newtype instance showPackageScore :: Show PackageScore
7575derive newtype instance decodeJsonPackageScore :: DecodeJson PackageScore
7676derive newtype instance encodeJsonPackageScore :: EncodeJson PackageScore
77+
78+type URL = String
79+
80+newtype GlobalIdentifier = GlobalIdentifier String
81+
82+derive instance newtypeGlobalIdentifier :: Newtype GlobalIdentifier _