-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Fix pasting multi-line text into commit message panel #4234
base: master
Are you sure you want to change the base?
Conversation
Coverage summary from CodacySee diff coverage on Codacy
Coverage variation details
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: Diff coverage details
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: See your quality gate settings Change summary preferencesCodacy stopped sending the deprecated coverage status on June 5th, 2024. Learn more Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work, see comments
@@ -75,6 +75,22 @@ func (self *CommitDescriptionController) switchToCommitMessage() error { | |||
return nil | |||
} | |||
|
|||
func (self *CommitDescriptionController) handleTogglePanel() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something that is not clear here is that opts.Config.Universal.TogglePanel
defaults to tab
. So a reader could get confused as to why we're conditionally inserting spaces. A comment should clear up that confusion.
Things probably get awkward when a user remaps these keys, and I'm not sure of a good way of dealing with that (doesn't need to be solved in this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah interesting, I hadn't considered remapping keys at all. I added a condition and a comment in 8256ed2, please have a look.
@@ -1311,6 +1311,10 @@ func (g *Gui) onKey(ev *GocuiEvent) error { | |||
switch ev.Type { | |||
case eventKey: | |||
|
|||
if g.IsPasting && ev.Key == KeyCtrlJ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This deserves a code comment explaining what we're doing. Even reading the commit message, it's not actually clear to me how KeyCtrlJ and KeyCtrlM relate to \n and \r.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment in 0c0287c, does this help? It's still slightly mysterious to me, I tried to be honest about this in the comment.
case *tcell.EventPaste: | ||
return GocuiEvent{ | ||
Type: eventPaste, | ||
Start: tev.Start(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the idea that there's two paste events: one for starting the paste and one for finishing the paste, and if it's the first kind then Start will be true? If so it would be good to add a comment to that affect against the GocuiEvent struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's true. I added a comment in 76924d8, is that enough? Feel free to push fixups if you want to further improve it.
@@ -140,6 +156,10 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e | |||
} | |||
|
|||
func (self *CommitMessageController) confirm() error { | |||
if self.c.GocuiGui().IsPasting { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd spell this out in a comment too i.e. the default keybinding for confirm is enter, and newlines are interpreted as enter presses when pasting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a condition and a comment in 8256ed2, like for the other handlers.
Recognize bracketed paste events, and set a flag on Gui if a paste is active. Application code can use this to handle carriage returns or tabs differently when they come from a paste operation.
When pasting, Ghostty seems to convert all \n to \r for some reason. Convert them back to \n so that we can handle them normally. I have to admit that I'm confused as to why this is necessary. From what I understand from Ghostty's source code (e.g. ghostty-org/ghostty@010338354a0) it does this conversion only for non-bracketed paste mode, but I'm seeing it in bracketed paste mode, and it is only there that we convert it back.
My assumption is that pressing command-V on a non-editable view is always a mistake; it would execute arbitrary commands depending on what's in the clipboard, so prevent it.
When pasting a multi-line commit message into the subject field of the commit editor, we would interpret the first newline as the confirmation for closing the editor, and then all remaining characters as whatever command they are bound to, resulting in executing all sorts of arbitrary commands. Now we recognize this being a paste, and interpret the first newline as moving to the description. Also, prevent tabs in the pasted content from switching to the respective other panel; simply insert four spaces instead, which should be good enough for the leading indentation in pasted code snippets, for example.
943d78f
to
76924d8
Compare
When pasting a multi-line commit message into the subject field of the commit editor, we would interpret the first newline as the confirmation for closing the editor, and then all remaining characters as whatever command they are bound to, resulting in executing all sorts of arbitrary commands.
Now we recognize this being a paste, and interpret the first newline as moving to the description.
Also, prevent tabs in the pasted content from switching to the respective other panel; simply insert four spaces instead, which should be good enough for the leading indentation in pasted code snippets, for example.
Finally, disable pasting text into non-editable views; my assumption is that this is always a mistake, as it would execute arbitrary commands depending on what's in the clipboard.
This depends on the terminal emulator supporting bracketed paste; I didn't find one on Mac that doesn't (I tested with Terminal.app, iTerm2, Ghostty, kitty, Alacritty, WezTerm, and VSCode's builtin terminal. It works well in all of them).
I couldn't get it to work in Windows Terminal though, and I don't understand why, as it does seem to support bracketed paste (it works in bash).
Fixes #3151
Fixes #4066
Fixes #4216
go generate ./...
)