@@ -11,14 +11,19 @@ defmodule IEx.Autocomplete do
11
11
cond do
12
12
h === ?. and t != [ ] ->
13
13
expand_dot ( reduce ( t ) , server )
14
+
14
15
h === ?: and t == [ ] ->
15
16
expand_erlang_modules ( )
17
+
16
18
identifier? ( h ) ->
17
19
expand_expr ( reduce ( expr ) , server )
18
- ( h == ?/ ) and t != [ ] and identifier? ( hd ( t ) ) ->
20
+
21
+ h == ?/ and t != [ ] and identifier? ( hd ( t ) ) ->
19
22
expand_expr ( reduce ( t ) , server )
23
+
20
24
h in '([{' ->
21
25
expand ( '' )
26
+
22
27
true ->
23
28
no ( )
24
29
end
@@ -34,36 +39,44 @@ defmodule IEx.Autocomplete do
34
39
end
35
40
36
41
defp identifier? ( h ) do
37
- ( h in ?a .. ?z ) or ( h in ?A .. ?Z ) or ( h in ?0 .. ?9 ) or h in [ ?_ , ?? , ?! ]
42
+ h in ?a .. ?z or h in ?A .. ?Z or h in ?0 .. ?9 or h in [ ?_ , ?? , ?! ]
38
43
end
39
44
40
45
defp expand_dot ( expr , server ) do
41
- case Code . string_to_quoted expr do
46
+ case Code . string_to_quoted ( expr ) do
42
47
{ :ok , atom } when is_atom ( atom ) ->
43
48
expand_call ( atom , "" , server )
49
+
44
50
{ :ok , { :__aliases__ , _ , list } } ->
45
51
expand_elixir_modules ( list , "" , server )
52
+
46
53
{ :ok , { _ , _ , _ } = ast_node } ->
47
54
expand_call ( ast_node , "" , server )
55
+
48
56
_ ->
49
57
no ( )
50
58
end
51
59
end
52
60
53
61
defp expand_expr ( expr , server ) do
54
- case Code . string_to_quoted expr do
62
+ case Code . string_to_quoted ( expr ) do
55
63
{ :ok , atom } when is_atom ( atom ) ->
56
64
expand_erlang_modules ( Atom . to_string ( atom ) )
65
+
57
66
{ :ok , { atom , _ , nil } } when is_atom ( atom ) ->
58
67
expand_variable_or_import ( Atom . to_string ( atom ) , server )
68
+
59
69
{ :ok , { :__aliases__ , _ , [ root ] } } ->
60
70
expand_elixir_modules ( [ ] , Atom . to_string ( root ) , server )
71
+
61
72
{ :ok , { :__aliases__ , _ , [ h | _ ] = list } } when is_atom ( h ) ->
62
73
hint = Atom . to_string ( List . last ( list ) )
63
74
list = Enum . take ( list , length ( list ) - 1 )
64
75
expand_elixir_modules ( list , hint , server )
76
+
65
77
{ :ok , { { :. , _ , [ ast_node , fun ] } , _ , [ ] } } when is_atom ( fun ) ->
66
78
expand_call ( ast_node , Atom . to_string ( fun ) , server )
79
+
67
80
_ ->
68
81
no ( )
69
82
end
@@ -78,10 +91,8 @@ defmodule IEx.Autocomplete do
78
91
|> trim_leading ( ?% )
79
92
end
80
93
81
- defp trim_leading ( [ char | rest ] , char ) ,
82
- do: rest
83
- defp trim_leading ( expr , _char ) ,
84
- do: expr
94
+ defp trim_leading ( [ char | rest ] , char ) , do: rest
95
+ defp trim_leading ( expr , _char ) , do: expr
85
96
86
97
defp yes ( hint , entries ) do
87
98
{ :yes , String . to_charlist ( hint ) , Enum . map ( entries , & String . to_charlist / 1 ) }
@@ -99,15 +110,16 @@ defmodule IEx.Autocomplete do
99
110
100
111
defp format_expansion ( [ uniq ] , hint ) do
101
112
case to_hint ( uniq , hint ) do
102
- "" -> yes ( "" , to_uniq_entries ( uniq ) )
113
+ "" -> yes ( "" , to_uniq_entries ( uniq ) )
103
114
hint -> yes ( hint , [ ] )
104
115
end
105
116
end
106
117
107
118
defp format_expansion ( [ first | _ ] = entries , hint ) do
108
- binary = Enum . map ( entries , & ( & 1 . name ) )
119
+ binary = Enum . map ( entries , & & 1 . name )
109
120
length = byte_size ( hint )
110
121
prefix = :binary . longest_common_prefix ( binary )
122
+
111
123
if prefix in [ 0 , length ] do
112
124
yes ( "" , Enum . flat_map ( entries , & to_entries / 1 ) )
113
125
else
@@ -151,12 +163,14 @@ defmodule IEx.Autocomplete do
151
163
end
152
164
153
165
defp expand_require ( mod , hint ) do
154
- format_expansion match_module_funs ( get_module_funs ( mod ) , hint ) , hint
166
+ format_expansion ( match_module_funs ( get_module_funs ( mod ) , hint ) , hint )
155
167
end
156
168
157
169
defp expand_variable_or_import ( hint , server ) do
158
170
variables = expand_variable ( hint , server )
159
- funs = match_module_funs ( imports_from_env ( server ) ++ get_module_funs ( Kernel.SpecialForms ) , hint )
171
+ imports = imports_from_env ( server )
172
+ module_funs = get_module_funs ( Kernel.SpecialForms )
173
+ funs = match_module_funs ( imports ++ module_funs , hint )
160
174
format_expansion ( variables ++ funs , hint )
161
175
end
162
176
@@ -169,12 +183,11 @@ defmodule IEx.Autocomplete do
169
183
## Erlang modules
170
184
171
185
defp expand_erlang_modules ( hint \\ "" ) do
172
- format_expansion match_erlang_modules ( hint ) , hint
186
+ format_expansion ( match_erlang_modules ( hint ) , hint )
173
187
end
174
188
175
189
defp match_erlang_modules ( hint ) do
176
- for mod <- match_modules ( hint , true ) ,
177
- usable_as_unquoted_module? ( mod ) do
190
+ for mod <- match_modules ( hint , true ) , usable_as_unquoted_module? ( mod ) do
178
191
% { kind: :module , name: mod , type: :erlang }
179
192
end
180
193
end
@@ -207,6 +220,7 @@ defmodule IEx.Autocomplete do
207
220
:error -> { :ok , Module . concat ( [ name | rest ] ) }
208
221
end
209
222
end
223
+
210
224
defp expand_alias ( [ _ | _ ] , _ ) do
211
225
:error
212
226
end
@@ -220,9 +234,9 @@ defmodule IEx.Autocomplete do
220
234
end
221
235
222
236
defp match_elixir_modules ( module , hint ) do
223
- name = Atom . to_string ( module )
237
+ name = Atom . to_string ( module )
224
238
depth = length ( String . split ( name , "." ) ) + 1
225
- base = name <> "." <> hint
239
+ base = name <> "." <> hint
226
240
227
241
for mod <- match_modules ( base , module === Elixir ) ,
228
242
parts = String . split ( mod , "." ) ,
@@ -231,24 +245,23 @@ defmodule IEx.Autocomplete do
231
245
valid_alias_piece? ( "." <> name ) do
232
246
% { kind: :module , type: :elixir , name: name }
233
247
end
234
- |> Enum . uniq
248
+ |> Enum . uniq ( )
235
249
end
236
250
237
251
defp valid_alias_piece? ( << ?. , char , rest :: binary >> ) when char in ?A .. ?Z ,
238
252
do: valid_alias_rest? ( rest )
239
- defp valid_alias_piece? ( _ ) ,
240
- do: false
253
+
254
+ defp valid_alias_piece? ( _ ) , do: false
241
255
242
256
defp valid_alias_rest? ( << char , rest :: binary >> )
243
257
when char in ?A .. ?Z
244
258
when char in ?a .. ?z
245
259
when char in ?0 .. ?9
246
260
when char == ?_ ,
247
261
do: valid_alias_rest? ( rest )
248
- defp valid_alias_rest? ( << >> ) ,
249
- do: true
250
- defp valid_alias_rest? ( rest ) ,
251
- do: valid_alias_piece? ( rest )
262
+
263
+ defp valid_alias_rest? ( << >> ) , do: true
264
+ defp valid_alias_rest? ( rest ) , do: valid_alias_piece? ( rest )
252
265
253
266
## Helpers
254
267
@@ -261,8 +274,8 @@ defmodule IEx.Autocomplete do
261
274
defp match_modules ( hint , root ) do
262
275
get_modules ( root )
263
276
|> :lists . usort ( )
264
- |> Enum . drop_while ( & not String . starts_with? ( & 1 , hint ) )
265
- |> Enum . take_while ( & String . starts_with? ( & 1 , hint ) )
277
+ |> Enum . drop_while ( & not String . starts_with? ( & 1 , hint ) )
278
+ |> Enum . take_while ( & String . starts_with? ( & 1 , hint ) )
266
279
end
267
280
268
281
defp get_modules ( true ) do
@@ -271,6 +284,7 @@ defmodule IEx.Autocomplete do
271
284
272
285
defp get_modules ( false ) do
273
286
modules = Enum . map ( :code . all_loaded ( ) , & Atom . to_string ( elem ( & 1 , 0 ) ) )
287
+
274
288
case :code . get_mode ( ) do
275
289
:interactive -> modules ++ get_modules_from_applications ( )
276
290
_otherwise -> modules
@@ -295,29 +309,35 @@ defmodule IEx.Autocomplete do
295
309
end
296
310
297
311
defp match_module_funs ( funs , hint ) do
298
- for ( { fun , arity } <- funs ,
299
- name = Atom . to_string ( fun ) ,
300
- String . starts_with? ( name , hint ) ,
301
- do: % { kind: :function , name: name , arity: arity } )
312
+ for { fun , arity } <- funs , name = Atom . to_string ( fun ) , String . starts_with? ( name , hint ) do
313
+ % {
314
+ kind: :function ,
315
+ name: name ,
316
+ arity: arity
317
+ }
318
+ end
302
319
|> Enum . sort_by ( & { & 1 . name , & 1 . arity } )
303
320
end
304
321
305
322
defp match_map_fields ( map , hint ) do
306
- for ( { key , value } when is_atom ( key ) <- Map . to_list ( map ) ,
323
+ for { key , value } when is_atom ( key ) <- Map . to_list ( map ) ,
307
324
key = Atom . to_string ( key ) ,
308
- String . starts_with? ( key , hint ) ,
309
- do: % { kind: :map_key , name: key , value_is_map: is_map ( value ) } )
325
+ String . starts_with? ( key , hint ) do
326
+ % { kind: :map_key , name: key , value_is_map: is_map ( value ) }
327
+ end
310
328
|> Enum . sort_by ( & & 1 . name )
311
329
end
312
330
313
331
defp get_module_funs ( mod ) do
314
332
cond do
315
333
not ensure_loaded? ( mod ) ->
316
334
[ ]
335
+
317
336
docs = Code . get_docs ( mod , :docs ) ->
318
337
exports ( mod )
319
338
|> Kernel . -- ( default_arg_functions_with_doc_false ( docs ) )
320
339
|> Enum . reject ( & hidden_fun? ( & 1 , docs ) )
340
+
321
341
true ->
322
342
exports ( mod )
323
343
end
@@ -327,7 +347,7 @@ defmodule IEx.Autocomplete do
327
347
for { { fun_name , arity } , _ , _ , args , false } <- docs ,
328
348
count = count_defaults ( args ) ,
329
349
count > 0 ,
330
- new_arity <- ( arity - count ) .. arity ,
350
+ new_arity <- ( arity - count ) .. arity ,
331
351
do: { fun_name , new_arity }
332
352
end
333
353
@@ -339,34 +359,36 @@ defmodule IEx.Autocomplete do
339
359
case List . keyfind ( docs , fun , 0 ) do
340
360
nil ->
341
361
underscored_fun? ( fun )
362
+
342
363
{ _ , _ , _ , _ , false } ->
343
364
true
365
+
344
366
{ fun , _ , _ , _ , nil } ->
345
367
underscored_fun? ( fun )
368
+
346
369
{ _ , _ , _ , _ , _ } ->
347
370
false
348
371
end
349
372
end
350
373
351
- defp underscored_fun? ( { name , _ } ) ,
352
- do: hd ( Atom . to_charlist ( name ) ) == ?_
374
+ defp underscored_fun? ( { name , _ } ) , do: hd ( Atom . to_charlist ( name ) ) == ?_
353
375
354
376
defp ensure_loaded? ( Elixir ) , do: false
355
377
defp ensure_loaded? ( mod ) , do: Code . ensure_loaded? ( mod )
356
378
357
379
## Ad-hoc conversions
358
380
359
- defp to_entries ( % { kind: kind , name: name } ) when
360
- kind in [ :map_key , :module , :variable ] do
381
+ defp to_entries ( % { kind: kind , name: name } )
382
+ when kind in [ :map_key , :module , :variable ] do
361
383
[ name ]
362
384
end
363
385
364
386
defp to_entries ( % { kind: :function , name: name , arity: arity } ) do
365
387
[ "#{ name } /#{ arity } " ]
366
388
end
367
389
368
- defp to_uniq_entries ( % { kind: kind } ) when
369
- kind in [ :map_key , :module , :variable ] do
390
+ defp to_uniq_entries ( % { kind: kind } )
391
+ when kind in [ :map_key , :module , :variable ] do
370
392
[ ]
371
393
end
372
394
@@ -382,8 +404,8 @@ defmodule IEx.Autocomplete do
382
404
format_hint ( name , hint ) <> "."
383
405
end
384
406
385
- defp to_hint ( % { kind: kind , name: name } , hint ) when
386
- kind in [ :function , :map_key , :module , :variable ] do
407
+ defp to_hint ( % { kind: kind , name: name } , hint )
408
+ when kind in [ :function , :map_key , :module , :variable ] do
387
409
format_hint ( name , hint )
388
410
end
389
411
0 commit comments