on master help sign in
Try faster search
0bac6f6iko
frontend/Pages/Ciphers.elm+11−12
@@ -5,6 +5,7 @@ import Html exposing (..)
5import Html.Attributes as Attr
5import Html.Attributes as Attr
6import Html.Events as Ev
6import Html.Events as Ev
7import Html.Keyed as Keyed
7import Html.Keyed as Keyed
8+import Html.Lazy as Lazy
8import Page exposing (..)
9import Page exposing (..)
9import Pages.Navigation as Navigation
10import Pages.Navigation as Navigation
10import Search
11import Search
@@ -143,7 +144,7 @@ update { logOut } liftMsg msg model =
143
144
144
145
145subscriptions : Model -> Sub Msg
146subscriptions : Model -> Sub Msg
146−subscriptions model =
147+subscriptions _ =
147 Sub.none
148 Sub.none
148
149
149
150
@@ -157,10 +158,16 @@ view { selected } liftMsg { ciphers, search, ciphersListFilter } =
157 , Attr.attribute "autocomplete" "off"
158 , Attr.attribute "autocomplete" "off"
158 ]
159 ]
159 []
160 []
161+ , ciphers
162+ |> applyCipherFilter ciphersListFilter
163+ |> Search.searchList search .name (Lazy.lazy2 showCiphers selected)
164+ ]
165+
166+
167+showCiphers : (String -> msg) -> Bridge.Sub_LoadCiphers_List -> Html msg
168+showCiphers selected ciphers =
160− , Keyed.ul [ Attr.class "p-list--divided" ]
169+ Keyed.ul [ Attr.class "p-list--divided" ]
161 (ciphers
170 (ciphers
162− |> applyCipherFilter ciphersListFilter
163− |> Search.searchList (cipherSearch search)
164 |> List.map
171 |> List.map
165 (\{ name, date, id } ->
172 (\{ name, date, id } ->
166 ( id
173 ( id
@@ -173,11 +180,3 @@ view { selected } liftMsg { ciphers, search, ciphersListFilter } =
173 )
180 )
174 )
181 )
175 )
182 )
176− ]
177−
178−
179−cipherSearch : String -> Search.Search Bridge.Sub_LoadCiphers
180−cipherSearch query =
181− Search.Search
182− [ ( query, \q { name } -> Search.search q name )
183− ]
frontend/Search.elm+24−166
@@ -1,182 +1,40 @@
1−module Search exposing
1+module Search exposing (searchList)
2− ( Query
3− , Search(..)
4− , SearchResult
5− , combine
6− , contramap
7− , search
8− , searchList
9− )
10
2
11−import Set exposing (Set)
3+import Html exposing (..)
12−
4+import Html.Lazy as Lazy
13−
14−ignoredCharacters : Set Char
15−ignoredCharacters =
16− Set.fromList [ '_', '-', '.' ]
17−
18−
19−prepareString : String -> String
20−prepareString =
21− String.filter (\c -> Set.member c ignoredCharacters |> not)
22− >> String.toLower
23−
24−
25−type SearchResult
26− = Match Int
27− | NoMatch {- | A search result for an empty query. It is for the most part just ignored, hance the name. -}
28− | Ignore
29−
30−
31−{-| Used to combine different search results within one search entry.
32−-}
33−combine : List SearchResult -> SearchResult
34−combine ress =
35− case ress of
36− [] ->
37− NoMatch
38−
39− _ ->
40− if List.all ((==) Ignore) ress then
41− Ignore
42−
43− else
44− let
45− go : List SearchResult -> SearchResult
46− go rr =
47− case rr of
48− [] ->
49− NoMatch
50−
51− NoMatch :: xs ->
52− go xs
53−
54− (Match score) :: xs ->
55− case go xs of
56− NoMatch ->
57− Match score
58−
59− Match score_ ->
60− Match (score + score_)
61−
62− Ignore ->
63− Match score
64−
65− Ignore :: xs ->
66− go xs
67− in
68− go ress
69−
70−
71−type alias Haystack =
72− String
73
5
74
6
75type alias Needle =
7type alias Needle =
76 String
8 String
77
9
78
10
79−type Query
11+type alias Haystack =
80− = Query Needle
12+ String
81−
82−
83−{-| Constructs queries from an input string. (Splits on spaces and requires all words to match)
84−-}
85−constructQueries : String -> List Query
86−constructQueries =
87− prepareString >> String.words >> List.filter (String.isEmpty >> not) >> List.filter (String.length >> (<) 1) >> List.map Query
88−
89−
90−{-| Search a search term within a search entry.
91−-}
92−search : Query -> Haystack -> SearchResult
93−search (Query needle) haystack =
94− if String.contains needle (prepareString haystack) then
95− Match 1
96−
97− else
98− NoMatch
99
13
100
14
101−{-| Requires all search results to be matched
15+search : List Needle -> Haystack -> Bool
102−-}
16+search needles haystack =
103−searchAll : List SearchResult -> SearchResult
104−searchAll =
105 let
17 let
106− combineQueries : SearchResult -> SearchResult -> SearchResult
18+ haystack_ =
107− combineQueries x y =
19+ haystack |> String.toLower
108− case ( x, y ) of
109− ( NoMatch, _ ) ->
110− NoMatch
111−
112− ( _, NoMatch ) ->
113− NoMatch
114−
115− ( Ignore, a ) ->
116− a
117−
118− ( a, Ignore ) ->
119− a
120−
121− ( Match a, Match b ) ->
122− Match (a + b)
123 in
20 in
124− List.foldl combineQueries Ignore
21+ List.all (\needle -> String.contains needle haystack_) needles
125−
126−
127−{-| A list of search inputs with the definition of what it means to search for that query.
128−-}
129−type Search a
130− = Search (List ( String, Query -> a -> SearchResult ))
131−
132−
133−contramap : (b -> a) -> Search a -> Search b
134−contramap f (Search s) =
135− List.map (\( q, g ) -> ( q, \query b -> g query (f b) )) s
136− |> Search
137
22
138
23
139−{-| The main function of the module. Search a list with the given `Search`.
24+prepareNeedles : String -> List Needle
140−-}
25+prepareNeedles =
141−searchList : Search a -> List a -> List a
26+ String.toLower
142−searchList (Search searches) aa =
27+ >> String.words
143− let
144− searchByTerm =
145− searches
146− |> List.concatMap
147− (\( s, f ) ->
148− let
149− qq =
150− constructQueries s
151− in
152− List.map (\q a -> f q a) qq
28+ >> List.map String.trim
153− )
29+ >> List.filter (String.isEmpty >> not)
154−
30+ >> List.filter (String.length >> (<) 1)
155− searchEntry a =
156− List.map (\f -> f a) searchByTerm |> searchAll
157− in
158− aa
159− |> List.map (\a -> ( searchEntry a, a ))
160− |> sortResult Tuple.first
161− |> List.map Tuple.second
162
31
163
32
164−sortResult : (a -> SearchResult) -> List a -> List a
33+searchList : Needle -> (a -> Haystack) -> (List a -> Html msg) -> List a -> Html msg
165−sortResult f =
34+searchList needle getHaystack show aa =
166− List.filterMap
35+ case prepareNeedles needle of
167− (\a ->
36+ [] ->
168− case f a of
37+ Lazy.lazy show aa
169− Match score ->
170− Just ( score, a )
171−
172− NoMatch ->
173− Nothing
174
38
175− Ignore ->
39+ needles ->
176− Just ( 0, a )
40+ aa |> List.filter (\a -> search needles (getHaystack a)) |> show
177− )
178− -- Here we assume that the sort is stable which is not true for old
179− -- versions of ECMAScript which would result in undeterministic
180− -- ordering for empty queries.
181− >> List.sortBy Tuple.first
182− >> List.map Tuple.second