New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Copy/pasting: multiline in a single line prompt #519
Comments
Hi @gpotter2, At this point, the value of Pasting text is however not the same as pressing enter. A paste is recognised and ends up in a different key binding (bracketed paste is enabled). If the pasted text contains an newline, then this turns the input into a multiline buffer. It's different from how readline works (which doesn't support bracketed paste), but it's considered a good thing, because this behaviour allows the user to review any pasted input, before actually executing it. Prompt_toolkit can render Let me know what you think. |
Hi @jonathanslenders, thanks for answering We cannot use the
Apart from those, python-prompt-toolkit is great !! |
You can add a custom key binding for BracketedPaste (this is the default implementation). Assumedly you would want a multiline paste to act like entering multiple commands. You could split on newline and force it to execute each line separately. I don't know if it's the best way to do it, but I think it's possible using a
|
Thanks for your help, I'll create a custom class extending Filter as multiline parameter, and use tokenizing. That should be it for multi lines :) I'll come back if I have any problems :) |
This is the function I used to detect if a block of Python code is "multiline" or not, using the |
@asmeurer Thanks a lot for the tools ! |
@asmeurer Hello, thanks for your help. which gave me:
The doc isn't helpful:
Sadly the doc about SimpleFilter is very much like the void:
Any ideas ? |
I've found a way of avoding this mess. Thanks for your help. |
This may be of interest here, I recently wanted to implement some similar behavior. Basically, I want to have it so that if I copy some text from a Python example, like say >>> x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
>>> type(x)
<type 'numpy.ndarray'>
>>> x.shape
(2, 3)
>>> x.dtype
dtype('int32') (taken from the numpy docs), that it automatically strips the prompts and outputs. This is quite easy to do by setting a key for But when I do this, it pastes everything as a single multiline block, like x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
type(x)
x.shape
x.dtype meaning I only see the output of the last line. I really want it to paste an execute each line, as it would in a readline-style prompt (actually readline 6, since readline 7 also supports bracketed paste). At first, I tried to create a custom Input subclass that mixed stdin and a pipe, but this seems to be impossible to make work. The internals of prompt-toolkit use the fileno (the Next, I tried to pass two file numbers to the eventloop, as it apparently supports this. But I was unable to figure out how to make the input from the pipe actually get read. Is the handler supposed to do this? Can it be done without access to the data internal local to the Finally, I figured out a much more elegant solution. In my main loop, where I create a from collections import deque
from prompt_toolkit.input import PipeInput
CMD_QUEUE = deque()
def main_loop():
...
while True:
if CMD_QUEUE:
_input = PipeInput()
_input.send_text(CMD_QUEUE.popleft() + '\n')
else:
_input = None # The default stdin input
cli = CommandLineInterface(..., input=_input)
result = cli.run()
# Code to execute the result
... Then in the bracketed paste handler, I have some code that splits up the inputs in the way I want, and finally does: # inputs is a list of split up inputs
event.current_buffer.insert_text(inputs[0])
for text in inputs[1:]:
# TODO: Send last chunk as bracketed paste, so it can be edited
CMD_QUEUE.append(text)
if CMD_QUEUE:
accept_line(event) (I am still figuring out the TODO part). This works well, except prompt toolkit has a lot of problems with pipe inputs, where the prompts get messed up and CPR codes get printed (#456), so you have to be willing to deal with that. I hope this helps. It should be possible to use this idea to do what you were wanting to do (if you indeed still want to do that). |
Hi @asmeurer, Could you copy your comment in a new issue? That way we won't forget about this. |
My main issue on the prompt-toolkit side is with the Input classes. If it's possible, it would be nice if they didn't require a fileno, but it isn't completely clear to me from the code if it is possible. Also it seems they should just be file-like objects. I can open an issue about that. For the rest, it only seems like something that could go in prompt-toolkit if you ever want to add some abstractions for REPL loops (an abstraction around the common But for users who are less picky about customizing and are fine with prompt-toolkit defaults, these shortcut functions are nice. And they're great for starting because you can get up and running very quickly with a basic prompt application, and then build on top of them once you get the hang of the library. So maybe a shortcut function like def repl(execute_callback, message='', **kwargs):
while True:
try:
res = prompt(message, **kwargs)
except KeyboardInterrupt:
print("KeyboardInterrupt", file=sys.stderr)
continue
except (EOFError, SystemExit):
break
execute_callback(res) # Perhaps the callback should also be passed the cli instance in shortcuts.py could be useful. And then you could build on that to do the queueing behavior, and possibly other behaviors too (e.g., I keep IPython-style prompt numbers in my loop). |
Could we have an option so that
prompt
only accepts a single line, even when pasting some text ?Currently, even when
multiline
is set to False, you can paste multi-line text in it.Code: Here's the code i am using:
The goal of this code is to emulate a shell. In that way, we need to print "..." or ">>>" on each line.
readlinescapy
is usingprompt_toolkit.prompt
to get the same input as in a shell...When one copy multi-line, the
prompt
function takes all the lines, so...
is not printed.The text was updated successfully, but these errors were encountered: