2 * help.c, heavily based on filters.c
3 * (c) 2006, <ft@bewatermyfriend.de>
12 #include "command_mode.h"
16 struct window
*help_win
;
17 struct searchable
*help_searchable
;
19 static LIST_HEAD(help_head
);
20 static struct list_head
*bound_head
;
21 static struct list_head
*unbound_head
;
23 static inline void help_entry_to_iter(struct help_entry
*e
, struct iter
*iter
)
25 iter
->data0
= &help_head
;
30 static GENERIC_ITER_PREV(help_get_prev
, struct help_entry
, node
)
31 static GENERIC_ITER_NEXT(help_get_next
, struct help_entry
, node
)
33 static int help_search_get_current(void *data
, struct iter
*iter
)
35 return window_get_sel(help_win
, iter
);
38 static int help_search_matches(void *data
, struct iter
*iter
, const char *text
)
41 char **words
=get_words(text
);
42 if (words
[0] != NULL
) {
43 struct help_entry
*ent
;
46 ent
= iter_to_help_entry(iter
);
48 if (words
[i
] == NULL
) {
49 window_set_sel(help_win
, iter
);
52 } if (ent
->type
== HE_TEXT
) {
53 if (!u_strcasestr(ent
->text
, words
[i
]))
55 } else if (ent
->type
== HE_BOUND
) {
56 if (!u_strcasestr(key_context_names
[ent
->binding
->ctx
], words
[i
])
57 && !u_strcasestr(ent
->binding
->cmd
, words
[i
])
58 && !u_strcasestr(ent
->binding
->key
->name
, words
[i
]))
60 } else if (ent
->type
== HE_UNBOUND
) {
61 if (!u_strcasestr(ent
->command
->name
, words
[i
]))
66 free_str_array(words
);
70 static const struct searchable_ops help_search_ops
= {
71 .get_prev
= help_get_prev
,
72 .get_next
= help_get_next
,
73 .get_current
= help_search_get_current
,
74 .matches
= help_search_matches
77 static struct list_head
*help_add_text(const char *s
)
79 struct help_entry
*ent
;
80 ent
= xnew(struct help_entry
, 1);
83 list_add_tail(&ent
->node
, &help_head
);
87 static void help_add_defaults(void)
89 help_add_text("Current Keybindings");
90 help_add_text("-----------------------------");
91 bound_head
= help_add_text("");
92 help_add_text("Unbound Commands");
93 help_add_text("-----------------------------");
94 unbound_head
= help_add_text("");
97 void help_remove_unbound(struct command
*cmd
)
99 struct help_entry
*ent
;
101 list_for_each_entry(ent
, &help_head
, node
) {
102 if (ent
->type
!= HE_UNBOUND
)
104 if (ent
->command
== cmd
) {
105 help_entry_to_iter(ent
, &i
);
106 window_row_vanishes(help_win
, &i
);
107 list_del(&ent
->node
);
114 void help_add_unbound(struct command
*cmd
)
116 struct help_entry
*ent
;
117 struct command
*c
= cmd
;
119 ent
=xnew(struct help_entry
, 1);
120 ent
->type
=HE_UNBOUND
;
122 list_init(&ent
->node
);
123 list_add_tail(&ent
->node
, unbound_head
);
127 void help_add_all_unbound(void)
130 for (i
= 0; commands
[i
].name
; ++i
)
132 help_add_unbound(&commands
[i
]);
135 void help_select(void)
137 /* nothing right now */
140 void help_add(const struct binding
*bind
)
142 struct help_entry
*ent
;
143 ent
= xnew(struct help_entry
, 1);
144 ent
->type
= HE_BOUND
;
146 list_add_tail(&ent
->node
, bound_head
);
149 void help_remove(const struct binding
*bind
)
151 struct help_entry
*ent
;
153 list_for_each_entry(ent
, &help_head
, node
) {
154 if (ent
->binding
== bind
) {
155 help_entry_to_iter(ent
, &i
);
156 window_row_vanishes(help_win
, &i
);
157 list_del(&ent
->node
);
168 help_win
= window_new(help_get_prev
, help_get_next
);
169 window_set_contents(help_win
, &help_head
);
170 window_changed(help_win
);
173 iter
.data0
= &help_head
;
176 help_searchable
= searchable_new(NULL
, &iter
, &help_search_ops
);
181 searchable_free(help_searchable
);
182 window_free(help_win
);