def search(): search_str = '' sel_index = 0 init_line = cio.getcurpos().y res_limit = 10 matches = list(cur.execute("select id,name,path from app order by last_launch_time desc limit ?", (res_limit,))) while True: update_display(cio.get_console_size()[0], res_limit + 3, search_str, matches, sel_index) k = cio.wait_key() if ord(k) == 8: # BACKSPACE, erase last char search_str = search_str[:-1] elif ord(k) == 13: # ENTER, launch id,name,path = matches[sel_index] with conn: cur.execute("update app set launch_cnt=launch_cnt+1, last_launch_time=strftime('%s', 'now') WHERE id=?", (id,)) os.startfile(path) break elif ord(k) == 27: # ESC, quit break elif ord(k) == 224: other_k = cio.wait_key() if ord(other_k) == 72: if sel_index > 0: sel_index -= 1 elif ord(other_k) == 80: if sel_index < len(matches) - 1: sel_index += 1 else: search_str += k sel_index = 0 matches = list(cur.execute("select id,name,path from app where name like ? order by launch_cnt desc limit ?", ('%{}%'.format(search_str), res_limit))) cio.setcurpos(0, cio.getcurpos().y + res_limit + 3)
def update_display(width, height, search_str, matches, sel_index): assert width > 5 assert height > 0 width -= 1 search_str_prefix = 'app: ' cio.setcurpos(0, cio.getcurpos().y) print '{}{}'.format(search_str_prefix, cio.str_fill(search_str, width - len(search_str_prefix))) print line_count = 2 for i, (id, name, path) in enumerate(matches): if line_count >= height: break fmt_name = cio.str_fill(name, 30) fmt_path = cio.str_fill(path, width - len(fmt_name) - 3) # The 3 is for the two spaces and the * print '{} {} {}'.format('*' if sel_index == i else ' ', fmt_name, fmt_path) line_count += 1 for _ in range(height - line_count): print ' '*width cio.setcurpos(len(search_str_prefix) + len(search_str), cio.getcurpos().y - height)
def show(self, sort=True): """ Print menu items and wait for user input. Parameters: sort: if True, the menu items will be sorted by key. If False, the items will be displayed in the same order they were added. Returns: True when a valid item was selected, False if ESC was pressed. """ # The list of available keys (used to generate a key when none has been # provided for a given item) availKeys = list('abcdefghijklmnopqrstuvwxyz') # Loop on all items to validate the type of items, organize by key itemsNoKey = [] itemsByKey = dict() for item in self.items: if not isinstance(item, Item): raise Exception('Items composing the menu must be instances of the menu.Item class') if len(item.key) > 1: raise Exception('Item key cannot have more than one character') if item.key == '': itemsNoKey.append(item) else: if item.key in itemsByKey: raise Exception('Two items have the same key %s' % (item.key,)) itemsByKey[item.key] = item availKeys.remove(item.key) # If some items have no key, generate a key for those for item in itemsNoKey: item.key = availKeys.pop(0) if item.key in itemsByKey: raise Exception('An auto generated key was already allocated') itemsByKey[item.key] = item # Print menu sortedItems = sorted(self.items) if sort else self.items for i, item in enumerate(sortedItems): item.lineNumber = cio.getcurpos().y print item.getLine() # Wait for user input and return result(s) result = True while True: c = cio.wait_key() if c in itemsByKey: if itemsByKey[c].trigger(): break elif ord(c) == 13: # ENTER key break elif ord(c) == 27: # ESC key result = False break # Return result return result