This fixes a bug in ListContextTrait.FocusLine whereby the view would go blank
when scrolling by page (using ',' or '.') in views that have
renderOnlyVisibleLines set to true but refreshViewportOnChange set to false.
Currently we don't have any such views; the only ones who use
renderOnlyVisibleLines are commits and subcommits, and they also use
refreshViewportOnChange. However, we are going to add one in the next commit,
and eventually it might be a good idea to convert all our list views to that by
default, and get rid of the renderOnlyVisibleLines flag.
We have this logic to avoid constantly rerendering the main view when hitting
up-arrow when you are already at the top of the list. That's good, but we do
want to scroll the selection into view if it is outside and you hit up or down,
no matter if it changed.
It is possible to scroll the selection out of view using the mouse wheel; after
doing this, it would sometimes scroll into view by itself again, for example
when a background fetch occurred. In the files panel this would even happen
every 10s with every regular files refresh.
Fix this by adding a scrollIntoView parameter to HandleFocus, which is false by
default, and is only set to true from controllers that change the selection.
We want to do this whenever we switch branches; it wasn't done consistently
though. There are many different ways to switch branches, and only some of these
would reset the selection of all three panels (branches, commits, and reflog).
We move the selection down by the number of commits that were reverted (to keep
the same commits selected). However, this only happens after refreshing, which
has rendered the main view with the wrong commit, so we need to render it again
after moving the selection.
There are many other callers of MoveSelection in LocalCommitsController, but all
of them happen before the refresh. Revert is special because it needs to move
the selection after refreshing, e.g. when reverting the only commit of a branch.
Now that we can use 'k' as a menu item binding (this was fixed in #5131), use it
for the "keep" entry in the merge menu. I don't think this will be a problem for
people's muscle memory, given that this menu is not encountered every day; and
it's simply the better keybinding.
This reverts commit b32b55201e.
The confirmation used to make sense back when the Open MergeTool command was its
own top-level command; however, that command was changed in 703f053a7e to open a
menu instead, and Open MergeTool is now just a submenu entry in that menu, so it
no longer needs a confirmation.
Users have filed issues with crash reports that seem to indicate that the
FileTreeViewModel gets swapped out (by a refresh) while a call to itemsSelected
is in progress, iterating over the previous items. Guard against this by locking
the mutex that we already have for this for the duration of the call.
I don't have a good way of testing whether the fix helps, because the crashes
only occurred very infrequently. Let's just see if the crash reports stop coming
in after we ship this.
Note also that this is only the minimal fix for the crashes that were reported.
Theoretically, the same problem could happen for a key handler itself, but we
never saw reports about that, so we don't bother doing anything about that yet.
Note also that long-term I envision a different solution to this class of
problems (discussed in https://github.com/jesseduffield/lazygit/issues/2974),
that's why I want to avoid locking mutexes more than necessary now.
We move the code to push the branches context into CheckoutRef, this way it
works consistently no matter where we call it from. Previously, checking out
remote branches or tags would switch to the branches view, but checking out a
commit did not.
Note that it now also takes effect for undoing or redoing a checkout, which may
be a bit questionable; but I still think it makes sense for this, too.
This doesn't really solve a pressing problem, because I guess it's unlikely that
users add spaces at the beginning or end of what they type into a prompt; but it
could happen, and in this case we almost always want to strip it. Just adding
this here for completeness while I was working on this code.
The only exception is the input prompt of custom commands, because who knows
what users want to use that input for in their custom command.
Most of our prompts don't (shouldn't) allow empty input, but most callers didn't
check, and would run into cryptic errors when the user pressed enter at an empty
prompt (e.g. when creating a new branch). Now we simply don't allow hitting
enter in this case, and show an error toast instead.
This behavior is opt-out, because there are a few cases where empty input is
supported (e.g. creating a stash).
Previously it was used both for the Confirm handler and the Cancel handler, as
well as for the Confirm handler of confirmation popups (not prompts). There was
no other way to do it given how wrappedConfirmationFunction was shared between
all these; but now there is. The logic is really only needed for the Confirm
handler of prompts.
This doesn't fix anything, it just makes things clearer.
And call this new helper function from both wrappedConfirmationFunction and
wrappedPromptConfirmationFunction; this gives us more flexibility to do
different things in each of those.
When pressing '.' (next page) or ',' (previous page), the selection
now stays at the bottom or top of the viewport respectively, instead
of being centered which caused items to scroll off. If the selection is not
already on the last/first line of the view, '.'/',' moves it there without
scrolling.
This implements a special case for page navigation as suggested by
the maintainer in issue #5017, keeping the cursor position consistent
with user expectations for page-based navigation.
Fixes#5017
Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
The existing diff parser incorrectly treated subsequent lines beginning
with "---" as filename headers while processing hunks. This caused
corruption when dashed lines appeared within diffs themselves.
Restrict filename detection to only occur between hunks.
This will put whatever git's default merge variant is as the first menu item,
and add a second item which is the opposite (no-ff if the default is ff, and
vice versa).
If users prefer to always have the same option first no matter whether it's
applicable, they can make ff always appear first by setting git's "merge.ff"
config to "true" or "only", or by setting lazygit's "git.merging.args" config to
"--ff" or "--ff-only"; if they want no-ff to appear first, they can do that by
setting git's "merge.ff" config to "false", or by setting lazygit's
"git.merging.args" config to "--no-ff". Which of these they choose depends on
whether they want the config to also apply to other git clients including the
cli, or only to lazygit.
- Squash and FastForwardOnly are mutually exclusive, and instead of asserting
this at runtime, model the API so that they can't be passed together.
- FastForwardOnly is unused, so remove it; however, we are going to need --ff
and --no-ff in the next commit, so add those instead.
- Instead of putting the enum into the MergeOpts struct, replace the struct by
the enum. We can reintroduce the struct when we add more arguments, but for
now it's an unnecessary indirection.
Stashing doesn't affect submodules, so if you have a working copy that has
out-of-date submodules but no other changes, and then you revert or paste a
commit (or invoke one of the many other lazygit commands that auto-stash, e.g.
undo), lazygit would previously try to stash changes (which did nothing, but
also didn't return an error), perform the operation, and then pop the stash
again. If no stashes existed before, then this would only cause a confusing
error popup ("error: refs/stash@{0} is not a valid reference"), but if there
were stashes, this would try to pop the newest one of these, which is very
undesirable and confusing.
Whenever git returns the error "The previous cherry-pick is now empty", we would
previously continue the rebase; this works for rebase because it behaves the
same as "git rebase --skip" in this case. That's not true for cherry-pick
though; if you continue a cherry-pick where the current commit is empty, it will
return the same error again, causing lazygit to be stuck in an endless loop.
Fix this by skipping instead of continuing; this shouldn't make a difference for
rebase, but works for cherry-pick.
Theoretically we could have a similar problem for revert (if you are trying to
revert a commit that has already been undone through some other means); this
should then be fixed in the same way with this change. However, the change is
not relevant for revert because git returns a different error in this case.
When focusing the main view, going into full screen mode by pressing '+' twice,
and then opening the search prompt ('/') or a menu (e.g. '?' or ':'), the full
screen display would switch to the focused side panel.
Fix this by always excluding popups from the window arrangement logic. No popup
should ever have any influence on how the views beneath it are laid out.
This is likely to do bad things; for example, if the prompt is the shell command
prompt, then we would run into what looks like a deadlock bug in tcell. In other
cases, the characters in the following lines might be treated as random commands
after the prompt is confirmed.
Doesn't make a difference currently, since the title is either StatusTitle when
the dashboard is showing, or LogTitle when one of the branch logs is showing.
This is going to change in the next commit, though.
Replace merge-tool with merge options menu that allows resolving all
conflicts for selected files as ours, theirs, or union, while still
providing access to the merge tool.
The root item's path is ".", and the path of a file at top level is "./file".
When using GetPath, this gives us "." and "file", respectively, and
isDescendentOfSelectedNodes would return false for these.
Working with the internal paths (i.e. without stripping the leading "./") fixes
this.
Previously, the feedback you got when pressing "-" was just a "Checking out..."
status in the bottom line. This was both easy to miss if you are used to looking
for an inline status in the branches panel, and it didn't provide information
about which branch was being checked out, which can be annoying in very large
repos where checking out takes a while, and you only see at the end if you are
now on the right branch.
Improve this by trying to figure out which branch was the previously checked out
one, and then checking it out normally so that you get an inline status next to
it (as if you had pressed space on it). There are cases where this fails, e.g.
when the previously checked out ref was a detached head, in which case we fall
back to the previous behavior.
In all other menus besides the keybindings menu it makes sense to hide
keybindings that match the confirmMenu binding. This is important to make it
clear which action will be triggered when you press the key.
In the keybindings menu this is different; the main purpose of that menu is not
to allow triggering commands by their key while the menu is open, but to serve
as a reference for what the keybindings are when it is not open. Because of
this, it is more important to show all bindings in this menu, even if they
conflict with the confirmMenu key.
This fixes a regression introduced in b3a3410a1a.
It seems useful to have the flexibility to remap "enter" in confirmations to
"y", but keep "enter" for menus and suggestions (even though we sometimes use
menus as confirmations, but it's still good to give users the choice).
The universal.confirm keybinding is the wrong one to use for this, we want
universal.goInto instead. They are both bound to "enter" by default, but when
remapping confirm to "y" we don't want to use that for entering worktrees.