@@ -87,8 +87,7 @@ defmodule IEx.Autocomplete do
87
87
length = byte_size ( hint )
88
88
prefix = :binary . longest_common_prefix ( binary )
89
89
if prefix in [ 0 , length ] do
90
- entries = Enum . reduce ( entries , [ ] , fn e , acc -> to_entries ( e ) ++ acc end )
91
- yes ( "" , entries )
90
+ yes ( "" , Enum . flat_map ( entries , & to_entries / 1 ) )
92
91
else
93
92
yes ( :binary . part ( first . name , prefix , length - prefix ) , [ ] )
94
93
end
@@ -111,13 +110,13 @@ defmodule IEx.Autocomplete do
111
110
end
112
111
113
112
defp expand_require ( mod , hint ) do
114
- format_expansion module_funs ( mod , hint ) , hint
113
+ format_expansion match_module_funs ( mod , hint ) , hint
115
114
end
116
115
117
116
defp expand_import ( hint ) do
118
- funs = module_funs ( IEx.Helpers , hint ) ++
119
- module_funs ( Kernel , hint ) ++
120
- module_funs ( Kernel.SpecialForms , hint )
117
+ funs = match_module_funs ( IEx.Helpers , hint ) ++
118
+ match_module_funs ( Kernel , hint ) ++
119
+ match_module_funs ( Kernel.SpecialForms , hint )
121
120
format_expansion funs , hint
122
121
end
123
122
@@ -128,10 +127,7 @@ defmodule IEx.Autocomplete do
128
127
end
129
128
130
129
defp match_erlang_modules ( hint ) do
131
- for { mod , _ } <- :code . all_loaded ,
132
- mod = Atom . to_string ( mod ) ,
133
- not match? ( "Elixir." <> _ , mod ) ,
134
- String . starts_with? ( mod , hint ) do
130
+ for mod <- match_modules ( hint , true ) do
135
131
% { kind: :module , name: mod , type: :erlang }
136
132
end
137
133
end
@@ -140,57 +136,58 @@ defmodule IEx.Autocomplete do
140
136
141
137
defp expand_elixir_modules ( list , hint ) do
142
138
mod = Module . concat ( list )
143
- format_expansion elixir_aliases ( mod , hint , list == [ ] ) ++ module_funs ( mod , hint ) , hint
144
- end
145
-
146
- defp elixir_aliases ( mod , hint , root ) do
147
- modname = Atom . to_string ( mod )
148
- depth = length ( String . split ( modname , "." ) ) + 1
149
- base = modname <> "." <> hint
150
-
151
- Enum . reduce modules_as_lists ( root ) , [ ] , fn ( m , acc ) ->
152
- if String . starts_with? ( m , base ) do
153
- tokens = String . split ( m , "." )
154
- if length ( tokens ) == depth do
155
- name = List . last ( tokens )
156
- [ % { kind: :module , type: :elixir , name: name } | acc ]
157
- else
158
- acc
159
- end
160
- else
161
- acc
162
- end
139
+ format_expansion match_elixir_modules ( mod , hint , list == [ ] ) ++
140
+ match_module_funs ( mod , hint ) , hint
141
+ end
142
+
143
+ defp match_elixir_modules ( module , hint , root ) do
144
+ module = Atom . to_string ( module )
145
+ depth = length ( String . split ( module , "." ) ) + 1
146
+ base = module <> "." <> hint
147
+
148
+ for mod <- match_modules ( base , root ) ,
149
+ tokens = String . split ( mod , "." ) ,
150
+ length ( tokens ) == depth do
151
+ name = List . last ( tokens )
152
+ % { kind: :module , type: :elixir , name: name }
163
153
end
164
154
end
165
155
166
- defp modules_as_lists ( true ) do
167
- [ "Elixir.Elixir" ] ++ modules_as_lists ( false )
156
+ ## Helpers
157
+
158
+ defp match_modules ( hint , root ) do
159
+ get_modules ( root )
160
+ |> :lists . usort ( )
161
+ |> Enum . drop_while ( & not String . starts_with? ( & 1 , hint ) )
162
+ |> Enum . take_while ( & String . starts_with? ( & 1 , hint ) )
163
+ end
164
+
165
+ defp get_modules ( true ) do
166
+ [ "Elixir.Elixir" ] ++ get_modules ( false )
168
167
end
169
168
170
- defp modules_as_lists ( false ) do
169
+ defp get_modules ( false ) do
171
170
modules = Enum . map ( :code . all_loaded , fn ( { m , _ } ) -> Atom . to_string ( m ) end )
172
171
173
172
if :code . get_mode ( ) === :interactive do
174
- Enum . uniq ( modules ++ loaded_applications_as_lists ( ) )
173
+ modules ++ get_modules_from_applications ( )
175
174
else
176
175
modules
177
176
end
178
177
end
179
178
180
- defp loaded_applications_as_lists do
179
+ defp get_modules_from_applications do
181
180
for { app , _ , _ } <- :application . loaded_applications ,
182
181
{ _ , modules } = :application . get_key ( app , :modules ) ,
183
182
module <- modules do
184
183
Atom . to_string ( module )
185
184
end
186
185
end
187
186
188
- ## Helpers
189
-
190
- defp module_funs ( mod , hint ) do
187
+ defp match_module_funs ( mod , hint ) do
191
188
case ensure_loaded ( mod ) do
192
189
{ :module , _ } ->
193
- falist = get_funs ( mod )
190
+ falist = get_module_funs ( mod )
194
191
195
192
list = Enum . reduce falist , [ ] , fn { f , a } , acc ->
196
193
case :lists . keyfind ( f , 1 , acc ) do
@@ -203,13 +200,13 @@ defmodule IEx.Autocomplete do
203
200
name = Atom . to_string ( fun ) ,
204
201
String . starts_with? ( name , hint ) do
205
202
% { kind: :function , name: name , arities: arities }
206
- end
203
+ end |> :lists . sort ( )
207
204
_ ->
208
205
[ ]
209
206
end
210
207
end
211
208
212
- defp get_funs ( mod ) do
209
+ defp get_module_funs ( mod ) do
213
210
if function_exported? ( mod , :__info__ , 1 ) do
214
211
if docs = Code . get_docs ( mod , :docs ) do
215
212
for { tuple , _line , _kind , _sign , doc } <- docs , doc != false , do: tuple
@@ -231,7 +228,7 @@ defmodule IEx.Autocomplete do
231
228
end
232
229
233
230
defp to_entries ( % { kind: :function , name: name , arities: arities } ) do
234
- for a <- arities , do: "#{ name } /#{ a } "
231
+ for a <- :lists . sort ( arities ) , do: "#{ name } /#{ a } "
235
232
end
236
233
237
234
defp to_uniq_entries ( % { kind: :module } ) do
0 commit comments