1 # HG changeset patch |
1 # HG changeset patch |
2 # Parent 3c7cebacae165329047f6859c26224e9c8a67807 |
2 # Parent f8958ab545ac1af3e3fbc3b3b025de66fd1ffa51 |
3 Make completion sorting order configurable |
3 Make completion sorting order configurable |
4 |
4 |
5 * Use allocated plain array for categories |
5 * Use allocated plain array for categories |
6 * Use callbacks for dynamic completions (private for now) |
6 * Use callbacks for dynamic completions (private for now) |
7 * Add compl_set_flags() to allow user to set completion order |
7 * Add compl_set_flags() to allow user to set completion order |
8 * [todo] Test ordering |
8 * [todo] Test ordering |
9 * [todo] Bump API (compatibly) |
9 * [todo] Bump API (compatibly) |
10 * [todo] Reallocate array, when need more completions |
10 * [todo] Reallocate array, when need more completions |
11 * [todo] Design and publish interface to dynamic completion cbs |
11 * [todo] Design and publish interface to dynamic completion cbs |
12 |
12 |
13 diff -r 3c7cebacae16 mcabber/mcabber/compl.c |
13 diff -r f8958ab545ac mcabber/mcabber/compl.c |
14 --- a/mcabber/mcabber/compl.c Wed Oct 17 02:33:43 2012 +0300 |
14 --- a/mcabber/mcabber/compl.c Mon Oct 15 19:53:02 2012 +0200 |
15 +++ b/mcabber/mcabber/compl.c Wed Oct 17 03:00:30 2012 +0300 |
15 +++ b/mcabber/mcabber/compl.c Thu Oct 18 00:00:39 2012 +0300 |
16 @@ -2,7 +2,7 @@ |
16 @@ -2,7 +2,7 @@ |
17 * compl.c -- Completion system |
17 * compl.c -- Completion system |
18 * |
18 * |
19 * Copyright (C) 2005-2010 Mikael Berthe <mikael@lilotux.net> |
19 * Copyright (C) 2005-2010 Mikael Berthe <mikael@lilotux.net> |
20 - * Copyright (C) 2009,2010 Myhailo Danylenko <isbear@ukrpost.net> |
20 - * Copyright (C) 2009,2010 Myhailo Danylenko <isbear@ukrpost.net> |
21 + * Copyright (C) 2009-2012 Myhailo Danylenko <isbear@ukrpost.net> |
21 + * Copyright (C) 2009-2012 Myhailo Danylenko <isbear@ukrpost.net> |
22 * |
22 * |
23 * This program is free software; you can redistribute it and/or modify |
23 * This program is free software; you can redistribute it and/or modify |
24 * it under the terms of the GNU General Public License as published by |
24 * it under the terms of the GNU General Public License as published by |
25 @@ -47,49 +47,96 @@ |
25 @@ -47,49 +47,97 @@ |
26 GSList *next; // pointer to next completion to try |
26 GSList *next; // pointer to next completion to try |
27 } compl; |
27 } compl; |
28 |
28 |
29 +typedef GSList *(*compl_handler_t) (void); // XXX userdata? *dynlist? |
29 +typedef GSList *(*compl_handler_t) (void); // XXX userdata? *dynlist? |
30 + |
30 + |
78 + compl = g_slist_append(compl, g_strdup("list")); |
78 + compl = g_slist_append(compl, g_strdup("list")); |
79 + return compl; |
79 + return compl; |
80 +} |
80 +} |
81 + |
81 + |
82 +static inline void register_builtin_cat(guint c, compl_handler_t dynamic) { |
82 +static inline void register_builtin_cat(guint c, compl_handler_t dynamic) { |
83 + Categories[c-1].flags = COMPL_CAT_BUILTIN | COMPL_CAT_ACTIVE; |
83 + Categories[c-1].flags = COMPL_CAT_BUILTIN | COMPL_CAT_ACTIVE; |
|
84 + Categories[c-1].words = NULL; |
|
85 + Categories[c-1].dynamic = dynamic; |
84 + if (dynamic != NULL) { |
86 + if (dynamic != NULL) { |
85 + Categories[c-1].flags |= COMPL_CAT_DYNAMIC; |
87 + Categories[c-1].flags |= COMPL_CAT_DYNAMIC; |
86 + Categories[c-1].dynamic = dynamic; |
|
87 + } |
88 + } |
88 } |
89 } |
89 |
90 |
90 void compl_init_system(void) |
91 void compl_init_system(void) |
91 { |
92 { |
92 +#ifdef MODULES_ENABLE |
93 +#ifdef MODULES_ENABLE |
93 + num_categories = 64; // XXX |
94 + num_categories = 64; // XXX |
94 +#else |
95 +#else |
95 + num_categories = COMPL_MODULE; |
96 + num_categories = COMPL_MODULE; |
96 +#endif |
97 +#endif |
97 + Categories = g_new0(category, num_categories); |
98 + Categories = g_new(category, num_categories); |
98 + |
99 + |
99 // Builtin completion categories: |
100 // Builtin completion categories: |
100 - register_builtin_cat(COMPL_CMD); |
101 - register_builtin_cat(COMPL_CMD); |
101 - register_builtin_cat(COMPL_JID); |
102 - register_builtin_cat(COMPL_JID); |
102 - register_builtin_cat(COMPL_URLJID); |
103 - register_builtin_cat(COMPL_URLJID); |
179 // and specify exactly what you get from compl_new_category. |
191 // and specify exactly what you get from compl_new_category. |
180 -void compl_del_category(guint id) |
192 -void compl_del_category(guint id) |
181 +void compl_del_category(guint compl) |
193 +void compl_del_category(guint compl) |
182 { |
194 { |
183 - if (!id) { |
195 - if (!id) { |
|
196 - scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category() - " |
|
197 - "Invalid category."); |
|
198 + GSList *wel; |
|
199 + |
184 + if (!compl) { |
200 + if (!compl) { |
185 scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category() - " |
201 + scr_log_print(LPRINT_DEBUG, "Error: compl_del_category() - " |
186 - "Invalid category."); |
202 + "Invalid category."); |
187 + "Invalid category."); |
|
188 return; |
203 return; |
189 } |
204 } |
190 - id--; |
205 - id--; |
191 - registered_cats &= ~(1<<id); |
206 - registered_cats &= ~(1<<id); |
|
207 + |
192 + compl--; |
208 + compl--; |
|
209 + |
193 + if ((compl >= num_categories) || |
210 + if ((compl >= num_categories) || |
194 + (Categories[compl].flags & COMPL_CAT_BUILTIN)) { |
211 + (Categories[compl].flags & COMPL_CAT_BUILTIN)) { |
195 + scr_log_print(LPRINT_DEBUG, "Error: compl_del_category() " |
212 + scr_log_print(LPRINT_DEBUG, "Error: compl_del_category() " |
196 + "Invalid category."); |
213 + "Invalid category."); |
197 + return; |
214 + return; |
198 + } |
215 + } |
199 + |
216 + |
200 + Categories[compl].flags = 0; |
217 + Categories[compl].flags = 0; |
201 + // XXX free words |
218 + for (wel = Categories[compl].words; wel; wel = g_slist_next (wel)) |
202 +} |
219 + g_free (wel -> data); |
203 + |
220 + g_slist_free (Categories[compl].words); |
204 +// compl_set_sorting_order(category,order) |
221 +} |
|
222 + |
|
223 +// compl_set_flags (category, flags) |
205 +// Sets sorting order for given category. |
224 +// Sets sorting order for given category. |
206 +// In future can be merged with new_category, set more flags, |
225 +// In future can be merged with new_category, set more flags, |
207 +// maybe even set dynamic callback. |
226 +// maybe even set dynamic callback. |
208 +void compl_set_flags(guint compl, guint new_flags) |
227 +void compl_set_flags(guint compl, guint new_flags) |
209 +{ |
228 +{ |
210 + if (!compl) { |
229 + if (!compl) { |
211 + scr_log_print(LPRINT_LOGNORM, "Error: compl_set_flags() - " |
230 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
212 + "Invalid category."); |
231 + "Invalid category."); |
213 + return; |
232 + return; |
214 + } |
233 + } |
|
234 + |
215 + compl--; |
235 + compl--; |
|
236 + |
216 + if (compl < num_categories) { |
237 + if (compl < num_categories) { |
217 + guint flags = Categories[compl].flags; |
238 + guint flags = Categories[compl].flags; |
218 + if (flags & COMPL_CAT_BUILTIN) |
239 + if (flags & COMPL_CAT_BUILTIN) |
219 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
240 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
220 + "Invalid category."); |
241 + "Rejecting builtin category."); |
221 + else if (!(flags & COMPL_CAT_ACTIVE)) |
242 + else if (!(flags & COMPL_CAT_ACTIVE)) |
222 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
243 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
223 + "Invalid category."); |
244 + "Not existing category."); |
224 + else |
245 + else |
225 + Categories[compl].flags = (flags & ~COMPL_CAT_USERFLAGS) |
246 + Categories[compl].flags = (flags & ~COMPL_CAT_USERFLAGS) |
226 + | ((new_flags << 2) & COMPL_CAT_USERFLAGS); |
247 + | ((new_flags << 2) & COMPL_CAT_USERFLAGS); |
227 + } else |
248 + } else |
228 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
249 + scr_log_print(LPRINT_DEBUG, "Error: compl_set_flags() - " |
229 + "Invalid category."); |
250 + "Not existing category."); |
230 } |
251 } |
231 #endif |
252 #endif |
232 |
253 |
233 @@ -222,13 +305,30 @@ |
254 @@ -136,12 +239,15 @@ |
|
255 guint new_completion(const char *prefix, GSList *compl_cat, const gchar *suffix) |
|
256 { |
|
257 compl *c; |
|
258 + guint ret_len = 0; |
|
259 GSList *sl_cat; |
|
260 gint (*cmp)(const char *s1, const char *s2, size_t n); |
|
261 size_t len = strlen(prefix); |
|
262 |
|
263 if (InputCompl) { // This should not happen, but hey... |
|
264 - cancel_completion(); |
|
265 + scr_log_print(LPRINT_DEBUG, "Warinng: new_completion() - " |
|
266 + "Previous completion exists!"); |
|
267 + done_completion(); |
|
268 } |
|
269 |
|
270 if (settings_opt_get_int("completion_ignore_case")) |
|
271 @@ -160,14 +266,15 @@ |
|
272 compval = g_strdup_printf("%s%s", word+len, suffix); |
|
273 else |
|
274 compval = g_strdup(word+len); |
|
275 - c->list = g_slist_insert_sorted(c->list, compval, |
|
276 - (GCompareFunc)g_ascii_strcasecmp); |
|
277 + // for a bit of efficiency, will reverse order afterwards |
|
278 + c->list = g_slist_prepend(c->list, compval); |
|
279 + ret_len ++; |
|
280 } |
|
281 } |
|
282 } |
|
283 - c->next = c->list; |
|
284 + c->next = c->list = g_slist_reverse (c->list); |
|
285 InputCompl = c; |
|
286 - return g_slist_length(c->list); |
|
287 + return ret_len; |
|
288 } |
|
289 |
|
290 // done_completion(); |
|
291 @@ -222,35 +329,46 @@ |
234 |
292 |
235 /* Categories functions */ |
293 /* Categories functions */ |
236 |
294 |
237 +static gint compl_sort_forward(gconstpointer a, gconstpointer b) |
295 +static gint compl_sort_forward(gconstpointer a, gconstpointer b) |
238 +{ |
296 +{ |
323 void compl_del_category_word(guint categ, const gchar *word) |
382 void compl_del_category_word(guint categ, const gchar *word) |
324 { |
383 { |
325 - guint64 catv; |
384 - guint64 catv; |
326 - GSList *sl_cat, *sl_elt; |
385 - GSList *sl_cat, *sl_elt; |
327 - category *cat; |
386 - category *cat; |
328 + GSList *sl_elt; |
387 + GSList *wel; |
329 char *nword; |
388 char *nword; |
330 |
389 |
331 if (!categ) { |
390 if (!categ) { |
332 @@ -285,16 +387,13 @@ |
391 - scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category_word() - " |
|
392 + scr_log_print(LPRINT_DEBUG, "Error: compl_del_category_word() - " |
|
393 "Invalid category."); |
|
394 return; |
333 } |
395 } |
334 |
396 |
335 categ--; |
397 categ--; |
336 - catv = 1UL << categ; |
398 - catv = 1UL << categ; |
337 |
399 |
338 - // Look for category |
400 - // Look for category |
339 - for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) { |
401 - for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) { |
340 - if (catv == ((category*)sl_cat->data)->flag) |
402 - if (catv == ((category*)sl_cat->data)->flag) |
341 - break; |
403 - break; |
342 + if ((categ > num_categories) || |
404 + if ((categ >= num_categories) || |
343 + !(Categories[categ].flags & COMPL_CAT_ACTIVE)) { |
405 + !(Categories[categ].flags & COMPL_CAT_ACTIVE)) { |
344 + scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category_word() - " |
406 + scr_log_print(LPRINT_DEBUG, "Error: compl_del_category_word() - " |
345 + "Invalid category."); |
407 + "Not existing category."); |
346 + return; |
408 + return; |
347 } |
409 } |
348 - if (!sl_cat) return; // Category not found, finished! |
410 - if (!sl_cat) return; // Category not found, finished! |
349 - |
411 - |
350 - cat = (category*)sl_cat->data; |
412 - cat = (category*)sl_cat->data; |
351 |
413 |
352 // If word is not space-terminated, we add one trailing space |
414 // If word is not space-terminated, we add one trailing space |
353 for (nword = (char*)word; *nword; nword++) |
415 for (nword = (char*)word; *nword; nword++) |
354 @@ -306,11 +405,12 @@ |
416 ; |
355 nword = g_strdup(word); |
417 if (nword > word) nword--; |
|
418 - if (*nword != ' ') { // Add a space |
|
419 - nword = g_strdup_printf("%s ", word); |
|
420 - } else { // word is fine |
|
421 - nword = g_strdup(word); |
|
422 + if (*nword != ' ') // Add a space |
|
423 + word = nword = g_strdup_printf("%s ", word); |
|
424 + else |
|
425 + nword = NULL; |
|
426 + |
|
427 + for (wel = Categories[categ].words; wel; wel = g_slist_next (wel)) { |
|
428 + if (!strcasecmp((char*)wel->data, word)) { |
|
429 + g_free(wel->data); |
|
430 + Categories[categ].words = g_slist_delete_link |
|
431 + (Categories[categ].words, wel); |
|
432 + break; // Only remove first occurence |
|
433 + } |
356 } |
434 } |
357 |
435 |
358 - sl_elt = cat->words; |
436 - sl_elt = cat->words; |
359 + sl_elt = Categories[categ].words; |
437 - while (sl_elt) { |
360 while (sl_elt) { |
438 - if (!strcasecmp((char*)sl_elt->data, nword)) { |
361 if (!strcasecmp((char*)sl_elt->data, nword)) { |
439 - g_free(sl_elt->data); |
362 g_free(sl_elt->data); |
|
363 - cat->words = g_slist_delete_link(cat->words, sl_elt); |
440 - cat->words = g_slist_delete_link(cat->words, sl_elt); |
364 + Categories[categ].words = g_slist_delete_link |
441 - break; // Only remove first occurence |
365 + (Categories[categ].words, sl_elt); |
442 - } |
366 break; // Only remove first occurence |
443 - sl_elt = g_slist_next(sl_elt); |
367 } |
444 - } |
368 sl_elt = g_slist_next(sl_elt); |
445 + g_free (nword); |
369 @@ -323,48 +423,28 @@ |
446 } |
|
447 |
|
448 // compl_get_category_list() |
|
449 @@ -323,48 +446,28 @@ |
370 // whole list after use. |
450 // whole list after use. |
371 GSList *compl_get_category_list(guint categ, guint *dynlist) |
451 GSList *compl_get_category_list(guint categ, guint *dynlist) |
372 { |
452 { |
373 - guint64 cat_flags; |
453 - guint64 cat_flags; |
374 - GSList *sl_cat; |
454 - GSList *sl_cat; |
375 - |
455 - |
376 if (!categ) { |
456 if (!categ) { |
377 scr_log_print(LPRINT_LOGNORM, "Error: compl_get_category_list() - " |
457 - scr_log_print(LPRINT_LOGNORM, "Error: compl_get_category_list() - " |
|
458 + scr_log_print(LPRINT_DEBUG, "Error: compl_get_category_list() - " |
378 "Invalid category."); |
459 "Invalid category."); |
379 return NULL; |
460 return NULL; |
380 } |
461 } |
381 |
462 |
382 - *dynlist = FALSE; |
463 - *dynlist = FALSE; |
448 void compl_del_category(guint id); |
529 void compl_del_category(guint id); |
449 +void compl_set_flags(guint id, guint flags); |
530 +void compl_set_flags(guint id, guint flags); |
450 #endif |
531 #endif |
451 |
532 |
452 void compl_add_category_word(guint categ, const gchar *command); |
533 void compl_add_category_word(guint categ, const gchar *command); |
453 diff -r 3c7cebacae16 mcabber/mcabber/main.c |
534 diff -r f8958ab545ac mcabber/mcabber/main.c |
454 --- a/mcabber/mcabber/main.c Wed Oct 17 02:33:43 2012 +0300 |
535 --- a/mcabber/mcabber/main.c Mon Oct 15 19:53:02 2012 +0200 |
455 +++ b/mcabber/mcabber/main.c Wed Oct 17 03:00:30 2012 +0300 |
536 +++ b/mcabber/mcabber/main.c Thu Oct 18 00:00:39 2012 +0300 |
456 @@ -368,13 +368,13 @@ |
537 @@ -364,13 +364,13 @@ |
457 } |
538 } |
458 |
539 |
459 /* Initialize command system, roster and default key bindings */ |
540 /* Initialize command system, roster and default key bindings */ |
460 + compl_init_system(); |
541 + compl_init_system(); |
461 cmd_init(); |
542 cmd_init(); |