def run(): vi_mode_enabled = False # Create a set of key bindings that have Vi mode enabled if the # ``vi_mode_enabled`` is True.. manager = KeyBindingManager.for_prompt( enable_vi_mode=Condition(lambda cli: vi_mode_enabled)) # Add an additional key binding for toggling this flag. @manager.registry.add_binding(Keys.F4) def _(event): " Toggle between Emacs and Vi mode. " nonlocal vi_mode_enabled vi_mode_enabled = not vi_mode_enabled # Add a bottom toolbar to display the status. style = style_from_dict({ Token.Toolbar: 'reverse', }) def get_bottom_toolbar_tokens(cli): " Display the current input mode. " text = 'Vi' if vi_mode_enabled else 'Emacs' return [ (Token.Toolbar, ' [F4] %s ' % text) ] prompt('> ', key_bindings_registry=manager.registry, get_bottom_toolbar_tokens=get_bottom_toolbar_tokens, style=style)
def __init__(self, prompt=None, histfile=None, eventloop=None): cmd.Cmd.__init__(self) self.title = u"mailnex" self.completer = Completer(self) # ttyBusy tracks times when printing is a Bad Idea self.ttyBusy = False # lexerEnabled is a marker for the lexer to check before doing # interpretations. Currently, this just turns it off when the prompt # isn't for the command line but for composing messages. self.lexerEnabled = True if histfile: self.history = prompt_toolkit.history.FileHistory(histfile) else: self.history = prompt_toolkit.history.InMemoryHistory() if prompt is None: prompt = "> " self.prompt = prompt def gpt(cli): return [ (Token, self.prompt), ] self.ptkevloop = ptk_pyuv_wrapper(eventloop) registry = KeyBindingManager.for_prompt().registry @registry.add_binding(Keys.ControlZ) def _(event): """Support backrounding ourselves.""" # I'm surprised this isn't part of the default maps. # # Ideally, we shouldn't actually have to handle this ourselves; the # terminal should handle it for us. However, we are putting the # terminal into raw mode, so it won't. The next best thing would be # to try to get the actual background character the terminal would # use and use that. It is controlZ by default on every Unix system # I've used, but it is adjustable, with the 'stty' utility for # example. # TODO: Figure out how to use an appropriate key here, or allow it # to be customized. event.cli.suspend_to_background() self.cli = prompt_toolkit.interface.CommandLineInterface( application = prompt_toolkit.shortcuts.create_prompt_application( u"", #multiline = True, get_prompt_tokens = gpt, style = prompt_style, lexer = PygmentsLexer(PromptLexerFactory(self)), completer = self.completer, history = self.history, auto_suggest = prompt_toolkit.auto_suggest.AutoSuggestFromHistory(), get_title = self.get_title, get_bottom_toolbar_tokens=self.toolbar, key_bindings_registry=registry, ), eventloop = self.ptkevloop, output = prompt_toolkit.shortcuts.create_output(true_color = False), ) # ui_lines is the number of lines occupied by the UI. # For example, 1 line for command prompt, 7 lines for completion menu, # 1 line for toolbar. self.ui_lines = 9 self.status = {'unread': None}
def _feed_cli_with_input(text, editing_mode=EditingMode.EMACS, clipboard=None, history=None): """ Create a CommandLineInterface, feed it with the given user input and return the CLI object. This returns a (result, CLI) tuple. """ # If the given text doesn't end with a newline, the interface won't finish. assert text.endswith('\n') loop = PosixEventLoop() try: inp = PipeInput() inp.send_text(text) cli = CommandLineInterface( application=Application( buffer=Buffer(accept_action=AcceptAction.RETURN_DOCUMENT, history=history), editing_mode=editing_mode, clipboard=clipboard or InMemoryClipboard(), key_bindings_registry=KeyBindingManager.for_prompt().registry, ), eventloop=loop, input=inp, output=DummyOutput()) result = cli.run() return result, cli finally: loop.close() inp.close()
def run(): # Create a set of key bindings that have Vi mode enabled if the # ``vi_mode_enabled`` is True.. manager = KeyBindingManager.for_prompt() # Add an additional key binding for toggling this flag. @manager.registry.add_binding(Keys.F4) def _(event): " Toggle between Emacs and Vi mode. " if event.cli.editing_mode == EditingMode.VI: event.cli.editing_mode = EditingMode.EMACS else: event.cli.editing_mode = EditingMode.VI # Add a bottom toolbar to display the status. style = style_from_dict({ Token.Toolbar: 'reverse', }) def get_bottom_toolbar_tokens(cli): " Display the current input mode. " text = 'Vi' if cli.editing_mode == EditingMode.VI else 'Emacs' return [ (Token.Toolbar, ' [F4] %s ' % text) ] prompt('> ', key_bindings_registry=manager.registry, get_bottom_toolbar_tokens=get_bottom_toolbar_tokens, style=style)
async def td_client_interactive_shell(callback): eventloop = create_asyncio_eventloop() key_bindings_manager = KeyBindingManager.for_prompt() load_td_client_kay_bindings(key_bindings_manager=key_bindings_manager) cli = CommandLineInterface( application=create_prompt_application('待开发指令,just echo: ', key_bindings_registry=key_bindings_manager.registry, get_bottom_toolbar_tokens=get_td_client_bottom_toolbar_tokens, style=get_td_client_styles() ), eventloop=eventloop ) sys.stdout = cli.stdout_proxy() while True: try: result = await cli.run_async() if callback is not None: resp = callback(user_input=result.text) print(resp) else: print('You said: "{0}"'.format(result.text)) except (EOFError, KeyboardInterrupt): return
def pt_init(self): def get_prompt_tokens(cli): return [(Token.Prompt, self.prompt)] def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) if self._ptcomp is None: compl = IPCompleter(shell=self.shell, namespace={}, global_namespace={}, parent=self.shell, ) self._ptcomp = IPythonPTCompleter(compl, patch_stdout=patch_stdout) kbmanager = KeyBindingManager.for_prompt() supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend )(suspend_to_bg) self._pt_app = create_prompt_application( editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), key_bindings_registry=kbmanager.registry, history=self.shell.debugger_history, completer= self._ptcomp, enable_history_search=True, mouse_support=self.shell.mouse_support, get_prompt_tokens=get_prompt_tokens ) self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop)
def __init__(self, graphuri, *args, **kwargs): super(GraphCLI, self).__init__(*args, **kwargs) self.graph = GraphMiddleware.get_middleware_by_uri(graphuri) self.kbmgr = KeyBindingManager.for_prompt() self.histmgr = HistoryManager() self.register_shortcuts()
def init_prompt_toolkit_cli(self): if self.simple_prompt: # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): isp = self.input_splitter prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens()) while isp.push_accepts_more(): line = cast_unicode_py2(input(prompt_text)) isp.push(line) prompt_text = prompt_continuation return isp.source_reset() self.prompt_for_code = prompt return # Set up keyboard shortcuts kbmanager = KeyBindingManager.for_prompt( enable_open_in_editor=self.extra_open_editor_shortcuts, ) register_ipython_shortcuts(kbmanager.registry, self) # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for __, ___, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) last_cell = cell self._style = self._make_style_from_name_or_cls(self.highlighting_style) self.style = DynamicStyle(lambda: self._style) editing_mode = getattr(EditingMode, self.editing_mode.upper()) def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) self._pt_app = create_prompt_application( editing_mode=editing_mode, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(shell=self, patch_stdout=patch_stdout), enable_history_search=True, style=self.style, mouse_support=self.mouse_support, **self._layout_options() ) self._eventloop = create_eventloop(self.inputhook) self.pt_cli = CommandLineInterface( self._pt_app, eventloop=self._eventloop, output=create_output(true_color=self.true_color))
def main(): # We start with a `KeyBindingManager` instance, because this will already # nicely load all the default key bindings. key_bindings_manager = KeyBindingManager.for_prompt() # Add our own key binding to the registry of the key bindings manager. @key_bindings_manager.registry.add_binding(Keys.F4) def _(event): """ When F4 has been pressed. Insert "hello world" as text. """ event.cli.current_buffer.insert_text('hello world') @key_bindings_manager.registry.add_binding('x', 'y') def _(event): """ (Useless, but for demoing.) Typing 'xy' will insert 'z'. Note that when you type for instance 'xa', the insertion of 'x' is postponed until the 'a' is typed. because we don't know earlier whether or not a 'y' will follow. However, prompt-toolkit should already give some visual feedback of the typed character. """ event.cli.current_buffer.insert_text('z') @key_bindings_manager.registry.add_binding('a', 'b', 'c') def _(event): " Typing 'abc' should insert 'd'. " event.cli.current_buffer.insert_text('d') @key_bindings_manager.registry.add_binding(Keys.ControlT) def _(event): """ Print 'hello world' in the terminal when ControlT is pressed. We use ``run_in_terminal``, because that ensures that the prompt is hidden right before ``print_hello`` gets executed and it's drawn again after it. (Otherwise this would destroy the output.) """ def print_hello(): print('hello world') event.cli.run_in_terminal(print_hello) # Read input. print('Press F4 to insert "hello world", type "xy" to insert "z":') text = prompt('> ', key_bindings_registry=key_bindings_manager.registry) print('You said: %s' % text)
def init_prompt_toolkit_cli(self): if self.simple_prompt: # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return # Set up keyboard shortcuts kbmanager = KeyBindingManager.for_prompt() register_ipython_shortcuts(kbmanager.registry, self) # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for __, ___, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) last_cell = cell self._style = self._make_style_from_name_or_cls(self.highlighting_style) style = DynamicStyle(lambda: self._style) editing_mode = getattr(EditingMode, self.editing_mode.upper()) self._pt_app = create_prompt_application( editing_mode=editing_mode, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(shell=self), enable_history_search=True, style=style, mouse_support=self.mouse_support, **self._layout_options() ) self._eventloop = create_eventloop(self.inputhook) self.pt_cli = CommandLineInterface( self._pt_app, eventloop=self._eventloop, output=create_output(true_color=self.true_color))
def pt_init(self): def get_prompt_tokens(cli): return [(Token.Prompt, self.prompt)] def patch_stdout(**kwargs): return self.pt_cli.patch_stdout_context(**kwargs) if self._ptcomp is None: compl = IPCompleter(shell=self.shell, namespace={}, global_namespace={}, parent=self.shell, ) self._ptcomp = IPythonPTCompleter(compl, patch_stdout=patch_stdout) kbmanager = KeyBindingManager.for_prompt() supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend )(suspend_to_bg) if self.shell.display_completions == 'readlinelike': kbmanager.registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & ViInsertMode() | EmacsInsertMode() & ~cursor_in_leading_ws ))(display_completions_like_readline) multicolumn = (self.shell.display_completions == 'multicolumn') self._pt_app = create_prompt_application( editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), key_bindings_registry=kbmanager.registry, history=self.shell.debugger_history, completer= self._ptcomp, enable_history_search=True, mouse_support=self.shell.mouse_support, get_prompt_tokens=get_prompt_tokens, display_completions_in_columns=multicolumn, style=self.shell.style ) self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop)
def __init__(self, username, fs, starting_path=None, prompt_style=DEFAULT_PROMPT_STYLE): # TODO: Consider rewriting to pass in a fake host/IP self.host = gethostname() # TODO: Uhhh....wat self.ip = gethostbyname(self.host) homedir = '/home/%s' % username starting_path = starting_path if starting_path else homedir self.env = Env( SHELL=SHELL_PATH, USER=username, PWD=starting_path, HOME=homedir ) self.fs = fs self.manager = KeyBindingManager.for_prompt() self.manager.registry.add_binding(Keys.ControlC)(self.on_ctrlc) self.prompt_style = prompt_style # TODO: Use on-disk history file self.history = InMemoryHistory() self.is_running = True self.last_exit_code = 0 self.status = 'Welcome back, %s' % username
def init_prompt_toolkit_cli(self): self._app = None if self.simple_prompt: # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2( input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return kbmanager = KeyBindingManager.for_prompt() insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode)) def _(event): b = event.current_buffer d = b.document if b.complete_state: cc = b.complete_state.current_completion if cc: b.apply_completion(cc) else: b.cancel_completion() return if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return status, indent = self.input_splitter.check_complete(d.text + '\n') if (status != 'incomplete') and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + (' ' * (indent or 0))) @kbmanager.registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER))) def _previous_history_or_previous_completion(event): """ Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. If completer is open this still select previous completion. """ event.current_buffer.auto_up() @kbmanager.registry.add_binding(Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER))) def _next_history_or_next_completion(event): """ Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. If completer is open this still select next completion. """ event.current_buffer.auto_down() @kbmanager.registry.add_binding(Keys.ControlG, filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions())) def _dismiss_completion(event): b = event.current_buffer if b.complete_state: b.cancel_completion() @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _reset_buffer(event): b = event.current_buffer if b.complete_state: b.cancel_completion() else: b.reset() @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)) def _reset_search_buffer(event): if event.current_buffer.document.text: event.current_buffer.reset() else: event.cli.push_focus(DEFAULT_BUFFER) supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend) def _suspend_to_bg(event): event.cli.suspend_to_background() @Condition def cursor_in_leading_ws(cli): before = cli.application.buffer.document.current_line_before_cursor return (not before) or before.isspace() # Ctrl+I == Tab @kbmanager.registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & cursor_in_leading_ws)) def _indent_buffer(event): event.current_buffer.insert_text(' ' * 4) if self.display_completions == 'readlinelike': @kbmanager.registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & ~cursor_in_leading_ws)) def _disaply_compl(ev): display_completions_like_readline(ev) if sys.platform == 'win32': from IPython.lib.clipboard import (ClipboardEmpty, win32_clipboard_get, tkinter_clipboard_get) @kbmanager.registry.add_binding(Keys.ControlV, filter=(HasFocus(DEFAULT_BUFFER) & ~ViMode())) def _paste(event): try: text = win32_clipboard_get() except TryNext: try: text = tkinter_clipboard_get() except (TryNext, ClipboardEmpty): return except ClipboardEmpty: return event.current_buffer.insert_text(text.replace('\t', ' ' * 4)) # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for __, ___, cell in self.history_manager.get_tail( self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) self._style = self._make_style_from_name(self.highlighting_style) style = DynamicStyle(lambda: self._style) editing_mode = getattr(EditingMode, self.editing_mode.upper()) self._app = create_prompt_application( editing_mode=editing_mode, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(self.Completer), enable_history_search=True, style=style, mouse_support=self.mouse_support, **self._layout_options()) self._eventloop = create_eventloop(self.inputhook) self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
def init_prompt_toolkit_cli(self): if not sys.stdin.isatty(): # Piped input - e.g. for tests. Fall back to plain non-interactive # output. This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode) insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT) # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode )) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return status, indent = self.input_splitter.check_complete(d.text) if (status != 'incomplete') and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + (' ' * (indent or 0))) @kbmanager.registry.add_binding(Keys.ControlC) def _(event): event.current_buffer.reset() # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) style_overrides = { Token.Prompt: '#009900', Token.PromptNum: '#00ff00 bold', } if self.highlighting_style: style_cls = get_style_by_name(self.highlighting_style) else: style_cls = get_style_by_name('default') # The default theme needs to be visible on both a dark background # and a light background, because we can't tell what the terminal # looks like. These tweaks to the default theme help with that. style_overrides.update({ Token.Number: '#007700', Token.Operator: 'noinherit', Token.String: '#BB6622', Token.Name.Function: '#2080D0', Token.Name.Class: 'bold #2080D0', Token.Name.Namespace: 'bold #2080D0', }) style_overrides.update(self.highlighting_style_overrides) style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, style_dict=style_overrides) app = create_prompt_application(multiline=True, lexer=PygmentsLexer(Python3Lexer if PY3 else PythonLexer), get_prompt_tokens=self.get_prompt_tokens, get_continuation_tokens=self.get_continuation_tokens, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(self.Completer), enable_history_search=True, style=style, mouse_support=self.mouse_support, ) self.pt_cli = CommandLineInterface(app, eventloop=create_eventloop(self.inputhook))
from prompt_toolkit.interface import AbortAction from prompt_toolkit.filters import Always from prompt_toolkit.interface import AcceptAction from prompt_toolkit.token import Token from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.keys import Keys from utils import TextUtils from completer import Completer from slack import Slack from style import DocumentStyle from threading import Event, Thread manager = KeyBindingManager.for_prompt() def find_user_name(user_id): url = "https://slack.com/api/users.list?token={token}".format(token=settings.token) response = requests.get(url).json() for i in response["members"]: if i["id"] == user_id: return i["name"] return None def get_alert(text): #TODO : add notification sound url = "https://slack.com/api/auth.test?token={token}".format(token=settings.token) response = requests.get(url).json()
def manager_for_environment(env): def load_bindings(key_bindings_manager): handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() @key_bindings_manager.registry.add_binding(Keys.ControlL)#, eager=True) def clear_(event): clear() print(env.welcome) PROMPT = env.prompt PROMPT = PROMPT.replace(r"\u", env.user).replace(r"\w", env.directory) print(unicode_(PROMPT), end="") @key_bindings_manager.registry.add_binding(Keys.ControlB) def list_(event): print("\n".join(ls(env, [], {}))) PROMPT = env.prompt PROMPT = PROMPT.replace(r"\u", env.user).replace(r"\w", env.directory) print(env.default_color, end="") print(unicode_(PROMPT), end="") @handle(Keys.ControlJ, filter= ~has_selection & (ViInsertMode() | EmacsInsertMode()) & HasFocus(DEFAULT_BUFFER) & IsMultiline()) def _(event): """ Behaviour of the Enter key. Auto indent after newline/Enter. (When not in Vi navigaton mode, and when multiline is enabled.) """ b = event.current_buffer empty_lines_required = 2 def at_the_end(b): """ we consider the cursor at the end when there is no text after the cursor, or only whitespace. """ text = b.document.text_after_cursor return text == '' or (text.isspace() and not '\n' in text) if at_the_end(b) and (b.document.text.replace(' ', '').endswith('\n' * (empty_lines_required - 1)) or (b.document.text.replace("\n", "").endswith(";"))): # When the cursor is at the end, and we have an empty line: # drop the empty lines, but return the value. b.document = Document( text=b.text.rstrip(), cursor_position=len(b.text.rstrip())) b.accept_action.validate_and_handle(event.cli, b) else: _auto_newline(b) def _auto_newline(_buffer): r""" Insert \n at the cursor position. Also add necessary padding. """ insert_text = _buffer.insert_text if _buffer.document.current_line_after_cursor: # When we are in the middle of a line. Always insert a newline. insert_text('\n') else: # Go to new line, but also add indentation. current_line = _buffer.document.current_line_before_cursor.rstrip() insert_text('\n') # Unident if the last line ends with 'pass', remove four spaces. unindent = current_line.rstrip().endswith(' pass') # Copy whitespace from current line current_line2 = current_line[4:] if unindent else current_line for c in current_line2: if c.isspace(): insert_text(c) else: break # If the last line ends with a colon, add four extra spaces. if current_line[-1:] == ':': for x in range(4): insert_text(' ') manager = KeyBindingManager.for_prompt() load_bindings(manager) return manager
def read(self, prompt_str='λ く'): ''' The main read eval print loop for RIPL. Uses prompt_toolkit: http://python-prompt-toolkit.readthedocs.io/en/stable/ ''' def exit_message(): print('\nThanks for giving RIPL a try!\nさようなら!\n') if not self.global_scope: raise EnvironmentError('Things have gone horribly wrong...') print(' <({[ RIPL -- RIPL Is Pythonic Lisp ]})>\n' ' Ctrl-Space to enter selection mode.\n' ' Ctrl-W/Y to cut/paste to system clipboard.\n' ' Ctrl-D to exit\n') history = InMemoryHistory() completer = WordCompleter(self.completions, ignore_case=True) kbm = KeyBindingManager.for_prompt(enable_system_bindings=True) add_binding = kbm.registry.add_binding @add_binding(Keys.Tab, filter=Tab_to_whitespace()) def _(event): '''Either indent or do completion''' event.cli.current_buffer.insert_text(' ') @add_binding(Keys.ControlJ) def __(event): '''Either enter a newline or accept input based on context''' b = event.current_buffer txt = b.document.text def at_end(b): '''Is the cursor at the end of the buffer?''' text = b.document.text_after_cursor return text == '' or (text.isspace() and '\n' not in text) at_end = at_end(b) has_empty_line = txt.replace(' ', '').endswith('\n') balanced = is_balanced(b.document.text) if (at_end and has_empty_line) or balanced: if b.validate(): b.accept_action.validate_and_handle(event.cli, b) else: newline_and_indent(b) # Show matching parentheses, but only while editing. highlight_parens = ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=~IsDone()) while True: repl = create_prompt_application( prompt_str, multiline=True, history=history, style=ripl_style, mouse_support=True, completer=completer, validator=ParenValidator(), enable_history_search=True, complete_while_typing=False, clipboard=PyperclipClipboard(), lexer=PygmentsLexer(RiplLexer), key_bindings_registry=kbm.registry, display_completions_in_columns=True, auto_suggest=AutoSuggestFromHistory(), get_continuation_tokens=self.cont_tokens, extra_input_processors=[highlight_parens]) try: eventloop = create_eventloop() cli = CommandLineInterface( application=repl, eventloop=eventloop, output=create_output(true_color=True)) user_input = cli.run(reset_current_buffer=False) if user_input: if isinstance(user_input, Document): user_input = user_input.text lines = user_input.split('\n') expression = ' '.join([l.strip() for l in lines]) self.eval_and_print(expression) except (EOFError, KeyboardInterrupt): # User hit Ctl+d exit_message() break finally: eventloop.close()
def get_prompt_args(): key_bindings_manager = KeyBindingManager.for_prompt() @key_bindings_manager.registry.add_binding(Keys.Escape) def h1(event): """ When ESC has been pressed, clear the input text. """ event.cli.current_buffer.cursor_right(999) event.cli.current_buffer.delete_before_cursor(999) @key_bindings_manager.registry.add_binding(Keys.ControlV) def h2(event): """ When Ctrl-V has been pressed, insert clipboard text to the cursor. """ from hlutils import get_clipboard_text text = get_clipboard_text(True) event.cli.current_buffer.insert_text(text) @key_bindings_manager.registry.add_binding(Keys.ControlO) def h3(event): """ When Ctrl-O has been pressed, open a Vim process to select a history command. """ import subprocess as sp import random rcfile = os.path.dirname(__file__) + "\\history.vim" randval = random.randint(1000000, 9999999) histfile = os.path.expandvars("$TMP/cmdex_%d.hist" % randval) selectfile = os.path.expandvars("$TMP/cmdex_%d.sel" % randval) with open(histfile, "w") as f: for cmd in hist_obj.strings: print >> f, cmd.encode("utf-8") os.system("vim.exe -R --noplugin + -u %s -- %s" % (rcfile, histfile)) os.remove(histfile) global default_input if os.path.exists(selectfile): text = open(selectfile).read().strip() default_input = text.decode("utf-8", "ignore") os.remove(selectfile) event.cli.current_buffer.cursor_right(999) event.cli.current_buffer.delete_before_cursor(999) event.cli.set_return_value(Document("")) args = { "style": style_from_dict({ Token.PATH: "#80C0FF", Token.HOST: "#00FF00", Token.TIP: "#FF0000", }), "get_prompt_tokens": lambda cli: [ (Token.HOST, "%s@%s " % (os.getenv("USERNAME", ""), os.getenv("COMPUTERNAME", ""))), (Token.PATH, "%s\n" % os.getcwdu().replace("\\", "/")), (Token.TIP, "$ "), ], "completer": CmdExCompleter(), "display_completions_in_columns": True, "history": hist_obj, "key_bindings_registry": key_bindings_manager.registry, } return args
def run_shell(): ppm_password = require_pwd() account_manager = new_account_manager(ppm_password) shell_history = FileHistory(ppm_shell_history) key_bindings_manager = KeyBindingManager.for_prompt() g = create_grammar() lexer = GrammarLexer(g, lexers={ 'command': SimpleLexer(Token.Command), 'value': SimpleLexer(Token.Value), 'accountName': SimpleLexer(Token.Value), 'force': SimpleLexer(Token.Option), 'option': SimpleLexer(Token.Option), 'updateOption': SimpleLexer(Token.Option), 'updateValue': SimpleLexer(Token.OptionValue), 'keyword': SimpleLexer(Token.Value), 'path': SimpleLexer(Token.Value), }) @key_bindings_manager.registry.add_binding('c', 't') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('create') @key_bindings_manager.registry.add_binding('l', 's') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('list') @key_bindings_manager.registry.add_binding('e', 't') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('exit') @key_bindings_manager.registry.add_binding('r', 'm') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('remove') @key_bindings_manager.registry.add_binding('p', 'w') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('password') @key_bindings_manager.registry.add_binding('s', 't') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('switch') @key_bindings_manager.registry.add_binding('w', 'e') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('where') @key_bindings_manager.registry.add_binding('u', 'd') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('update') @key_bindings_manager.registry.add_binding('s', 'h') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('search') @key_bindings_manager.registry.add_binding('h', 'p') def _(event): if len(event.cli.current_buffer.text) == 0: event.cli.current_buffer.insert_text('help') while True: completer = GrammarCompleter(g, { 'command': WordCompleter(shell_commands), 'accountName': WordCompleter(account_manager.get_all_name()), 'force': WordCompleter(['-f']), 'updateOption': WordCompleter(update_options), 'path': PathCompleter(), }) text = prompt(">> ", history=shell_history, key_bindings_registry=key_bindings_manager.registry, lexer=lexer, completer=completer, style=PygmentsStyle(CommandStyle), on_abort=AbortAction.RETRY) m = g.match(text) if m: _vars = m.variables() command = _vars.get('command') if command == 'list': target = _vars.get('accountName') do_list(account_manager, target=target) elif command == 'create': do_create(account_manager) elif command == 'remove': target = _vars.get('accountName') force_option = _vars.get('force') do_remove(account_manager, target=target, force=force_option) elif command == 'update': target = _vars.get('accountName') update_option = _vars.get('updateOption') force_option = _vars.get('force') do_update(account_manager, target=target, field=update_option, force=force_option) elif command == 'search': keyword = _vars.get('keyword') do_search(account_manager, keyword=keyword) elif command == 'password': store_path = _vars.get('path') if not store_path: store_path = default_store_path account_manager = do_password(account_manager, store_path=store_path) elif command == 'switch': store_path = _vars.get('path') try: account_manager = do_switch(store_path) except Exception, e: print "ERROR: Wrong password!" elif command == 'where': print account_manager.get_store_path() elif command == 'exit': sys.exit(0) elif command == 'help': do_help() else: print 'ERROR: Command error!'
def manager_for_environment(env): """Return a key bindings manager given an Ergonomica environment.""" def load_bindings(key_bindings_manager): """ Load keybindings into prompt_toolkit. """ handle = key_bindings_manager.registry.add_binding has_selection = HasSelection() # for some reason Pylint doesn't think this function is "used" @key_bindings_manager.registry.add_binding(Keys.ControlL) def clear_(event): # pylint: disable=unused-variable """ Clear the screen. """ clear() print(env.welcome) print(env.get_prompt(), end="") @handle(Keys.Tab, filter=TabShouldInsertWhitespaceFilter()) def _(event): """ When tab should insert whitespace, do that instead of completion. """ event.cli.current_buffer.insert_text(' ') # prompt_toolkit _wants_ these two methods (they have different filter # attributes) @handle(Keys.ControlJ, filter=~has_selection & (ViInsertMode() | EmacsInsertMode()) & HasFocus(DEFAULT_BUFFER) & IsMultiline()) def _(event): # pylint: disable=function-redefined """ Behaviour of the Enter key. Auto indent after newline/Enter. (When not in Vi navigaton mode, and when multiline is enabled.) """ current_buffer = event.current_buffer empty_lines_required = 2 def at_the_end(ptk_buffer): """ we consider the cursor at the end when there is no text after the cursor, or only whitespace. """ text = ptk_buffer.document.text_after_cursor return text == '' or (text.isspace() and not '\n' in text) def all_blocks_closed(ptk_buffer): """Return True when all Ergonomica code blocks are closed.""" return tokenize(ptk_buffer.text).count("(") == tokenize( ptk_buffer.text).count(")") if at_the_end(current_buffer)\ and (current_buffer.document.text.replace(' ', '') .endswith('\n' * (empty_lines_required - 1) ) or all_blocks_closed(current_buffer)): current_buffer.document = Document( text=current_buffer.text.rstrip(), cursor_position=len(current_buffer.text.rstrip())) current_buffer.accept_action.validate_and_handle( event.cli, current_buffer) else: _auto_newline(current_buffer) def _auto_newline(_buffer): r""" Insert \n at the cursor position. Also add necessary padding. """ insert_text = _buffer.insert_text if _buffer.document.current_line_after_cursor: # When we are in the middle of a line. Always insert a newline. insert_text('\n') else: # Go to new line, but also add indentation. current_line = _buffer.document.current_line_before_cursor.rstrip() insert_text('\n') for character in current_line: if character.isspace(): insert_text(character) else: break # If the last line ends with a colon, add four extra spaces. insert_text(' ' * (tokenize(current_line).count("(") - tokenize(current_line).count(")"))) manager = KeyBindingManager.for_prompt() load_bindings(manager) return manager
"leopard", "lion", "mouse", "rabbit", "rat", "snake", "spider", "turkey", "turtle", ], ignore_case=True, ) # Create key bindings registry with a custom binding for the Tab key that # displays completions like GNU readline. key_bindings_manager = KeyBindingManager.for_prompt() key_bindings_manager.registry.add_binding(Keys.ControlI)(display_completions_like_readline) def main(): text = prompt( "Give some animals: ", completer=animal_completer, key_bindings_registry=key_bindings_manager.registry, # Important: for this to work: `complete_while_typing` needs # to be False. complete_while_typing=False, ) print("You said: %s" % text)
def __call__(self): def get_prompt_tokens(cli): return [ (Token.Username, Context().session.user or ''), (Token.At, '@' if Context().session.user else ''), (Token.Host, Context().session.host), (Token.Colon, ':'), (Token.Path, text_type(Context().shell.current_path)), (Token.Pound, '> ') ] key_bindings_registry = KeyBindingManager.for_prompt().registry manager = CommandManager() manager.load_namespace('contrail_api_cli.shell_command') completer = ShellCompleter() history = FileHistory(os.path.join(CONFIG_DIR, 'history')) cmd_aliases = ShellAliases() for cmd_name, cmd in manager.list: map(cmd_aliases.set, cmd.aliases) # load home resources to have them in cache # also build shortcut list for resource types # typing vmi/ will be expanded to virtual-machine-interface/ # automagically res_aliases = ShellAliases() try: for c in RootCollection(fetch=True): short_name = "".join([p if p == "ip" else p[0].lower() for p in c.type.split('-')]) res_aliases.set("%s = %s" % (short_name, c.type)) except HTTPClientError as e: return text_type(e) def _(event, aliases, char): b = event.cli.current_buffer w = b.document.get_word_before_cursor() if w is not None: if not w == aliases.get(w): b.delete_before_cursor(count=len(w)) b.insert_text(aliases.get(w)) b.insert_text(char) @key_bindings_registry.add_binding(' ') def _sa(event): _(event, cmd_aliases, ' ') @key_bindings_registry.add_binding('/') def _ra(event): _(event, res_aliases, '/') while True: try: action = prompt(get_prompt_tokens=get_prompt_tokens, history=history, completer=completer, style=default_style, eventloop=eventloop(), key_bindings_registry=key_bindings_registry) action = cmd_aliases.apply(action) except (EOFError, KeyboardInterrupt): break try: action = action.split('|') pipe_cmds = action[1:] action = shlex.split(action[0]) cmd = manager.get(action[0]) args = action[1:] if pipe_cmds: p = pipes.Template() for pipe_cmd in pipe_cmds: p.append(str(pipe_cmd.strip()), '--') cmd.is_piped = True else: cmd.is_piped = False except IndexError: continue except CommandNotFound as e: printo(text_type(e)) continue try: result = cmd.parse_and_call(*args) except (HttpError, HTTPClientError, CommandError, SchemaError, NotFound, Exists) as e: printo(text_type(e)) continue except KeyboardInterrupt: continue except EOFError: break else: if not result: continue elif pipe_cmds: t = tempfile.NamedTemporaryFile('r') with p.open(t.name, 'w') as f: f.write(result) printo(t.read().strip()) else: printo(result)
def question(message, **kwargs): # TODO disabled, dict choices if not 'choices' in kwargs: raise PromptParameterException('choices') choices = kwargs.pop('choices', None) default = kwargs.pop('default', 0) # TODO qmark = kwargs.pop('qmark', ' ') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, qmark)) tokens.append((Token.Question, ' %s ' % message)) if ic.answered: tokens.append((Token.Answer, ' ' + ic.get_selection()[0])) else: tokens.append((Token.Instruction, ' (Используйте стрелочки)')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens)), ConditionalContainer(Window(ic), filter=~IsDone()) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # event.cli.set_return_value(None) @manager.registry.add_binding(Keys.Down, eager=True) def move_cursor_down(event): def _next(): ic.selected_option_index = ((ic.selected_option_index + 1) % ic.choice_count) _next() while isinstance(ic.choices[ic.selected_option_index][0], Separator) or\ ic.choices[ic.selected_option_index][2]: _next() @manager.registry.add_binding(Keys.Up, eager=True) def move_cursor_up(event): def _prev(): ic.selected_option_index = ((ic.selected_option_index - 1) % ic.choice_count) _prev() while isinstance(ic.choices[ic.selected_option_index][0], Separator) or \ ic.choices[ic.selected_option_index][2]: _prev() @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(ic.get_selection()[1]) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
def get_app(choices): class InquirerControl(TokenListControl): selected_option_index = 0 answered = False choices = [] def __init__(self, choices, **kwargs): self.choices = choices super(InquirerControl, self).__init__(self._get_choice_tokens, **kwargs) @property def choice_count(self): return len(self.choices) def _get_choice_tokens(self, cli): tokens = [] T = Token def append(index, label): selected = (index == self.selected_option_index) tokens.append((T.Selected if selected else T, '> ' if selected else ' ')) if selected: tokens.append((Token.SetCursorPosition, '')) tokens.append((T.Selected if selected else T, '%-24s' % label)) tokens.append((T, '\n')) for i, choice in enumerate(self.choices): append(i, choice) tokens.pop() # Remove last newline. return tokens def get_selection(self): return self.choices[self.selected_option_index] ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] if ic.answered: cli.return_value = lambda: ic.get_selection() return tokens layout = HSplit([ Window(height=D.exact(0), content=TokenListControl(get_prompt_tokens, align_center=False)), ConditionalContainer(Window(ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=~IsDone()) ]) manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): event.cli.set_return_value(None) @manager.registry.add_binding(Keys.Down, eager=True) @manager.registry.add_binding(Keys.ControlN, eager=True) def move_cursor_down(event): ic.selected_option_index = ((ic.selected_option_index + 1) % ic.choice_count) @manager.registry.add_binding(Keys.Up, eager=True) @manager.registry.add_binding(Keys.ControlP, eager=True) def move_cursor_up(event): ic.selected_option_index = ((ic.selected_option_index - 1) % ic.choice_count) @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(None) inquirer_style = style_from_dict({ Token.QuestionMark: '#5F819D', Token.Selected: '#FF9D00', Token.Instruction: '', Token.Answer: '#FF9D00 bold', Token.Question: 'bold', }) app = Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=inquirer_style) return app
def __call__(self): def get_prompt_tokens(cli): return [(Token.Username, Context().session.user or ''), (Token.At, '@' if Context().session.user else ''), (Token.Host, Context().session.host), (Token.Colon, ':'), (Token.Path, text_type(Context().shell.current_path)), (Token.Pound, '> ')] key_bindings_registry = KeyBindingManager.for_prompt().registry manager = CommandManager() manager.load_namespace('contrail_api_cli.shell_command') completer = ShellCompleter() history = FileHistory(os.path.join(CONFIG_DIR, 'history')) cmd_aliases = ShellAliases() for cmd_name, cmd in manager.list: map(cmd_aliases.set, cmd.aliases) # load home resources to have them in cache # also build shortcut list for resource types # typing vmi/ will be expanded to virtual-machine-interface/ # automagically res_aliases = ShellAliases() try: for c in RootCollection(fetch=True): short_name = "".join([ p if p == "ip" else p[0].lower() for p in c.type.split('-') ]) res_aliases.set("%s = %s" % (short_name, c.type)) except HTTPClientError as e: return text_type(e) def _(event, aliases, char): b = event.cli.current_buffer w = b.document.get_word_before_cursor() if w is not None: if not w == aliases.get(w): b.delete_before_cursor(count=len(w)) b.insert_text(aliases.get(w)) b.insert_text(char) @key_bindings_registry.add_binding(' ') def _sa(event): _(event, cmd_aliases, ' ') @key_bindings_registry.add_binding('/') def _ra(event): _(event, res_aliases, '/') while True: try: action = prompt(get_prompt_tokens=get_prompt_tokens, history=history, completer=completer, style=default_style, eventloop=eventloop(), key_bindings_registry=key_bindings_registry) action = cmd_aliases.apply(action) except (EOFError, KeyboardInterrupt): break try: action = action.split('|') pipe_cmds = action[1:] action = shlex.split(action[0]) cmd = manager.get(action[0]) args = action[1:] if pipe_cmds: p = pipes.Template() for pipe_cmd in pipe_cmds: p.append(str(pipe_cmd.strip()), '--') cmd.is_piped = True else: cmd.is_piped = False except IndexError: continue except CommandNotFound as e: printo(text_type(e)) continue try: result = cmd.parse_and_call(*args) except (HttpError, HTTPClientError, CommandError, SchemaError, NotFound, Exists) as e: printo(text_type(e)) continue except KeyboardInterrupt: continue except EOFError: break else: if not result: continue elif pipe_cmds: t = tempfile.NamedTemporaryFile('r') with p.open(t.name, 'w') as f: f.write(result) printo(t.read().strip()) else: printo(result)
from __future__ import print_function from __future__ import unicode_literals from prompt_toolkit.completion import Completer, Completion from prompt_toolkit import prompt from prompt_toolkit.styles import PygmentsStyle from pygments.token import Token from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.keys import Keys from datetime import datetime import os import subprocess import random import sys manager = KeyBindingManager.for_prompt() toolbar_style = PygmentsStyle.from_defaults({ Token.Toolbar: '#ffffff bg:#333333', Token.SCM: '#FF1A00 bg:#333333', Token.QUIT: '#ffffff bg:#ff0000' }) # GIT COMMANDS GIT_STATUS = ['git', 'status', '--porcelain'] GIT_BRANCH = ['git', 'rev-parse', '--abbrev-ref', 'HEAD'] GIT_MODIFICATIONS = ['git', '--no-pager', 'diff', '--numstat', 'HEAD'] GIT_AUTHORS = ["git", "log", "--format=%aN"] @manager.registry.add_binding(Keys.ControlC)
def main(tenant, host, port, verbose): """Leapsight Semantic Dataspace Command Line Tool""" # Create a set of key bindings that have Vi mode enabled if the # ``vi_mode_enabled`` is True. if verbose: format = '[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s' logging.basicConfig(level=logging.DEBUG, format=format) # try to connect to lsd try: shell_ctx['lsd_api'] = Lsd(tenant, host, port) except Exception as e: click.echo(colorize('ERROR: connection refused {0}:{1}({2})'.format( host, port, tenant), rgb=0xE11500)) logging.debug(e) exit(1) manager = KeyBindingManager.for_prompt( enable_vi_mode=Condition(lambda cli: shell_ctx['vi_mode_enabled'])) # add an additional key binding for toggling this flag. @manager.registry.add_binding(Keys.F4) def _f4(_event): """ Toggle between Emacs and Vi mode. """ shell_ctx['vi_mode_enabled'] = not shell_ctx['vi_mode_enabled'] # add an additional key binding for toggling this flag. @manager.registry.add_binding(Keys.F5) def _f5(_event): """ Toggle between Json and Tabular mode. """ shell_ctx['json_mode_enabled'] = not shell_ctx['json_mode_enabled'] click.clear() click.echo(colorize(""" Welcome to _/ _/_/_/_/ _/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/_/_/ _/_/_/ command line interface! """ , rgb=0x2cb9d0)) ll_completer = WordCompleter( ['@prefix prefix: <uri>.', '@include <uri>.', '++().', '--().', '+().', '-().', '?().', 'import(filename)', 'export(filename)', 'h()', 'e()']) # load init file ~/lsd-cli.rc try: _load_context(shell_ctx, cli_rc) except: pass while True: input = prompt('lsd> ', history=history, auto_suggest=auto_suggest, get_bottom_toolbar_tokens=get_bottom_toolbar_tokens, style=style, vi_mode=shell_ctx['vi_mode_enabled'], key_bindings_registry=manager.registry, get_title=get_title, completer=ll_completer) try: if input: process_input(shell_ctx, input.strip()) except Exception as e: click.echo(colorize(e, rgb=0xE11500)) logging.debug(traceback.print_exc())
def question(message, **kwargs): # TODO disabled, dict choices if not 'choices' in kwargs: raise PromptParameterException('choices') choices = kwargs.pop('choices', None) default = kwargs.pop('default', 0) # TODO page_size = kwargs.pop('page_size', 0) qmark = kwargs.pop('qmark', '?') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices, page_size) def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, qmark)) tokens.append((Token.Question, ' %s ' % message)) if ic.answered: tokens.append((Token.Answer, ' ' + ic.get_selection()[0])) else: tokens.append((Token.Instruction, ' (Use arrow keys)')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens)), ConditionalContainer(Window(ic), filter=~IsDone()) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # event.cli.set_return_value(None) @manager.registry.add_binding(Keys.Down, eager=True) def move_cursor_down(event): ic.increment_selected_index() @manager.registry.add_binding(Keys.Up, eager=True) def move_cursor_up(event): ic.decrement_selected_index() @manager.registry.add_binding(Keys.Left, eager=True) def move_page_left(event): ic.decrement_page() @manager.registry.add_binding(Keys.Right, eager=True) def move_page_right(event): ic.increment_page() @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(ic.get_selection()[1]) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
def question(message, **kwargs): # TODO need ENTER confirmation default = kwargs.pop('default', True) # TODO style defaults on detail level style = kwargs.pop('style', style_from_dict({ Token.QuestionMark: '#5F819D', #Token.Selected: '#FF9D00', # AWS orange Token.Instruction: '', # default Token.Answer: '#FF9D00 bold', # AWS orange Token.Question: 'bold', })) status = {'answer': None} qmark = kwargs.pop('qmark', '?') def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, qmark)) tokens.append((Token.Question, ' %s ' % message)) if isinstance(status['answer'], bool): tokens.append((Token.Answer, ' Yes' if status['answer'] else ' No')) else: if default: instruction = ' (Y/n)' else: instruction = ' (y/N)' tokens.append((Token.Instruction, instruction)) return tokens # assemble layout # TODO this does not work without the HSplit?? layout = HSplit([ Window( height=D.exact(1), content=TokenListControl(get_prompt_tokens, align_center=False), ) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() @manager.registry.add_binding('n') @manager.registry.add_binding('N') def key_n(event): status['answer'] = False event.cli.set_return_value(False) @manager.registry.add_binding('y') @manager.registry.add_binding('Y') def key_y(event): status['answer'] = True event.cli.set_return_value(True) @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): status['answer'] = default event.cli.set_return_value(default) return Application( layout=layout, key_bindings_registry=manager.registry, mouse_support=False, style=style, erase_when_done=False, )
def question(message, **kwargs): # TODO extract common parts for list, checkbox, rawlist, expand # TODO up, down navigation if not 'choices' in kwargs: raise PromptParameterException('choices') choices = kwargs.pop('choices', None) default = kwargs.pop('default', None) qmark = kwargs.pop('qmark', '?') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices, default) def get_prompt_tokens(cli): tokens = [] T = Token tokens.append((T.QuestionMark, qmark)) tokens.append((T.Question, ' %s ' % message)) if not ic.answered: tokens.append((T.Instruction, ' (%s)' % ''.join( [k[0] for k in ic.choices if not isinstance(k, Separator)]))) else: tokens.append((T.Answer, ' %s' % ic.get_selected_value())) return tokens #@Condition #def is_help_active(cli): # return ic._help_active # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens)), ConditionalContainer( Window(ic), #filter=is_help_active & ~IsDone() # ~ bitwise inverse filter=~IsDone() # ~ bitwise inverse ) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # add key bindings for choices for i, c in enumerate(ic.choices): if not isinstance(c, Separator): def _reg_binding(i, keys): # trick out late evaluation with a "function factory": # http://stackoverflow.com/questions/3431676/creating-functions-in-a-loop @manager.registry.add_binding(keys, eager=True) def select_choice(event): ic.pointer_index = i if c[0] not in ['h', 'H']: _reg_binding(i, c[0]) if c[0].isupper(): _reg_binding(i, c[0].lower()) @manager.registry.add_binding('H', eager=True) @manager.registry.add_binding('h', eager=True) def help_choice(event): ic._help_active = True @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): selected_value = ic.get_selected_value() if selected_value == '__HELP__': ic._help_active = True else: ic.answered = True event.cli.set_return_value(selected_value) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
def create_prompt_application(self, message='', multiline=False, wrap_lines=True, is_password=False, vi_mode=False, complete_while_typing=True, enable_history_search=False, lexer=None, enable_system_bindings=False, enable_open_in_editor=False, validator=None, completer=None, reserve_space_for_menu=8, auto_suggest=None, style=None, history=None, clipboard=None, get_prompt_tokens=None, get_bottom_toolbar_tokens=None, display_completions_in_columns=False, get_title=None, mouse_support=False, extra_input_processors=None, key_bindings_registry=None, on_abort=AbortAction.RAISE_EXCEPTION, on_exit=AbortAction.RAISE_EXCEPTION, accept_action=AcceptAction.RETURN_DOCUMENT, default=''): """Create an :class:`~Application` instance for a prompt. (It is meant to cover 90% of the prompt use cases, where no extreme customization is required. For more complex input, it is required to create a custom :class:`~Application` instance.) message : Text to be shown before the prompt. mulitiline : Allow multiline input. Pressing enter will insert a newline. (This requires Meta+Enter to accept the input.) wrap_lines : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. When True (the default), automatically wrap long lines instead of scrolling horizontally. is_password : Show asterisks instead of the actual typed characters. vi_mode : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. If True, use Vi key bindings. complete_while_typing : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Enable autocompletion while typing. enable_history_search : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Enable up-arrow parting string matching. lexer : :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for the syntax highlighting. validator : :class:`~prompt_toolkit.validation.Validator` instance for input validation. completer : :class:`~prompt_toolkit.completion.Completer` instance for input completion. reserve_space_for_menu : Space to be reserved for displaying the menu. (0 means that no space needs to be reserved.) auto_suggest : :class:`~prompt_toolkit.auto_suggest.AutoSuggest` instance for input suggestions. style : Pygments style class for the color scheme. enable_system_bindings : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Pressing Meta+'!' will show a system prompt. enable_open_in_editor : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Pressing 'v' in Vi mode or C-X C-E in emacs mode will open an external editor. history : :class:`~prompt_toolkit.history.History` instance. clipboard : :class:`~prompt_toolkit.clipboard.base.Clipboard` instance. (e.g. :class:`~prompt_toolkit.clipboard.in_memory.InMemoryClipboard`) get_bottom_toolbar_tokens : Optional callable which takes a :class:`~prompt_toolkit.interface.CommandLineInterface` and returns a list of tokens for the bottom toolbar. display_completions_in_columns : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in multiple columns. get_title : Callable that returns the title to be displayed in the terminal. mouse_support : `bool` or :class:`~prompt_toolkit.filters.CLIFilter` to enable mouse support. default : The default text to be shown in the input buffer. (This can be edited by the user.) Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. WARNING; This method is due for removal once prompt-toolkit >v0.54 is released. """ if key_bindings_registry is None: key_bindings_registry = KeyBindingManager.for_prompt( enable_vi_mode=vi_mode, enable_system_bindings=enable_system_bindings, enable_open_in_editor=enable_open_in_editor).registry # Make sure that complete_while_typing is disabled when enable_history_search # is enabled. (First convert to SimpleFilter, to avoid doing bitwise operations # on bool objects.) complete_while_typing = to_simple_filter(complete_while_typing) enable_history_search = to_simple_filter(enable_history_search) multiline = to_simple_filter(multiline) complete_while_typing = complete_while_typing & ~enable_history_search # Accept Pygments styles as well for backwards compatibility. try: if issubclass(style, pygments.style.Style): style = PygmentsStyle(style) except TypeError: # Happens when style is `None` or an instance of something else. pass # Create application return Application( layout=self.create_prompt_layout( message=message, lexer=lexer, is_password=is_password, reserve_space_for_menu=(reserve_space_for_menu if completer is not None else 0), multiline=Condition(lambda cli: multiline()), get_prompt_tokens=get_prompt_tokens, get_bottom_toolbar_tokens=get_bottom_toolbar_tokens, display_completions_in_columns=display_completions_in_columns, extra_input_processors=extra_input_processors, wrap_lines=wrap_lines), buffer=Buffer( enable_history_search=enable_history_search, complete_while_typing=complete_while_typing, is_multiline=multiline, history=(history or InMemoryHistory()), validator=validator, completer=completer, auto_suggest=auto_suggest, accept_action=accept_action, initial_document=Document(default), ), style=style or DEFAULT_STYLE, clipboard=clipboard, key_bindings_registry=key_bindings_registry, get_title=get_title, mouse_support=mouse_support, on_abort=on_abort, on_exit=on_exit)
def main(): if prompt_toolkit.__version__[0:2] != "1.": from prompt_toolkit import PromptSession from prompt_toolkit.lexers import PygmentsLexer from prompt_toolkit.styles.pygments import style_from_pygments_cls from prompt_toolkit.key_binding import KeyBindings def key_bindings(): key_binding = KeyBindings() key_binding.add('enter')(return_handler) key_binding.add('tab')(tab_handler) return key_binding def return_handler(event): buffer = event.current_buffer # document = buffer.document if buffer.text.endswith("\\"): buffer.text = buffer.text[:-1] + '\n' else: buffer.validate_and_handle() def tab_handler(event): buffer = event.current_buffer document = buffer.document if buffer.auto_suggest: suggestion = buffer.auto_suggest.get_suggestion( buffer, document) if suggestion.text: buffer.text += suggestion.text buffer.cursor_position += len(suggestion.text) def prompt_continuation(width, line_number, is_soft_wrap): return ' ' * (width - 2) + "… " style = style_from_pygments_cls( get_style_by_name(env.get('_debug_read_color_scheme', 'vim'))) session = PromptSession( message=env.get('_debug_prompt', '$ '), lexer=PygmentsLexer(BashLexer), style=style, key_bindings=key_bindings(), history=FileHistory( env.get('JUST_DEBUG_HISTORY', os.path.expanduser('~/.debug_bash_history')) + '3'), enable_history_search=True, multiline=True, auto_suggest=AutoSuggestFromHistory(), prompt_continuation=prompt_continuation) try: text = session.prompt() sys.stderr.write(text) except KeyboardInterrupt: pass else: # from __future__ import unicode_literals from prompt_toolkit import prompt from prompt_toolkit.styles import style_from_pygments from prompt_toolkit.layout.lexers import PygmentsLexer from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.keys import Keys manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.Enter) def return_handler(event): buffer = event.current_buffer if buffer.text.endswith("\\"): buffer.text = buffer.text[:-1] + '\n' else: buffer.accept_action.validate_and_handle(event.cli, buffer) @manager.registry.add_binding(Keys.Tab) def tab_handler(event): buffer = event.current_buffer document = buffer.document if buffer.auto_suggest: suggestion = buffer.auto_suggest.get_suggestion( event.cli, buffer, document) if suggestion.text: buffer.text += suggestion.text buffer.cursor_position += len(suggestion.text) style = style_from_pygments( get_style_by_name(env.get('_debug_read_color_scheme', 'vim'))) try: text = prompt( env.get('_debug_prompt', '$ '), lexer=PygmentsLexer(BashLexer), style=style, key_bindings_registry=manager.registry, history=FileHistory( env.get('JUST_DEBUG_HISTORY', os.path.expanduser('~/.debug_bash_history')) + '3'), multiline=True, auto_suggest=AutoSuggestFromHistory()) sys.stderr.write(text) except KeyboardInterrupt: pass
def init_prompt_toolkit_cli(self): if ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or not sys.stdin.isatty(): # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode) insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT) # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode )) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return status, indent = self.input_splitter.check_complete(d.text) if (status != 'incomplete') and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + (' ' * (indent or 0))) @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _(event): event.current_buffer.reset() @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)) def _(event): if event.current_buffer.document.text: event.current_buffer.reset() else: event.cli.push_focus(DEFAULT_BUFFER) supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend) def _(event): event.cli.suspend_to_background() @Condition def cursor_in_leading_ws(cli): before = cli.application.buffer.document.current_line_before_cursor return (not before) or before.isspace() # Ctrl+I == Tab @kbmanager.registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & cursor_in_leading_ws )) def _(event): event.current_buffer.insert_text(' ' * 4) # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) self._style = self._make_style_from_name(self.highlighting_style) style = DynamicStyle(lambda: self._style) self._app = create_prompt_application( key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(self.Completer), enable_history_search=True, style=style, mouse_support=self.mouse_support, **self._layout_options() ) self.pt_cli = CommandLineInterface(self._app, eventloop=create_eventloop(self.inputhook))
class CmdManager(object): """Command manager to init the aiml kernel, accept commands, parse and execute same """ # Create a set of key bindings. manager = KeyBindingManager.for_prompt() cmd_style = style_from_dict({ # User input. Token: '#ff0066', # Prompt. Token.Username: '******', Token.At: '#00aa00', Token.Colon: '#00aa00', Token.Pound: '#00aa00', Token.Host: '#000088 bg:#aaaaff', Token.Path: '#884444 underline', }) def __init__(self, user='******', host='localhost', home_dir='/'): """default constructor """ self._username = user self._host = host self._home_dir = home_dir self._kernel = aiml.Kernel() self._kernel.verbose(True) self._kernel.bootstrap(learnFiles=os.path.join(config.KNOWLEDGE_BASE_PATH, 'startup.xml'), chdir=config.KNOWLEDGE_BASE_PATH) self._kernel.respond('load aiml b') def start(self): """Starts the loop to take inputs from cmd line """ print('Trying to load following path: %s/*.aiml' % config.KNOWLEDGE_BASE_PATH) self._kernel.learn('%s/*.aiml' % config.KNOWLEDGE_BASE_PATH) text = '' while text.lower() not in ['exit', 'quit']: text = prompt(get_prompt_tokens=self.get_prompt_tokens, style=CmdManager.cmd_style, key_bindings_registry=CmdManager.manager.registry, get_bottom_toolbar_tokens=self.get_bottom_toolbar_tokens) print(self._kernel.respond(text)) # Add an additional key binding for toggling this flag. @manager.registry.add_binding(Keys.F4) def _(self, event): " Toggle between Emacs and Vi mode. " cli = event.cli if cli.editing_mode == EditingMode.VI: cli.editing_mode = EditingMode.EMACS else: cli.editing_mode = EditingMode.VI # Add a toolbar at the bottom to display the current input mode. def get_bottom_toolbar_tokens(self, cli): " Display the current input mode. " text = 'Vi' if cli.editing_mode == EditingMode.VI else 'Emacs' return [ (Token.Toolbar, ' [F4] %s ' % text) ] def get_prompt_tokens(self, cli): return [ (Token.Username, self._username), (Token.At, '@'), (Token.Host, self._host), (Token.Colon, ':'), (Token.Path, self._home_dir), (Token.Pound, '# '), ]
def init_prompt_toolkit_cli(self): self._app = None if self.simple_prompt: # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return kbmanager = KeyBindingManager.for_prompt() insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode )) def _(event): b = event.current_buffer d = b.document if b.complete_state: cs = b.complete_state b.apply_completion(cs.current_completion) return if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return status, indent = self.input_splitter.check_complete(d.text) if (status != 'incomplete') and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + (' ' * (indent or 0))) @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _reset_buffer(event): event.current_buffer.reset() @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)) def _reset_search_buffer(event): if event.current_buffer.document.text: event.current_buffer.reset() else: event.cli.push_focus(DEFAULT_BUFFER) supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend) def _suspend_to_bg(event): event.cli.suspend_to_background() @Condition def cursor_in_leading_ws(cli): before = cli.application.buffer.document.current_line_before_cursor return (not before) or before.isspace() # Ctrl+I == Tab @kbmanager.registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & cursor_in_leading_ws )) def _indent_buffer(event): event.current_buffer.insert_text(' ' * 4) # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for __, ___, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) self._style = self._make_style_from_name(self.highlighting_style) style = DynamicStyle(lambda: self._style) editing_mode = getattr(EditingMode, self.editing_mode.upper()) self._app = create_prompt_application( editing_mode=editing_mode, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(self.Completer), enable_history_search=True, style=style, mouse_support=self.mouse_support, **self._layout_options() ) self._eventloop = create_eventloop(self.inputhook) self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
def question(message, **kwargs): # TODO need ENTER confirmation default = kwargs.pop('default', True) # TODO style defaults on detail level style = kwargs.pop( 'style', style_from_dict({ Token.QuestionMark: '#5F819D', #Token.Selected: '#FF9D00', # AWS orange Token.Instruction: '', # default Token.Answer: '#FF9D00 bold', # AWS orange Token.Question: 'bold', })) status = {'answer': None} qmark = kwargs.pop('qmark', '?') def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, qmark)) tokens.append((Token.Question, ' %s ' % message)) if isinstance(status['answer'], bool): tokens.append( (Token.Answer, ' Да' if status['answer'] else ' Нет')) else: if default: instruction = ' (Д/н)' else: instruction = ' (д/Н)' tokens.append((Token.Instruction, instruction)) return tokens # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() @manager.registry.add_binding('н') @manager.registry.add_binding('Н') def key_n(event): status['answer'] = False event.cli.set_return_value(False) @manager.registry.add_binding('д') @manager.registry.add_binding('Д') def key_y(event): status['answer'] = True event.cli.set_return_value(True) @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): status['answer'] = default event.cli.set_return_value(default) return create_prompt_application( get_prompt_tokens=get_prompt_tokens, key_bindings_registry=manager.registry, mouse_support=False, style=style, erase_when_done=False, )
def init_prompt_toolkit_cli(self): if ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or not sys.stdin.isatty(): # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2( input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode) insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT) # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode)) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return status, indent = self.input_splitter.check_complete(d.text) if (status != 'incomplete') and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + (' ' * (indent or 0))) @kbmanager.registry.add_binding(Keys.ControlC) def _(event): event.current_buffer.reset() # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail( self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) style_overrides = { Token.Prompt: '#009900', Token.PromptNum: '#00ff00 bold', } if self.highlighting_style: style_cls = get_style_by_name(self.highlighting_style) else: style_cls = get_style_by_name('default') # The default theme needs to be visible on both a dark background # and a light background, because we can't tell what the terminal # looks like. These tweaks to the default theme help with that. style_overrides.update({ Token.Number: '#007700', Token.Operator: 'noinherit', Token.String: '#BB6622', Token.Name.Function: '#2080D0', Token.Name.Class: 'bold #2080D0', Token.Name.Namespace: 'bold #2080D0', }) style_overrides.update(self.highlighting_style_overrides) style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, style_dict=style_overrides) app = create_prompt_application( multiline=True, lexer=PygmentsLexer(Python3Lexer if PY3 else PythonLexer), get_prompt_tokens=self.get_prompt_tokens, get_continuation_tokens=self.get_continuation_tokens, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(self.Completer), enable_history_search=True, style=style, mouse_support=self.mouse_support, ) self.pt_cli = CommandLineInterface(app, eventloop=create_eventloop( self.inputhook))
def question(message, **kwargs): # TODO add bottom-bar (Move up and down to reveal more choices) # TODO extract common parts for list, checkbox, rawlist, expand # TODO validate if not 'choices' in kwargs: raise PromptParameterException('choices') # this does not implement default, use checked... if 'default' in kwargs: raise ValueError('Checkbox does not implement \'default\' ' 'use \'checked\':True\' in choice!') choices = kwargs.pop('choices', None) validator = setup_simple_validator(kwargs) # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] tokens.append((Token.QuestionMark, '?')) tokens.append((Token.Question, ' %s ' % message)) if ic.answered: nbr_selected = len(ic.selected_options) if nbr_selected == 0: tokens.append((Token.Answer, ' done')) elif nbr_selected == 1: tokens.append((Token.Answer, ' [%s]' % ic.selected_options[0])) else: tokens.append( (Token.Answer, ' done (%d selections)' % nbr_selected)) else: tokens.append((Token.Instruction, ' (<up>, <down> to move, <space> to select, <a> ' 'to toggle, <i> to invert)')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens, align_center=False)), ConditionalContainer(Window(ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=~IsDone()) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # event.cli.set_return_value(None) @manager.registry.add_binding(' ', eager=True) def toggle(event): pointed_choice = ic.choices[ic.pointer_index][0] # name if pointed_choice in ic.selected_options: ic.selected_options.remove(pointed_choice) else: ic.selected_options.append(pointed_choice) @manager.registry.add_binding('i', eager=True) def invert(event): inverted_selection = [ c[0] for c in ic.choices if not isinstance(c, Separator) and c[0] not in ic.selected_options ] ic.selected_options = inverted_selection @manager.registry.add_binding('a', eager=True) def all(event): all_selected = True # all choices have been selected for c in ic.choices: if not isinstance(c, Separator) and c[0] not in ic.selected_options: # add missing ones ic.selected_options.append(c[0]) all_selected = False if all_selected: ic.selected_options = [] @manager.registry.add_binding(Keys.Down, eager=True) def move_cursor_down(event): def _next(): ic.pointer_index = ((ic.pointer_index + 1) % ic.line_count) _next() while isinstance(ic.choices[ic.pointer_index], Separator) or \ ic.choices[ic.pointer_index][2]: _next() @manager.registry.add_binding(Keys.Up, eager=True) def move_cursor_up(event): def _prev(): ic.pointer_index = ((ic.pointer_index - 1) % ic.line_count) _prev() while isinstance(ic.choices[ic.pointer_index], Separator) or \ ic.choices[ic.pointer_index][2]: _prev() @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True # TODO use validator event.cli.set_return_value(ic.get_selected_values()) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
def init_prompt_toolkit_cli(self): if 'JUPYTER_CONSOLE_TEST' in os.environ: # Simple restricted interface for tests so we can find prompts with # pexpect. Multi-line input not supported. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt self.print_out_prompt = \ lambda: print('Out[%d]: ' % self.execution_count, end='') return kbmanager = KeyBindingManager.for_prompt() insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode )) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return more, indent = self.check_complete(d.text) if (not more) and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + indent) @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _(event): event.current_buffer.reset() # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) style_overrides = { Token.Prompt: '#009900', Token.PromptNum: '#00ff00 bold', Token.OutPrompt: '#ff2200', Token.OutPromptNum: '#ff0000 bold', } if self.highlighting_style: style_cls = get_style_by_name(self.highlighting_style) else: style_cls = get_style_by_name('default') # The default theme needs to be visible on both a dark background # and a light background, because we can't tell what the terminal # looks like. These tweaks to the default theme help with that. style_overrides.update({ Token.Number: '#007700', Token.Operator: 'noinherit', Token.String: '#BB6622', Token.Name.Function: '#2080D0', Token.Name.Class: 'bold #2080D0', Token.Name.Namespace: 'bold #2080D0', }) style_overrides.update(self.highlighting_style_overrides) style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, style_dict=style_overrides) editing_mode = getattr(EditingMode, self.editing_mode.upper()) langinfo = self.kernel_info.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', 'text')) app = create_prompt_application(multiline=True, editing_mode=editing_mode, lexer=PygmentsLexer(get_pygments_lexer(lexer)), get_prompt_tokens=self.get_prompt_tokens, get_continuation_tokens=self.get_continuation_tokens, key_bindings_registry=kbmanager.registry, history=history, completer=JupyterPTCompleter(self.Completer), enable_history_search=True, style=style, ) self._eventloop = create_eventloop() self.pt_cli = CommandLineInterface(app, eventloop=self._eventloop, output=create_output(true_color=self.true_color), )
def create_prompt_application(self, message='', multiline=False, wrap_lines=True, is_password=False, vi_mode=False, complete_while_typing=True, enable_history_search=False, lexer=None, enable_system_bindings=False, enable_open_in_editor=False, validator=None, completer=None, reserve_space_for_menu=8, auto_suggest=None, style=None, history=None, clipboard=None, get_prompt_tokens=None, get_bottom_toolbar_tokens=None, display_completions_in_columns=False, get_title=None, mouse_support=False, extra_input_processors=None, key_bindings_registry=None, on_abort=AbortAction.RAISE_EXCEPTION, on_exit=AbortAction.RAISE_EXCEPTION, accept_action=AcceptAction.RETURN_DOCUMENT, default=''): """Create an :class:`~Application` instance for a prompt. (It is meant to cover 90% of the prompt use cases, where no extreme customization is required. For more complex input, it is required to create a custom :class:`~Application` instance.) message : Text to be shown before the prompt. mulitiline : Allow multiline input. Pressing enter will insert a newline. (This requires Meta+Enter to accept the input.) wrap_lines : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. When True (the default), automatically wrap long lines instead of scrolling horizontally. is_password : Show asterisks instead of the actual typed characters. vi_mode : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. If True, use Vi key bindings. complete_while_typing : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Enable autocompletion while typing. enable_history_search : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Enable up-arrow parting string matching. lexer : :class:`~prompt_toolkit.layout.lexers.Lexer` to be used for the syntax highlighting. validator : :class:`~prompt_toolkit.validation.Validator` instance for input validation. completer : :class:`~prompt_toolkit.completion.Completer` instance for input completion. reserve_space_for_menu : Space to be reserved for displaying the menu. (0 means that no space needs to be reserved.) auto_suggest : :class:`~prompt_toolkit.auto_suggest.AutoSuggest` instance for input suggestions. style : Pygments style class for the color scheme. enable_system_bindings : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Pressing Meta+'!' will show a system prompt. enable_open_in_editor : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Pressing 'v' in Vi mode or C-X C-E in emacs mode will open an external editor. history : :class:`~prompt_toolkit.history.History` instance. clipboard : :class:`~prompt_toolkit.clipboard.base.Clipboard` instance. (e.g. :class:`~prompt_toolkit.clipboard.in_memory.InMemoryClipboard`) get_bottom_toolbar_tokens : Optional callable which takes a :class:`~prompt_toolkit.interface.CommandLineInterface` and returns a list of tokens for the bottom toolbar. display_completions_in_columns : `bool` or :class:`~prompt_toolkit.filters.CLIFilter`. Display the completions in multiple columns. get_title : Callable that returns the title to be displayed in the terminal. mouse_support : `bool` or :class:`~prompt_toolkit.filters.CLIFilter` to enable mouse support. default : The default text to be shown in the input buffer. (This can be edited by the user.) Notes ----- This method was forked from the mainline prompt-toolkit repo. Copyright (c) 2014, Jonathan Slenders, All rights reserved. WARNING; This method is due for removal once prompt-toolkit >v0.54 is released. """ if key_bindings_registry is None: key_bindings_registry = KeyBindingManager.for_prompt( enable_vi_mode=vi_mode, enable_system_bindings=enable_system_bindings, enable_open_in_editor=enable_open_in_editor).registry # Make sure that complete_while_typing is disabled when enable_history_search # is enabled. (First convert to SimpleFilter, to avoid doing bitwise operations # on bool objects.) complete_while_typing = to_simple_filter(complete_while_typing) enable_history_search = to_simple_filter(enable_history_search) multiline = to_simple_filter(multiline) complete_while_typing = complete_while_typing & ~enable_history_search # Accept Pygments styles as well for backwards compatibility. try: if issubclass(style, pygments.style.Style): style = PygmentsStyle(style) except TypeError: # Happens when style is `None` or an instance of something else. pass # Create application return Application(layout=self.create_prompt_layout( message=message, lexer=lexer, is_password=is_password, reserve_space_for_menu=(reserve_space_for_menu if completer is not None else 0), multiline=Condition(lambda cli: multiline()), get_prompt_tokens=get_prompt_tokens, get_bottom_toolbar_tokens=get_bottom_toolbar_tokens, display_completions_in_columns=display_completions_in_columns, extra_input_processors=extra_input_processors, wrap_lines=wrap_lines), buffer=Buffer( enable_history_search=enable_history_search, complete_while_typing=complete_while_typing, is_multiline=multiline, history=(history or InMemoryHistory()), validator=validator, completer=completer, auto_suggest=auto_suggest, accept_action=accept_action, initial_document=Document(default), ), style=style or DEFAULT_STYLE, clipboard=clipboard, key_bindings_registry=key_bindings_registry, get_title=get_title, mouse_support=mouse_support, on_abort=on_abort, on_exit=on_exit)
def init_prompt_toolkit_cli(self): self._app = None if self.simple_prompt: # Fall back to plain non-interactive output for tests. # This is very limited, and only accepts a single line. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt return kbmanager = KeyBindingManager.for_prompt() insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode )) def _(event): b = event.current_buffer d = b.document if b.complete_state: cc = b.complete_state.current_completion if cc: b.apply_completion(cc) else: b.cancel_completion() return if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return status, indent = self.input_splitter.check_complete(d.text) if (status != 'incomplete') and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + (' ' * (indent or 0))) @kbmanager.registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER))) def _previous_history_or_previous_completion(event): """ Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. If completer is open this still select previous completion. """ event.current_buffer.auto_up() @kbmanager.registry.add_binding(Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER))) def _next_history_or_next_completion(event): """ Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. If completer is open this still select next completion. """ event.current_buffer.auto_down() @kbmanager.registry.add_binding(Keys.ControlG, filter=( HasFocus(DEFAULT_BUFFER) & HasCompletions() )) def _dismiss_completion(event): b = event.current_buffer if b.complete_state: b.cancel_completion() @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _reset_buffer(event): b = event.current_buffer if b.complete_state: b.cancel_completion() else: b.reset() @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)) def _reset_search_buffer(event): if event.current_buffer.document.text: event.current_buffer.reset() else: event.cli.push_focus(DEFAULT_BUFFER) supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP')) @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend) def _suspend_to_bg(event): event.cli.suspend_to_background() @Condition def cursor_in_leading_ws(cli): before = cli.application.buffer.document.current_line_before_cursor return (not before) or before.isspace() # Ctrl+I == Tab @kbmanager.registry.add_binding(Keys.ControlI, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode & cursor_in_leading_ws )) def _indent_buffer(event): event.current_buffer.insert_text(' ' * 4) # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for __, ___, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cell.rstrip() if cell and (cell != last_cell): history.append(cell) self._style = self._make_style_from_name(self.highlighting_style) style = DynamicStyle(lambda: self._style) editing_mode = getattr(EditingMode, self.editing_mode.upper()) self._app = create_prompt_application( editing_mode=editing_mode, key_bindings_registry=kbmanager.registry, history=history, completer=IPythonPTCompleter(self.Completer), enable_history_search=True, style=style, mouse_support=self.mouse_support, **self._layout_options() ) self._eventloop = create_eventloop(self.inputhook) self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
def question(message, **kwargs): # TODO extract common parts for list, checkbox, rawlist, expand if not 'choices' in kwargs: raise PromptParameterException('choices') # this does not implement default, use checked... # TODO #if 'default' in kwargs: # raise ValueError('rawlist does not implement \'default\' ' # 'use \'checked\':True\' in choice!') choices = kwargs.pop('choices', None) if len(choices) > 9: raise ValueError('rawlist supports only a maximum of 9 choices!') # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] T = Token tokens.append((T.QuestionMark, '?')) tokens.append((T.Question, ' %s ' % message)) if ic.answered: tokens.append((T.Answer, ' %s' % ic.get_selected_value())) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens)), ConditionalContainer(Window(ic), filter=~IsDone()) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # add key bindings for choices for i, c in enumerate(ic.choices): if not isinstance(c, Separator): def _reg_binding(i, keys): # trick out late evaluation with a "function factory": # http://stackoverflow.com/questions/3431676/creating-functions-in-a-loop @manager.registry.add_binding(keys, eager=True) def select_choice(event): ic.pointer_index = i _reg_binding(i, '%d' % c[0]) @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(ic.get_selected_value()) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.keys import Keys animal_completer = WordCompleter([ 'alligator', 'ant', 'ape', 'bat', 'bear', 'beaver', 'bee', 'bison', 'butterfly', 'cat', 'chicken', 'crocodile', 'dinosaur', 'dog', 'dolphine', 'dove', 'duck', 'eagle', 'elephant', 'fish', 'goat', 'gorilla', 'kangoroo', 'leopard', 'lion', 'mouse', 'rabbit', 'rat', 'snake', 'spider', 'turkey', 'turtle', ], ignore_case=True) # Create key bindings registry with a custom binding for the Tab key that # displays completions like GNU readline. key_bindings_manager = KeyBindingManager.for_prompt() key_bindings_manager.registry.add_binding(Keys.ControlI)(display_completions_like_readline) def main(): text = prompt('Give some animals: ', completer=animal_completer, key_bindings_registry=key_bindings_manager.registry, # Important: for this to work: `complete_while_typing` needs # to be False. complete_while_typing=False) print('You said: %s' % text) if __name__ == '__main__': main()
""" Base structures """ from prompt_toolkit.key_binding.manager import KeyBindingManager from prompt_toolkit.keys import Keys MAIN_ACTIONS = ['cd ..', 'cd', 'quit'] WORDS = ['ls', 'help'] + MAIN_ACTIONS CRED = '\033[91m' CEND = '\033[0m' CBLUE = '\033[34m' CGRE = '\033[32m' CORA = '\033[93m' MANAGER = KeyBindingManager.for_prompt() @MANAGER.registry.add_binding(Keys.ControlC) @MANAGER.registry.add_binding(Keys.ControlD) def _(event): print('By by...') event.cli.set_return_value('quit')
class AimlGeneratorCLI(object): """Command Line Interface(CLI) to generate AIML files based on the input provided by user """ manager = KeyBindingManager.for_prompt() cmd_style = style_from_dict({ # User input. Token: config.Token.Color, # Prompt. Token.Colon: config.Token.Colon.Color, Token.Pound: config.Token.Pound.Color, Token.Dollar: config.Token.Dollar.Color, Token.Pattern: config.Token.Pattern.Color, Token.Template: config.Token.Template.Color, Token.Default: config.Token.Default.Color, Token.LeftBracket: config.Token.LBracket.Color, Token.RightBracket: config.Token.RBracket.Color, Token.Command: config.Token.Command.Color, Token.SubCommand: config.Token.SubCommand.Color, Token.CmdOpt: config.Token.CmdOpt.Color, Token.SubCmdOpt: config.Token.SubCmdOpt.Color, Token.LessThan: config.Token.LessThan.Color, Token.GreaterThan: config.Token.GreaterThan.Color, }) def __init__(self): """docstring for __init__""" self._parser = CommandParser() self._db_user = config.AIML_DB_USER self._db_password = config.AIML_DB_PASSWORD self._db_host = config.AIML_DB_HOST self._db_port = config.AIML_DB_PORT self._database = config.AIML_DB self._connection = mysql.connector.connect(host=self._db_host,\ port=self._db_port, user=self._db_user,\ password=self._db_password, database=self._database) self._cmd_history = FileHistory('.ide_aiml_gen.history') self._current_cmd_missing_opt = None self._current_sub_cmd_missing_opt = None self.__test_register_commands() def __test_new_cmd_callback(self, *args, **kwargs): """docstring for new_cmd_callback""" print('NEW CMD: ') print(*args) print(**kwargs) def __test_new_category_sub_cmd_callback(self, *args, **kwargs): """docstring for new_category_sub_cmd_callback""" print('NEW CATEGORY SUB-CMD: ') print(*args) print(**kwargs) def __test_register_commands(self): """docstring for register_commands""" #-------------------- COMMAND => [NEW] SUB-COMMAND => [CATEGORY] -------------------- cmd = 'NEW' cmd_description = 'Help in creating new object passed as sub-command' sub_cmd = 'CATEGORY' sub_cmd_description = 'The Category object available in AIML namespace' sub_cmd_kw_opts = {'PATTERN':'', 'TEMPLATE':'', 'SYSTEM':'',\ 'REF_THAT':'', 'REF_TOPIC':'', 'FORWARD_TO':''} sub_cmd_opts = {'--USE_DEFAULTS': False} sub_cmd_required = ['PATTERN', 'TEMPLATE'] #-------------------- Register Commands -------------------- self._parser.register_command(cmd, description\ =cmd_description, prompt_tokens_callback\ =self.get_cmd_prompt_tokens, \ cmd_processor_callback\ =self.__test_new_cmd_callback) self._parser.register_sub_command(cmd, sub_cmd,\ description=sub_cmd_description,\ prompt_tokens_callback\ =self.get_sub_cmd_prompt_tokens, cmd_processor_callback=\ self.__test_new_category_sub_cmd_callback, options=sub_cmd_opts,\ kw_options=sub_cmd_kw_opts,\ required_fields=sub_cmd_required) #-------------------- End Register Commands -------------------- #-------------------- Populate command completer dicts -------------------- cmd_completer = self._parser.get_cmd_completer() self._cmd_completer = WordCompleter(cmd_completer[0], meta_dict=cmd_completer[1], ignore_case=True) def get_default_prompt_tokens(self, cli): """Prompt when in default/no cmd modes """ return [ (Token.Dollar, config.Token.Dollar.Symbol), (Token.LeftBracket, config.Token.LBracket.Symbol), (Token.Default, config.Token.Default.Symbol), (Token.RightBracket, config.Token.RBracket.Symbol), (Token.Colon, config.Token.Colon.Symbol), ] def get_sub_cmd_prompt_tokens(self, cli): """Prompt when in sub command mode """ return [ (Token.Dollar, config.Token.Dollar.Symbol), (Token.LeftBracket, config.Token.LBracket.Symbol), (Token.Command, '%s' % self._current_cmd), (Token.RightBracket, config.Token.RBracket.Symbol), (Token.Seperator, '-'), (Token.LeftBracket, config.Token.LBracket.Symbol), (Token.SubCommand, '%s' % self._current_sub_cmd), (Token.RightBracket, config.Token.RBracket.Symbol), (Token.Dot, '.'), (Token.Dot, '.'), (Token.LeftBracket, config.Token.LBracket.Symbol), (Token.SubCmdOpt, self._current_sub_cmd_missing_opt \ if self._current_sub_cmd_missing_opt is not None\ else 'OPT'), (Token.RightBracket, config.Token.RBracket.Symbol), (Token.Colon, config.Token.Colon.Symbol), ] def get_cmd_prompt_tokens(self, cli): """Prompt when in main command and prompting values for missing options or kw-options """ return [ (Token.Dollar, config.Token.Dollar.Symbol), (Token.LeftBracket, config.Token.LBracket.Symbol), (Token.Command, '%s' % self._current_cmd), (Token.RightBracket, config.Token.RBracket.Symbol), (Token.Dot, '.'), (Token.Dot, '.'), (Token.LeftBracket, config.Token.LBracket.Symbol), (Token.CmdOpt, self._current_cmd_missing_opt\ if self._current_cmd_missing_opt is not None\ else 'OPT'), (Token.RightBracket, config.Token.RBracket.Symbol), (Token.Colon, config.Token.Colon.Symbol), ] def validate_for_required_args(self, parsed_cmd): """docstring for validate_for_required_args""" #SCENARIO: Return True (i.e., cmd is valid) #if no required attributes for main cmd #and no sub-cmd for this main cmd found if len(parsed_cmd['REQUIRED']) <= 0 and\ len(parsed_cmd['SUB_CMD']) <= 0: return (True, {}) #SCENARIO: Main cmd has required attr's and\ #no-sub cmd for this main cmd elif len(parsed_cmd['REQUIRED']) > 0 and\ len(parsed_cmd['SUB_CMD']) <= 0: #SUB-SCENARIO: if no opts or kw-opts exists #in cmd, return true if len(parsed_cmd['OPTIONS']) <= 0 and\ len(parsed_cmd['KW_OPTIONS']) <= 0: return (True, {}) #SUB-SCENARIO: if opts or kw-opts exist in cmd #check whether all required flds exists in any #opt or kw-opt else: (status, cmd_flds) = self.validate_options(parsed_cmd) flds_dict = {} flds_dict['CMD'] = cmd_flds return (status, flds_dict) elif len(parsed_cmd['REQUIRED']) <= 0 and\ len(parsed_cmd['SUB_CMD']) > 0: #sub_cmds = parsed_cmd['SUB_CMD'] sub_cmd_name = tuple(parsed_cmd['SUB_CMD'])[0] sub_cmd_details = parsed_cmd['SUB_CMD'][sub_cmd_name] (status, sub_cmd_flds) = self.validate_options(sub_cmd_details) flds_dict = {} flds_dict['SUB_CMD'] = sub_cmd_flds return (status, flds_dict) elif len(parsed_cmd['REQUIRED']) > 0 and\ len(parsed_cmd['SUB_CMD']) > 0: flds_dict={} (cmd_status, cmd_flds) = self.validate_options(parsed_cmd) flds_dict['CMD'] = cmd_flds #sub_cmds = parsed_cmd['SUB_CMD'] sub_cmd_name = tuple(parsed_cmd['SUB_CMD'])[0] sub_cmd_details = parsed_cmd['SUB_CMD'][sub_cmd_name] (sub_cmd_status, sub_cmd_flds) = \ self.validate_options(sub_cmd_details) flds_dict['SUB_CMD'] = sub_cmd_flds if cmd_status is False or sub_cmd_status is False: return (False, flds_dict) else: return (True, {}) def validate_options(self, parsed_cmd): required_fields = parsed_cmd['REQUIRED'] req_fld_dict = { fld : False for fld in required_fields } if req_fld_dict is not None and len(req_fld_dict) > 0: if len(parsed_cmd['OPTIONS']) > 0: for fld_name, status in req_fld_dict.items(): #check if fld available in options if status is False: if parsed_cmd['OPTIONS'].\ __contains__(fld_name)\ and parsed_cmd['OPTIONS'][fld_name]\ is not None: req_fld_dict[fld_name] = True if len(parsed_cmd['KW_OPTIONS']) > 0: for fld_name, status in req_fld_dict.items(): #check if fld available in kw-options if status is False: if parsed_cmd['KW_OPTIONS'].\ __contains__(fld_name) and\ parsed_cmd['KW_OPTIONS'][fld_name]\ is not None: req_fld_dict[fld_name] = True #return required fields dict containing items in following form: # { field_name : status } where status it true or false based on # whether the field has a value or not. # #We start with first item in dict and return as soon as we get the #first field with no value. No need to check the remaining fields #since dict already contains the status of each field. # #A list of fields with empty value will be returned only # #Calling method will iterate all list items and will prompt input #from user for fld, status in req_fld_dict.items(): if status is False: return (False, [fld for fld, status in req_fld_dict\ .items() if status is False]) return (True, []) def start(self): """Start the while loop for prompt """ cmd_text = '' #prompt will use the input provided by user for the same main command #until is_cmd_session_in_progress is True. As soon as the cmd_session #is marked as False, all the collected information will be forwarded to #command processor callable and prompt will be rested to accept next new #main command while cmd_text not in ['QUIT', 'EXIT']: cmd_text = prompt( get_prompt_tokens=self.get_default_prompt_tokens, style=AimlGeneratorCLI.cmd_style, history=self._cmd_history, enable_history_search=True, on_abort=AbortAction.RETRY, auto_suggest=AutoSuggestFromHistory(), completer=self._cmd_completer, display_completions_in_columns=True, complete_while_typing=True ) cmd_text = cmd_text.upper() #Process command text if atleast 2 tokens are provided #It can be a combo of "CMD SUB-CMD" or "CMD OPTIONS" if len(cmd_text.split()) > 1: parsed_cmd = self._parser.parse_cmd_text(cmd_text) if parsed_cmd is None: print('Invalid command syntax!') self.list_all_cmds() continue (valid, missing_flds) = self.validate_for_required_args(parsed_cmd) if valid: self._current_cmd = parsed_cmd['MAIN_CMD'] if len(parsed_cmd['SUB_CMD']) > 0: self._current_sub_cmd = tuple(parsed_cmd['SUB_CMD'])[0] else: self._current_sub_cmd = None self.execute_command(parsed_cmd) else: #required fields are missing, prompt for same self._current_cmd = parsed_cmd['MAIN_CMD'] if len(parsed_cmd['SUB_CMD']) > 0: self._current_sub_cmd = tuple(parsed_cmd['SUB_CMD'])[0] else: self._current_sub_cmd = None for flds_type, flds_list in missing_flds.items(): for fld in flds_list: parsed_cmd = self.get_missing_fld_input(fld,\ flds_type, parsed_cmd) self.execute_command(parsed_cmd) #Only one token is provided in the command text else: #if the only token provided is a valid command #process it if self._parser.cmd_exists(cmd_text): if not self._parser.cmd_has_sub_cmds(cmd_text): processor_callback = \ self._parser.get_cmd_processor_callback(cmd_text) if processor_callback is not None\ and callable(processor_callback): processor_callback(cmd_text) else: print("No callable found for command: %s" % cmd_text) else: print('No sub-command provided for command: %s' % cmd_text) self.list_sub_cmds_of_cmd(cmd_text) else: print('No such command found: %s' % cmd_text) self.list_all_cmds() def list_all_cmds(self): """docstring for list_all_cmds""" self._parser.list_all_cmds(); def list_sub_cmds_of_cmd(self, cmd_name): """docstring for list_sub_cmds_of_cmd""" self._parser.list_sub_cmds_of_cmd(cmd_name) def execute_command(self, parsed_cmd): """docstring for execute_command""" #SCENARIO: Command don't have any sub command if parsed_cmd['SUB_CMD'] is None or len(parsed_cmd['SUB_CMD']) <= 0: processor_callback = parsed_cmd['PROCESSOR_CALLBACK'] if processor_callback is None or not callable(processor_callback): print('No callable found for command: %s' % parsed_cmd['MAIN_CMD']) else: processor_callback(parsed_cmd['MAIN_CMD'], parsed_cmd['OPTIONS'], parsed_cmd['KW_OPTIONS']) #SCENARIO: Command have an sub command elif parsed_cmd['SUB_CMD'] is not None and len(parsed_cmd['SUB_CMD']) > 0: cmd_name = parsed_cmd['MAIN_CMD'] sub_cmd_name = tuple(parsed_cmd['SUB_CMD'])[0] options = parsed_cmd['SUB_CMD'][sub_cmd_name]['OPTIONS'] kw_options = parsed_cmd['SUB_CMD'][sub_cmd_name]['KW_OPTIONS'] processor_callback = parsed_cmd['SUB_CMD'][sub_cmd_name]['PROCESSOR_CALLBACK'] if processor_callback is None or not callable(processor_callback): print('No callable found for sub-command: %s' % sub_cmd_name) else: processor_callback(cmd_name, sub_cmd_name, options, kw_options) def get_missing_fld_input(self, fld_name, flds_type, parsed_cmd): """docstring for get_missing_fld_input""" missing_cmd_value = '' missing_cmd_dict = parsed_cmd if flds_type == 'CMD' else parsed_cmd['SUB_CMD'][self._current_sub_cmd] prompt_tokens_callback = None self._current_cmd_missing_opt = None self._current_sub_cmd_missing_opt = None if flds_type == 'CMD': prompt_tokens_callback = self._parser.get_cmd_prompt_token_callback(self._current_cmd)\ if self._parser.get_cmd_prompt_token_callback(self._current_cmd) is not None\ else self.get_cmd_prompt_tokens #the default prompt tokens callback self._current_sub_cmd_missing_opt = None self._current_cmd_missing_opt = fld_name else: prompt_tokens_callback = self._parser.get_sub_cmd_prompt_token_callback(self._current_cmd, self._current_sub_cmd)\ if self._parser.get_sub_cmd_prompt_token_callback(self._current_cmd, self._current_sub_cmd) is not None\ else self.get_sub_cmd_prompt_tokens #the default prompt tokens callback self._current_cmd_missing_opt = None self._current_sub_cmd_missing_opt = fld_name missing_cmd_value = prompt( get_prompt_tokens=prompt_tokens_callback, style=AimlGeneratorCLI.cmd_style ) if fld_name.startswith('-'): if missing_cmd_value is not None and missing_cmd_value in ['YES', 'Y', 'TRUE', 'T']: missing_cmd_dict['OPTIONS'][fld_name] = True else: missing_cmd_dict['OPTIONS'][fld_name] = False else: missing_cmd_dict['KW_OPTIONS'][fld_name] = missing_cmd_value if flds_type == 'CMD': return missing_cmd_dict #i.e., parsed_cmd else: parsed_cmd['SUB_CMD'][self._current_sub_cmd] = missing_cmd_dict return parsed_cmd def print_cmd_help(self, cmd_name, sub_cmd_name=None): """docstring for print""" print('Will print help here!')
from prompt_toolkit.keys import Keys from ..core.validators import validate_option_requirements from ..core.object import Modes from ..core._options import Options from .completers import ( ObjectFilenameCompleter, ObjectModeCompleter, ObjectOptionValueCompleter, ObjectUIDCompleter, YesNoCompleter) from .exceptions import CancelPromptException from .validators import ( ObjectUIDValidator, ContainerValidator, ObjectOptionValueValidator, PackageUIDValidator) manager = KeyBindingManager.for_prompt() # pylint: disable=invalid-name @manager.registry.add_binding(Keys.ControlD) def ctrl_d(_): """Ctrl D quits appliaction returning 0 to sys.""" sys.exit(0) @manager.registry.add_binding(Keys.ControlC) def ctrl_c(_): """Ctrl C raises an exception to be caught by functions. Main prompt must exit uhu with code status 1, while subprompts must returns to main prompt. """