-
Notifications
You must be signed in to change notification settings - Fork 88
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
less should support bracketed paste #523
Comments
I want to clarify the details of this request. The simplest enhancement is to simply ignore the brackets. So the sequences "ESC [ 200 ~" and "ESC [ 201 ~" would be ignored. Any text between the brackets would be processed as usual. But I think you may be asking for something more when you say "pasted text should not be interpreted as commands" but I'm not sure what it is. I think that about the only time it's useful to paste text into less is when entering a search string. Are you asking that line editing commands be ignored in that mode? So typing "/abc" and then pasting the escape sequence for your terminal's left-arrow key would enter the escape sequence literally rather than moving the cursor left? Also, there is no terminfo entry that defines paste brackets. So the brackets would need to be hardcoded (possibly problematic for some terminals), or specified by environment variables. |
Commands are the keys described under the COMMANDS section in the man page. Note that some of them, like
I think that you just need an option that enables or disables the support of bracketed paste. This is what the zsh and bash shells do. The main terminals support bracketed paste: xterm, GNOME Terminal, rxvt, sakura, mlterm, Termux (under Android), iTerm2 (macOS), and others. |
Ok, I understand now that you are concerned with someone accidentally pasting into less, rather than deliberately pasting and getting unexpected results. Ignoring a bracketed paste has the risk that if an open bracket without a close bracket is somehow entered, all subsequent input will be ignored until a close bracket is entered. But perhaps there could be a timeout so that input would only be ignored for a reasonable period of time. |
It could also be deliberate pasting, but with contents that are not what the user expects, for various reasons such as bugs (Firefox does not always copy the selection to the PRIMARY selection) or hidden contents (e.g. from a web page due to CSS - various kinds of attacks). |
The --no-paste option was added in a8ae92e, currently in the post659 branch. |
Support for bracketed paste depends on whether it's implemented at As far as I know there's no way to detect support on Windows, and after minimal testing I think it's currently unsupported in both the native conhost in windows 10 19045, and in the latest I tested outside of "less", by printing There do exist 8 open issues and 50 closed ones for the windows terminal about bracketed paste - https://github.com/microsoft/terminal/issues?q=is%3Aissue+is%3Aopen+bracketed So i would think that if it's not implemented yet, it probably would at some stage in the future. It's also possible that it's implemented in some 3rd patty terminal emulator for windows. However, does that matter? Can you clarify what "support bracketed paste" means in "less" other than possibly special-handling of the content between Because it it only does the startup/exit thing (to enable/disable it), and doing something special with the wraped content, then I think it would "work" on Windows too, in the sense that if bracketed paste is suppoeted by the terminal then it's fine, and if not then the start/exit sequences would be ignored by the terminal, and the wrap sequences won't exist so there's nothing special to do about it anyway (same behavior as if bracketed paste was not enabled). Or am I missing something? for instance in terminals which don't support it, can |
Not sure why the above didn't work as expected when bracketed paste is supported, but I think it's actually supported. TL;DR: I think it works in Windows terminal (and its openconsole) but currently not in the native windows 10 conhost. I didn't try windows 11 conhost. (the windows terminal openconsole is the future conhost of windows, so windows conhost is expected to follow the new openconsole and support it at some stage). At least when using (windows) ssh into a linux system, where the shell is bash, and bracketed-paste is enabled via However, It doesn't work when using the native windows 10 (19045) When disabling bracketed-paste in bash via I did try to check if --enable-paste works in the post659 branch, but the BP initialization is disabled on windows as far as I can tell, and I didn't try to enable it, so it doesn't work currently, but I think it should be possible to make it work if the init/deinit sequences would be sent. |
Confirmed on windows terminal and openconsole with a minimal test program which sets input and output vt mode, then printing Setting vt mode for the input console handle (ENABLE_VIRTUAL_TERMINAL_INPUT) seems to be required for this to work, but currently "less" explicitly unsets this bit, so the init sequence would need to change for this to work. As expected from the ssh experiment, on native windows 10 conhost bracketed paste doesn't currently work, but will likely work in the future (unless win10 EOL arrives first). WIndows 11 probably does or will support it. |
Windows 11 (10.0.22621.3085) ConHost also does not. |
I've tested the post659 branch, and the only issue I've found is after typing |
What would you expect here? Do you expect less to drain all input before exiting? |
I'd think that if bracketed paste start is detected, to drain the whole bracketed paste content and its termination. This is one thing which bracketed paste can help with, because we know it was pasted as a single unit, rather than (without BP) processing the input as it comes, quitting to the shell, and letting the shell (highly likely incorrectly) keep processing the paste. Additionally, if "less" quits before it digests the BP end sequence, then the next application (probably shell) will get a BP end sequence which it never saw starting (and even if the terminal wanted to cancel the BP content after "less" disabled BP on quit, it might not be able to, because it might already be buffered by libc/OS and outside of the terminal control). Unrelated, I don't know if there are conventions about the application aborting the wait for the BP termination, but I'd think there should be a timeout, probably of less than 1s (in "less" case). For instance, if the BP end sequence never arrives, does "less" hang forever? Or if the terminal doesn't support it, but |
Yeah, I thought of that argument. It seems reasonable to try to read the whole bracketed sequence, but we can't get stuck unable to exit if an unmatched open bracket is received. So there would have to be a timeout to guard against that. I don't think less currently has a way to drain tty input without reading it, except in the Windows build. That relates to your last question -- currently after an open bracket is received, less ignores input for a maximum of 5 seconds or until the close bracket is received (defined by MAX_PASTE_IGNORE_SEC). |
Maybe I used the wrong terminology, but I meant reading up to and including the BP end sequence (while ignoring whatever "less" wants to ignore, like everything after a quit command, or everything starting at the 1st newline, whichever comes first), but not beyond the BP end sequence. Is there a semantic or functional difference in this case between "read" and "drain"? If the content includes a quit command, and the implementation doesn't buffer the effective BP content (up to ignored content) before applying it, then indeed it might require adding some implementation details of reading the rest of the BP content if we identify a quit command before it ends. A different implementation approach could be to always process the whole BP content up to and including the end sequence, while buffering up to the first newline (excluding), and only once the BP is complete, start processing it. This approach won't require special handling of quit inside BP, because less already drained the whole BP anyway by the time quit is applied. But also, I think the fact that the rest of the paste goes to the shell is not the real bug, but rather only a side effect of the bug. The real bug, I think, is that the BP content is interpreted as a command in the first place, because both the initial request and the docs suggest otherwise: request:
docs:
So if less quits after pasting qqq in a place where only search string or file name etc can be entered, then that's the real bug because the paste was interpreted as a command. Or maybe "less" crashed (hard to tell from the issue report, and I didn't try it). Either way, a paste which results in exit to the shell is the bug which needs fixing, and then there shouldn't be an issue of draining the BP before quitting. |
What I was getting at by calling it "drain" is that in this scenario less will be trying to read input which may not exist. If less just naively reads data until it receives the end bracket, but no input appears (because the start bracket was entered manually or whatever), less will just hang on the read. We would need something like poll() or select() to implement a timeout on the read. Less currently uses poll for another feature so maybe some of that code can be repurposed. But I think you're correct that the pasted 'q' should not be handled as a command. If you just paste in a 'q' it will be correctly ignored, but if you type a ':' and then paste the 'q', the 'q' is treated as part of a "command line" and so executed, since ":q" is an alias for "q". This is a side effect of how multicharacter commands are all processed similarly. I think only a few multicharacter commands should actually allow paste; probably just examine, search, shell, and toggle-option. |
Yeah. So I think that while the request and the docs looked to me suggesting the same thing (paste should not be applied as command), they're actually different, and the docs don't actually say that it's never applied as command, because the implementation doesn't actually enforce that. I think a better doc (and matching implementation) would be something like: With --enable-paste, "less" ignores pasted content, unless it's pasted when less expects the user to type a file name, or search expression etc. In such case, the paste is inserted into the text field. If the paste includes one or more newlines, then the first newline and everything which follows is ignored. Specifically, "less" would not execute any part of pasted content as a command. I didn't check the code, but there might also be a need to still filter the paste even if it's never executes as a command, for instance if it includes control chars like tab - which might trigger completion, or ^C char, or editing key sequences, or escape sequences in general, etc. So maybe the solution is to ignore the paste starting at the first control character, if there is one. |
I think that if So, just after |
Yes, I think that is the desired behavior. Unfortunately it is turning out to be trickier than one might expect, because the a multicharacter command like " |
At least for mouse input (wheel and clicks?), while it would be nice if it worked while in command mode or search (after I have no insight about the bracketed paste implementation details. However, eventhough I do like bracketed paste and use it elsewhere and is probably useful in "less", I would think that if this ends up requiring significant effort or refactoring then maybe it's not worth it. But at this time I can't judge the specifics. |
Disabling the mouse during entry of a multicharacter command might work. Unfortunately we can't use a similar technique of disabling bracketed paste during command entry, since doing so would just allow the pasted content to come through. I will consider other options. The easiest option is to just leave it as it is currently implemented, which does allow pasted commands to be entered in some cases. It's better than the released version which doesn't disallow pasted commands at all, and it seems to me that it takes a fairly deliberate attempt to do something weird to cause a problem (why would someone type |
Bracketed paste should be ignored both before |
Yes, I agree that it SHOULD be ignored in both cases. The issue is that it is tricky to do that given the current implementation of command parsing. There is a list of commands with an action associated with each one. Part of that list looks something like
When command characters are received, they are looked up in this list. A single-char command like " |
I see. The code is really ugly, and even broken (without even considering bracketed paste support). For instance, type So, what you first need would be to recognize multicharacter keys in all contexts. Then it would be much easier to recognize the start of a paste. |
Yeah, you're right. The code is pretty poorly designed. It's one of the oldest parts of the code, written some 40 years ago when I had been programming professionally for less than 5 years. It could stand to be redesigned and rewritten. |
OK. The good thing is that if the user starts a multicharacter command, he will probably enter the second character of the command immediately after the first one, so that it is a bit unlikely that he will paste anything after That said, I wonder whether paste-after-
in |
Cute. However, I'm guessing it also leaves command mode? If yes, I guess it should be acceptable, but maybe there could be some trickery to use a different command, like A_START_PASTE_IN_COMMAND, which is identical to A_START_PASTE, but after the paste end bracket, generates a keypress of |
I'm not sure what you mean by that. This cancels the
would be better, IMHO, in order to signal that something wrong was done, just as if one had typed a key that does not correspond to any command. So...
or put BTW, I would also add
or something similar, because On this subject, I can see that zsh doesn't handle prefix+paste correctly. |
It's a clever approach and is obviously much easier than rewriting the command processor. However it doesn't solve the similar cases mentioned above of mouse movement after |
Apparently neither does bash. Do
then type ESC followed by a paste and you get garbage. |
Yes. However, they could probably be added automatically, either dynamically at the start of the program or statically (generation of C code) with a script. |
It probably would need to be done dynamically, to handle new cases created by commands defined in the user's lesskey file. |
The problem of misparsing a paste bracket, HOME, etc. when entered after a colon or other partial command should be fixed in d8aa003. |
less
should support bracketed paste, that is, pasted text should not be interpreted as commands (generally a mistake).The text was updated successfully, but these errors were encountered: