@@ -143,6 +143,87 @@ bool mp_repl_continue_with_input(const char *input) {
143
143
return false;
144
144
}
145
145
146
+ STATIC bool test_qstr (mp_obj_t obj , qstr name ) {
147
+ // try object member
148
+ mp_obj_t dest [2 ];
149
+ mp_load_method_protected (obj , name , dest , true);
150
+ return dest [0 ] != MP_OBJ_NULL ;
151
+ }
152
+
153
+ STATIC const char * find_completions (const char * s_start , size_t s_len ,
154
+ mp_obj_t obj , size_t * match_len , qstr * q_first , qstr * q_last ) {
155
+
156
+ const char * match_str = NULL ;
157
+ * match_len = 0 ;
158
+ * q_first = * q_last = 0 ;
159
+ size_t nqstr = QSTR_TOTAL ();
160
+ for (qstr q = MP_QSTR_ + 1 ; q < nqstr ; ++ q ) {
161
+ size_t d_len ;
162
+ const char * d_str = (const char * )qstr_data (q , & d_len );
163
+ // special case; filter out words that begin with underscore
164
+ // unless there's already a partial match
165
+ if (s_len == 0 && d_str [0 ] == '_' ) {
166
+ continue ;
167
+ }
168
+ if (s_len <= d_len && strncmp (s_start , d_str , s_len ) == 0 ) {
169
+ if (test_qstr (obj , q )) {
170
+ if (match_str == NULL ) {
171
+ match_str = d_str ;
172
+ * match_len = d_len ;
173
+ } else {
174
+ // search for longest common prefix of match_str and d_str
175
+ // (assumes these strings are null-terminated)
176
+ for (size_t j = s_len ; j <= * match_len && j <= d_len ; ++ j ) {
177
+ if (match_str [j ] != d_str [j ]) {
178
+ * match_len = j ;
179
+ break ;
180
+ }
181
+ }
182
+ }
183
+ if (* q_first == 0 ) {
184
+ * q_first = q ;
185
+ }
186
+ * q_last = q ;
187
+ }
188
+ }
189
+ }
190
+ return match_str ;
191
+ }
192
+
193
+ STATIC void print_completions (const mp_print_t * print ,
194
+ const char * s_start , size_t s_len ,
195
+ mp_obj_t obj , qstr q_first , qstr q_last ) {
196
+
197
+ #define WORD_SLOT_LEN (16)
198
+ #define MAX_LINE_LEN (4 * WORD_SLOT_LEN)
199
+
200
+ int line_len = MAX_LINE_LEN ; // force a newline for first word
201
+ for (qstr q = q_first ; q <= q_last ; ++ q ) {
202
+ size_t d_len ;
203
+ const char * d_str = (const char * )qstr_data (q , & d_len );
204
+ if (s_len <= d_len && strncmp (s_start , d_str , s_len ) == 0 ) {
205
+ if (test_qstr (obj , q )) {
206
+ int gap = (line_len + WORD_SLOT_LEN - 1 ) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len ;
207
+ if (gap < 2 ) {
208
+ gap += WORD_SLOT_LEN ;
209
+ }
210
+ if (line_len + gap + d_len <= MAX_LINE_LEN ) {
211
+ // TODO optimise printing of gap?
212
+ for (int j = 0 ; j < gap ; ++ j ) {
213
+ mp_print_str (print , " " );
214
+ }
215
+ mp_print_str (print , d_str );
216
+ line_len += gap + d_len ;
217
+ } else {
218
+ mp_printf (print , "\n%s" , d_str );
219
+ line_len = d_len ;
220
+ }
221
+ }
222
+ }
223
+ }
224
+ mp_print_str (print , "\n" );
225
+ }
226
+
146
227
size_t mp_repl_autocomplete (const char * str , size_t len , const mp_print_t * print , const char * * compl_str ) {
147
228
// scan backwards to find start of "a.b.c" chain
148
229
const char * org_str = str ;
@@ -155,8 +236,6 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
155
236
}
156
237
}
157
238
158
- size_t nqstr = QSTR_TOTAL ();
159
-
160
239
// begin search in outer global dict which is accessed from __main__
161
240
mp_obj_t obj = MP_OBJ_FROM_PTR (& mp_module___main__ );
162
241
mp_obj_t dest [2 ];
@@ -196,40 +275,10 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
196
275
}
197
276
198
277
// look for matches
199
- const char * match_str = NULL ;
200
- size_t match_len = 0 ;
201
- qstr q_first = 0 , q_last = 0 ;
202
- for (qstr q = MP_QSTR_ + 1 ; q < nqstr ; ++ q ) {
203
- size_t d_len ;
204
- const char * d_str = (const char * )qstr_data (q , & d_len );
205
- // special case; filter out words that begin with underscore
206
- // unless there's already a partial match
207
- if (s_len == 0 && d_str [0 ] == '_' ) {
208
- continue ;
209
- }
210
- if (s_len <= d_len && strncmp (s_start , d_str , s_len ) == 0 ) {
211
- mp_load_method_protected (obj , q , dest , true);
212
- if (dest [0 ] != MP_OBJ_NULL ) {
213
- if (match_str == NULL ) {
214
- match_str = d_str ;
215
- match_len = d_len ;
216
- } else {
217
- // search for longest common prefix of match_str and d_str
218
- // (assumes these strings are null-terminated)
219
- for (size_t j = s_len ; j <= match_len && j <= d_len ; ++ j ) {
220
- if (match_str [j ] != d_str [j ]) {
221
- match_len = j ;
222
- break ;
223
- }
224
- }
225
- }
226
- if (q_first == 0 ) {
227
- q_first = q ;
228
- }
229
- q_last = q ;
230
- }
231
- }
232
- }
278
+ size_t match_len ;
279
+ qstr q_first , q_last ;
280
+ const char * match_str =
281
+ find_completions (s_start , s_len , obj , & match_len , & q_first , & q_last );
233
282
234
283
// nothing found
235
284
if (q_first == 0 ) {
@@ -257,36 +306,7 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print
257
306
}
258
307
259
308
// multiple matches found, print them out
260
-
261
- #define WORD_SLOT_LEN (16)
262
- #define MAX_LINE_LEN (4 * WORD_SLOT_LEN)
263
-
264
- int line_len = MAX_LINE_LEN ; // force a newline for first word
265
- for (qstr q = q_first ; q <= q_last ; ++ q ) {
266
- size_t d_len ;
267
- const char * d_str = (const char * )qstr_data (q , & d_len );
268
- if (s_len <= d_len && strncmp (s_start , d_str , s_len ) == 0 ) {
269
- mp_load_method_protected (obj , q , dest , true);
270
- if (dest [0 ] != MP_OBJ_NULL ) {
271
- int gap = (line_len + WORD_SLOT_LEN - 1 ) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len ;
272
- if (gap < 2 ) {
273
- gap += WORD_SLOT_LEN ;
274
- }
275
- if (line_len + gap + d_len <= MAX_LINE_LEN ) {
276
- // TODO optimise printing of gap?
277
- for (int j = 0 ; j < gap ; ++ j ) {
278
- mp_print_str (print , " " );
279
- }
280
- mp_print_str (print , d_str );
281
- line_len += gap + d_len ;
282
- } else {
283
- mp_printf (print , "\n%s" , d_str );
284
- line_len = d_len ;
285
- }
286
- }
287
- }
288
- }
289
- mp_print_str (print , "\n" );
309
+ print_completions (print , s_start , s_len , obj , q_first , q_last );
290
310
291
311
return (size_t )(-1 ); // indicate many matches
292
312
}
0 commit comments