0

I am trying to use prompt_toolkit so I can get input from the user without waiting for them to press Enter. I managed to create events and associate them with keys, but I can't figure out how to actually manipulate my program from within the events.

from prompt_toolkit import prompt
from prompt_toolkit.application import run_in_terminal
from prompt_toolkit.key_binding import KeyBindings

i = 2

bindings = KeyBindings()

@bindings.add('c-t')
def _(event):
    " Say 'hello' when `c-t` is pressed. "
    def print_hello():
        print('hello world')
    run_in_terminal(print_hello)

@bindings.add('c-x')
def _(event):
    " Exit when `c-x` is pressed. "
    event.app.exit()

@bindings.add('d')
def _(event):
    i *= 2

text = prompt('> ', key_bindings=bindings)
print(f'You said: {text}')
print(f'i is now {i}')

I expect this program to:

  • Print "hello world" when Ctrl + T is pressed.
  • Exit when Ctrl + X is pressed.
  • Double the value of i when d is pressed.

It does 1 and 2, but 3 gives Exception local variable 'i' referenced before assignment. But even in the Python documentation we see the example (https://docs.python.org/3/reference/executionmodel.html):

i = 10
def f():
    print(i)
i = 42
f()

So how do I make a key binding that alters my variable?

Neuron
  • 5,141
  • 5
  • 38
  • 59
user8493571
  • 119
  • 4
  • Does this answer your question? [Local (?) variable referenced before assignment](https://stackoverflow.com/questions/11904981/local-variable-referenced-before-assignment) – Neuron Jul 12 '22 at 09:48

1 Answers1

0

You are referencing a global variable from a local function, you just simply need to indicate that is what you intended, otherwise you are referencing a non-existing local variable.

@bindings.add('d')
def _(event):
    global i     # fixes your problem
    i *= 2

See the one-line change above!

Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
  • Any way to pass variables to the event? – user8493571 May 09 '20 at 13:02
  • @user8493571 You need to provide a lot more information for me to answer that question, maybe close off this question and open a new one because I need more context, what are you doing with it, etc. Comments are not a good place for something that might explode into a big conversation. – Jayson Minard May 16 '20 at 14:57