From 3173bd13995ba79de776f8c0239704bfe25e5bf1 Mon Sep 17 00:00:00 2001 From: Gil Forsyth Date: Tue, 14 Feb 2017 16:00:25 -0500 Subject: [PATCH] finish first pass on ptk keybinding tutorial --- docs/index.rst | 1 + docs/tutorial_ptk.rst | 70 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 351cc7b04..5b400663f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -130,6 +130,7 @@ Contents tutorial_events tutorial_completers tutorial_history_backend + tutorial_ptk bash_to_xsh python_virtual_environments diff --git a/docs/tutorial_ptk.rst b/docs/tutorial_ptk.rst index 7b5b2b834..25b25d563 100644 --- a/docs/tutorial_ptk.rst +++ b/docs/tutorial_ptk.rst @@ -17,28 +17,46 @@ Overview The ``prompt_toolkit`` shell has a registry for handling custom keybindings. You may not like the default keybindings in xonsh, or you may want to add a new key -command. +binding. We'll walk you though how to do this using ``prompt_toolkit`` tools to define keybindings and warn you about potential pitfalls. All of the code below can be entered into your `xonshrc `_ -The danger keys -=============== +Control characters +================== We can't and won't stop you from doing what you want, but in the interest of a -functioning shell, you probably shouldn't mess with the following keystrokes as -they have some important functions already assigned to them. +functioning shell, you probably shouldn't mess with the following keystrokes. +Some of them are `ASCII control characters +`_ and _really_ +shouldn't be used. The others are used by xonsh and will result in some loss of +functionality (in less you take the time to rebind them elsewhere). .. list-table:: - :widths: 2 2 + :widths: 2 2 2 :header-rows: 1 * - Keystroke + - ASCII control representation - Default commmand - * - Control J - - + * - ``Control J`` + - ```` + - Run command + * - ``Control I`` + - ```` + - Indent, autocomplete + * - ``Control R`` + - + - Backwards history search + * - ``Control Z`` + - + - SIGSTOP current job + * - ``Control C`` + - + - SIGINT current job + Useful imports ============== @@ -59,13 +77,13 @@ Custom keyload function To load the keybindings after the shell is initialized, we define a function that contains all of our custom keybindings and decorate it with the appropriate -event, in our case ``on_post_init``. +event, in our case ``on_ptk_create``. We'll start with a toy example that just inserts the text "hi" into the current line of the prompt:: - @events.on_post_init - def custom_keybindings(): - handler = __xonsh_shell__.shell.key_bindings_manager.registry.add_binding + @events.on_ptk_create + def custom_keybindings(**kw): + handler = kw['bindings'].registry.add_binding @handler(Keys.ControlW) def say_hi(event): @@ -95,6 +113,32 @@ Restrict actions with filters ============================= Often we want a key command to only work if certain conditions are met. For -instance, the key in xonsh brings up the completions menu, but then it +instance, the ```` key in xonsh brings up the completions menu, but then it also cycles through the available completions. We use filters to create this behavior. + +A few helpful filters are included with ``prompt_toolkit``, like +``ViInsertMode`` and ``EmacsInsertMode``, which return ``True`` when the +respective insert mode is active. + +But it's also easy to create our own filters that take advantage of xonsh's +beautiful strangeness. Suppose we want a filter to restrict a given command to +run only when there are fewer than ten files in a given directory. We just need a function that returns a Bool that matches that requirement and then we decorate it! And remember, those functions can be in xonsh-language, not just pure Python:: + + @Condition + def lt_ten_files(cli): + return len(g`*`) < 10 + +.. note:: See `the tutorial section on globbing + `_ for more globbing options. + +Now that the condition is defined, we can pass it as a ``filter`` keyword to a keybinding definition:: + + @handler(Keys.ControlL, filter=lt_ten_files) + def ls_if_lt_ten(event): + ls -l + event.cli.renderer.erase() + +With both of those in your ``.xonshrc``, pressing ``Control L`` will list the +contents of your current directory if there are fewer than 10 items in it. +Useful? Debatable. Powerful? Yes.