diff --git a/README.md b/README.md index 9834585..9ca6231 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ It is lightweight and easy to customize - `3` - edit resource - `4` - logs of pod - `5` - exec to pod +- `6` - network debug of pod (with nicolaka/netshoot container attached) - `delete` - delete resource You can customize these bindings or add extra bindings in `KEY_BINDINGS` variable of `kls` (in a row #6). diff --git a/a.out b/a.out new file mode 100755 index 0000000..c6a6ac7 Binary files /dev/null and b/a.out differ diff --git a/ccc.c b/ccc.c new file mode 100644 index 0000000..31b01cd --- /dev/null +++ b/ccc.c @@ -0,0 +1,200 @@ +/* + * This is a simple example of "scrolling" form with ncurses. + * It use "page" to allow forms with more fields than your window can print. + * + * It prints a "label" (inactive field) and a regular field and let you + * "scroll" pages of the form. + * + * How to compile: + * gcc -o test scrolling_form.c -lform -lncurses + */ + +#include // this includes +#include +#include +#include + +WINDOW *wbody, *inner; +FIELD **field; +FORM *form; + +int nb_field; // how many fields you want (modify it in main()) +int cur_y = 1, cur_x = 1; // current y and x for the inner window +char str_label[7], str_field[6]; +char cur_ch_label = 'A', cur_ch_field = 'a'; +int lines = 21, cur_page = 0; + +/* + ++----------------------------------+ <-- wbody +|+--------------------------------+ <-- inner +|| ^ || +|| | || +|| | || +|| | || +|| | lines || +|| | || +|| | || +|| | || +|| v || +|+--------------------------------+| ++----------------------------------+ + +*/ + +// We free everything here +void quit() { + int i; + + unpost_form(form); + + for (i = 0; i < nb_field; i++) { + free(field_buffer(field[i], 0)); + free_field(field[i]); + } + + free_form(form); + delwin(wbody); + delwin(inner); +} + +char* get_next_str_field() { + int i; + + if (str_field[0] != '\0') + cur_ch_field++; + + for (i = 0; i < 4; i++) + str_field[i] = cur_ch_field; + + str_field[5] = '\0'; + + return str_field; +} + +char* get_next_str_label() { + int i; + + if (str_label[0] != '\0') + cur_ch_label++; + + for (i = 0; i < 5; i++) + str_label[i] = cur_ch_label; + + str_label[5] = ':'; + str_label[6] = '\0'; + + return str_label; +} + +/* + * Create nb_field fields, one as a label, one as an active field e.g.: + * [label]: [field] + */ +void create_nb_fields() { + int i; + + field = calloc(nb_field, sizeof(FIELD *)); + + if (!field) // No memory for you ! + assert(1); + + for (i = 0; i < nb_field-1; i++, cur_y += 2) { + // label + field[i] = new_field(1, 20, cur_y, cur_x, 0, 0); + field_opts_on(field[i], O_VISIBLE); + field_opts_off(field[i], O_EDIT); + field_opts_off(field[i], O_ACTIVE); + set_field_buffer(field[i], 0, get_next_str_label()); + + i++; + + /* + * This is a nasty tric: + * I check if we wrote at the tail of the inner window, + * if so, I move the field where it belongs (head of + * the inner window). + */ + if (cur_y % lines == 0) { + cur_y = 1; + set_new_page(field[i-1], TRUE); + move_field(field[i-1], cur_y, cur_x); + } + + // field + field[i] = new_field(1, 20, cur_y, cur_x + 10, 0, 0); + set_field_back(field[i], A_UNDERLINE); + field_opts_on(field[i], O_VISIBLE); + field_opts_on(field[i], O_ACTIVE); + field_opts_off(field[i], O_EDIT); + set_field_buffer(field[i], 0, get_next_str_field()); + } + + field[nb_field-1] = NULL; +} + +int main() { + int ch; + + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + // This is required to init get_next_str_XXXX + str_label[0] = '\0'; + str_field[0] = '\0'; + + wbody = newwin(lines + 2, 44, 1, 1); + box(wbody, 0, 0); + keypad(wbody, TRUE); + + nb_field = 43; // this is too much fields for the window + create_nb_fields(); + form = new_form(field); + + // Check the doc here: + // http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/forms.html#FORMWINDOWS + set_form_win(form, wbody); + inner = derwin(wbody, lines, 42, 1 ,1); + set_form_sub(form, inner); + + post_form(form); + + mvprintw(LINES - 4, 0, "Use F1 to quit"); + mvprintw(LINES - 3, 0, "Use PAGE_UP, PAGE_DOWN to switch between pages"); + mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields"); + refresh(); + + while ((ch = wgetch(wbody)) != KEY_F(1)) { + switch (ch) { + case KEY_DOWN: + form_driver(form, REQ_NEXT_FIELD); + form_driver(form, REQ_END_LINE); + break; + + case KEY_UP: + form_driver(form, REQ_PREV_FIELD); + form_driver(form, REQ_END_LINE); + break; + + /* + * This is where you want to look to see how + * to "scroll" to the next/previous page. + */ + case KEY_NPAGE: + form_driver(form, REQ_NEXT_PAGE); + set_form_page(form, ++cur_page); + break; + + case KEY_PPAGE: + form_driver(form, REQ_PREV_PAGE); + set_form_page(form, --cur_page); + break; + } + } + + quit(); + endwin(); + return 0; +} diff --git a/kls b/kls index 3afd02a..459f783 100755 --- a/kls +++ b/kls @@ -7,6 +7,7 @@ KEY_BINDINGS = { # can be extended "3": 'kubectl -n {namespace} edit {api_resource} {resource}', "4": 'kubectl -n {namespace} logs {resource} | batcat -l log --paging always --style numbers', "5": 'kubectl -n {namespace} exec -it {resource} sh', + "6": 'kubectl -n {namespace} debug {resource} -it --image=nicolaka/netshoot', "KEY_DC": 'kubectl -n {namespace} delete {api_resource} {resource}' # KEY_DC is the delete key } # which api resources are on the top of menu?