diff --git a/kls b/kls index c338e9f..b68f42e 100755 --- a/kls +++ b/kls @@ -16,6 +16,8 @@ TOP_API_RESOURCES = ["pods", "services", "configmaps", "secrets", "persistentvol HELP_TEXT = "Esc: exit filter mode or exit kls, 1: get yaml, 2: describe, 3: edit, 4: pod logs, arrows/TAB: navigation" +MOUSE = True + class Menu: def __init__(self, title: str, rows: list, begin_x: int, width: int): @@ -32,6 +34,8 @@ class Menu: self.__visible_row_index = lambda: self.filtered_row_index - self.__start_index() # index of the selected visible row # selected row from visible rows self.selected_row = lambda: self.visible_rows()[self.__visible_row_index()] if self.visible_rows() else None + self.width = width + self.begin_x = begin_x self.win = curses.newwin(curses.LINES - 3, width, 0, begin_x) @@ -68,6 +72,8 @@ def run_command(key: str): subprocess.call(command, shell=True) curses.reset_prog_mode() # restore the previous terminal state SCREEN.refresh() + curses.mousemask(curses.REPORT_MOUSE_POSITION) # mouse tracking + print('\033[?1003h') # enable mouse tracking with the XTERM API. That's the magic def handle_filter_state(key: str, menu: Menu): @@ -85,6 +91,35 @@ def handle_filter_state(key: str, menu: Menu): MENUS[2].filtered_row_index = 0 # reset the selected row index of third menu before redrawing +def handle_mouse(mouse_info: tuple, menu: Menu): + row_number = mouse_info[2] - 3 + column_number = mouse_info[1] + next_menu = None + if column_number > (menu.begin_x + menu.width): + next_menu = MENUS[(MENUS.index(menu) + 1) % 3] + if column_number > (next_menu.begin_x + next_menu.width): + next_menu = MENUS[(MENUS.index(next_menu) + 1) % 3] + globals().update(SELECTED_MENU=next_menu) + elif column_number < menu.begin_x: + next_menu = MENUS[(MENUS.index(menu) - 1) % 3] + if column_number < next_menu.begin_x: + next_menu = MENUS[(MENUS.index(next_menu) - 1) % 3] + globals().update(SELECTED_MENU=next_menu) + if next_menu: + draw_row(menu.win, menu.title, 1, 2, selected=False) # remove selection from the current menu title + draw_row(next_menu.win, next_menu.title, 1, 2, selected=True) # and select the new menu title + menu = next_menu + char_int = menu.win.inch(mouse_info[2], column_number - menu.begin_x - 1) # get char from current mouse position + char_str = chr(char_int & 0xFF) + if not char_str or ord(char_str) > 127 or ' ' in char_str: + return + if 0 <= row_number < len(menu.visible_rows()): + menu.filtered_row_index = row_number + draw_rows(menu) # this will change selected row in menu + if menu != MENUS[2]: + MENUS[2].filtered_row_index = 0 # reset the selected row index of third menu before redrawing + + def catch_input(menu: Menu): while True: # refresh third menu until key pressed try: @@ -105,6 +140,9 @@ def catch_input(menu: Menu): draw_rows(menu) # this will change selected row in menu if menu != MENUS[2]: MENUS[2].filtered_row_index = 0 # reset the selected row index of third menu before redrawing + elif key == "KEY_MOUSE" and MOUSE: + mouse_info = curses.getmouse() + handle_mouse(mouse_info, menu) elif key in KEY_BINDINGS.keys() and MENUS[2].selected_row(): run_command(key) elif key == "\x1b" and not menu.filter: @@ -139,6 +177,8 @@ def main(screen): curses.curs_set(0) # make the cursor invisible curses.use_default_colors() # don't change the terminal color curses.noecho() # don't output characters at the top + curses.mousemask(curses.REPORT_MOUSE_POSITION) # mouse tracking + print('\033[?1003h') # enable mouse tracking with the XTERM API. That's the magic for menu in MENUS: # draw the main windows draw_menu(menu) draw_row(curses.newwin(3, curses.COLS, curses.LINES - 3, 0), HELP_TEXT, 1, 2) # and the help window